Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing C and C++ in CMake, what CMakeCCompilerId.c and how can I discard it

Tags:

c++

c

cmake

I have simple project that mixes C and C++ (wrapping a C lib into a C++ class and making it easy to use in C++ project). The project was build with VisualStudio and I'm under Linux or Mac so I'd like to convert it in a CMake project.

The VS project content is full of

<ClInclude Include="a_file.h" />

so I think the file are just included without any complex build system. Here is my CMakeLists.txt:

cmake_minimum_required(VERSION 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}

)

I know that is not a good rule to follow, but I just need a quick and dirty way to use this code.

Now, if I make with this test main.cpp:

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

I get a duplicate symbol error for 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)

As far as I get this CMakeCCompilerId.c file is something that cmake add for dealing with C...

So, here my question: what is the cmake-auto-added CMakeCCompilerId.c ? How can I compile a project with a main function that contains bot C and C++?

EDIT:

I resolved the problem just using

project(${PROJECTNAME} CXX)

instead of

project(${PROJECTNAME} C CXX)

But I'm curious anyway to understand it and how CMake mixes the two languages

like image 219
nkint Avatar asked Oct 15 '25 19:10

nkint


1 Answers

The file(GLOB_RECURSE ${PROJECTNAME}_SOURCES ${CMAKE_SOURCE_DIR}/*.c) might be the reason of your issue.

CMake runs some checks on the compiler, and to do so, it generates some .c files and saves them in the build directory

If the build directory is a subdirectory of the main one, the second time that the GLOB_RECURSE runs, it will descend in the build directory, and therefore will add these cmake files in the ${PROJECTNAME}_SOURCES variable.

If your sources are all in the "src" directory, and your headers in the "header" directory, you can use

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)

And this should fix the issue, because it will not try to recurse in the build directory.

like image 129
Daniele E. Domenichelli Avatar answered Oct 17 '25 10:10

Daniele E. Domenichelli