如何告诉CMake在源目录中链接静态库?

139

我有一个小项目,其中有一个Makefile,我试图将其转换为CMake,主要是为了获得使用CMake的经验。在本例中,该项目包含一个源文件(C++,尽管我认为语言并不特别相关)和一个静态库文件,我从其他地方复制了它。出于论证的目的,假定库的源代码不可用;我只有.a文件和相应的头文件。

我的手工制作的Makefile包含以下构建规则:

main: main.o libbingitup.a
    g++ -o main main.o libbingitup.a

这个工作很好。我该如何告诉CMake来复现它呢?当然不是字面上的这个makefile,但需要包含等效的链接命令。我尝试了一些显而易见但幼稚的方式,比如:

这个可以正常工作。我要怎么告诉CMake去复制它呢?当然不是字面上的那个makefile,但是需要包括等效的链接命令。我已经尝试了一些显而易见但幼稚的方法,例如

add_executable(main main.cpp libbingitup.a)
或者
add_executable(main main.cpp)
target_link_libraries(main libbingitup.a)

我尝试过使用link_directories(.)或者add_library(bingitup STATIC IMPORTED)等方法,但是没有成功链接。请问还有什么需要做的吗?


版本信息:CMake 2.8.7在Linux (Kubuntu 12.04)上,使用GCC 4.6.3。

4个回答

160

CMake更偏好传递完整的链接库路径,因此假设libbingitup.a在${CMAKE_SOURCE_DIR}中,执行以下操作应该会成功:

add_executable(main main.cpp)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a)

2
太好了,可以工作了,谢谢!在这里明确地放入完整路径似乎有点hackish,但我想这就是CMake的方式... - David Z
4
我同意这似乎有些过头了,但是如果您安装了多个不同版本的相同库,则明确指定完整路径会带来好处。 - Fraser
1
像往常一样,太棒了!在我的情况下,解决了一个关于库依赖的问题,其中一个动态库依赖于一个静态库:依赖库也试图链接到这个静态库。 - Antonio
2
主函数如何知道包含目录? - ManuelSchneid3r
5
你需要使用target_include_directoriesinclude_directories(前者更为推荐,因为它更加具体),这将使内容更易懂。请参考链接:target_include_directoriesinclude_directories - Fraser
显示剩余3条评论

42
如果您不想包含完整路径,可以执行以下操作:
add_executable(main main.cpp)
target_link_libraries(main bingitup)

bingitup是在CMake项目中创建静态库时给目标命名的相同名称:

add_library(bingitup STATIC bingitup.cpp)

CMake会自动在Linux系统上将lib添加到库名前面并在末尾添加.a,在Windows系统上则在末尾添加.lib

如果库是外部库,您可能需要使用以下方式添加库路径

link_directories(/path/to/libraries/)

3
如果存在同名的 .a 和 .so 文件,你如何指定在这种情况下链接到 .a 还是 .so 文件? - George
4
你不能这样做。如果两种类型都存在,请包括你想要链接的文件的完整名称。 - Cris Luengo

28

我发现这个有用...

http://www.cmake.org/pipermail/cmake/2011-June/045222.html

根据他们的例子:

ADD_LIBRARY(boost_unit_test_framework STATIC IMPORTED)
SET_TARGET_PROPERTIES(boost_unit_test_framework PROPERTIES IMPORTED_LOCATION /usr/lib/libboost_unit_test_framework.a)
TARGET_LINK_LIBRARIES(mytarget A boost_unit_test_framework C)

4
包含目录是什么意思? - kyb
1
只有当库是cmake构建的一部分时,这才有效,但对于外部库,这不起作用。 - daparic
1
该项目包含一个源文件(使用C++编写,尽管我认为语言并不是特别相关)和一个静态库文件,我已经从其他地方复制过来了。 - stu

1

我希望补充其他评论,项目名称是第一个参数。我有一个名为cmakecompile的项目,想要添加libusb到其中,代码如下:

add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")

这个项目只有一个main.c文件,在target_link_libraries中,第一个参数是项目名称,第二个参数是库的路径注意:由于我在Windows下编译,必须安装msys2,因为你所使用的库必须使用相同的编译器进行编译。例如,如果你得到了libusb并尝试在qt-creator项目中使用它,它将无法工作,你可能会得到未引用的函数。因此,我不得不安装msys2,从msys2中安装libusb,安装make并创建一个QT Cmake项目,并使用msys2 make从Qt creator进行编译。
完整的cmakelists.txt如下:
cmake_minimum_required(VERSION 3.5)

project(cmakecompile LANGUAGES C)

add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")

这似乎基本上与Fraser的答案说的是一样的。如果您想在其他答案的基础上添加更多信息,您可以澄清您想要添加什么以及为什么认为它是必要的吗? - David Z
我正在添加其他重要细节,例如如果是针对Qt而不是Visual Studio,则应该遵循哪个路径。还有,为了使其编译,需要的最小CMake内容是什么。我记得曾经花费了2天时间来查找这些信息,这就是为什么我为社区提供它的原因。 - Sherif O.
感谢@DrlSherifOmran展示显式目录形式。 - EndsOfInvention

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接