Introduce _qt_internal_configure_file

The function is the internal public counterpart of the
qt_configure_file command, but also supports two modes:
GENERATE and CONFIGURE. The CONFIGURE mode is plain replacement
of file(CONFIGURE or configure_file command depending of specified
arguments.

In the GENERATE mode the function allows using the generator
expressions when evaluating the CONTENT. The function doesn't support
INPUT argument as its counterpart(there are no limitations, author left
this unimplemented).

Change-Id: I9bef2265210404113596db95085b6e0d5f03ae13
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
(cherry picked from commit 1c886724bcb70f706e2a729461e4f1ea88e27ae3)
(cherry picked from commit 78f4273b97a6eaf9d3722e60ad3c9385906126ba)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Alexey Edelev 2025-03-05 12:21:41 +01:00 committed by Qt Cherry-pick Bot
parent 2cc2618f9d
commit 779dcc9a34
2 changed files with 84 additions and 45 deletions

View File

@ -1,57 +1,24 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# The common implementation of qt_configure_file functionality.
macro(qt_configure_file_impl)
if(NOT arg_OUTPUT)
message(FATAL_ERROR "No output file provided to qt_configure_file.")
endif()
# We use this check for the cases when the specified CONTENT is empty. The value of arg_CONTENT
# is undefined, but we still want to create a file with empty content.
if(NOT "CONTENT" IN_LIST arg_KEYWORDS_MISSING_VALUES)
if(arg_INPUT)
message(WARNING "Both CONTENT and INPUT are specified. CONTENT will be used to generate"
" output")
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
file(CONFIGURE OUTPUT "${arg_OUTPUT}" CONTENT "${arg_CONTENT}" @ONLY)
return()
endif()
set(template_name "QtFileConfigure.txt.in")
# When building qtbase, use the source template file.
# Otherwise use the installed file (basically wherever Qt6 package is found).
# This should work for non-prefix and superbuilds as well.
if(QtBase_SOURCE_DIR)
set(input_file "${QtBase_SOURCE_DIR}/cmake/${template_name}")
else()
set(input_file "${_qt_6_config_cmake_dir}/${template_name}")
endif()
set(__qt_file_configure_content "${arg_CONTENT}")
elseif(arg_INPUT)
set(input_file "${arg_INPUT}")
else()
message(FATAL_ERROR "No input value provided to qt_configure_file.")
endif()
configure_file("${input_file}" "${arg_OUTPUT}" @ONLY)
endmacro()
# qt_configure_file(OUTPUT output-file <INPUT input-file | CONTENT content>)
# input-file is relative to ${CMAKE_CURRENT_SOURCE_DIR}
# output-file is relative to ${CMAKE_CURRENT_BINARY_DIR}
#
# This function is similar to file(GENERATE OUTPUT) except it writes the content
# to the file at configure time, rather than at generate time.
#
# TODO: Once we require 3.18+, this can use file(CONFIGURE) in its implementation,
# or maybe its usage can be replaced by file(CONFIGURE). Until then, it uses
# configure_file() with a generic input file as source, when used with the CONTENT
# signature.
# This function is the universal replacement for file(CONFIGURE CMake command.
function(qt_configure_file)
cmake_parse_arguments(PARSE_ARGV 0 arg "" "OUTPUT;INPUT;CONTENT" "")
qt_configure_file_impl()
if("CONTENT" IN_LIST ARGV)
if(arg_INPUT)
message(WARNING "Both CONTENT and INPUT are specified. CONTENT will be used to generate"
" output")
endif()
_qt_internal_configure_file(CONFIGURE OUTPUT "${arg_OUTPUT}" CONTENT "${arg_CONTENT}")
elseif(arg_INPUT)
_qt_internal_configure_file(CONFIGURE OUTPUT "${arg_OUTPUT}" INPUT "${arg_INPUT}")
else()
message(FATAL_ERROR "No input value provided to _qt_internal_configure_file.")
endif()
endfunction()
# A version of cmake_parse_arguments that makes sure all arguments are processed and errors out

View File

@ -774,3 +774,75 @@ function(_qt_internal_relative_path path_var)
endif()
set(${arg_OUTPUT_VARIABLE} "${${arg_OUTPUT_VARIABLE}}" PARENT_SCOPE)
endfunction()
# Configures the file using either the input template or the CONTENT.
# Behaves as either file(CONFIGURE or configure_file( command, but do not depend
# on CMake version.
#
# Synopsis
# _qt_internal_configure_file(<CONFIGURE|GENERATE>
# OUTPUT <path>
# <INPUT path|CONTENT data>
# )
#
# Arguments
# `CONFIGURE` Run in pure CONFIGURE mode.
#
# `GENERATE` Configure CONTENT and generate file with the generator expression
# support.
#
# `OUTPUT` The output file name to generate.
#
# `INPUT` The input template file name.
#
# `CONTENT` The template content. If both INPUT and CONTENT are specified, INPUT
# argument is ignored.
function(_qt_internal_configure_file mode)
cmake_parse_arguments(PARSE_ARGV 1 arg "" "OUTPUT;INPUT;CONTENT" "")
if(NOT arg_OUTPUT)
message(FATAL_ERROR "No OUTPUT file provided to _qt_internal_configure_file.")
endif()
# Substitute the '@' wrapped variables and generate the file with the
# the generator expressions evaluation inside the resulting CONTENT.
if(mode STREQUAL "GENERATE")
if(arg_INPUT)
# This is not a limitation of any kind, simply is not required at
# implementation time. Feel free to extend.
message(FATAL_ERROR "GENERATE mode doesn't support INPUT argument.")
endif()
string(CONFIGURE "${arg_CONTENT}" arg_CONTENT @ONLY)
file(GENERATE OUTPUT "${arg_OUTPUT}" CONTENT "${arg_CONTENT}")
return()
endif()
# We use this check for the cases when the specified CONTENT is empty. The value of arg_CONTENT
# is undefined, but we still want to create a file with empty content.
if("CONTENT" IN_LIST ARGV)
if(arg_INPUT)
message(WARNING "Both CONTENT and INPUT are specified. CONTENT will be used to generate"
" output")
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
file(CONFIGURE OUTPUT "${arg_OUTPUT}" CONTENT "${arg_CONTENT}" @ONLY)
return()
endif()
set(template_name "QtFileConfigure.txt.in")
# When building qtbase, use the source template file.
# Otherwise use the installed file (basically wherever Qt6 package is found).
# This should work for non-prefix and superbuilds as well.
if(QtBase_SOURCE_DIR)
set(input_file "${QtBase_SOURCE_DIR}/cmake/${template_name}")
else()
set(input_file "${_qt_6_config_cmake_dir}/${template_name}")
endif()
set(__qt_file_configure_content "${arg_CONTENT}")
elseif(arg_INPUT)
set(input_file "${arg_INPUT}")
else()
message(FATAL_ERROR "No input value provided to _qt_internal_configure_file.")
endif()
configure_file("${input_file}" "${arg_OUTPUT}" @ONLY)
endfunction()