31

this is my current CMakeLists.txt file

cmake_minimum_required(VERSION 3.3)
set(CMAKE_C_FLAGS " -Wall -g ")
project( bmi )
file( GLOB SRCS *.cpp *.h )
add_executable( bmi ${SRCS}) 

This builds from my source directory, but I have to clean up all the extra files after. My question is how do I build this from a build directory if all my source files are in the same source directory?

thanks

Will Meyers
  • 500
  • 1
  • 4
  • 7
  • 1
    If you want to not mess executables with sources, use *out-of-source* build. Can you be more specific? Which files exactly do you want to select in build directory(with example)? – Tsyvarev Jan 18 '16 at 20:54
  • 2
    Also, why are You adding *.h to sources list? – Kamiccolo Jan 18 '16 at 22:40
  • cause the program which calculates BMI uses a main.cpp a bmi.cpp and a bmi.h file all of these are in the source directory. Without the .h file the program won't run. I want to compile these 3 files into 1 executable without all the cmake stuff generating in my source folder. – Will Meyers Jan 19 '16 at 04:20
  • @WillMeyers: That's why you use out of source builds, to not pollute your source dir. And CMake figures out the needed header by itself. You don't need to add them to your executable. And BTW, use `set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -g ")`, with your code you will loose additional flags from the user. – usr1234567 Jan 19 '16 at 06:20
  • [ 33%] Building CXX object CMakeFiles/webcam.dir/main.cpp.o /home/devbox/webcam/main.cpp:5:23: error: camera.h: No such file or directory --devbox@linux-clof:~/webcam> ls --camera.cpp CMakeCache.txt cmake_install.cmake main.cpp camera.h CMakeFiles CMakeLists.txt Makefile it cant find the file that is in the same directory! – Will Meyers Jan 19 '16 at 19:11

2 Answers2

30

If you really need to use file(GLOB …), this CMakeLists.txt should work :

cmake_minimum_required(VERSION 3.3)
project(bmi)
add_definitions("-Wall" "-g")
include_directories(${PROJECT_SOURCE_DIR})
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
add_executable(bmi ${SRC_FILES})

In this case you have to launch cmake from your build directory every time you add or delete a source file :

cmake <your_source_dir> -G <your_build_generator>

As Phil reminds, CMake documentation doesn't recommend this use of GLOB. But there are some exceptions. You'll get more information on this post.

If you don't meet those exceptions, you'd rather list your source files than use GLOB :

set(SRC_FILES ${PROJECT_SOURCE_DIR}/main.cpp
              ${PROJECT_SOURCE_DIR}/bmi.cpp
              … )

NB : if you have #include of your .h files in .cpp files, I don't see any reason to put them in add_executable, you just need to specify include directory with include_directories.

Community
  • 1
  • 1
cromod
  • 1,721
  • 13
  • 26
  • 3
    The reason to add header files to the executable is that when generating VS projects (and maybe projects for other IDEs?) the headers will appear in the source file lists together with the corresponding cpp files. Otherwise they'll be buried in the automatically generated, infinite "external dependencies" folder. In fact, when all project headers are added that way one can switch off visibility of the external dependencies in Options/Text Editor/C-C++/Advanced/Browsing-Navigation. – Peter - Reinstate Monica Nov 16 '18 at 10:59
  • You can add now use file(GLOB … CONFIGURE_DEPENDS …) to pick up changes to the glob and rerun the cmake build if necessary. – Lance E.T. Compte May 25 '19 at 20:59
  • GLOB came earlier then 3.3 – Sergei Krivonos May 01 '20 at 20:57
9

Cmake used to only update the list of source files if CMakeLists.txt was changed since the last cmake run or if cmake was used to configure the project again.

In cmake 3.11.0 recursive search and automatic re-configuration on adding or deleting source files was added. Since then you can use the following snippet:

if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.11.0")
    file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp *.h)
else()
    file(GLOB SOURCE_FILES *.cpp *.h */*.h */*.cpp)
endif()

The file() command after the else() provides at least a bit of backwards compatibility: It still searches for source files in the current folder and its direct subfolders. But it doesn't automatically recognize if there are new files or old files have been deleted.

Note that VERSION_GREATER_EQUAL is only available in cmake >= 3.7

albert
  • 8,285
  • 3
  • 19
  • 32