不同编译器下混合C/C++项目的CMake目标OpenMP链接问题
核心原因
你遇到的参数污染问题由两个常见原因导致:
- 你的
atc库链接OpenMP::OpenMP_CXX时使用了PUBLIC属性,导致内部依赖的编译选项被传递给下游所有链接atc的目标,包括C语言目标 - CMake 3.10版本的
FindOpenMP模块默认全局查找所有语言的OpenMP配置时,会出现不同编译器的参数交叉污染问题
解决方案
第一步:修正atc库的OpenMP依赖属性
atc是内部使用OpenMP、对外暴露纯C接口的库,OpenMP属于内部实现依赖,不需要传递给下游,因此链接时必须使用PRIVATE属性:
# 仅对atc内部生效,不会传递给下游目标 target_link_libraries(atc PRIVATE OpenMP::OpenMP_CXX)
修改后下游的example-c链接atc时,不会继承任何C++版本OpenMP的编译、链接参数,从根源避免参数污染。
第二步:分开查找不同语言的OpenMP配置
不要直接调用find_package(OpenMP)全局查找,按语言分别查找,避免不同编译器的参数互相覆盖:
# 先查找C++版本OpenMP,给atc库使用 find_package(OpenMP REQUIRED COMPONENTS CXX) # 再单独查找C版本OpenMP,给C语言目标使用 find_package(OpenMP REQUIRED COMPONENTS C)
备选兼容方案(针对CMake 3.10的兼容性问题)
如果上述方案仍有问题,可以放弃使用OpenMP::OpenMP_C导入目标,直接使用C语言对应的OpenMP原生参数配置example-c:
add_executable(example-c src/executables/example.c) target_link_libraries(example-c PRIVATE atc) if(OpenMP_C_FOUND) target_compile_options(example-c PRIVATE ${OpenMP_C_FLAGS}) target_link_options(example-c PRIVATE ${OpenMP_C_FLAGS}) target_link_libraries(example-c PRIVATE ${OpenMP_C_LIBRARIES}) endif()
内容的提问来源于stack exchange,提问作者Wout12345
相关产品推荐
相关产品推荐

