在 CMake 中混合 C 和 C++,啥 CMakeCCompilerId.c 以及如何丢弃它
Posted
技术标签:
【中文标题】在 CMake 中混合 C 和 C++,啥 CMakeCCompilerId.c 以及如何丢弃它【英文标题】:Mixing C and C++ in CMake, what CMakeCCompilerId.c and how can I discard it在 CMake 中混合 C 和 C++,什么 CMakeCCompilerId.c 以及如何丢弃它 【发布时间】:2014-02-12 18:55:30 【问题描述】:我有一个混合 C 和 C++ 的简单项目(将 C 库包装到 C++ 类中,使其易于在 C++ 项目中使用)。该项目是使用 VisualStudio 构建的,我在 Linux 或 Mac 下,所以我想将其转换为 CMake 项目。
VS项目内容满满
<ClInclude Include="a_file.h" />
所以我认为该文件只是包含在没有任何复杂的构建系统的情况下。这是我的 CMakeLists.txt:
cmake_minimum_required(2.8 版)
# project
set(PROJECTNAME "Test")
project($PROJECTNAME C CXX)
set (CMAKE_CXX_FLAG "-Wall")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "./")
include_directories($CMAKE_CURRENT_BINARY_DIR)
find_package(OpenCV REQUIRED)
file(GLOB_RECURSE $PROJECTNAME_HEADERS $CMAKE_SOURCE_DIR/*.h)
file(GLOB_RECURSE $PROJECTNAME_SOURCES $CMAKE_SOURCE_DIR/*.cpp)
file(GLOB_RECURSE $PROJECTNAME_SOURCES $CMAKE_SOURCE_DIR/*.c)
include_directories (include)
include_directories (src)
SET($PROJECTNAME_SOURCES
main.cpp
$$PROJECTNAME_SOURCES
)
ADD_EXECUTABLE($PROJECTNAME
$$PROJECTNAME_SOURCES
$$PROJECTNAME_HEADERS
)
我知道这不是一个好的规则,但我只需要一种快速而肮脏的方式来使用此代码。
现在,如果我用这个测试 main.cpp:
#include <iostream>
int main(int argc, char *argv[])
std::cout << "main > ." << std::endl;
return 0;
我收到 CMakeCCompilerId.c 的 重复符号 错误
duplicate symbol _main in:
CMakeFiles/Test.dir/main.cpp.o
CMakeFiles/Test.dir/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
据我所知,这个 CMakeCCompilerId.c 文件是 cmake 添加的用于处理 C...
所以,我的问题是:cmake 自动添加的 CMakeCCompilerId.c 是什么?如何编译包含 bot C 和 C++ 的 main 函数的项目?
编辑:
我只是使用解决了问题
project($PROJECTNAME CXX)
而不是
project($PROJECTNAME C CXX)
但无论如何我都很想了解它以及 CMake 如何混合这两种语言
【问题讨论】:
【参考方案1】:file(GLOB_RECURSE $PROJECTNAME_SOURCES $CMAKE_SOURCE_DIR/*.c)
可能是您的问题的原因。
CMake 会对编译器进行一些检查,为此,它会生成一些 .c 文件并将它们保存在构建目录中
如果构建目录是主目录的子目录,GLOB_RECURSE
第二次运行时,它将下降到构建目录,因此会将这些 cmake 文件添加到 $PROJECTNAME_SOURCES 变量中。
如果你的源码都在“src”目录下,而你的头文件在“header”目录下,你可以使用
file(GLOB_RECURSE $PROJECTNAME_HEADERS $CMAKE_SOURCE_DIR/include/*.h)
file(GLOB_RECURSE $PROJECTNAME_SOURCES $CMAKE_SOURCE_DIR/src/*.cpp)
file(GLOB_RECURSE $PROJECTNAME_SOURCES $CMAKE_SOURCE_DIR/src/*.c)
这应该可以解决问题,因为它不会尝试在构建目录中递归。
【讨论】:
听起来很有道理。使用 GLOB_RECURSE 添加源是邪恶的,在源目录中配置构建也是也是邪恶的。 任何关于只使用project($PROJECTNAME CXX)
而不是project($PROJECTNAME C CXX)
的评论
@JanHudec 对,不做这两件事的好理由!以上是关于在 CMake 中混合 C 和 C++,啥 CMakeCCompilerId.c 以及如何丢弃它的主要内容,如果未能解决你的问题,请参考以下文章
使用 CMake 链接到可可库(C++ 与 Objective-C 混合)
C++学习(二七零)AndroidStudio如何配置其它版本的CMake