View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0012382CMakeModulespublic2011-08-02 18:472016-06-10 14:31
ReporterGregory Crosswhite 
Assigned ToKitware Robot 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionmoved 
PlatformApple MacOSOS XOS Version10.4.10
Product VersionCMake 2.8.5 
Target VersionFixed in Version 
Summary0012382: fixup_bundle_item dies on libraries copied to a directory outside bundle directory
DescriptionWhen using a Linux-style layout for the installation with bin/, lib/, etc. and directing the required shared libraries to be installed in lib/ instead of bin/, fixup_bundle_item does not recognize that they have been installed into the bundle and reports a fatal error.

The problem comes from the fact that when calling fixup_bundle on an executable in the bin/ directory, fixup_bundle sets the bundle directory to bin/ which is a sibling but not a parent of lib/, and so fixup_bundle_item does not recognize that the library it is fixing up has already been put in the bundle.
Steps To ReproduceThe attached file has an example setup that triggers the issue; inside the ZIPfile are three files which are listed below:

===== CMakeLists.txt =====
cmake_minimum_required(VERSION 2.8.5)

set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/bundle)

find_package( Boost COMPONENTS thread REQUIRED )
link_directories ( ${Boost_LIBRARY_DIRS} )
include_directories ( ${Boost_INCLUDE_DIRS} )

add_executable(hello hello)
target_link_libraries(hello ${Boost_LIBRARIES})
install (TARGETS hello RUNTIME DESTINATION bin)

configure_file(
    ${CMAKE_SOURCE_DIR}/FixBundle.cmake.in
    ${CMAKE_BINARY_DIR}/FixBundle.cmake
    @ONLY
)
install(SCRIPT ${CMAKE_BINARY_DIR}/FixBundle.cmake)

===== FixBundle.cmake =====
include (BundleUtilities)

function(gp_item_default_embedded_path item default_embedded_path_var)
  set(${default_embedded_path_var} "@executable_path/../lib" PARENT_SCOPE)
endfunction(gp_item_default_embedded_path)

fixup_bundle("${CMAKE_INSTALL_PREFIX}/bin/hello${CMAKE_EXECUTABLE_SUFFIX}" "" "@LIBRARY_OUTPUT_PATH@")
===== hello.cpp =====
#include <iostream>

using namespace std;

int main() {
  cout << "Hello, world!" << endl;
  return 0;
}
======================

Note that hello.cpp doesn't use Boost, I just included the dependency in order to make sure that an external non-system shared library was pulled in.
TagsNo tags attached.
Attached Fileszip file icon cmake-issue-example.zip [^] (1,342 bytes) 2011-08-02 18:47
zip file icon cmake-issue-example-2.zip [^] (1,396 bytes) 2011-08-02 19:12

 Relationships
related to 0013052closedKitware Robot BundleUtilities (fixup_bundle_item): location checks are too strict 

  Notes
(0027151)
Gregory Crosswhite (reporter)
2011-08-02 19:12

Note that this problem is triggered even when there are *no* outside shared libraries being pulled in if a build shared library is listed in the second argument of fixup_bundle but is not installed in the executable directory. See cmake-issue-example-2.zip for this; libhello.cpp is empty, and CMakeLists.txt and FixBundle.cmake.in are as follows:

===== CMakeLists.txt =====
cmake_minimum_required(VERSION 2.8.5)

set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/bundle)

add_executable(hello hello)
add_library(hellolib SHARED hellolib)
install (TARGETS hello DESTINATION bin)
install (TARGETS hellolib DESTINATION lib)

configure_file(
    ${CMAKE_SOURCE_DIR}/FixBundle.cmake.in
    ${CMAKE_BINARY_DIR}/FixBundle.cmake
    @ONLY
)
install(SCRIPT ${CMAKE_BINARY_DIR}/FixBundle.cmake)

===== FixBundle.cmake.in =====
include (BundleUtilities)

fixup_bundle(
  "${CMAKE_INSTALL_PREFIX}/bin/hello@CMAKE_EXECUTABLE_SUFFIX@"
  "${CMAKE_INSTALL_PREFIX}/lib/@CMAKE_SHARED_LIBRARY_PREFIX@hellolib@CMAKE_SHARED_LIBRARY_SUFFIX@"
  "@LIBRARY_OUTPUT_PATH@"
)

=====================

The resulting error message is

=====================
-- Install configuration: ""
-- Up-to-date: /Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/bin/hello
-- Installing: /Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/libhellolib.dylib
-- fixup_bundle
-- app='/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/bin/hello'
-- libs='/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/libhellolib.dylib'
-- dirs=''
-- fixup_bundle: preparing...
-- fixup_bundle: copying...
-- 1/4: *NOT* copying '/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/libhellolib.dylib'
-- 2/4: *NOT* copying '/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/bin/hello'
-- fixup_bundle: fixing...
-- 3/4: fixing up '/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/libhellolib.dylib'
  exe_dotapp_dir/='/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/bin/'
  item_substring='/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/'
  resolved_embedded_item='/Users/gcross/Documents/ThrowawayCode/cmake-issue-example/build/bundle/lib/libhellolib.dylib'

Install or copy the item into the bundle before calling fixup_bundle.
Or maybe there's a typo or incorrect path in one of the args to fixup_bundle?

CMake Error at /Applications/CMake 2.8-5.app/Contents/share/cmake-2.8/Modules/BundleUtilities.cmake:568 (message):
  cannot fixup an item that is not in the bundle...
Call Stack (most recent call first):
  /Applications/CMake 2.8-5.app/Contents/share/cmake-2.8/Modules/BundleUtilities.cmake:656 (fixup_bundle_item)
  FixBundle.cmake:3 (fixup_bundle)
  cmake_install.cmake:54 (INCLUDE)
=====================
(0027152)
Gregory Crosswhite (reporter)
2011-08-02 19:13

It seems to me like the best way to resolve this is to let the user override the way that the bundle directory is obtained from the path to the executable; this would also cause fixup_bundle to correctly scan through the entire bundle looking for libraries rather than just the subdirectory containing the executable specified in the first parameter of fixup_bundle.
(0027153)
Clinton Stimpson (developer)
2011-08-02 19:33

The fix for this bug is to modify the check that throws the "Install or copy..." error.
(0027154)
Gregory Crosswhite (reporter)
2011-08-02 19:49

Okidoke; you're the developer, not me. :-)
(0030269)
David Cole (manager)
2012-08-11 11:28

Clinton,

How should we modify this?

The intent everywhere is to make sure the final bundle is truly stand-alone and may be relocated to another machine and another root directory and still work.

The intent on Mac was to make sure all files are contained within the .app directory structure to ensure that it is "stand-alone".

The intent on Windows is to make sure *all* files are in *the same* directory so that DLL loading "just works".

What is the intent with "fixup_bundle" on Linux? Is *any* directory structure ok, and if so, how do know the "bundle" will work when it is simply copied/moved to a new machine/location on Linux?

I'd be happy to take this one, but I still don't have a good grasp on how useful this is on Linux. One of these days, I've got to get into building my own little bundle example app on Linux, so I have a little sandbox app that I understand fully.

Thanks...
(0030323)
Clinton Stimpson (developer)
2012-08-11 12:45

BundleUtilities is likely less popular on Linux, and is most likely used by those shipping their own binaries with their own 3rd party libraries which may or may not exist on any given target machine. I don't think these users are bound to the bin/ lib/ convention, since the intent of BundleUtilities is to make a relocatable/standalone application.

Any directory structure is allowed on Linux when using rpaths.
When using a bin/ lib/ structure, an executable can have an rpath of "$ORIGIN/../lib" so any dependent shared library will be found. For a plugin down in "plugins/typeA/" directory, it could have an rpath of $ORIGIN/../../lib to find its dependencies.
So, if one were to copy/move the parent directory (containing bin/ lib/ plugins/), it would still work.

We had a discussion a while back about the user passing in a prefix which could be different than the executable directory or the .app directory. Perhaps that is the solution we need here.
That would also fix this one: http://www.cmake.org/Bug/view.php?id=13052. [^]

I'd also like to see full @rpath support someday on the Mac, and move away from @executable_path. Perhaps if you took the time to use @rpath on Mac, you would fully understand rpaths on Linux. Though on Linux, its a bit simpler.
(0030324)
Clinton Stimpson (developer)
2012-08-11 12:47

Oh, I just realized the Reporter is on Mac, not Linux, which means this is even more similar to bug 0013052.
(0031656)
David Cole (manager)
2012-11-21 14:57

Un-assigning bugs that are not on the active roadmap, which no developers are actively working on for the CMake 2.8.11 release.

If one gets put back on the roadmap, re-assign it appropriately at that time.
(0031663)
David Cole (manager)
2012-11-21 15:11

Re-setting status back to "new" for bugs that are "assigned" but not assigned to a specific developer. When/if these bugs go back on the roadmap for a specific version, assignment to an appropriate developer should take place then...
(0032915)
Craig Scott (reporter)
2013-04-22 01:27

Any chance this one can make it back on someone's todo list? I've hit exactly this scenario on linux. We have a bin/ lib/ structure and we use the include(InstallRequiredSystemLibraries) feature to ensure we get packages which are fully self-contained. We use an RPATH of $ORIGIN/../lib as described by Clinton. The arrangement works well on Windows and would probably work well on Mac, but on linux it means the install step is broken because it doesn't find libraries in lib/. Strangely, the install step copies duplicates of those libraries into bin/ which is probably a direct consequence, but that just makes it even harder to understand why the verify_app step fails!

Not sure if it's related, but it might also be worth reviewing bug 0013433 just in case it is relevant. Personally though, I suspect the problem is more related to the fact that the RPATH substitution results in a full path containing /../ and somewhere in the CMake code it compares this against a canonical path or something similar.
(0040459)
Florian Apolloner (reporter)
2016-02-10 08:49

@Craig: I've fixed it like this for me:

set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib")

set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/BAPGui")
install(TARGETS bap-gui DESTINATION bin)

get_target_property(QMAKE_PATH Qt5::qmake IMPORTED_LOCATION)
execute_process(COMMAND ${QMAKE_PATH} -query QT_INSTALL_PREFIX OUTPUT_VARIABLE QT_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)

install(CODE "
    function(gp_item_default_embedded_path_override item path_var)
        set(\${path_var} \"@executable_path/../lib\" PARENT_SCOPE)
    endfunction()
    function(gp_resolved_file_type_override item type_var)
        if(\${item} MATCHES \"\\\\.\\\\./lib\")
            set(\${type_var} \"local\" PARENT_SCOPE)
        endif()
    endfunction()
    include(${CMAKE_CURRENT_SOURCE_DIR}/BundleUtilitiesLocal.cmake)
    fixup_bundle(\"\$ENV{DESTDIR}/\${CMAKE_INSTALL_PREFIX}/bin/bap-gui\" \"\" \"${QT_PREFIX}/lib\")
")

set(CPACK_GENERATOR "TGZ")
(0041881)
Kitware Robot (administrator)
2016-06-10 14:28

Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2011-08-02 18:47 Gregory Crosswhite New Issue
2011-08-02 18:47 Gregory Crosswhite File Added: cmake-issue-example.zip
2011-08-02 19:12 Gregory Crosswhite Note Added: 0027151
2011-08-02 19:12 Gregory Crosswhite File Added: cmake-issue-example-2.zip
2011-08-02 19:13 Gregory Crosswhite Note Added: 0027152
2011-08-02 19:33 Clinton Stimpson Note Added: 0027153
2011-08-02 19:49 Gregory Crosswhite Note Added: 0027154
2012-08-11 11:24 David Cole Assigned To => David Cole
2012-08-11 11:24 David Cole Status new => assigned
2012-08-11 11:28 David Cole Note Added: 0030269
2012-08-11 12:45 Clinton Stimpson Note Added: 0030323
2012-08-11 12:47 Clinton Stimpson Note Added: 0030324
2012-08-11 17:08 David Cole Relationship added related to 0013052
2012-11-21 14:57 David Cole Note Added: 0031656
2012-11-21 15:00 David Cole Assigned To David Cole =>
2012-11-21 15:11 David Cole Status assigned => new
2012-11-21 15:11 David Cole Note Added: 0031663
2013-04-22 01:27 Craig Scott Note Added: 0032915
2016-02-10 08:49 Florian Apolloner Note Added: 0040459
2016-06-10 14:28 Kitware Robot Note Added: 0041881
2016-06-10 14:28 Kitware Robot Status new => resolved
2016-06-10 14:28 Kitware Robot Resolution open => moved
2016-06-10 14:28 Kitware Robot Assigned To => Kitware Robot
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team