3

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. 
4
  • 1
    Doesn't Src and Inc belong to the same project? Why would you create so many CMakeLists? but I would like to make it more generic. Also, I would not like to use the So what would you want to use instead and how do you want to make it "generic"? Commented Aug 20, 2020 at 16:04
  • I don't think it makes sense to make a library out of only headers and no source files. I know the concept of header only libraries exist but they don't really compile into .lib files. Commented Aug 20, 2020 at 16:04
  • @KamilCuk Yes, they belong to the same project, I just want to separate files in different folders, also as a didactic way to learn for future projects. In regards to the number of CMakeLists, I just don't want to write that many lines on the upper CMakeLists. Generic, such that If somebody else want to add an additional file, it will be as simple as modifying the local CMakeList Commented Aug 20, 2020 at 16:09
  • @drescherjm As I mentioned, I am just beginner with CMake, I have attempted several versions, but I just do not want too many lines on the same CMakeLists. Commented Aug 20, 2020 at 16:13

1 Answer 1

4
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 ) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.