我想知道如何在没有任何FIND_PACKAGE的情况下查找/链接库。
假设我们有一个名为testlib的“个人”库:
/perso/testlib/include/testlib1.h
/perso/testlib/include/testlib2.h
/perso/testlib/lib/testlib1.a
/perso/testlib/lib/testlib2.a
如何将其与CMake链接?
1)在CMakeLists.txt的代码中直接链接它的功能是什么?
2)如何让用户选择文件的位置?
3)我很难理解CMake解释什么以及什么不是。例如,如果你定义一个变量$ {MYVARIABLE_INCLUDE_DIR}或$ {MYVARIABLE_LIBRARIES}是“INCLUDE_DIR”或“LIBRARIES”一个由CMake解释的扩展名,或者如果我调用这个变量$ {MYVARIABLE_INCDIR}没有区别?
4)如果你在lib目录中有一个包含10个或更多库文件的库,如何执行相同的程序(包括“个人”库)?
5)最后,当你输入TARGET_LINK_LIBRARIES(myexecutable gmp)
时,你怎么知道这个库的名字是“gmp”。为什么不“Gmp”或“GMP”?放入此函数的库的名称是否等于.a文件减去“lib”和“.a”?例如libgmp.a - > gmp?如果我想链接一个名为libtestlolexample.a的库,我是否必须输入TARGET_LINK_LIBRARIES(myexecutable testlolexample)
?
非常感谢。
答案 0 :(得分:15)
您可以使用target_link_libraries(myexecutable mylib)
链接到“mylib”库。编译器将使用其默认方式查找指定的库(例如,它将在Linux上查找libmylib.a)。编译器只会查看link_directories(directory1 directory2 ...)
,因此您可以尝试使用该命令将所需目录添加到搜索路径中。
当使用CMake编译“mylib”时,这将被识别,一切都应该自动生效。
如果希望用户指定目录,可以使用缓存的CMake变量。 set(MYPATH "NOT-DEFINED" CACHE PATH "docstring")
。
对于更复杂的东西,建议编写一个可以与find_package
一起使用的CMake查找模块。我建议你看看FindALSA.cmake
,它可以作为一个很好的起点。
有趣的部分是在最后:
if(ALSA_FOUND)
set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
endif()
mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)
ALSA_LIBRARY
和ALSA_INCLUDE_DIR
变量是用户可配置的并存储在缓存中,而ALSA_LIBRARIES
和ALSA_INCLUDE_DIRS
以及ALSA_FOUND
计算得出来发现模块的用户应该使用的那些。
通常会使用这样的find模块:
find_package(ALSA REQUIRED)
include_directories(${ALSA_INCLUDE_DIRS})
target_link_libraries(myexe ${ALSA_LIBRARIES})
我相信你可以为你的个人图书馆进行调整。
答案 1 :(得分:4)
通常当你想链接一个没有find_package模块的库时(例如它是一个不常见的库,或者它是你自己的库),那么你可以使用基本命令(find_X命令)来设置变量你需要的路径。然后您将这些变量用作find_package(include_directories
,target_link_libraries
)。
如果您要从多个包中使用此库,您可能需要创建一个find_package模块;基本上它使用具有某些约定的相同命令。
其中任何一个都允许您指定要查看的路径(在CMake模块中),并允许用户覆盖路径(变量显示为ccmake
/ cmake-gui
中的选项)
我很乐意添加其中一种或两种方法的示例,让我知道您在寻找什么。
如果你只想要一个快速而肮脏的解决方案,你可以这样做,但我不推荐它:
include_directories(/perso/testlib/include)
add_executable(myexecutable myexecutable.cpp)
target_link_libraries(myexecutable
/perso/testlib/lib/testlib1.a
/perso/testlib/lib/testlib2.a)
关于target_link_libraries
(#5)的问题,您可以采取多种方式。如果您愿意,可以提供全名(例如target_link_libraries(myexe libfoo.a)
),但我认为使用短名称(例如target_link_libraries(myexe foo
)会更好(我认为更便携)。您还可以包含链接器标志;我不确定我在哪里阅读它,但我认为它可能会转换不同链接器的-L和-l标志。
例如,如果我在同一目录中有一堆库,并且我知道名称,我可能会找到该目录,将其存储在变量中,然后执行此操作:
# First, find and set TESTLIB_LIBRARY_DIR, e.g. with find_path
# ...
# This assumes the libraries are e.g. 'libtestlib1.a' and 'libtestlib2.a'
set(TESTLIB_LIBRARIES
-L${TESTLIB_LIBRARY_DIR)
-l testlib1
-l testlib2)
add_executable(myexecutable myexecutable.cpp)
target_link_libraries(myexecutable ${TESTLIB_LIBRARIES})
如果你想创建自己的find_package模块(如提到的trenki,FindALSA.cmake
似乎是一个很好的起点),你可以通过将目录添加到CMAKE_MODULE_PATH
来使用它;例如,如果您将模块放在cmake/modules/
子目录中:
# Look for extra CMake modules in a subdirectory of this project
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/" ${CMAKE_MODULE_PATH})
FindALSA.cmake
的一个可能问题:我不确定CMAKE_CURRENT_LIST_DIR
是否可行。所以我认为你应该做这个改变(在我写的一个模块中对我来说是第二项工作):
# Change this line
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
# To this (with no path/extension it will search the CMake modules path):
include(FindPackageHandleStandardArgs)
要获得FIND_PACKAGE_HANDLE_STANDARD_ARGS
的使用,请查看CMake Modules目录中的FindPackageHandleStandardArgs.cmake
。
答案 2 :(得分:0)
CMake有一个很好的documentation。
${MYVARIABLE_INCLUDE_DIR}
只是一个变量名称,无论你想要什么。但我建议您遵循命名惯例。