1

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.

Yifangt
  • 151
  • 1
  • 10
  • 2
    relative paths are always relative to the current cmake file, `add_subdirectory` just processes the cmake file in the sub directory – Alan Birtles Jul 19 '22 at 19:07
  • Can you please elaborate more, esp. my case? What tripped me is the part `set(SOURCES src/xxx.cpp` when `add_subdirectory(src)` is already there. – Yifangt Jul 19 '22 at 19:20
  • `add_subdirectory` doesn't seem to do what you think it does, it has no effect on source paths – Alan Birtles Jul 19 '22 at 19:21

1 Answers1

2

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
   )
fabian
  • 80,457
  • 12
  • 86
  • 114
  • `list(TRANSFORM SOURCES PREPEND "src/")` is exactly what I was looking for, which I have tried with a mistake `${SOURCE}`. The variable name with or without `${}` always confused me at this moment, by the way. Thanks a lot! – Yifangt Jul 19 '22 at 19:58