这是我的简单
CMakeLists.txt
:
project(MyProject)
# Create the library from server.cpp
add_library(server OBJECT tcp_server.cpp tcp_server_priv.cpp)
# Add the current directory to the include path for this target
target_include_directories(server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
# Create the executable from main.cpp and link it to the library
add_executable(my_server main.cpp $<TARGET_OBJECTS:server>)
我最近了解了
add_library(x OBJECT y z ...)
结构;我的理解:这不会创建静态或共享库(.a 或 .so),而是形成对象文件的一些临时/逻辑分组,可以在其他地方作为同一组引用。 IE。在其他地方,我可以参考$<TARGET_OBJECTS:server>
来指代tcp_server.o和tcp_server_priv.o,所以add_executable(my_server main.cpp $<TARGET_OBJECTS:server>)
行的意思是“编译main.cpp,并将其与tcp_server.o和链接” tcp_server_priv.o 制作可执行文件我的服务器”。
即
add_executable
行同时进行编译和链接。
我希望我的可执行文件也与 libpthread 链接,所以我尝试对
add_executable
行进行此更改:
add_executable(my_server main.cpp $<TARGET_OBJECTS:server> pthread)
...但是使用 cmake:
生成了此错误-- Configuring done
CMake Error at src/CMakeLists.txt:9 (add_executable):
Cannot find source file:
pthread
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
.hpp .hxx .in .txx
CMake Error at src/CMakeLists.txt:9 (add_executable):
No SOURCES given to target: med_server
CMake Generate step failed. Build files cannot be regenerated correctly.
make: *** [Makefile:160: cmake_check_build_system] Error 1
上面的内容不是与下面类似吗,我在单个 g++
调用中编译
main.cpp、链接对象文件依赖项和库:
// tcp_server.cpp
#include <iostream>
extern void private_func();
void public_func() {
std::cout << __FUNCTION__ << std::endl;
private_func();
}
// tcp_server_priv.cpp
#include <iostream>
void private_func() {
std::cout << __FUNCTION__ << std::endl;
}
// main.cpp
#include <semaphore.h>
extern void public_func();
int main(int argc, char* argv[]) {
sem_t my_sem;
public_func();
sem_init(&my_sem, 0, 0);
sem_destroy(&my_sem);
return 0;
}
$ g++ -c ./tcp_server.cpp \
> && g++ -c ./tcp_server_priv.cpp \
> && g++ main.cpp tcp_server.o tcp_server_priv.o -lpthread \
> && ./a.out
public_func
private_func
$
?
当我可以链接目标文件时,为什么我不能用
add_executable
语句链接库?
所尝试的
add_executable(my_server main.cpp $<TARGET_OBJECTS:server> pthread)
实际上与g++ main.cpp tcp_server.o tcp_server_priv.o -lpthread
不一样吗?
编辑:链接到编译模型以更好地理解,注意:您感兴趣仅对第一张图片。
对于这个例子,我将使用一个静态库,即在 Linux 上,它会带有后缀
.a
,在 Windows 上 .lib
。让我们问问自己,当您构建并链接这个库时会发生什么:
.cpp
(或多个)编译为.o
目标文件.a
/ .lib
现在如果我们想“链接”一个static库:
.a
解压回目标文件中.o
目标文件所以你可以这样认为区别(以静态库为例):
目标文件:我们不必解压存档,只需将它们与新创建的目标文件链接即可
静态库:我们需要告诉编译器,嘿,我们需要先解压它,以便我们可以链接它。
CMake 的唯一作用是为编译器/链接器“创建某种配置”以完成工作。
关于
OBJECT
和 STATIC
库之间区别的一个有趣的事情是(这进一步证明了我提到的内容)是,如果您使用 OBJECT
库,您将无法利用优化。
假设您的静态库由三个对象
a.o
b.o
和 c.o
构成。如果将其打包到 lib.a
中,然后将可执行文件链接到它。优化可能会排除 c.o
(例如),这将使生成的可执行文件更小。
但是如果您与对象库链接
a.o
b.o
和c.o
那么所有的对象将被打包为可执行文件。
在你的
add_executable(my_server main.cpp $<TARGET_OBJECTS:server> pthread)
,问题在于
add_executable
中使用“pthread”,而不是 $<TARGET_OBJECTS:server>
。您应该这样做来链接到 pthread:
target_link_libraries(my_server PRIVATE pthread)
或
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_app PRIVATE Threads::Threads)
另请参阅:cmake 和 libpthread 以及 CMake 对象库文档。
正如对象库文档中所述,这就是 CMake 的工作原理。您可以像现在一样链接到对象库,但您也可以通过
target_link_libraries
来完成。您可以使用 target_link_libraries
链接到对象库(自 v3.12 起)和共享/静态库。对于target_link_libraries
来说,没有“区别”。