[CMake] not found library with package configuration files and changed CMAKE_INSTALL_PREFIX
Michael Hertling
mhertling at online.de
Tue Sep 20 10:38:06 EDT 2011
On 09/20/2011 11:26 AM, Alexander Dahl wrote:
> Hello there,
>
> after using FindFOO.cmake scripts for our own projects for a long time
> I'm trying to migrate this to the "real" CMake approach of package
> configuration files. Therefor I read chapter 5.7 of the book »Mastering
> CMake« and two HowTos [1] [2] on the web merging all of these in some
> files. I have own shared C library "foo" and one C command line tool
> "bar" and try to build this on Ubuntu Lucid 10.04 with a self compiled
> cmake 2.8.4.
>
> This works fine as long as I don't change CMAKE_INSTALL_PREFIX (with
> `make edit_cache` or earlier when calling `cmake
> -DCMAKE_INSTALL_PREFIX=/some/path /path/to/src`) and it is /usr/local –
> however when changing this to /home/adahl/usr (or any other non standard
> path) linking the library fails although the include files are still
> found (FOO_DIR is correctly set to /home/adahl/usr/lib/cmake/foo).
>
> I'll show my CMakeList.txt files and the package configuration stuff,
> maybe someone could have a look and point me to my errors.
>
> In project "foo" which builds a shared C library:
>
> CMakeLists.txt:
>
> 4 project(foo)
> 5
> 6 cmake_minimum_required(VERSION 2.8)
> 7
> 8 set(PACKAGE_MAJOR_VERSION "0")
> 9 set(PACKAGE_MINOR_VERSION "1")
> 10 set(PACKAGE_BUILD_VERSION "0")
> 11 set(PACKAGE_VERSION
> "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_BUILD_VERSION}"
> )
> 12
> 13 add_subdirectory("inc")
> 14 add_subdirectory("src")
> 15
> 16 configure_file(
> 17 ${CMAKE_CURRENT_SOURCE_DIR}/foo-config.cmake.in
> 18 ${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake @ONLY
> 19 )
> 20 configure_file(
> 21 ${CMAKE_CURRENT_SOURCE_DIR}/foo-config-version.cmake.in
> 22 ${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake @ONLY
> 23 )
> 24 install(FILES
> 25 ${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake
> 26 ${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake
> 27 DESTINATION "lib/cmake/${PROJECT_NAME}"
> 28 )
>
> foo-config.cmake.in:
>
> 4 get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
> 5 get_filename_component(_prefix "${_dir}/../../.." ABSOLUTE)
> 6 include("${_dir}/@PROJECT_NAME at -targets.cmake")
> 7 set(FOO_INCLUDE_DIRS "${_prefix}/include/@PROJECT_NAME@")
>
> foo-config-version.cmake.in:
>
> 4 set(PACKAGE_VERSION "@PACKAGE_VERSION@")
> 5
> 6 if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
> 7 set(PACKAGE_VERSION_COMPATIBLE FALSE)
> 8 else()
> 9 set(PACKAGE_VERSION_COMPATIBLE TRUE)
> 10 if ("${PACKAGE_VERSION}" VERSION_EQUAL
> "${PACKAGE_FIND_VERSION}")
> 11 set(PACKAGE_VERSION_EXACT TRUE)
> 12 endif()
> 13 endif()
>
> inc/CMakeLists.txt:
>
> 4 install(FILES
> 5 foo.h
> 6 DESTINATION "include/${PROJECT_NAME}"
> 7 )
>
> src/CMakeLists.txt:
>
> 4 set(FOO_SRC
> 5 foo.c
> 6 )
> 7
> 8 include_directories(
> 9 "${PROJECT_SOURCE_DIR}/inc"
> 10 )
> 11
> 12 add_library(${PROJECT_NAME}-shared SHARED ${FOO_SRC})
> 13 set_target_properties(${PROJECT_NAME}-shared PROPERTIES
> 14 OUTPUT_NAME ${PROJECT_NAME}
> 15 SOVERSION ${PACKAGE_MAJOR_VERSION}
> 16 VERSION ${PACKAGE_VERSION}
> 17 )
This leaves the target named "foo-shared", not "foo"; the latter is
just the base name of the target's disk file, i.e. libfoo.so.0.1.0.
> 18 install(TARGETS ${PROJECT_NAME}-shared DESTINATION "lib" EXPORT
> ${PROJECT_NAME}-targets)
> 19 install(EXPORT ${PROJECT_NAME}-targets DESTINATION
> "lib/cmake/${PROJECT_NAME}")
The foo-targets.cmake file contains "foo-shared" as imported target,
and it is this name that must be supplied to TARGET_LINK_LIBRARIES().
Besides, the DESTINATION clause of INSTALL() should be qualified with
ARCHIVE/LIBRARY/RUNTIME/..., and EXPORT must precede DESTINATION then.
> This allows successful build of the library with all files installed
> where they should be, at least binaries and header files. The package
> configuration files are installed like this:
>
> % ls -l /home/adahl/usr/lib/cmake/foo
> insgesamt 16
> -rw-r--r-- 1 adahl adahl 248 2011-09-20 11:09 foo-config.cmake
> -rw-r--r-- 1 adahl adahl 334 2011-09-20 11:09 foo-config-version.cmake
> -rw-r--r-- 1 adahl adahl 924 2011-09-20 11:09 foo-targets.cmake
> -rw-r--r-- 1 adahl adahl 1041 2011-09-20 11:09
> foo-targets-noconfig.cmake
>
> Now first I build this library like this:
>
> ~/Work/build/libfoo % cmake -DCMAKE_INSTALL_PREFIX=/home/adahl/usr
> ../../src/libfoo
> ~/Work/build/libfoo % make
> ~/Work/build/libfoo % make install
>
> No problem so far, but when building the cli tool »bar« like this:
>
> ~/Work/build/bar % cmake -DCMAKE_INSTALL_PREFIX=/home/adahl/usr
> ../../src/bar
> ~/Work/build/bar % make
>
> This fails like this:
>
> Linking C executable bar
> /usr/bin/ld: cannot find -lfoo
The "-lfoo" notation instead of a full path is a typical hint that CMake
doesn't recognize "foo" as an [imported] target but as a simple library
passed to TARGET_LINK_LIBRARIES(). However, libraries residing in an
"implicit system location" constitute an exception, refer to [3].
> collect2: ld returned 1 exit status
>
> (Note: when not changing CMAKE_INSTALL_PATH this works.)
>
> The cmake files for "bar" look like this:
>
> CMakeLists.txt:
>
> 4 project(m16c-progflash)
> 5
> 6 cmake_minimum_required(VERSION 2.8)
> 7
> 8 set(PACKAGE_MAJOR_VERSION "0")
> 9 set(PACKAGE_MINOR_VERSION "1")
> 10 set(PACKAGE_BUILD_VERSION "0")
> 11 set(PACKAGE_VERSION
> "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_BUILD_VERSION}"
> )
> 12
> 16 find_package(FOO 0.1 REQUIRED)
> 17
> 18 add_subdirectory("src")
>
> src/CMakeLists.txt:
>
> 11 set(BAR_SRC
> 12 bar.c
> 13 )
> 14
> 15 include_directories(
> 16 ${CMAKE_CURRENT_BINARY_DIR}
> 17 ${FOO_INCLUDE_DIRS}
> 18 )
> 19 add_executable(${PROJECT_NAME} ${BAR_SRC})
> 20
> 21 target_link_libraries(${PROJECT_NAME} foo)
Try TARGET_LINK_LIBRARIES(${PROJECT_NAME} foo-shared).
^^^^^^^
> 22
> 23 install(TARGETS ${PROJECT_NAME} DESTINATION bin)
>
> With the former find scripts I would have had FOO_LIBRARIES and used
> this in target_link_libraries() instead of "foo" but this variable is
> not set anymore. So the includes are found, also in the changed
> CMAKE_INSTALL_PREFIX tree, but linking fails. I guess this is some
> misunderstanding or error in the package files of libfoo, but I can not
> see where.
You should still provide the variable FOO_LIBRARIES which contains
"foo-shared", i.e. the name of the imported target. For the user, it
should not make any difference whether the find module / config file
uses full paths to library targets immediately or via imported targets
and their IMPORTED_LOCATION properties. If you read the tutorial in [1]
carefully, you will see that there's still a FOOBAR_LIBRARIES variable
in the FooBar/FooBarConfig.cmake.in template of the configuration file.
'hope that helps.
Regards,
Michael
[3] http://cmake.org/Wiki/CMake_2.6_Notes#Linking_to_System_Libraries
> Any help appreciated. O:-)
> Greets
> Alex
>
> [1]
> http://cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
> [2] http://www.vtk.org/Wiki/CMake/Tutorials/Packaging
More information about the CMake
mailing list