11

I am trying to compile a project that has only one main function, but CMake find more.

My CMakeLists.txt is like:

cmake_minimum_required(VERSION 2.8)
project(my_proj)

include_directories(".")

add_subdirectory(main)
add_subdirectory(resources)

find_package(OpenCV REQUIRED)
find_package(Boost REQUIRED COMPONENTS system regex program_options)
include_directories(${Boost_INCLUDE_DIRS})

file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE HDR_FILES ${PROJECT_SOURCE_DIR}/*.hpp)

add_executable(my_proj ${SRC_FILES} ${HDR_FILES})

target_link_libraries(my_proj ${OpenCV_LIBS})

target_link_libraries(my_proj ${OpenCV_LIBS} 
                  ${Boost_PROGRAM_OPTIONS_LIBRARY} 
                  ${Boost_REGEX_LIBRARY}
                  ${Boost_FILESYSTEM_LIBRARY}
                  ${Boost_SYSTEM_LIBRARY})

I have more folders with .hpp and .cpp files that is why I have added file(GLOB_RECURSE... statements and also include_directories(".").

I get an error after it compiles all files that says:

CMakeFiles/my_proj.dir/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp.o: In    function `main':
/media/N/my_proj/build/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp:209: multiple definition of `main'
CMakeFiles/my_proj.dir/main.cpp.o:/media/N/my_proj/main.cpp:10: first defined here
CMakeFiles/my_proj.dir/main/solution2/sources/CRunSolution2.cpp.o: In function `boost::filesystem3::path::codecvt()':
/usr/include/boost/filesystem/v3/path.hpp:377: undefined reference to `boost::filesystem3::path::wchar_t_codecvt_facet()'

Has anyone met something like that? If yes, how to fix it?

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
thedarkside ofthemoon
  • 2,251
  • 6
  • 31
  • 48

1 Answers1

28

In your executable you simply have 2 main functions (print out SRC_FILES by MESSAGE(${SRC_FILES})). One is in main.cpp and one in CMakeCXXCompilerId.cpp (which is a file that CMake generates to test if your CXX compiler works correctly). The GLOB_RECURSE probably finds and adds both of these files to SRC_FILES

Using FILE(GLOB ...) is tricky:

We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.

You should list your source and header files in your CMakeLists.txt directly

Peter Petrik
  • 9,701
  • 5
  • 41
  • 65
  • 3
    +1 for 'list your source and header files in your CMakeLists.txt directly' – Ankit Singh Mar 04 '14 at 16:24
  • So you suggest me to add the files by had? something like `add_executable(my_proj main.cpp dir1/sources/cls1.cpp ... dir1/headers/cls1.hpp ... )` instead of `file(GLOB_RESCUE ... )`? – thedarkside ofthemoon Mar 04 '14 at 16:25
  • Yes, you can create a variable by SET(src_files file1.cpp ...) and use that – Peter Petrik Mar 04 '14 at 16:28
  • 2
    If you have your files in a source-control you can create a script to grab all cpp/h files that are in source control and add them to your application. I personally do this for my projects generated by CMake. – Vite Falcon Mar 04 '14 at 16:34
  • 3
    You should use a separate *binary* directory where you build your project. Then you should be able to safely use globbing on your *source* directory. – Johannes S. Mar 04 '14 at 21:48
  • 1
    @thedarksideofthemoon: If you're thinking of a way to learn it, I'm afraid there are no articles on it. I can share relevant sections of the code with you though. Here's a paste of how I work on my Git repository to update CMake files (DISCLAIMER - Parts of scripts could be missing. But hopefully you'll get the idea): https://gist.github.com/ViteFalcon/a77c1c135304f5afce53 – Vite Falcon Mar 04 '14 at 22:00
  • @JohannesS. unfortunately, even using `file(GLOB_RECURSE srcs RELATIVE path glob)` from a directory containg both a `build/` and a `path/` subdirectory will go upward and find `build/CMakeFiles` and hidden .cpp files there. – TemplateRex May 23 '15 at 19:07
  • @TemplateRex `RELATIVE` does not modify the search location but only ensures that the output is relative to the given path (instead of the current directory or maybe even absolute, not sure ATM). So I still recommend to explicitly list the files in you `CMakeLists.txt` instead of using `FILE (GLOB....)` – Johannes S. Jun 29 '15 at 08:12
  • 1
    @JohannesS. Thanks, but globbing is the way to go in projects that are being refactored frequently, it's insanely tedious to manually edit hundreds of targets – TemplateRex Jun 29 '15 at 08:15