MantisBT - CMake
View Issue Details
0012369CMakeCPackpublic2011-07-28 17:192013-01-09 10:57
Jean-Christophe Fillion-Robin 
David Cole 
normalminoralways
closednot fixable 
 
CMake 2.8.6 
0012369: BundleUtilities - Add support for library built against plugin
Use case:
 "A" is a plugin for my application
 "B" is a plugin for Qt Designer

 "B" also depends on "A"


Problem:
 "A" will be fixed and copied in the location different from the app plugin folder


Solution:
 get_prerequisites() should fixup a library only if it hasn't been passed as a plugin to fixup_bundle()
No tags attached.
Issue History
2011-07-28 17:19Jean-Christophe Fillion-RobinNew Issue
2011-07-28 17:27David ColeAssigned To => David Cole
2011-07-28 17:27David ColeStatusnew => assigned
2011-07-28 17:32David ColeNote Added: 0027102
2011-07-28 17:32David ColeStatusassigned => resolved
2011-07-28 17:32David ColeFixed in Version => CMake 2.8.6
2011-07-28 17:32David ColeResolutionopen => not fixable
2011-07-28 17:40Clinton StimpsonNote Added: 0027103
2011-07-28 17:40Clinton StimpsonStatusresolved => feedback
2011-07-28 17:40Clinton StimpsonResolutionnot fixable => reopened
2011-07-28 17:40Clinton StimpsonStatusfeedback => resolved
2011-07-28 17:40Clinton StimpsonResolutionreopened => not fixable
2011-07-28 17:45David ColeNote Added: 0027104
2011-07-28 20:25Jean-Christophe Fillion-RobinNote Added: 0027106
2011-07-28 20:25Jean-Christophe Fillion-RobinStatusresolved => feedback
2011-07-28 20:25Jean-Christophe Fillion-RobinResolutionnot fixable => reopened
2011-07-28 20:49Clinton StimpsonNote Added: 0027107
2011-07-28 21:07Jean-Christophe Fillion-RobinNote Added: 0027109
2011-07-28 21:07Jean-Christophe Fillion-RobinStatusfeedback => assigned
2011-07-28 21:07Jean-Christophe Fillion-RobinNote Edited: 0027109bug_revision_view_page.php?bugnote_id=27109#r389
2011-07-28 23:54Clinton StimpsonNote Added: 0027110
2011-07-29 00:04Jean-Christophe Fillion-RobinNote Added: 0027111
2011-07-29 00:04Jean-Christophe Fillion-RobinNote Edited: 0027111bug_revision_view_page.php?bugnote_id=27111#r391
2011-07-29 00:12Jean-Christophe Fillion-RobinNote Edited: 0027111bug_revision_view_page.php?bugnote_id=27111#r392
2012-08-13 15:15David ColeNote Added: 0030608
2012-08-13 15:15David ColeStatusassigned => resolved
2012-08-13 15:15David ColeResolutionreopened => not fixable
2013-01-09 10:57Robert MaynardNote Added: 0032054
2013-01-09 10:57Robert MaynardStatusresolved => closed

Notes
(0027102)
David Cole   
2011-07-28 17:32   
plugins that depend on libraries MUST be fixed up by fixup_bundle or you'll end up with a bundle that is not really stand-alone. If you do not want a plugin fixed up by fixup_bundle then simply do not pass it as a plugin to fixup_bundle.

plugins should really be as stand-alone as possible, too, and not have complex dependencies. If you, as the developer of a plugin, can't write a couple lines of install code for a plugin, then how in the world is a script supposed to figure it out for you and do the right thing...?

You say "A" is a plugin for your application, and "B" is a plugin for Qt Designer. If that's really the case, then "B" does not even belong in your bundle. It should be installed somewhere else, and fixed up accordingly... including possibly copying "A" to another location where "B" can find it, and then fixing up "B" and "A" in that location such that it works in Qt Designer.

Let me know if you disagree, but I don't see how this is fixable in the general case and yet still maintain the goal of producing "stand-alone" bundles.
(0027103)
Clinton Stimpson   
2011-07-28 17:40   
I wanted to add some comments too...

Normally one shouldn't link plugins against other plugins. Changing that by creating another shared library that both link against might fix your problem.

But, if you insist, BundleUtilities has a default path for where dependencies get copied. If you don't like the defaults, you can override GetPrerequsites by implementing a function gp_item_default_embedded_path_override(). In that function, if "A" is passed in, you can return the location of "A" that you installed. That should prevent BundleUtilities from copying it into the default path for prerequisites.
(0027104)
David Cole   
2011-07-28 17:45   
Feel free to re-open this issue for additional discussion... I just wanted to make it crystal clear by resolving it as "not fixable" that I do not think there is a reasonable fix for this problem that can be elegantly handled automatically by BundleUtilities.

Thanks for the comments, Clinton, -- it would definitely make sense to separate out the dependencies of A and B so that they do not depend on each other.
(0027106)
Jean-Christophe Fillion-Robin   
2011-07-28 20:25   
To clarify: Both A and B are built. B is a custom Qt designer plugin that's linked against A so that it could rely on some custom widget class provided by A.

After spending some time trying to understand why on of our plugin (A) wasn't properly fixed, the question of updating fixup_bundle came to our mind.

Note that (as mentioned by Clinton) we already created a shared library common to both A and B. This library is named AWidgets. And this is the scheme we were already applying everywhere else in our application. I will make sure to update our module template and guidelines so that other developer can easily apply it.

I would suggest to do update fixup_bundle to throw an error with a clear description explaining that a library that is supposed to be standalone (without dependencies) is required by either an executable or a library.


Remark: We already heavily rely on gp_item_default_embedded_path_override - See https://github.com/Slicer/Slicer/blob/master/Utilities/LastConfigureStep/SlicerCompleteBundles.cmake.in [^]
(0027107)
Clinton Stimpson   
2011-07-28 20:49   
I meant to put code used by B into Awidget so B doesn't link with A.
I don't see how fixup_bundle() can know whether it should be standalone since it doesn't really know that it is a plugin. The libs argument could take both plugins and non-plugins.

An easier way to enforce this is at the cmake level and use the MODULE option instead of SHARED for the add_library()'s for plugins.
(0027109)
Jean-Christophe Fillion-Robin   
2011-07-28 21:07   
//------------------------
Before:

 B (QtDesignerCustomPlugin) link agains/depends on A (Module + Widgets)

After:

 B ((QtDesignerCustomPlugin) link "against/depends" on AWidgets

 A (Module) link "against/depends on" AWidgets


//------------------------
By design, fixup_bundle expects a list of plugins as 'libs' parameter. It means if a library being fixed depends on a library passed as "libs", it could skip it or display an error message.

Checking if the target is a MODULE could work .. but I am not sure CPack can access that information since it is simply running the cmake_install script generated at configure time.

From the documentation of BundleUtilities,
See http://cmake.org/gitweb?p=cmake.git;a=blob_plain;f=Modules/BundleUtilities.cmake [^]

"
# If you pass plugins to fixup_bundle as the libs parameter, you should install
# them or copy them into the bundle before calling fixup_bundle. The "libs"
# parameter is a list of libraries that must be fixed up, but that cannot be
# determined by otool output analysis. (i.e., plugins)
"

When fixup_bundle encounters a library that depends on a plugin, it ends up calling "gp_item_default_embedded_path_override" with the item parameter being set to the filename of the library and not the complete path. As a consequence the regular expression within "gp_item_default_embedded_path_override" doesn't match as expected and the plugin end up in the wrong folder.

(0027110)
Clinton Stimpson   
2011-07-28 23:54   
CPack wouldn't need to ask if a target is a MODULE because CMake will fail to configure.

Consider:
add_library(A MODULE ...)
add_library(B MODULE ...)
target_link_libraries(B A) # <---- cmake will error on this line because A is a MODULE
  CMake Error at CMakeLists.txt:4 (target_link_libraries):
    Target "A" of type MODULE_LIBRARY may not be linked into another target.
    One may link only to STATIC or SHARED libraries, or to executables with the
    ENABLE_EXPORTS property set.
(0027111)
Jean-Christophe Fillion-Robin   
2011-07-29 00:04   
(edited on: 2011-07-29 00:12)
Got it ... Thanks :) I guess we could close the issue now.

Note: The CustomQtDesigner were already built as MODULE .. but didn;t specify it for the application module/plugin.

Last thing ...

1) to be consistent, the parameter of fixup_bundle could be named "modules" instead of "libs"

2) May be it would be worth adding a safeguard to BundleUtilities so that it complain if libraries (plugins) passed as a parameter to fixup_bundle are also prerequisites of other libraries.

That message could give some hints .. about using MODULE option, etc ...

Doing so could save some time when debugging bundling process and help identify problem early.

(0030608)
David Cole   
2012-08-13 15:15   
resolving again based on further discussion in the bug notes...
(0032054)
Robert Maynard   
2013-01-09 10:57   
Closing resolved issues that have not been updated in more than 4 months.