93

I have a CMakeLists.txt in my project root and one in my /src folder. The one in the /src folder only contains a variable with the .cpp files (set (SOURCEFILES main.cpp foo.cpp)) and in the root CMakeLists.txt I do add_subdirectory(src) and later I do add_executable(MyApp ${SOURCEFILES}).

But cmake gives me the error

add_executable called with incorrect number of arguments, no sources provided

How do I get cmake to see the variable? I read that cmake only knows global variables, but that's obviously not the case...

danijar
  • 30,040
  • 39
  • 151
  • 272
blubberbernd
  • 3,491
  • 7
  • 33
  • 45

1 Answers1

143

As mentioned in the documentation of the set command, each directory added with add_subdirectory or each function declared with function creates a new scope.

The new child scope inherits all variable definitions from its parent scope. Variable assignments in the new child scope with the set command will only be visible in the child scope unless the PARENT_SCOPE option is used.

To make the SOURCEFILES assignment visible in the root folder of your project, try:

set (SOURCEFILES main.cpp foo.cpp PARENT_SCOPE) 
Razakhel
  • 713
  • 13
  • 31
sakra
  • 57,919
  • 14
  • 164
  • 145
  • 6
    Thanks, this solved it. But another note: in the sub directory you have now to use `${CMAKE_CURRENT_SOURCE_DIR}/foo.cpp` instead of only `foo.cpp` because cmake is now in the parent scope. – blubberbernd Jul 31 '11 at 18:56
  • 2
    Alternatively, you could set the variable in the parent CMakeLists.txt file before the add_subdirectory call, and have its definition inherit down to the child CMakeLists file. Again, you'll need to qualify the names of the files if you need to refer to them from multiple CMakeLists files. – DLRdave Aug 01 '11 at 12:32
  • 8
    You'll need to create the variable also in the current-scope to use its values in the sub-dir/function: `set(VAR value PARENT_SCOPE); set(VAR ${VAR});` – Patrick B. Sep 10 '12 at 09:32
  • 11
    @PatrickB. in my case `set(VAR value PARENT_SCOPE); set(VAR ${VAR});` is not working, however, `set(VAR value); set(VAR ${VAR} PARENT_SCOPE);` works. – Deqing Feb 05 '13 at 10:12
  • 10
    Additonaly you can access from parent dir to specific variable in suddir like this `get_directory_property(VAR1 DIRECTORY subdir1 DEFINITION VAR1)` – Maxim Suslov May 18 '16 at 07:31
  • It is not quite fully correct. For example, `ARGV0..N` parameters might still contains old values on a moment BEFORE a `add_subdirectory` call (which means the `add_subdirectory` in that case is not quite a function), in case where u hooked up the `add_subdirectory` through the another function and call into `_add_subdirectory`. I think, this is important in case of fully compatible implementation. – Andry Oct 22 '18 at 13:44
  • how about target_... commands? I mean this discussion is about just functions and set, but what is the scope of other commands like target_link_library()? can we add a library in a subdirectory and then target_link in the parent? – SdSaati Mar 25 '20 at 10:47