mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Both files are relatively small and contain utilities used by the build system. So it makes sense to merge them.
163 lines
6.1 KiB
CMake
163 lines
6.1 KiB
CMake
include(CMakeParseArguments)
|
|
include(SwiftUtils)
|
|
|
|
# Populate the variable 'args' in the parent scope with a keyword
|
|
# argument list. We read the variables options, ${k}_keyword, and
|
|
# ACCT_${k} from the parent scope, for each ${k} in the list of
|
|
# keyword names other than COMMAND accepted by
|
|
# add_custom_command_target.
|
|
#
|
|
# ${k}_keyword must expand to ${k} if ${k} was passed to
|
|
# add_custom_command_target, and be empty otherwise.
|
|
#
|
|
# ACCT_${k} must expand to the list of arguments to
|
|
# add_custom_command_target marked by ${k}, and be empty otherwise.
|
|
#
|
|
function(_make_acct_argument_list)
|
|
set(args)
|
|
foreach(k ${ARGN})
|
|
list(FIND options ${k} option_index)
|
|
if(${option_index} EQUAL -1)
|
|
list(APPEND args ${${k}_keyword} ${ACCT_${k}})
|
|
else()
|
|
list(APPEND args ${${k}_keyword})
|
|
endif()
|
|
endforeach()
|
|
set(args ${args} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# Add a custom command/target pair. Use this instead of
|
|
# add_custom_command because it provides proper dependency tracking
|
|
# when used with parallel builds and the 'Unix Makefiles' generator.
|
|
# See https://www.cmake.org/Bug/view.php?id=10082
|
|
#
|
|
# The CMake documentation for add_custom_command quoth,
|
|
#
|
|
# "Do not list the output in more than one independent target that
|
|
# may build in parallel or the two instances of the rule may
|
|
# conflict (instead use add_custom_target to drive the command and
|
|
# make the other targets depend on that one)."
|
|
#
|
|
# This function implements the suggested pattern.
|
|
#
|
|
# add_custom_command_target(
|
|
# dependency_out_var_name
|
|
#
|
|
# COMMAND command1 [ARGS] [args1...]
|
|
# [COMMAND command2 [ARGS] [args2...] ...]
|
|
#
|
|
# OUTPUT output1 [output2 ...]
|
|
# [MAIN_DEPENDENCY depend]
|
|
# [DEPENDS [depends...]]
|
|
# [IMPLICIT_DEPENDS <lang1> depend1
|
|
# [<lang2> depend2] ...]
|
|
# [WORKING_DIRECTORY dir]
|
|
# [COMMENT comment] [VERBATIM] [APPEND]
|
|
# [ALL]
|
|
# [SOURCES src1 [src2...]])
|
|
#
|
|
# dependency_out_var_name is the name of a variable, to be set in the
|
|
# parent scope with the name of a target that all targets using the
|
|
# OUTPUT should depend on. For example:
|
|
#
|
|
# add_custom_command_target(
|
|
# TheDependency
|
|
# COMMAND echo "int main() {}" ">" z.c
|
|
# OUTPUT z.c
|
|
# VERBATIM
|
|
# DEPENDS z.c.gyb)
|
|
#
|
|
# add_executable(exe1 z.c)
|
|
# add_dependencies(exe1 ${TheDependency})
|
|
# add_executable(exe2 z.c)
|
|
# add_dependencies(exe2 ${TheDependency})
|
|
#
|
|
# **Note1**: all COMMAND arguments must immediately follow
|
|
# dependency_out_var_name or this function will misbehave.
|
|
#
|
|
# **Note2**: any subdirectories that define targets dependent on
|
|
# OUTPUT ${o} should invoke:
|
|
#
|
|
# set_source_files_properties(${o} PROPERTIES GENERATED true)
|
|
#
|
|
# All arguments other than ALL, SOURCES, and dependency_out_var_name
|
|
# are forwarded to add_custom_command; arguments ALL, SOURCES, and
|
|
# WORKING_DIRECTORY are forwarded to add_custom_target. See the
|
|
# documentation of those functions for a description of all arguments.
|
|
#
|
|
# How This Function Works
|
|
#
|
|
# CMake offers one way to add new build rules: add_custom_command.
|
|
# Most people, however, overlook its actual semantics.
|
|
# add_custom_command does *not* create a target. The CMake
|
|
# documentation declareth,
|
|
#
|
|
# "A target created in the same directory (CMakeLists.txt file) that
|
|
# specifies any output of the custom command as a source file is
|
|
# given a rule to generate the file using the command at build
|
|
# time."
|
|
#
|
|
# Therefore, when two targets built in parallel depend on an output of
|
|
# the same custom command, they may race to rebuild that output.
|
|
# Hilarity ensues. You might not notice this effect depending on the
|
|
# generator you use, but it happens with 'Unix Makefiles'.
|
|
#
|
|
# By injecting a target into the dependency graph between the custom
|
|
# command output and any targets that depend on that output, we force
|
|
# the output to be built before starting on any of its dependent
|
|
# targets.
|
|
function(add_custom_command_target dependency_out_var_name)
|
|
# Parse the arguments. We don't look for COMMAND arguments because
|
|
# they don't follow the pattern supported by cmake_parse_arguments.
|
|
# As a result, they end up in ACCT_UNPARSED_ARGUMENTS and are
|
|
# forwarded verbatim.
|
|
set(options ALL VERBATIM APPEND IDEMPOTENT)
|
|
set(single_value_args
|
|
MAIN_DEPENDENCY WORKING_DIRECTORY COMMENT CUSTOM_TARGET_NAME)
|
|
set(multi_value_args OUTPUT DEPENDS IMPLICIT_DEPENDS SOURCES)
|
|
cmake_parse_arguments(
|
|
ACCT # prefix
|
|
"${options}" "${single_value_args}" "${multi_value_args}" ${ARGN})
|
|
set(ACCT_COMMANDS ${ACCT_UNPARSED_ARGUMENTS})
|
|
|
|
if("${ACCT_CUSTOM_TARGET_NAME}" STREQUAL "")
|
|
# Construct a unique name for the custom target.
|
|
# Use a hash so that the file name does not push the OS limits for filename
|
|
# length.
|
|
list(GET ACCT_OUTPUT 0 output_filename)
|
|
string(MD5 target_md5
|
|
"add_custom_command_target${CMAKE_CURRENT_BINARY_DIR}/${output_filename}")
|
|
get_filename_component(output_filename_basename "${output_filename}" NAME)
|
|
set(target_name
|
|
"add_custom_command_target-${target_md5}-${output_filename_basename}")
|
|
else()
|
|
set(target_name "${ACCT_CUSTOM_TARGET_NAME}")
|
|
endif()
|
|
|
|
if((NOT ACCT_IDEMPOTENT) OR (ACCT_IDEMPOTENT AND NOT TARGET "${target_name}"))
|
|
# For each keyword argument k that was passed to this function, set
|
|
# ${k}_keyword to ${k}. That will allow us to use the incantation
|
|
# '${${k}_keyword} ${ACCT_${k}}' to forward the arguments on.
|
|
foreach(var ${options} ${single_value_args} ${multi_value_args})
|
|
translate_flag(ACCT_${var} ${var} ${var}_keyword)
|
|
endforeach()
|
|
|
|
_make_acct_argument_list(
|
|
OUTPUT MAIN_DEPENDENCY DEPENDS
|
|
IMPLICIT_DEPENDS WORKING_DIRECTORY COMMENT VERBATIM APPEND)
|
|
add_custom_command(${ACCT_COMMANDS} ${args})
|
|
|
|
_make_acct_argument_list(ALL WORKING_DIRECTORY SOURCES)
|
|
add_custom_target(
|
|
"${target_name}" ${args}
|
|
DEPENDS ${ACCT_OUTPUT}
|
|
COMMENT "${ACCT_OUTPUT}")
|
|
set_target_properties(
|
|
"${target_name}" PROPERTIES
|
|
FOLDER "add_custom_command_target artifacts")
|
|
endif()
|
|
|
|
# "Return" the name of the custom target
|
|
set("${dependency_out_var_name}" "${target_name}" PARENT_SCOPE)
|
|
endfunction()
|