在 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 以及如何丢弃它的主要内容,如果未能解决你的问题,请参考以下文章

调试经验C++和C的混合编程以及库调用

使用 CMake 链接到可可库(C++ 与 Objective-C 混合)

C++学习(二七零)AndroidStudio如何配置其它版本的CMake

使用 CMake 和 c++ 编译时,如果两个头文件名称相同,会发生啥情况?

arduino 开发用啥编程语言

C、C++ 和 C# 中的 void 是啥意思?