我想使用最新版本的Boost库,并拥有CMakeLists.txt文件的以下内容:
cmake_minimum_required (VERSION 3.0)
project (foo)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY -lpthread")
# set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")
add_executable (first first.cpp)
由此我不断收到以下链接器错误:
未定义对`pthread_detach
的引用
但是,如果我在不使用cmake的情况下编译代码,请使用以下命令:
g++ foo.cpp -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY -lpthread
工作正常。
问题是如何使用cmake让它工作。当我通过设置CMAKE_CXX_FLAGS指定编译器标志时,为什么它不起作用?我想我可能不得不指定CMAKE_EXE_LINKER_FLAGS,但这样做根本没有帮助。
答案 0 :(得分:7)
CMake对您通过显式标志规范尝试解决的所有问题提供本机支持,因此您应该使用它:
cmake_minimum_required (VERSION 3.0)
project (foo)
add_executable (first first.cpp)
target_compile_options (first PRIVATE -std=c++11)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)
如果您可以将最低CMake版本要求增加到3.1,则可以用本机CMake替换硬编码的std
标志:
cmake_minimum_required (VERSION 3.1)
project (foo)
add_executable (first first.cpp)
set_target_properties (first PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED TRUE
CXX_EXTENSIONS FALSE
)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)
值得一提的是,并非所有编译器都表达了#34;使用没有扩展的C ++ 11"以同样的方式,CMake会将需求转换为正确的标志。
如果您需要为许多可执行文件设置相同的C ++ 11,则可以设置预填充属性的CMake变量。请注意,必须在创建可执行文件之前设置变量:
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED TRUE)
set (CMAKE_CXX_EXTENSIONS FALSE)
add_executable (first first.cpp)
target_compile_definitions (first PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (first pthread)
add_executable (second second.cpp)
target_compile_definitions (second PRIVATE BOOST_ERROR_CODE_HEADER_ONLY)
target_link_libraries (second pthread)
# ... and so on
答案 1 :(得分:2)
通常,应该使用target_link_libraries
指定库,而不是直接覆盖链接器标记。
在这种情况下,您可以采用不同的方式:
add_executable (first first.cpp)
find_package(Threads REQUIRED)
target_link_libraries(first PRIVATE Threads::Threads)
上面的 Threads::Threads
代表系统的线程库。这具有跨平台的优势 - 当您想要编译项目时,例如。 G。 Windows,链接器不会抱怨未知的pthread
库。
出于同样的原因,以@Angew在他们的答案中的方式设置C ++版本是首选 - 它只是工作,而不必手动调整每个编译器的标志。