I just would like to create my CMakeLists.txt like this, but the CMake guide is not that user friendly for beginners, I have already researched too much, do not downvote, please.
I have seen some solutions including in the add_executable() every source file manually, but I would like to make it more generic. Also, I would not like to use the file(GLOB SOURCES *.cpp *.h).
By the way, I am just attempting to create a Unix Makefile with the command
cmake -G 'Unix Makefiles'..
How can I do this?
CMakeLists.txt
build/
...
project/
CMakeLists.txt
Inc/
CMakeLists.txt
*.h
Src/
CMakeLists.txt
main.cpp
*.cpp
I have so far for the main directory/CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(my_project)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")
add_subdirectory(project)
for the project/CMakeLists.txt
add_subdirectory(Inc)
add_subdirectory(Src)
add_executable(exec ${Sources})
target_link_libraries(exec ${Headers})
For the Inc/CMakeLists.txt
add_library(
Headers
H1.h
H2.h
...
Hn.h
)
and for the Src/CMakeLists.txt
set(Sources main.cpp
Src1.cpp
Src2.cpp
...
Srcn.cpp
)
As it is so far, it throws the following error
-- Version: 7.0.3
-- Build type:
-- CXX_STANDARD: 11
-- Required features: cxx_variadic_templates
-- Configuring done
CMake Error: Cannot determine link language for target "exec".
CMake Error: CMake can not determine linker language for target: exec
CMake Error: Cannot determine link language for target "Headers".
CMake Error: CMake can not determine linker language for target: Headers
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
add_library( Headers H1.h H2.h
does not add a include directory to search path. It only adds the headers to sources - and because headers are not compiled, it effectively does nothing. You can do that with target_include_directories. Because cmake doesn't know if these are C or C++ headers, it cannot determine the link language.
add_subdirectory(Src) add_executable(exec ${Sources})
add_subdirectory introduces a new "scope". Variables set in add_subdirectory are not visible outside, unless you set them with PARENT_SCOPE like set(var "value" PARENT_SCOPE). ${Sources} is effectively empty, so it does add_executable(exec) with no sources, so cmake cannot determine the link language.
target_link_libraries(exec ${Headers})
A target is not a variable. ${Headers} is empty. To link with a target just use it's name.
I also subjectively advice do not use mixed case variables (and folder names).
You could:
# project/CMakeLists.txt
include(Inc/CMakeLists.txt)
include(Src/CMakeLists.txt)
add_executable(exec ${exec_sources} ${exec_headers})
target_include_directories(exec PUBLIC Inc)
# Inc/CMakeLists.txt
set(exec_headers
Inc/H1.h
Inc/H2.h
...
Inc/Hn.h
)
# Src/CMakeLists.txt
set(exec_sources
Src/main.cpp
Src/Src1.cpp
Src/Src2.cpp
...
Src/Srcn.cpp
)
# Instead of `Src/` in front you could write a `foreach()` loop.
but I do not see a point in having so many CMakeLists.txt. Just have one file:
# project/CMakeLists.txt
include(Inc/CMakeLists.txt)
include(Src/CMakeLists.txt)
add_executable(exec
Src/main.cpp
Src/Src1.cpp
Src/Src2.cpp
...
Src/Srcn.cpp
Inc/H1.h
Inc/H2.h
...
Inc/Hn.h
)
target_include_direcotories(exec PUBLIC Inc)
Och, there is also target_sources you could use, so you could also do it like this I think:
# project/CMakeLists.txt
add_executable(exec ${exec_sources} ${exec_headers})
add_subdirectory(Inc)
add_subdirectory(Src)
# Inc/CMakeLists.txt
target_include_directories(exec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_sources(exec PRIVATE
H1.h
H2.h
...
Hn.h
)
# Src/CMakeLists.txt
target_sources(exec PRIVATE
main.cpp
Src1.cpp
Src2.cpp
...
Srcn.cpp
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With