I want to build my C++ project with CMake and I want to include automatically every new file on "cmake ." my project structure is:
Application/ Graphics/ CMakeLists.txt CMakeLists.txt.user main.cpp
./Application:
CMakeLists.txt Logger/ Recovery/ application.cpp application.hpp firstclass.cpp firstclass.hpp singleton.hpp
./Application/Logger:
CMakeLists.txt logger.cpp logger.hpp
./Application/Recovery:
CMakeLists.txt recovery.cpp recovery.hpp
./Graphics:
CMakeLists.txt drawableobject.cpp drawableobject.hpp graphics.cpp graphics.hpp
Each folder has own CMakeLists.txt
I did so far this in master CMake:
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Asteri VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
message("Source dir: ${SOURCE_DIR}")
#file(GLOB_RECURSE SRC_FILES ${SOURCE_DIR}/*.cpp)
#file(GLOB_RECURSE HEADER_FILES ${HEADER_DIR}/*.hpp)
set(PROJECT_NAME "Asteri")
macro(SUBDIRLIST result curdir)
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
foreach(child ${children})
if(IS_DIRECTORY ${curdir}/${child})
list(APPEND dirlist ${child})
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR})
foreach(subdir ${SUBDIRS})
message("Subdirectory: ${subdir}")
add_subdirectory(${subdir})
endforeach()
add_executable(${Asteri} main.cpp)
The question is how to connect all pieces together?
What I need in other CMakeLists.txt?
How to communicate children -> parent or I misunderstood the concept of CMake?
No need for other CMakeLists.
I guess you want something like this in top CMakeLists:
cmake_minimum_required(VERSION 3.12)
project(Asteri VERSION 1.0)
file(GLOB_RECURSE ASTERI_SRC_FILES CONFIGURE_DEPENDS
"${PROJECT_SOURCE_DIR}/Application/*.cpp"
"${PROJECT_SOURCE_DIR}/Graphics/*.cpp"
)
add_executable(Asteri main.cpp ${ASTERI_SRC_FILES})
It's worth noting that GLOB/GLOB_RECURSE -even with CONFIGURE_DEPENDS- is bad practice: it's slow, specially on Windows from my experience, and may not work as expected depending on generator used.
I found out the answer to my problems.
set(SOURCES "${PROJECT_DIR}/main.cpp" CACHE INTERNAL STRINGS)
add_subdirectory(application)
FOREACH(it ${SOURCES})
message("source file: ${it}")
ENDFOREACH()
add_executable(Asteri ${SOURCES})
In this way I store main.cpp path into variable SOURCES
You can see your variables after 'make' in CMakeCache.txt.
After this is done, my variable SOURCES looks like:
/STRINGS
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;
After that in application subdirectory I have CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
# Get source files
file(GLOB CPP_LIST "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(SOURCES ${SOURCES} ${CPP_LIST} CACHE INTERNAL STRINGS)
And now SOURCES looks like:
SOURCES:INTERNAL=/home/default/cpp_testing_project/cmake_project/source/main.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.cpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.cpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.cpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.cpp;/home/default/cpp_testing_project/cmake_project/source/application/application.hpp;/home/default/cpp_testing_project/cmake_project/source/application/drawableobject.hpp;/home/default/cpp_testing_project/cmake_project/source/application/firstclass.hpp;/home/default/cpp_testing_project/cmake_project/source/application/graphics.hpp;
Related
Here is my directory tree
I implemented accident component which have to be a standalone library. Here is CMakeLists.txt for it
set (ACCIDENT accident)
file (GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file (GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
add_library (${ACCIDENT} STATIC ${HEADER_FILES} ${SOURCE_FILES})
target_include_directories (${ACCIDENT} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
add_subdirectory (test)
and that works fine. Now I am trying to use that library in note part which should be linked with accident. Especially the accident.hpp file should be visible in my IDE without doing things like this
#include "../../accident/include/accident.hpp"
and the code from accident.cpp should also be accessible. My attempts was similar to this one
set (MUSIC_NOTE music_note)
file (GLOB SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file (GLOB HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
add_library (${MUSIC_NOTE} STATIC ${HEADER_FILES} ${SOURCE_FILES})
target_include_directories (${MUSIC_NOTE}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../accident/include"
)
target_link_libraries (${MUSIC_NOTE} accident)
add_subdirectory (test)
unfortunately, it does not work - accident.hpp header is not found. Do you know where I am doing a mistake?
EDIT
In response to #Martin's question, here is my top level CMakeLists.txt
cmake_minimum_required (VERSION 3.5)
set (CMAKE_BUILD_TYPE Debug)
set (PROJECT_NAME scales)
project (${PROJECT_NAME} LANGUAGES CXX)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set (CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}" "${CMAKE_MODULE_PATH}")
set (CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}" "${CMAKE_PREFIX_PATH}")
add_subdirectory (src)
add_subdirectory (external)
option (BUILD_TESTS "Build tests" ON)
enable_testing ()
if (BUILD_TESTS)
add_subdirectory (test)
endif ()
# Add google test
include (FetchContent)
FetchContent_Declare (
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
The note directory is in src, and src includes CMakeLists.txt with only one line
add_subdirectory (note)
In this note directory we have the stuff I pasted above Top level CMakeLists.txt in note directory contains
add_subdirectory (accident)
add_subdirectory (note)
EDIT 2
Problem resolved - see Ave Milia comment below. Thanks!
As we figured out in the comment section, the test executable was forgotten to be linked to the relevant static library.
I have a simple exercise on cmake with following file tree:
proj01/
include/
functions.h
src/
main.cpp
functions.cpp
CMakeLists.txt
CMakeLists.txt
README
My project CMakeLists.txt is like this:
cmake_minimum_required(VERSION 3.21)
project (test01)
add_subdirectory(src)
set(SOURCES
main.cpp
functions.cpp
)
add_executable(myProgram ${SOURCES})
and when I tried to build, I got error:
# Error!
CMake Error at CMakeLists.txt:18 (add_executable):
Cannot find source file:
main.cpp
CMake Error at CMakeLists.txt:18 (add_executable):
No SOURCES given to target: myProgram
If I change the project CMakeLists.txt by giving the absolute path(relative to the project), it worked!
#add_subdirectory(src)
set(SOURCES
src/main.cpp
src/functions.cpp
)
add_executable(myProgram ${SOURCES})
When there is multiple source files in multiple subdirectories, it would be better to explicitly list all source files including their paths as what is done with my working version of the CMakeLists.txt.
Spent hours to search for command add_subdirectories(), this, this, and this, but no luck.
The closest one would be this question, but there is no solution for that question so far.
What did I miss with my add_subdirectory(src) in this simple specific scenario? Any help is appreciated.
add_subdirectory(src) results in cmake parsing src/CMakeLists.txt creating a new directory src in the build tree for building the part of the project in this cmake file.
It doesn't result in you being able to use shorter paths in the CMakeLists.txt file containing the add_subdirectory command.
If you move the target to src/CMakeLists.txt you could use the shorter paths:
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project (test01)
add_subdirectory(src) # add src/CMakeLists.txt to this project
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
set(SOURCES
main.cpp
functions.cpp
)
add_executable(myProgram ${SOURCES})
Personally I'd avoid adding an additional CMakeLists.txt file just to shorten the paths. It's easy to remove the duplication of the src dir, if that's what you're worried about.
set(SOURCES
main.cpp
functions.cpp
)
list(TRANSFORM SOURCES PREPEND "src/")
or
function(subdir_files VAR DIR FILE1)
set(FILES)
foreach(SRC IN ITEMS ${FILE1} ${ARGN})
list(APPEND FILES ${DIR}/${SRC})
endforeach()
set(${VAR} ${FILES} PARENT_SCOPE)
endfunction()
subdir_files(SOURCES src
main.cpp
functions.cpp
)
How to make a project in cmake that collects all c++ files into one header?
I have this project structure.
/
project/
folder1/
file.cpp
file.hpp
folder2/
...etc
CMakeLists.txt
tests/
test.cpp
CMakeLists.txt
CMakeList.txt
root cmakelists.txt
cmake_minimum_required (VERSION 3.8)
project ("CMakeProject"
LANGUAGES C CXX)
set(CMAKE_EXECUTABLE_SUFFIX ".exe")
include(GNUInstallDirs)
add_subdirectory ("project")
option(ENABLE_TESTING OFF)
if (ENABLE_TESTING)
enable_testing()
add_subdirectory("tests")
endif()
CMakeLists.txt in project
cmake_minimum_required (VERSION 3.8)
file(GLOB projectSRC
"*/*.cpp"
"*/*.hpp"
"*.cpp"
"*.hpp"
)
add_library(project INTERFACE)
message(STATUS "CMake inatall directory: " ${CMAKE_INSTALL_INCLUDEDIR})
target_include_directories(project
INTERFACE
$<BUILD_INTERFACE:${PROJECT_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
and test cmakelist.txt
cmake_minimum_required (VERSION 3.8)
# install Catch2 testing library
# (https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#installing-catch2-from-git-repository or use packet manager)
find_package(Catch2 REQUIRED)
file(GLOB testSRC
"*.cpp"
)
add_executable(tests ${testSRC})
target_link_libraries(tests
Catch2::Catch2
project)
include(CTest)
include(Catch)
catch_discover_tests(tests)
How to generate one header and use it (in tests or other projects) or make this library able to have templates? The first is better.
How to make a header-only library with cmake?
Like this:
add_library(project INTERFACE)
target_include_directories(project INTERFACE .)
Then in the target that uses the library:
target_link_libraries(dependee
PUBLIC/INTERFACE/PRIVATE # pick one
project)
and include the header like this:
#include <project/folder1/file.hpp>
I'm new to CMake and I'm trying to figure out how to build dependencies. My project folders are organized like this:
Scrubber
-- FileIO
-- CDEs
-- Utilities
-- Scrubber
FileIO, CDEs, and Utilities are static libraries that are used by the executable in Scrubber.
I want to be able to execute a single make command from the top dir that will build everything. If I build each library independently, then it all comes together fine when I execute the top make. But if I don't do that it ahead of time then it won't build the dependencies and, not surprisingly, complains that the libraries weren't found.
So very simple question: how do I cause the system to build the libraries?
TOP LEVEL CMAKELISTS IN SCRUBBER
cmake_minimum_required(VERSION 3.2)
project(Scrubber)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_subdirectory(FileIO)
add_subdirectory(CDEs)
add_subdirectory(Utilities)
add_subdirectory(Scrubber)
FILEIO CMAKELISTS IN SCRUBBER/FILEIO
cmake_minimum_required(VERSION 3.2)
project(FileIO)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
file(GLOB SOURCE_FILES *.cpp)
add_library(FileIO STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(FileIO PROPERTIES PREFIX "")
CDES CMAKELISTS IN SCRUBBER/CDES
cmake_minimum_required(VERSION 3.2)
project(CDEs)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
include_directories( ${BOOST_INCLUDE_DIR} )
file(GLOB SOURCE_FILES *.cpp)
add_library(CDEs STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(CDEs PROPERTIES PREFIX "")
UTILITIES CMAKELIST IN SCRUBBER/UTILITIES
cmake_minimum_required(VERSION 3.2)
project(Utilities)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
include_directories( ${BOOST_INCLUDE_DIR} )
file(GLOB SOURCE_FILES *.cpp)
add_library(Utilities STATIC ${SOURCE_FILES})
#Don't prepend with "lib"
set_target_properties(Utilities PROPERTIES PREFIX "")
SCRUBBER CMAKELIST IN SCRUBBER/SCRUBBER
cmake_minimum_required(VERSION 3.2)
project(Scrubber)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(BOOST_INCLUDE_DIR "/usr/lib/boost_1_60_0")
set(PROJECT_INCLUDE_DIR "..")
include_directories(${BOOST_INCLUDE_DIR} ${PROJECT_INCLUDE_DIR})
find_library(FILEIO_LIB FileIO.a HINTS ../FileIO/)
find_library(CDES_LIB CDEs.a HINTS ../CDEs/)
find_library(UTILITIES_LIB Utilities.a HINTS ../Utilities/)
file(GLOB SOURCE_FILES *.cpp)
add_executable(Scrubber ${SOURCE_FILES})
target_link_libraries(Scrubber ${FILEIO_LIB} ${CDES_LIB} ${UTILITIES_LIB})
This is wrong:
target_link_libraries(Scrubber ${FILEIO_LIB} ${CDES_LIB} ${UTILITIES_LIB})
if you have library add_library(FileIO STATIC ${SOURCE_FILES}), then you should
write:
target_link_libraries(Scrubber FileIO )
cmake find out that this is also target, and create make file with proper dependencies, and you not have to point any dependencies with add_dependency,
cmake do it for automatically. At least current for me cmake version 3.5
CMake includes the add_dependency command that does exactly what you need.
Make a top-level depend on other top-level targets to ensure that they build before does.
I have a directory structure in CMake as follows:
root
CMakeLists.txt
subproject_folder
my_dll_library
CMakeLists.txt
src
source1.cpp
source2.cpp
inc
library.h
CMakeLists.txt
library_demo
src
demo.cpp
CMakeLists.txt
build
bin
My root CmakeLists.txt contains this:
cmake_minimum_required(VERSION 2.8)
add_subdirectory(subproject_folder)
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
# Update if necessary
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
The CMakeLists in the subproject folder just contains
add_subdirectory(my_dll_library)
add_subdirectory(library_demo)
The CMakeLists in the library_demo folder contains
project(library_demo)
add_executable(librarydemo src/demo.cpp)
target_link_libraries(librarydemo my_dll_library)
install(TARGETS librarydemo DESTINATION bin)
The CMakeLists in the my_dll_library folder contains
add_library(lib_zaber SHARED src/source1.cpp src/source2.cpp)
install(TARGETS lib_zaber DESTINATION bin)
I want to have the demo executable and the library DLL copied to the bin folder, but it isn't working.
What am I doing wrong?
Try to set those variables too:
CMAKE_BINARY_DIR
CMAKE_CURRENT_BINARY_DIR
There's a whole list of variables you could try here:
http://www.cmake.org/Wiki/CMake_Useful_Variables
The command
install(.. DESTINATION <dir>)
installs to ${CMAKE_INSTALL_PREFIX}/<dir>.
You need to set CMAKE_INSTALL_PREFIX either in the CMakeLists.txt or when calling cmake:
cmake ... -DCMAKE_INSTALL_PREFIX=<dir>