【问题标题】:How do I force cmake to include "-pthread" option during compilation?如何在编译期间强制 cmake 包含“-pthread”选项?
【发布时间】:2011-07-20 16:48:04
【问题描述】:

我知道有类似find_package(Threads) 的东西,但它似乎并没有什么不同(至少就其本身而言)。目前我使用的是SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread"),但它对我来说似乎不是一个正确的解决方案。

【问题讨论】:

  • 您将此 2011 年的帖子标记为 2013 年的帖子的副本。请!
  • @HenkvanBoeijen,确切地说,这个问题也有更好的答案
  • @maxschlepzig 这是高度基于意见的。我认为具有公认答案和大量赞成票的高质量问题永远不应该被关闭。
  • @maxschlepzig 我相信这个问题可能有更好的答案,但列出的答案真的更好吗?如果您看,它实际上并没有回答该用户提出的问题,即“将 pthreads 选项添加到我的编译行的更好方法是什么”。被标记为重复的帖子提出并回答的问题是为什么此处列出的已接受答案有时不起作用。提示:导致您的项目设置不正确。
  • 这个问题是如何让线程进入 c++ cmake 模块。另一个问题是我如何让 cmake 识别模块是 c++。它实际上是针对同一主题提出不同的问题,而@ltc 的简短问题和非常简短的好答案使这篇文章对这个特定问题更有用。

标签: gcc build build-automation cmake


【解决方案1】:

CMake 最新版本 (>= 3.1) 中的 Threads 模块生成 Threads::Threads 导入目标。将目标链接到 Threads::Threads 会添加所有必要的编译和链接标志。可以这样做:

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

add_executable(test test.cpp)
target_link_libraries(test Threads::Threads)

根据CMake docs,强烈建议对新代码使用导入的目标

【讨论】:

  • 这两个标志有什么区别?如果你只是 find_package(Threads REQUIRED) 和链接会发生什么?
  • 来自链接的文档页面:CMAKE_THREAD_PREFER_PTHREAD - 更喜欢在具有多个线程库的系统上使用 pthread 库。 THREADS_PREFER_PTHREAD_FLAG - 更喜欢 -pthread 编译器和链接器标志。省略这两个选项可能会导入另一个线程库或在编译或链接期间跳过-pthread 标志。
【解决方案2】:

find_package( Threads ) 调用一个 CMake 模块,该模块首先在文件系统中搜索适用于该平台的线程包,然后设置 CMAKE_THREAD_LIBS_INIT 变量(以及其他一些变量)。它不会告诉 CMake 将任何可执行文件链接到它找到的任何线程库。您告诉 CMake 使用 target_link_libraries() 命令将您的可执行文件链接到“线程”库。因此,例如,假设您的程序称为测试。要将其链接到线程,您需要:

find_package( Threads )
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )

【讨论】:

  • 但重点是在编译时添加这个“-pthread”选项,而不是链接。
  • 哦,我明白你的意思了。我不相信有一种特殊的方法可以做到这一点。在大多数平台上,-pthread 添加了 -D_REENTRANT 和 -lpthread。您可以相当容易地添加 -D_REENTRANT (顺便说一句,这是我曾经检查过的任何现代平台上的一个 noop)。但真正的问题是您想要获得哪种类型的可移植性。 -pthead 选项是其他编译器可能不存在的 gcc 选项。如果您想使用 gcc 支持尽可能多的操作系统平台,那么您目前正在做的就是要走的路。如果您想在几个平台上支持多个编译器,请使用上述内容。
  • 我个人并不关心这个选项。问题是 Boost.Interprocess 关心。没有它,编译器将退出 #error 指令,该指令明确指出需要 -pthread (为不同的系统提供了替代方案 - 现在无法引用它,因为我目前无法访问该系统)。
  • 啊。那么 boost 无法知道您是否确实将 -pthread 选项添加到 gcc 命令行。它可以知道是否设置了 _REENTRANT 宏。我看了看,这确实是检查 -pthread 选项是否设置的作用。无论如何,鉴于您的要求,您已经实施的解决方案看起来很好。我会保持原样。
  • @ltc 很抱歉我没有注意日期。假设这不是迄今为止最准确的答案。
【解决方案3】:

以下内容如何:

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
if(CMAKE_USE_PTHREADS_INIT)
    set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread")
elseif(...)
    ...
endif()
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )

【讨论】:

  • set(CMAKE_THREAD_PREFER_PTHREAD TRUE) 行将我从数小时的尝试获取 beignet 编译(Debian Jessie)中解救出来
  • 除非运行 cmake ${CMAKE_THREAD_LIBS_INIT} 变量(参见 @alex-che 的回答)。
  • 我同意 helmesjo 的这篇文章,该文章解释了为什么我们应该优先考虑目标而不是变量pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right
【解决方案4】:

如果我明确指定默认入口点和要使用的库,则编译不会出现问题。这里的默认入口点是在 cmake 中指定版本。 cmake_minimum_required(...), target_link_libraries(...) 下面是一个例子。

# important
cmake_minimum_required(VERSION 2.8)

project(main)

# set c++ version & etc...
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# important
find_package( Threads )

add_executable(main main.cpp)

# important
target_link_libraries(main ${CMAKE_THREAD_LIBS_INIT})

【讨论】:

    猜你喜欢
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 2020-03-27
    • 2017-03-19
    • 2015-09-07
    相关资源
    最近更新 更多