116 lines
5.2 KiB
CMake
116 lines
5.2 KiB
CMake
# Copyright 2022-2023 The Mumble Developers. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license
|
|
# that can be found in the LICENSE file at the root of the
|
|
# Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
# This function allows to delay calls to configure_file to the post-build phase. This can become necessary, if one wants to
|
|
# use the result of generator expressions for the substitutions performed via configure_file. Generator expressions are only
|
|
# evaluated at build time, while configure_file runs at configure time. To work around this issue, this function will create
|
|
# an auxiliary target that generates a new cmake script at build time and this cmake script in turn will call configure_file.
|
|
# The variables set in that cmake script are passed as arguments to this function. Since the auxiliary script is generated
|
|
# at build time, generator expressions can be used in the variable definitions.
|
|
#
|
|
# Parameters:
|
|
# PYTHON_INTERPRETER <path> Path to a working Python interpreter. Mandatory argument.
|
|
# FILES <inFile=outFile> ... Set of files to configure as key-value-pairs (in-file=out-file). Mandatory argument.
|
|
# TARGET <target> If given, it is made sure that <target> is fully built, before the configure_file action happens
|
|
# SCRIPT_NAME <name> The name of the auxiliary cmake script. If not provided, a default name is generated
|
|
# PASSTHROUGH_VARIABLES <var> ... Set of existing variables to pass-through to the generated script so that they can be used
|
|
# in the configured file(s).
|
|
# VARIABLES <name=value> ... Set of additional variables defined as key-value-pairs. The definition of <value> may make
|
|
# use of generator expressions.
|
|
# @ONLY Passes the @ONLY parameter to the generated configure_file invocations
|
|
function(delayed_configure_files)
|
|
set(options "@ONLY")
|
|
set(oneValueArgs TARGET SCRIPT_NAME PYTHON_INTERPRETER)
|
|
set(multiValueArgs FILES PASSTHROUGH_VARIABLES VARIABLES)
|
|
|
|
cmake_parse_arguments(DELAYED_CONFIGURE_FILES "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
if(DELAYED_CONFIGURE_FILES_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unrecognized arguments to delayed_configure_file: \"${DELAYED_CONFIGURE_FILES_UNPARSED_ARGUMENTS}\"")
|
|
endif()
|
|
# Check required args
|
|
if(NOT DELAYED_CONFIGURE_FILES_FILES)
|
|
message(FATAL_ERROR "Called delayed_configure_files without the FILES parameter")
|
|
endif()
|
|
if(DELAYED_CONFIGURE_FILES_TARGET)
|
|
if(NOT TARGET ${DELAYED_CONFIGURE_FILES_TARGET})
|
|
message(FATAL_ERROR "delayed_configure_files: Provided target \"${DELAYED_CONFIGURE_FILES_TARGET}\" is not actually a (valid) target")
|
|
endif()
|
|
endif()
|
|
if(NOT DELAYED_CONFIGURE_FILES_PYTHON_INTERPRETER)
|
|
message(FATAL_ERROR "Called delayed_configure_files without the PYTHON_INTERPRETER parameter")
|
|
endif()
|
|
|
|
|
|
# Generate a free target name
|
|
set(AUX_TARGET_NUM 1)
|
|
set(AUX_TARGET_BASENAME "delayed_configure_files_target_")
|
|
while(TARGET "${AUX_TARGET_BASENAME}${AUX_TARGET_NUM}")
|
|
math(EXPR AUX_TARGET_NUM "${AUX_TARGET_NUM} + 1")
|
|
endwhile()
|
|
set(AUX_TARGET_NAME "${AUX_TARGET_BASENAME}${AUX_TARGET_NUM}")
|
|
|
|
|
|
# Handle defaults
|
|
if(NOT DELAYED_CONFIGURE_FILES_SCRIPT_NAME)
|
|
set(DELAYED_CONFIGURE_FILES_SCRIPT_NAME "configure_files_${AUX_TARGET_NUM}.cmake")
|
|
endif()
|
|
|
|
if(DELAYED_CONFIGURE_FILES_@ONLY)
|
|
set(AT_ONLY "--at-only")
|
|
else()
|
|
set(AT_ONLY "")
|
|
endif()
|
|
|
|
|
|
if(DELAYED_CONFIGURE_FILES_VARIABLES)
|
|
set(VARIABLES ${DELAYED_CONFIGURE_FILES_VARIABLES})
|
|
else()
|
|
set(VARIABLES "")
|
|
endif()
|
|
if(DELAYED_CONFIGURE_FILES_PASSTHROUGH_VARIABLES)
|
|
foreach(CURRENT_VAR IN LISTS DELAYED_CONFIGURE_FILES_PASSTHROUGH_VARIABLES)
|
|
if(NOT DEFINED ${CURRENT_VAR})
|
|
message(FATAL_ERROR "delayed_configure_files: Can't passthrough non-existing variable \"${CURRENT_VAR}\"")
|
|
endif()
|
|
|
|
list(APPEND VARIABLES "${CURRENT_VAR}=${${CURRENT_VAR}}")
|
|
endforeach()
|
|
endif()
|
|
|
|
if(NOT VARIABLES STREQUAL "")
|
|
set(VARIABLES --variables ${VARIABLES})
|
|
endif()
|
|
|
|
|
|
|
|
# Create a command to generate an intermediary cmake script that will take care of configuring the respective
|
|
# files, once executed
|
|
add_custom_command(
|
|
OUTPUT "${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
COMMAND "${DELAYED_CONFIGURE_FILES_PYTHON_INTERPRETER}"
|
|
ARGS "${CMAKE_SOURCE_DIR}/scripts/generate_configure_cmake_script.py"
|
|
--files ${DELAYED_CONFIGURE_FILES_FILES} ${VARIABLES}
|
|
--output "${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
${AT_ONLY}
|
|
COMMENT "Generating delayed configure script ${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
)
|
|
|
|
# Create a target that will execute the generated cmake script. Make sure that this target will be
|
|
# added to the default build target, ensuring that it is always executed.
|
|
add_custom_target(
|
|
${AUX_TARGET_NAME} ALL
|
|
DEPENDS "${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
COMMAND "${CMAKE_COMMAND}" -P "${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
COMMENT "Executing delayed configure script ${DELAYED_CONFIGURE_FILES_SCRIPT_NAME}"
|
|
)
|
|
|
|
if(DELAYED_CONFIGURE_FILES_TARGET)
|
|
# Make our auxiliary target depend on the provided main target to ensure that the main target is always built
|
|
# before our auxiliary target executes.
|
|
add_dependencies(${AUX_TARGET_NAME} ${DELAYED_CONFIGURE_FILES_TARGET})
|
|
endif()
|
|
endfunction()
|