如何导出cmake库所依赖的库,以便依赖于该库的可执行文件不必手动依赖该库的依赖项?
这有点拗口,所以这是一个例子:
虚拟(应用)---->取决于liba
liba ---->取决于libpng
编译虚拟生成错误:
-- Found LIBPNG
-- Found LIBA
-- Configuring done
-- Generating done
-- Build files have been written to: /home/doug/projects/dummy/build
Linking C executable dummy
../deps/liba/build/liba.a(a.c.o): In function `a_dummy':
/home/doug/projects/dummy/deps/liba/src/a.c:6: undefined reference to `png_sig_cmp'
collect2: ld returned 1 exit status
make[2]: *** [dummy] Error 1
make[1]: *** [CMakeFiles/dummy.dir/all] Error 2
make: *** [all] Error 2
我可以通过将其添加到CMakeLists.txt中来修复它:
TARGET_LINK_LIBRARIES(虚拟png)
然而,dummy并不知道liba如何实现其api。在某些时候,可能会变成libjpg或其他东西,这将打破虚拟应用程序。
在从cmake邮件列表中获得一些帮助之后,我被引导到这个例子来导出东西: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
但是,遵循这种方法让我陷入了这条路:
export(TARGETS $ {LIBPNG_LIBRARY} FILE“$ {PROJECT_BINARY_DIR} /ALibraryDepends.cmake”)
显然我在这里遗漏了一些东西;这个'export'命令看起来像是为了将子项目输出到高水平;即。 liba中的嵌套项目。
但是,这不是问题所在。
配置liba(或任何cmake库)时,我将始终生成一个不属于该项目的依赖项列表。
当我使用find_package()解析liba时,如何导出它们以便它们作为LIBA_LIBRARY的一部分出现?
使用静态库不是一个选项(链接到opengl的静态库?没有。)
答案 0 :(得分:7)
鉴于你对arrowdodger关于恐惧的答案的评论 安装一些东西会搞砸我选择给你的系统 以答案形式出现的概念性评论 长度。
链接cmake项目通过查找的find_package工作 * Config.cmake和* -config.cmake文件。
Project A&#39的CMakeLists.txt:
#CMakeLists.txt
project(A)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake
)
#AConfig.cmake
message("Yepp, you've found me.")
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
Project B&#39的CMakeLists.txt:
project(B)
find_package(A)
然后
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
结果
...
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Yepp, you've found me.
B找到了A,因为它将AConfig.cmake安装到一个位置 cmake会在哪里找到它/分享/ A / cmake'和给予相同的 CMAKE_INSTALL_PREFIX的值。
现在就是这样。让我们考虑一下你可以做些什么 AConfig.cmake:AFAIK你想要的一切。但最常见的 任务是通过include()获取有关A目标的信息, 为第三方做一些额外的find_package调用 包(HINT HINT)并创建变量
A_LIBRARIES
A_INCLUDE_DIRS
您要包含的内容是由
创建的文件install(EXPORT A-targets
DESTINATION share/A/cmake
)
在A&#39的CMakeLists.txt中,其中A-targets是指全局cmake 在
中使用时累积所有目标信息的变量install(TARGETS ...
EXPORT A-targets
...
)
statments。 make install创建的内容是
/tmp/test-install/share/A/cmake/A-targets.cmake
然后与AConfig.cmake一起驻留在同一目录中。 请再看一下如何使用此文件的Wiki页面 在AConfig.cmake内。
关于export()命令:如果你的话,这很方便 项目已经变得巨大,需要相当多的时间 是时候安装它们了。为了加快速度,你想要使用什么 直接在A&#39的构建/目录中。它是一种优化,也是一种优化 在维基中解释。它仍然可以通过find_package()工作,参见
但我强烈建议您选择通常的make install 现在路线。
答案 1 :(得分:2)
我使用上面接受的解决方案找到了我自己的解决方案,我将其留给其他人使用:
在liba / CMakeLists.txt中:
# Self
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include")
set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a")
# Libpng
FIND_PACKAGE(libpng REQUIRED)
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS})
set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES})
ADD_LIBRARY(a ${SOURCES})
# Includes
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
# Allow other projects to use this
configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake")
在liba / AConfig.cmake中:
set(A_LIBRARIES @A_LIBRARIES@)
set(A_INCLUDE_DIRS @A_INCLUDE_DIRS@)
在dummy / CMakeLists.txt中:
FIND_PACKAGE(A REQUIRED)
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES})
这会产生一个AConfig.cmake,其内容为:
set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so)
set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include)
详细的编译内容如下:
/usr/bin/gcc -std=c99 -g CMakeFiles/dummy.dir/src/main.c.o -o dummy -rdynamic ../deps/liba/build/liba.a -lpng
这正是我所寻找的。 p>
答案 2 :(得分:1)
如果liba没有提供任何方法来确定它的依赖关系,那么你就无法做任何事情。 如果liba是由您开发的库并且您正在使用CMake构建它,那么您应该使用liba本身安装libaConfig.cmake文件,其中包含必要的定义。然后在dummy的CMakeLists.txt中包含libaConfig,以获取有关如何构建liba的信息。
您可以在LLVM项目中查看它是如何完成的,相关文件的扩展名为cmake.in http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/
最后,在虚拟项目中你应该使用
target_link_libraries( ${LIBA_LIBRARIES} )
include_directories( ${LIBA_INCLUDE_DIR} )
link_directories( ${LIBA_LIBRARY_DIR} )
如果该liba仅由dummy使用,则可以从单个CMake项目构建它。这样更方便,因为每次重新编译时都不需要安装liba,每次运行make
时都会自动重建和重新链接。
如果您喜欢这种方法,那么您应该做的唯一事情 - 使用PARENT_SCOPE选项在liba中定义CMakeLists.txt变量(参见set()命令手册)。
最后,你可以使用共享库,.so没有这样的问题。