在 CMake 中混合 C 和 C++,什么是 CMakeCCompilerId.c 以及如何丢弃它

nki*_*int 4 c c++ cmake

我有一个混合 C 和 C++ 的简单项目(将 C 库包装到 C++ 类中并使其易于在 C++ 项目中使用)。该项目是使用 VisualStudio 构建的,我在 Linux 或 Mac 下,所以我想将其转换为 CMake 项目。

VS项目内容满满的

<ClInclude Include="a_file.h" />
Run Code Online (Sandbox Code Playgroud)

所以我认为该文件只是包含在内,没有任何复杂的构建系统。这是我的 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}

)
Run Code Online (Sandbox Code Playgroud)

我知道这不是一个好遵循的规则,但我只需要一种快速而肮脏的方法来使用此代码。

现在,如果我用这个测试 main.cpp 进行:

#include <iostream>
int main(int argc, char *argv[]) {
    std::cout << "main > ." << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我收到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)
Run Code Online (Sandbox Code Playgroud)

据我所知,这个 CMakeCCompilerId.c 文件是 cmake 添加的用于处理 C 的文件...

所以,我的问题是:cmake-auto-added CMakeCCompilerId.c 是什么?如何编译一个包含 bot C 和 C++ 的 main 函数的项目?

编辑:

我只是使用解决了问题

project(${PROJECTNAME} CXX)
Run Code Online (Sandbox Code Playgroud)

代替

project(${PROJECTNAME} C CXX)
Run Code Online (Sandbox Code Playgroud)

但无论如何我很好奇理解它以及 CMake 如何混合这两种语言

Dan*_*lli 6

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)
Run Code Online (Sandbox Code Playgroud)

这应该可以解决问题,因为它不会尝试在构建目录中递归。

  • 听起来似乎有道理。使用 GLOB_RECURSE 添加源是**邪恶的**,在源目录中配置构建也是**邪恶的**。 (3认同)