1

I have a generated header that I'm trying to populate with the contents of a CMake list.

My top level CMakeLists file looks like this


cmake_minimum_required(VERSION 3.16)

project(Rocket_RTOS VERSION 0.0.1 LANGUAGES CXX)

  #[[Bring in helper functions and configuration]]
  set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_scripts")
  include(config)
  include(compile_config)
  include(functions)

  #add_subdir_lib(docs)
  add_collection(kernel_core)
  add_collection(modules)
  add_collection(tools)
  add_subdir_lib(fwd_decleration)

The config module defines empty a list called PROCESS_NAMES

set(ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(PROCESS_NAMES none count)
set(DRIVER_NAMES none count)

The functions module defines all of the functions used.

#[[
  @brief Adds a subdirectory with library assuming it has a standard layout
    The tests directory is also automatically added if the the CMAKE_BUILD_TYPE
    is equal to debug and the mocking directory will be added if it exists
  @param name the name of the subdirectory
]]
function(add_subdir_lib name)

  set(path "${CMAKE_CURRENT_SOURCE_DIR}")
  if(NOT "${ARGN}" STREQUAL "")
    set(path "${ARGN}")
  endif()

  add_subdirectory("${path}/${name}/src/"
    "${path}/${name}/${CMAKE_BUILD_TYPE}")

  if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG" AND NOT "${name}" STREQUAL "tests")
    if(EXISTS "${path}/${name}/tests")
      add_subdirectory("${path}/${name}/tests/src"
        "${path}/${name}/tests/${CMAKE_BUILD_TYPE}")
    endif()
    if(EXISTS "${path}/${name}/tests/mocking")
      add_subdirectory("${path}/${name}/tests/mocking/src"
        "${path}/${name}/tests/mocking/${CMAKE_BUILD_TYPE}")
    endif()
  endif()
endfunction()

#[[
  @brief Adds a lib with standard arguments
  @param name the name of the library to add including the extension
    (.hpp, .tpp, .cpp)
  @param ... additional arguments will be passed to the target_link_libraries
    command
]]
function(add_lib full_name)
  string(REGEX REPLACE ".tpp|.cpp|.hpp" "" name ${full_name})
  add_library(${name} STATIC
    "${CMAKE_CURRENT_SOURCE_DIR}/../include/${name}.hpp"
    ${full_name})
  target_include_directories(${name} PUBLIC
    "${CMAKE_CURRENT_SOURCE_DIR}/../include/")
  set_target_properties(${name} PROPERTIES
    LINKER_LANGUAGE CXX CXX_STANDARD 20
    CXX_STANDARD_REQUIRED ON)
  if(${ARGC} GREATER 0)
    target_link_libraries(${name} PUBLIC ${ARGN})
  endif()
endfunction()

#[[
  @brief Adds a config lib that is configured each time CMake is run
  @param full_name the name of the lib including the extension
  @param ... additional arguments will be passed to the target_link_libraries
    command
]]
function(add_config_lib full_name)
  string(REGEX REPLACE ".tpp|.cpp|.hpp" "" name ${full_name})
  file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/../include/${name}.hpp")
  configure_file("${name}.hpp.in"
    "${CMAKE_CURRENT_SOURCE_DIR}/../include/${name}.hpp")
  add_lib("${name}.cpp" ${ARGN})
endfunction()

#[[
  @brief Adds a driver lib that has it's name added to the list of drivers so
    it is present for lookup in the driver enum also increments the driver
    count
  @param the full name of the driver library including the extension
  @param ... additional arguments will be passed to the target_link_libraries
    command
]]
function(add_driver_lib type full_name)
  string(REGEX REPLACE ".tpp|.cpp|.hpp" "" name ${full_name})
  list(INSERT DRIVER_NAMES "${name}")
  math(EXPR VAR "${DRIVER_NAME_COUNT}+1")
  add_lib(${full_name} ${ARGN})
endfunction()

#[[
  @brief adds a named process library
  @param type the type of the process, this is added to the PROCESS_NAMES list
  @param the full name of the library including the extension
  @param ... additional arguments will be passed to the target_link_libraries
    command
]]
function(add_named_proc type full_name)
  list(INSERT PROCESS_NAMES "1" ${type})
  message("list after insertion is ${PROCESS_NAMES}")
  add_lib(${full_name} ${ARGN})
endfunction()

#[[
  @brief Adds a collection of libraries and builds them in a location named
    after the build type path the relative path of the diretory from the
    current one
  @param path the path from the current directory to the subdirectory
]]
function(add_collection path)
  add_subdirectory(
    "${CMAKE_CURRENT_SOURCE_DIR}/${path}"
    "${CMAKE_CURRENT_SOURCE_DIR}/${path}/${CMAKE_BUILD_TYPE}")
endfunction()

Within kernel_core there is a library that calls add_named_proc(kernel ) which appends "kernel" to the process name list. Finally I have fwd_decleration which uses the PROCESS_NAMES list to populate an enum. CMakeLists for fwd_decleration

#[[CMakeLists for forward decleration]]

cmake_minimum_required(VERSION 3.19)

project(forward_declare LANGUAGES CXX VERSION 0.8)

  #[[Joins the process name list into a comma seperated list]]
  list(JOIN PROCESS_NAMES ", " PROC_NAME_CSL)
  message("The final process name list is ${PROC_NAME_CSL}")

  list(LENGTH PROCESS_NAMES PROC_NAME_COUNT)

  FILE(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/../include/fwd_decleration.hpp")
  configure_file(fwd_decleration.hpp.in
    "${CMAKE_CURRENT_SOURCE_DIR}/../include/fwd_decleration.hpp")

  add_lib(fwd_decleration.cpp bit_utils)

Relevant snippet of fwd_decleration.hpp.in

/**
 * @brief Process name enum populated by cmake from a comma
 *   seperated list of process_names.
 */
enum class serv_name :  uint8_t {@PROC_NAME_CSL@};

But despite kernel_core being added at the beginning of the top level CMakeLists and fwd_decleration being added last the output of CMake -DCMAKE_BUILD_TYPE=DEBUG is

list after insertion is none;kernel;count
The final process name list is none, count
-- Configuring done
-- Generating done
-- Build files have been written to: /home/<user>/rkt/DEBUG

Which makes it seem like fwd_decleration's CMakeLists is being processed before kernel is inserted. How do I make sure that the PROCESS_NAME list is not used until the end of the configure step?

BZKN
  • 1,499
  • 2
  • 10
  • 25
  • The command `list(INSERT PROCESS_NAMES ...)` is executed **inside** the function `add_driver_lib`. After returning from the function the value of variable is restored. [They said](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variables) a function introduces a **scope** for variables. – Tsyvarev Mar 12 '22 at 23:43

0 Answers0