为啥 CMake 似乎没有使用 add_compile_options 命令应用 -pthread?

Posted

技术标签:

【中文标题】为啥 CMake 似乎没有使用 add_compile_options 命令应用 -pthread?【英文标题】:Why CMake does not seem to apply -pthread using add_compile_options command?为什么 CMake 似乎没有使用 add_compile_options 命令应用 -pthread? 【发布时间】:2014-10-13 15:08:36 【问题描述】:

我正在尝试使用 CMake 2.8.12.2 使用 g++ 4.8.2 编译一个简单的 C++ 程序,该程序利用 C++11 功能和多线程。为此,必须使用编译器标志 -std=c++11 和 -pthread。据我了解,在 CMake 中,可以通过多种方式设置这些标志,一种是使用 set 命令:

set(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++11 -pthread")

另一种(据说是首选的)方法是使用 add_compile_options 命令:

add_compile_options(-std=c++11)
add_compile_options(-pthread)

(或一行:add_compile_options(-std=c++11 -pthread)

所以,问题在于,就我而言,只有第一种方法有效 - 通过使用 set 命令。问题在于使用 add_compile_options 会导致编译的输出可执行文件崩溃并显示以下消息(就像根本没有指定 -pthread 一样):

terminate called after throwing an instance of 'std::system_error'
  what():  Enable multithreading to use std::thread: Operation not permitted
Aborted (core dumped)

我测试的代码:

#include <future>

int main()

    auto a = std::async(std::launch::async, []());
    a.wait();
    return 0;

从这个程序编译的事实,我可以推断出应用了-std=c++11。问题是为什么没有应用-pthread?

【问题讨论】:

如果您分享您的编译行输出可能会有所帮助。你能在上面看到你正在编译的对象的这些标志吗? 好吧,我不知道我能看到它,但是当我执行make -n 时我能想到。使用 add_compile_options 编译命令为:/usr/bin/c++ -g -pthread -std=c++11 -o CMakeFiles/test.dir/main.o -c /home/batman/stuff/testprojects/test/main.cpp 使用 set,编译命令为:/usr/bin/c++ -pthread -std=c++11 -g -o CMakeFiles/test.dir/main.o -c /home/batman/stuff/testprojects/test/main.cpp 【参考方案1】:

假设您肯定使用 g++ 进行编译(值得通过检查 /usr/bin/c++ 实际上是什么来澄清 - 我假设它是 g++ 的链接)g++ 的手册页给出:

gcc [-c|-S|-E] [-std=standard]
    [-g] [-pg] [-Olevel]
    [-Wwarn...] [-pedantic]
    [-Idir...] [-Ldir...]
    [-Dmacro[=defn]...] [-Umacro]
    [-foption...] [-mmachine-option...]
    [-o outfile] [@file] infile...

这意味着您需要:

g++ -std=c++11 -g -pthread ...

按这个顺序。

也许值得尝试通过此调整手动运行命令行,看看生成的内容是否符合您的预期。

在我看来(没有任何研究,我会补充)add_compile_options 可能仅对添加严格的编译器选项有用,因此您可能必须使用 set 来设置 @ 987654326@ 和 add_compile_options 用于所有其他编译器选项 - 即在 -g 之后指定

【讨论】:

我想我现在明白发生了什么。如果我使用 add_compile_options 设置 -std=c++11 但 -pthread 像这样:set(CMAKE_EXE_LINKER_FLAGS "$CMAKE_EXE_LINKER_FLAGS -pthread") 则应用程序运行时不会出现错误。我的假设是 -pthread 是一个链接器标志,但 CMake 不会将 add_compile_options 传递给链接器,因此必须单独添加它。以及为什么将两个标志都设置为 CMAKE_CXX_FLAGS 的原因是,两个标志(-std=c++11 和 -pthread)都被添加到两个阶段 - 编译和链接。 好的,添加 -pthreads 的更好方法是使用 target_link_libraries 命令,如下所示:target_link_libraries(projectname -pthread)【参考方案2】:

尝试以下方法:

set (
  CMAKE_CXX_FLAGS
  "$CMAKE_CXX_FLAGS "
  "-Wall -Werror -pthread -std=c++11 -Wl,--no-as-needed"
)

来源:here

【讨论】:

以上是关于为啥 CMake 似乎没有使用 add_compile_options 命令应用 -pthread?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 CMake 在 Qt Creator 中过早结束?

为啥 CMake 在没有 CMAKE_CXX_FLAGS 的情况下生成 Makefile?

为啥cmake没有在makefile中添加库链接命令?

为啥 cmake 文件 GLOB 是邪恶的?

为啥 CMake 没有与我的自定义库(add_library/set_property)链接?

CMake+MinGW编译OpenCV2.1以后为啥Bin和Lib文件夹是空的