1

I've been trying to migrate a project from VS to CMake, but I'm not sure my project structure is quite fit to a simple migration:

project/
|- CMakeLists.txt
|- build/
    |- (cmake stuff)
|- src/
    |- main.cpp
    |- tests.cpp // also contains a main()
    |- class1.hpp
    |- class1.cpp
    |- class2.hpp
    |- class2.cpp
    |- ...
|- included/
    | - (external libs)

My CMakeLists.txt attempt so far has been:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)

add_executable(webnectar src/main.cpp
                         src/test.cpp)

enable_testing()
add_test(tests project)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/included)

But I get linking errors with my own classes., I don't understand why.

In several other SO questions I've seen people using file GLOBs to include all sources from a subfolder, which I guess would be a solution. Still, I wish I understood why include_directories is not enough and why (if it would work) file GLOB is OK.

Also, using file GLOB would mess with my build because both test.cpp and main.cpp have a main function.

Although it would look like a different matter (for a different question), please consider this question as more general in the sense of how could I fix all these issues with either a CMake syntax or with a more suitable file structure.

villasv
  • 6,304
  • 2
  • 44
  • 78
  • Hmm, shouldn't those `class.cpp` be included into the source? Regarding the glob: there're pros and cons, but the cons are much more serios. – user3159253 Feb 19 '16 at 04:26
  • @user3159253, I thought they would be, since CMake finds the headers. But I get linking errors with those classes. `undefined reference to "class1 ctor"` and so on. – villasv Feb 19 '16 at 04:30
  • Possible duplicate of [Is it better to specify source files with GLOB or each file individually in CMake?](https://stackoverflow.com/questions/1027247/is-it-better-to-specify-source-files-with-glob-or-each-file-individually-in-cmak) – villasv Nov 29 '18 at 22:29

1 Answers1

3
  1. Regarding include_directories This directive corresponds to -I compiler flag and allows compiler to find header files, i.e. those which are included in #include ....
  2. You should mention all your source files in the arguments of add_executable. That's unavoidable.

You could form the complete list of sources with FILE(GLOB..):

FILE(GLOB webnectar_SOURCES RELATIVE src/ *.cpp)

and then use it in add_executable(webnectar ${webnectar_SOURCES}).

However, this would not be the best and safest option, because it contains a significant flaw. The list of files is formed during the "configuring" stage of the build process (e.g. cmake -D<....> -D<.....> .) and then it's never rebuilt until CMake-related files (CMakeLists.txt, CMakeCache.txt and so on) somehow change. So if you first run cmake... and then add a new file, it won't be noticed, and Makefiles won't be regenerated.

Additionally, if some extra files (e.g. left after an interrupted merge) fit the mask you will get some quite unexpected results.

So it's safer to form and maintain an explicit list of sources, that is,

set(webnectar_SOURCES
  src/main.cpp
  src/class1.cpp
  src/class2.cpp
  ...
)

and then use it in add_executable(webnectar ${webnectar_SOURCES}). The name of variable can be any but some IDEs like KDevelop prefer a standard naming <artifact>_SOURCES, so they can mantain the list automatically for you (or at least try to maintain :) )

user3159253
  • 16,836
  • 3
  • 30
  • 56
  • I guess this is a solution, but it will be quite annoying to add every source file manually. Is that the way most people actually work, or they won't separate sources from headers in the first place? – villasv Feb 19 '16 at 04:53
  • 1
    Actually, it seems that the question is a duplicate of the ancient one: http://stackoverflow.com/questions/1027247/best-way-to-specify-sourcefiles-in-cmake The pros and cons haven't changed since. – user3159253 Feb 19 '16 at 04:58
  • 1
    Oh, thanks. I didn't find that one. I wished that rearranging the folder structure could help, or any other solution except file glob and listing files manually. – villasv Feb 19 '16 at 05:08
  • 1
    No, rearraning folders couldn't help. Any build system (not necessarily CMake, but also GNU autotools etc) has to generate build rules for all files. They all generate per-file rules (not wildcard rules like `.c.o:` in Makefiles) so they have to know the exact list of source files. So you have to supply the file list. And if you supply a file list made with globbing, then you suffer from all those problems described above – user3159253 Feb 19 '16 at 06:25