CMake中pthread、-pthread、-lpthread的差异及最优选择
CMake链接pthread的三种写法差异及最优选择
先聊聊你遇到的问题:你的std::promise代码运行抛异常,根源是只链接了pthread库,但没让编译器开启线程安全的编译选项。咱们先把三种写法的差异说透,再讲哪种更适合你的场景。
三种写法的具体差异
1. target_link_libraries(promise pthread)
这是CMake的「目标式」写法,CMake会根据当前平台自动转换对应链接命令:
- 在Linux下,它会被转换成
-lpthread,告诉链接器链接libpthread.so; - 但它只负责链接环节,不会影响编译阶段——GCC编译C++线程相关代码时,需要
-pthread选项来开启线程安全的代码生成(比如定义_REENTRANT宏,调整内部函数的线程安全实现),这种写法不会自动添加这个编译选项,这也是你代码崩溃的核心原因。
2. target_link_libraries(promise -pthread)
这是直接给链接器传递-pthread标志,而GCC里的-pthread是个「全能选手」:
- 编译阶段:自动添加线程安全相关的预定义宏,生成符合线程安全要求的代码;
- 链接阶段:自动链接
libpthread.so库; - 说白了,它同时搞定了编译和链接两个环节的线程支持需求,能直接解决你遇到的
std::promise运行异常问题。
3. target_link_libraries(promise -lpthread)
这是传统的链接器原始选项,和第一种写法效果类似:
- 只告诉链接器去链接
libpthread.so库,完全不涉及编译阶段的设置; - 相比第一种写法,它没有CMake的平台适配性——比如换个非Linux平台(像BSD),可能需要改成
-pthread或者其他标志,而CMake的pthread写法会自动适配,但同样没解决编译阶段的核心问题。
哪种更优?
如果只在你列出的三种里选,-pthread是最优解,因为它一次性解决了编译和链接的线程支持需求,刚好匹配C++11线程组件(比如std::promise、std::thread)的要求。
不过更规范的CMake写法是用官方提供的Threads模块,步骤如下:
find_package(Threads REQUIRED) add_executable(promise promise.cpp) target_link_libraries(promise Threads::Threads)
这种写法的好处是完全由CMake处理平台差异,不管是Linux、macOS还是Windows,都会自动生成正确的编译和链接选项,是跨平台项目的首选。
回到你的问题,把原来的target_link_libraries(promise pthread)改成target_link_libraries(promise -pthread),或者用Threads模块,就能解决运行时抛异常的问题了。
内容的提问来源于stack exchange,提问作者pingsoli
相关产品推荐
相关产品推荐

