Thursday, April 14, 2022

[SOLVED] CMake collect list of file contents into a variable from multiple submodules

Issue

A minimal example would be:

root CMake:

cmake_minimum_required(VERSION 3.22)

project(cmake_add_file LANGUAGES CXX)

function(add_file_contents FILE_NAME)
    file(READ ${FILE_NAME}  FILE_CONTENTS)
    get_filename_component(STEM_FILE_NAME ${FILE_NAME} NAME_WE)
    set(MY_ENTRIES "${MY_ENTRIES}${FILE_CONTENTS}" PARENT_SCOPE)
    message("Adding contents of file ${FILE_NAME}: ${FILE_CONTENTS}")
endfunction()

add_subdirectory(sub1)
add_subdirectory(sub2)

message("I'd like to see a nice message from the submodules please: \n ${MY_ENTRIES}")

both sub1 and sub2 CMake:

cmake_minimum_required(VERSION 3.22)

add_file_contents("message.txt")

When I run CMake for the above, it outputs the file contents ( in message.txt ) correctly, but it fails to print the last time;

Which is understandable, since all functions create a new scope, and setting the PARENT_SCOPE only sets the variable in the scope of the subfolder. I would not like to forward it again in the subfolder, because in this case there are many subfolders to append the CMakeLists.txt file, and while it is possible to do it like this, I'd like to avoid it.

  • Is there a way to forward the information two scopes up, so that it would be accessible from the root CMake?
  • Is there a way to make sure that all the subfolders processed before using this information (printing out the final message)? In this case order matters not, just that the information is appended correctly to the root scope. Unfoirtunately I am not sure that CMake executes this in the order it is in the CMakeLists.txt file.

Solution

Usually you should stay away from macros but in your case they look like a good solution. So change your function to the macro like this:

macro(add_file_contents FILE_NAME)
#<...>
endmacro()

Macros don't introduce a new scope so the parent scope will be the parent directory.

Also CMake scripts get executed in the order they written so whatever is written later in the file will be executed later.



Answered By - ixSci
Answer Checked By - Katrina (WPSolving Volunteer)