mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This flag disables the generation of dependency targets that are necessary to accurately rebuild Swift code, but which completely tank the Xcode IDE experience. Since Xcode is primarily useful as a source editor/navigator for the compiler C++ code, and Ninja is a more performant and featureful build system for Swift at this point, provide a mode that generates enough of an Xcode project to edit the Swift compiler source, but which can't build it, as a compromise so we can use Xcode's editor alongside a Ninja build environment. Swift SVN r24186
185 lines
7.0 KiB
CMake
185 lines
7.0 KiB
CMake
include(CMakeParseArguments)
|
|
include(SwiftTranslateFlag)
|
|
|
|
# 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})
|
|
|
|
# Skip generating the target if we are generating an Xcode project only
|
|
# for IDE use. The volume of dependencies here causes performance problems
|
|
# in Xcode that make it impractical to use.
|
|
if(NOT (SWIFT_XCODE_GENERATE_FOR_IDE_ONLY
|
|
AND "${ACCT_CUSTOM_TARGET_NAME}" STREQUAL ""))
|
|
_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()
|
|
endif()
|
|
|
|
# "Return" the name of the custom target
|
|
if(SWIFT_XCODE_GENERATE_FOR_IDE_ONLY
|
|
AND "${ACCT_CUSTOM_TARGET_NAME}" STREQUAL "")
|
|
set("${dependency_out_var_name}" xcode_generate_for_ide_only_dummy
|
|
PARENT_SCOPE)
|
|
else()
|
|
set("${dependency_out_var_name}" "${target_name}" PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
# A dummy target for XCODE_GENERATE_FOR_IDE_ONLY targets that stands in for
|
|
# the targets we don't generate in that mode.
|
|
if(SWIFT_XCODE_GENERATE_FOR_IDE_ONLY)
|
|
add_custom_command(OUTPUT xcode_generate_for_ide_only_dummy.txt
|
|
COMMAND echo "This Xcode project is configured for IDE use only and cannot build Swift."
|
|
COMMAND false)
|
|
add_custom_target(xcode_generate_for_ide_only_dummy ALL
|
|
DEPENDS xcode_generate_for_ide_only_dummy.txt)
|
|
endif()
|