| #!/bin/bash |
| # |
| # Copyright (C) 2018-2019 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| # This script generates .xcfilelist files to be used as input and output |
| # specifications of Run Script build phases. |
| # |
| # Currently, this script looks at the Generate Derived Sources and Generate |
| # Unified Sources build phases. For the former, it invokes the |
| # DerivedSources.make makefile, passing in options that print out the |
| # dependency tree and using that information to form the associated input and |
| # output .xcfilelist files. For the latter, it invokes the same |
| # generate-unified-bundles.rb script that generates the actual |
| # UnifiedSources*.cpp/mm files, albeit in a mode that produces .xcfilelist |
| # files instead. |
| # |
| # This script not only generates .xcfilelists, but -- when given a "check" |
| # command -- it also checks that they are up-to-date. In this mode, the |
| # .xcfilelist files are created in a temporary location and are then compared |
| # to the versions checked into the repository. If there are differences, the |
| # user is notified so that they know that the .xcfilelist files need to be |
| # regenerated. This facility can be incorporated into a build phase, a check-in |
| # hook, or into the EWS (perhaps as part of check-webkit-style). |
| # |
| # As part of its operation, this script can sub-launch itself under Xcode. It |
| # does this in order to establish the context in which builds occur. In |
| # particular, it does this in order to set needed environment variables. In |
| # order to protect against environment variable name collision, all variable |
| # names in this script start with "GX_". |
| |
| |
| function stdout() |
| { |
| (( ${GX_QUIET} )) || echo "$@" >&1 |
| } |
| |
| |
| function stderr() |
| { |
| echo "$@" >&2 |
| } |
| |
| |
| function remove_extra_spaces() |
| { |
| echo $1 |
| } |
| |
| function print_option() |
| { |
| local GX_OPTION="$1" |
| local GX_MESSAGE="$(remove_extra_spaces "$2")" |
| |
| local GX_LINE |
| local GX_LINE_WIDTH=90 |
| local GX_OPTION_WIDTH=17 |
| |
| if (( ${#GX_OPTION} <= GX_OPTION_WIDTH )) |
| then |
| local GX_MESSAGE_CATENATED=$(printf " %-${GX_OPTION_WIDTH}s %s" "$GX_OPTION" "$GX_MESSAGE") |
| if (( ${#GX_MESSAGE_CATENATED} <= GX_LINE_WIDTH )) |
| then |
| stderr "${GX_MESSAGE_CATENATED}" |
| return |
| fi |
| |
| local GX_MESSAGE_FIRST_LINE="${GX_MESSAGE_CATENATED:0:${GX_LINE_WIDTH}}" # Get the first 80 characters |
| GX_MESSAGE_FIRST_LINE="${GX_MESSAGE_FIRST_LINE% *}" # Trim back to the last space |
| GX_MESSAGE="${GX_MESSAGE_CATENATED:${#GX_MESSAGE_FIRST_LINE}+1}" # Get the rest after that space |
| |
| stderr "${GX_MESSAGE_FIRST_LINE}" |
| else |
| stderr " ${GX_OPTION}" |
| fi |
| |
| while IFS='' read -r GX_LINE |
| do |
| GX_LINE=$(printf " %${GX_OPTION_WIDTH}s %s" "" "$GX_LINE") |
| stderr "${GX_LINE}" |
| done < <(echo "${GX_MESSAGE}" | fold -w $(( GX_LINE_WIDTH - GX_OPTION_WIDTH - 3)) -s) |
| } |
| |
| |
| function join_by() |
| { |
| local GX_DELIM=$1 |
| shift |
| |
| echo -n "$1" |
| shift |
| |
| printf "%s" "${@/#/${GX_DELIM}}" |
| } |
| |
| |
| function usage() |
| { |
| local GX_JOINED_PROJECT_TAGS=$(join_by ", " "${GX_PROJECT_TAGS[@]}") |
| |
| stderr "Usage: $(basename "${GX_ME}") [OPTION...] COMMAND [PARAMETER...]" |
| stderr "" |
| stderr "Generate or check .xcfilelist files" |
| stderr "" |
| stderr "Commands:" |
| stderr "" |
| print_option "generate" "Generate a complete and up-to-date set of |
| .xcfilelist files and copy them to their appropriate places in the |
| project directories." |
| print_option "generate-xcode" "Generate .xcfilelist files for the current |
| target configuration an copy them to their appropriate places in the |
| project directories. Invoked from withing Xcode to update the current |
| build if needed." |
| print_option "check" "Generate a complete and up-to-date set of .xcfilelist |
| files and compare them to their counterparts in the project |
| directories." |
| print_option "check-xcode" "Generate .xcfilelist files for the current |
| target configuration and see if any files appear that aren't in the |
| checked-in .xcfilelist files. Invoked from within Xcode to validate the |
| current build." |
| print_option "subgenerate" "Generate an .xcfilelist file for a particular |
| combination of project, platform, and configuration. This operation is |
| performed in the context of an Xcode build in order to inherit the same |
| environment as that build." |
| print_option "help" "Print this text and exit." |
| stderr "" |
| stderr "Options:" |
| stderr "" |
| print_option "--project <project>" "Specify which project for which to |
| generate .xcfilelist files or to check. Possible values are |
| (${GX_JOINED_PROJECT_TAGS}). Default is to iterate over all projects." |
| print_option "--platform <platform>" "Specify which platform for which to |
| generate .xcfilelist files or to check. Possible values are (macosx, |
| iphoneos). Default is to iterate over all platforms, filtered to those |
| platforms that a particular project supports (e.g., you can't specify |
| 'iphoneos' for WebKitTestRunner)." |
| print_option "--configuration <configuration>" "Specify which configuration |
| for which to generate .xcfilelist files or to check, Possible values |
| are (release, debug). Default is to iterate over all configurations." |
| print_option "--xcode" "Specify that existing build output can be found in |
| the directory created by the Xcode IDE (in ~/Library/Developer/Xcode)." |
| print_option "--webkitbuild" "Specify that existing build output can be |
| found in the directory used by the WebKit make files or the |
| build-webkit script (that is, in WebKitBuild or in the directory |
| identified by WEBKIT_OUTPUTDIR). This option is the default, so it |
| doesn't really get you anything by specifying this option (or by my |
| implementing it)." |
| print_option "--nocleanup" "Disable cleaning up temporary files after a |
| subgenerate operation. Normally these are cleaned up, but if |
| 'subgenerate' is part of an overall 'generate' operation, then the |
| 'generate' operation needs to keep around the temporary files until it |
| can complete aggregating them." |
| stderr "" |
| print_option "--dry-run" "When running through the requested process, don't |
| make any material changes. For example, for 'generate', create the new |
| .xcfilelist files, but don't copy them into their final locations" |
| print_option "--debug" "Provide verbose output." |
| print_option "--quiet" "Don't print any std output." |
| print_option "--help" "Print this text and exit." |
| stderr "" |
| } |
| |
| |
| function cleanup() |
| { |
| if (( ${GX_DO_CLEANUP} )) && (( ${GX_DEFERRED_EXIT_CODE} == 0 )) |
| then |
| rm -rf "${GX_TEMP}" &> /dev/null |
| fi |
| } |
| |
| |
| function my_exit() |
| { |
| local GX_ERR=$1 |
| exit $GX_ERR |
| } |
| |
| |
| function die() |
| { |
| local GX_ERR=$2 |
| [[ "$GX_ERR" == "" ]] && GX_ERR=1 |
| stderr "### (${FUNCNAME[@]}) $1" |
| my_exit $GX_ERR |
| } |
| |
| |
| function log_debug() |
| { |
| (( "${GX_DEBUG}" > 0 )) && stderr "GXCF: $@" |
| } |
| |
| |
| function log_debug_var() |
| { |
| local GX_VAR_NAME=$1 |
| local GX_IS_ARRAY=$(declare -p ${GX_VAR_NAME} 2> /dev/null | grep -q '^declare -a' && echo 1 || echo 0) |
| |
| if (( $GX_IS_ARRAY )) |
| then |
| log_debug $(printf "%-47s = (%s)" $GX_VAR_NAME "$(eval echo \$\{${GX_VAR_NAME}\[\@\]\})") |
| else |
| log_debug $(printf "%-47s = %s" $GX_VAR_NAME "$(eval echo \$\{${GX_VAR_NAME}\})") |
| fi |
| } |
| |
| |
| function log_callstack_and_parameters() |
| { |
| if (( "${GX_DEBUG}" > "1" )) |
| then |
| local GX_ARGS=("$@") |
| local GX_CALLSTACK=("${FUNCNAME[@]}") |
| unset GX_CALLSTACK[0] |
| stderr "GXCF: (${GX_CALLSTACK[@]}): ${GX_ARGS[@]}" |
| fi |
| } |
| |
| |
| function log_progress() |
| { |
| stdout "GXCF: $@" |
| } |
| |
| |
| function log_progress_long() |
| { |
| local GX_MESSAGE="$(remove_extra_spaces "$1")" |
| local GX_LINE |
| while IFS='' read -r GX_LINE |
| do |
| log_progress $GX_LINE |
| done < <(echo "${GX_MESSAGE}" | fold -w 86 -s) |
| } |
| |
| |
| function normalize_directory_path() |
| { |
| log_callstack_and_parameters "$@" |
| |
| [[ -z "$1" ]] && { echo "$1"; return; } |
| cd "$1" 2> /dev/null || { echo "$1"; return; } |
| pwd -P |
| } |
| |
| |
| function normalize_file_path() |
| { |
| log_callstack_and_parameters "$@" |
| |
| [[ -z "$1" ]] && { echo "$1"; return; } |
| echo $(normalize_directory_path "$(dirname "$1")")/$(basename "$1") |
| } |
| |
| |
| function call() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_FN="$1" |
| [[ "$(type -t ${GX_FN})" == "function" ]] || return $? |
| eval "${GX_FN}" |
| } |
| |
| |
| function set_project_specific_settings_for_JavaScriptCore() |
| { |
| log_callstack_and_parameters "$@" |
| |
| GX_PS_PROJECT_FILE_PATH="${GX_OPENSOURCE_DIR}/Source/JavaScriptCore/JavaScriptCore.xcodeproj" # Can't use PROJECT_FILE_PATH because this is used pre-Xcode. |
| GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-derived-sources.sh" |
| GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-unified-sources.sh" |
| GX_PS_PLATFORM_NAMES=(macosx iphoneos) |
| } |
| |
| |
| function set_project_specific_settings_for_WebCore() |
| { |
| log_callstack_and_parameters "$@" |
| |
| GX_PS_PROJECT_FILE_PATH="${GX_OPENSOURCE_DIR}/Source/WebCore/WebCore.xcodeproj" # Can't use PROJECT_FILE_PATH because this is used pre-Xcode. |
| GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-derived-sources.sh" |
| GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-unified-sources.sh" |
| GX_PS_PLATFORM_NAMES=(macosx iphoneos) |
| } |
| |
| |
| function set_project_specific_settings_for_WebKit() |
| { |
| log_callstack_and_parameters "$@" |
| |
| GX_PS_PROJECT_FILE_PATH="${GX_OPENSOURCE_DIR}/Source/WebKit/WebKit.xcodeproj" # Can't use PROJECT_FILE_PATH because this is used pre-Xcode. |
| GX_PS_DERIVED_SOURCES_DIR="${BUILT_PRODUCTS_DIR}/DerivedSources/WebKit2" |
| GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-derived-sources.sh" |
| GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-unified-sources.sh" |
| GX_PS_PLATFORM_NAMES=(macosx iphoneos) |
| } |
| |
| |
| function set_project_specific_settings_for_DumpRenderTree() |
| { |
| log_callstack_and_parameters "$@" |
| |
| GX_PS_PROJECT_FILE_PATH="${GX_OPENSOURCE_DIR}/Tools/DumpRenderTree/DumpRenderTree.xcodeproj" # Can't use PROJECT_FILE_PATH because this is used pre-Xcode. |
| GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-derived-sources.sh" |
| GX_PS_PLATFORM_NAMES=(macosx) |
| } |
| |
| |
| function set_project_specific_settings_for_WebKitTestRunner() |
| { |
| log_callstack_and_parameters "$@" |
| |
| GX_PS_PROJECT_FILE_PATH="${GX_OPENSOURCE_DIR}/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj" # Can't use PROJECT_FILE_PATH because this is used pre-Xcode. |
| GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH="Scripts/generate-derived-sources.sh" |
| GX_PS_PLATFORM_NAMES=(macosx) |
| } |
| |
| |
| function set_project_specific_settings() |
| { |
| log_callstack_and_parameters "$@" |
| |
| # Unset the variables that the set_project_specific_settings_for_FOO |
| # functions set. We need to do this in case the function for project BAR |
| # doesn't define one or more of them, causing it to inherit the settings |
| # for a previous project FOO. |
| # |
| # To achieve this unsetting, we prefix all the variables we want to unset |
| # with "GX_PS_" ("PS for "project specific"). We can then gather all |
| # variables that start with this prefix and unset them. |
| |
| unset ${!GX_PS_*} |
| |
| [[ -n "${GX_PROJECT_TAG}" ]] || die "GX_PROJECT_TAG is not defined." |
| |
| call set_project_specific_settings_for_${GX_PROJECT_TAG} || die "Could not set build variables for ${GX_PROJECT_TAG}." |
| } |
| |
| |
| function set_common_project_settings() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_EFFECTIVE_PROJECT_FILE_PATH="${GX_PS_PROJECT_FILE_PATH}" |
| local GX_EFFECTIVE_PROJECT_DIR=$(dirname "${GX_EFFECTIVE_PROJECT_FILE_PATH}") |
| |
| [[ -n "${GX_EFFECTIVE_PROJECT_FILE_PATH}" ]] || die "GX_EFFECTIVE_PROJECT_FILE_PATH is not defined." |
| [[ -d "${GX_EFFECTIVE_PROJECT_FILE_PATH}" ]] || die "${GX_EFFECTIVE_PROJECT_FILE_PATH} is not a directory." |
| [[ -n "${GX_EFFECTIVE_PROJECT_DIR}" ]] || die "GX_EFFECTIVE_PROJECT_DIR is not defined." |
| [[ -d "${GX_EFFECTIVE_PROJECT_DIR}" ]] || die "${GX_EFFECTIVE_PROJECT_DIR} is not a directory." |
| |
| # Get the paths to the scripts that drive the generation of the |
| # .xcfilelists or the data going into the .xcfilelists. |
| |
| GX_DERIVEDSOURCES_GENERATOR="${GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH:+${GX_EFFECTIVE_PROJECT_DIR}/${GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH}}" |
| GX_UNIFIEDSOURCES_GENERATOR="${GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH:+${GX_EFFECTIVE_PROJECT_DIR}/${GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH}}" |
| |
| [[ -n "${GX_DERIVEDSOURCES_GENERATOR}" ]] && { [[ -f "${GX_DERIVEDSOURCES_GENERATOR}" ]] || die "${GX_DERIVEDSOURCES_GENERATOR} does not exist."; } |
| [[ -n "${GX_UNIFIEDSOURCES_GENERATOR}" ]] && { [[ -f "${GX_UNIFIEDSOURCES_GENERATOR}" ]] || die "${GX_UNIFIEDSOURCES_GENERATOR} does not exist."; } |
| |
| # Get the paths to the locations of the final .xcfilelist files. |
| |
| local GX_BASE_PATH="${GX_EFFECTIVE_PROJECT_DIR}/${GX_PS_XCFILELIST_RELATIVE_PATH}" |
| GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH="${GX_BASE_PATH}/DerivedSources-input.xcfilelist" |
| GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH="${GX_BASE_PATH}/DerivedSources-output.xcfilelist" |
| GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH="${GX_BASE_PATH}/UnifiedSources-output.xcfilelist" |
| |
| # Get the paths to the locations of the temporary .xcfilelist files (the |
| # ones being built up before being moved to their final locations). |
| |
| GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH="${GX_TEMP}/${GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH="${GX_TEMP}/${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH="${GX_TEMP}/${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH}" |
| |
| # Collect the default per-project commands to execute during the generate, |
| # merge, and compare stages. |
| |
| GX_SUBGENERATE_ACTIONS=() |
| GX_MERGE_ACTIONS=() |
| GX_CHECK_ACTIONS=() |
| |
| if [[ -n "${GX_DERIVEDSOURCES_GENERATOR}" ]] |
| then |
| GX_SUBGENERATE_ACTIONS+=(generate_derivedsources_xcfilelists) |
| GX_MERGE_ACTIONS+=(merge_derivedsources_xcfilelists) |
| GX_CHECK_ACTIONS+=(check_derivedsources_xcfilelists) |
| fi |
| |
| if [[ -n "${GX_UNIFIEDSOURCES_GENERATOR}" ]] |
| then |
| GX_SUBGENERATE_ACTIONS+=(generate_unifiedsources_xcfilelists) |
| GX_MERGE_ACTIONS+=(merge_unifiedsources_xcfilelists) |
| GX_CHECK_ACTIONS+=(check_unifiedsources_xcfilelists) |
| fi |
| |
| [[ -z "${GX_PS_DERIVED_SOURCES_DIR}" ]] && GX_PS_DERIVED_SOURCES_DIR="${BUILT_PRODUCTS_DIR}/DerivedSources/${PROJECT_NAME}" |
| |
| GX_TEMP_INPUT_XCFILELIST="${GX_TEMP}/input.xcfilelist" |
| GX_TEMP_OUTPUT_XCFILELIST="${GX_TEMP}/output.xcfilelist" |
| } |
| |
| |
| function dump_project_settings() |
| { |
| log_callstack_and_parameters "$@" |
| |
| log_debug_var BUILD_SCRIPTS_DIR |
| log_debug_var BUILT_PRODUCTS_DIR |
| log_debug_var CONFIGURATION |
| log_debug_var DERIVED_SOURCES_DIR |
| log_debug_var JAVASCRIPTCORE_PRIVATE_HEADERS_DIR |
| log_debug_var PROJECT_DIR |
| log_debug_var PROJECT_FILE_PATH |
| log_debug_var PROJECT_NAME |
| log_debug_var WEBCORE_PRIVATE_HEADERS_DIR |
| log_debug_var WEBKIT2_PRIVATE_HEADERS_DIR |
| log_debug |
| log_debug_var GX_PS_PROJECT_FILE_PATH |
| log_debug_var GX_PS_DERIVEDSOURCES_GENERATOR_RELATIVE_PATH |
| log_debug_var GX_PS_UNIFIEDSOURCES_GENERATOR_RELATIVE_PATH |
| log_debug_var GX_PS_XCFILELIST_RELATIVE_PATH |
| log_debug_var GX_PS_PLATFORM_NAMES |
| log_debug |
| log_debug_var GX_PROJECT_TAG |
| log_debug_var GX_PLATFORM_NAME |
| log_debug_var GX_CONFIGURATION |
| log_debug |
| log_debug_var GX_EFFECTIVE_PROJECT_FILE_PATH |
| log_debug_var GX_EFFECTIVE_PROJECT_DIR |
| log_debug |
| log_debug_var GX_DERIVEDSOURCES_GENERATOR |
| log_debug_var GX_UNIFIEDSOURCES_GENERATOR |
| log_debug |
| log_debug_var GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH |
| log_debug_var GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH |
| log_debug_var GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH |
| log_debug |
| log_debug_var GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH |
| log_debug_var GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH |
| log_debug_var GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH |
| log_debug |
| log_debug_var GX_PS_DERIVED_SOURCES_DIR |
| log_debug |
| log_debug_var GX_SUBGENERATE_ACTIONS |
| log_debug_var GX_MERGE_ACTIONS |
| log_debug_var GX_CHECK_ACTIONS |
| } |
| |
| |
| function set_project_settings() |
| { |
| log_callstack_and_parameters "$@" |
| |
| [[ -z "${GX_PROJECT_TAG}" ]] && return |
| |
| set_project_specific_settings |
| set_common_project_settings |
| dump_project_settings |
| } |
| |
| |
| function ensure_directories_exist() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_DIR |
| for GX_DIR in "$@" |
| do |
| log_debug "Creating ${GX_DIR}" |
| mkdir -p "${GX_DIR}" &> /dev/null || die "Unable to create "${GX_DIR}"." |
| done |
| } |
| |
| |
| function create_empty_files() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_FILE |
| for GX_FILE in "$@" |
| do |
| ensure_directories_exist "$(dirname "${GX_FILE}")" |
| |
| log_debug "Creating ${GX_FILE}" |
| echo -n '' > "${GX_FILE}" |
| done |
| } |
| |
| |
| function append_xcfilelist_header() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_FILE |
| for GX_FILE in "$@" |
| do |
| echo '# This file is generated by the generate-xcfilelists script.' >> "${GX_FILE}" |
| done |
| } |
| |
| |
| function sort_and_unique_in_place() |
| { |
| sort -u "$1" -o "$1" |
| } |
| |
| |
| function replace() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_FILE="$1" |
| local GX_PATTERN="$2" |
| local GX_REPLACEMENT="$3" |
| |
| [[ -n "${GX_FILE}" ]] || die "GX_FILE is not defined." |
| [[ -f "${GX_FILE}" ]] || die "${GX_FILE} does not exist." |
| |
| sed -E -e "s|${GX_PATTERN}|${GX_REPLACEMENT}|" -i '' "${GX_FILE}" |
| } |
| |
| |
| function unexpand() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_FILE="$1" |
| local GX_VAR="$2" |
| local GX_VALUE=$(eval echo \$${GX_VAR}) |
| |
| [[ -n "${GX_VALUE}" ]] && replace "${GX_FILE}" "^${GX_VALUE}/" "\$\($GX_VAR\)/" |
| } |
| |
| |
| function find_additions() |
| { |
| # Find additions and removals so that we can report them. |
| # |
| # UPDATE: We can't really report removals. It's possible -- even |
| # overwhelmingly likely -- that we are generating .xcfilelist information |
| # for only a subset of the possible configurations for which we build. For |
| # example, a developer may be building for macOS and iOS, but not watchOS. |
| # In situations like this, we'll be generating the .xcfilelist for those |
| # two platforms, but any files specific to watchOS will not be discovered |
| # and won't be included in the .xcfilelists. If we were to report those |
| # watchOS files as files that should be removed from the .xcfilelists, then |
| # the watchOS build may fail. So, for now, let any obsolete files |
| # accumulate in the .xcfilelist files; they're mostly harmless. |
| |
| local GX_NEW="$1" |
| local GX_ORIG="$2" |
| local GX_ADDITIONS="$3" |
| |
| [[ -f "${GX_NEW}" ]] || die "${GX_NEW} does not exist." |
| [[ -f "${GX_ORIG}" ]] || die "${GX_ORIG} does not exist." |
| |
| comm -2 -3 <(sort "${GX_NEW}") <(sort "${GX_ORIG}") > "${GX_ADDITIONS}" |
| } |
| |
| |
| function get_sdks() |
| { |
| log_callstack_and_parameters "$@" |
| |
| (( ${#GX_SDKS[@]} )) && return |
| |
| GX_SDKS=($( |
| xcodebuild -showsdks \ |
| | grep -e '\s-sdk\s' \ |
| | sed -E \ |
| -e 's/.*-sdk ([^[:digit:]]+)$/\1/' \ |
| -e 's/.*-sdk ([^[:digit:]]+)([[:digit:]\.]+)$/\1/' \ |
| -e 's/.*-sdk ([^[:digit:]]+)([[:digit:]\.]+)([^[:digit:]]+)$/\1.\3/' \ |
| | sort -u |
| )) |
| |
| (( ${#GX_SDKS[@]} )) || die "Unable to find any SDKs." |
| } |
| |
| |
| function get_canonical_configuration() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_PROVISIONAL_CONFIGURATION=$(echo "$1" | tr '[:upper:]' '[:lower:]') |
| local GX_RESULT=$2 |
| |
| [[ "${GX_PROVISIONAL_CONFIGURATION}" == "" ]] && { eval $GX_RESULT=""; return; } |
| |
| [[ "${GX_PROVISIONAL_CONFIGURATION}" == "debug" ]] && { eval $GX_RESULT="Debug"; return; } |
| [[ "${GX_PROVISIONAL_CONFIGURATION}" == "release" ]] && { eval $GX_RESULT="Release"; return; } |
| [[ "${GX_PROVISIONAL_CONFIGURATION}" == "production" ]] && { eval $GX_RESULT="Production"; return; } |
| [[ "${GX_PROVISIONAL_CONFIGURATION}" == "profiling" ]] && { eval $GX_RESULT="Profiling"; return; } |
| |
| die "Unrecognized configuration: $1" |
| } |
| |
| |
| function get_canonical_platform_name() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_PROVISIONAL_PLATFORM_NAME=$(echo "$1" | tr '[:upper:]' '[:lower:]') |
| local GX_RESULT=$2 |
| |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "" ]] && { eval $GX_RESULT=""; return; } |
| |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "ios" ]] && { eval $GX_RESULT="iphoneos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "iphone" ]] && { eval $GX_RESULT="iphoneos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "ipad" ]] && { eval $GX_RESULT="iphoneos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "iphoneos" ]] && { eval $GX_RESULT="iphoneos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "iphonesimulator" ]] && { eval $GX_RESULT="iphonesimulator"; return; } |
| |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "mac" ]] && { eval $GX_RESULT="macosx"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "osx" ]] && { eval $GX_RESULT="macosx"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "macos" ]] && { eval $GX_RESULT="macosx"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "macosx" ]] && { eval $GX_RESULT="macosx"; return; } |
| |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "tvos" ]] && { eval $GX_RESULT="appletvos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "appletvos" ]] && { eval $GX_RESULT="appletvos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "tvsimulator" ]] && { eval $GX_RESULT="appletvsimulator"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "appletvsimulator" ]] && { eval $GX_RESULT="appletvsimulator"; return; } |
| |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "watchos" ]] && { eval $GX_RESULT="watchos"; return; } |
| [[ "${GX_PROVISIONAL_PLATFORM_NAME}" == "watchsimulator" ]] && { eval $GX_RESULT="watchsimulator"; return; } |
| |
| die "Unrecognized platform name: $1" |
| } |
| |
| |
| function get_sdk_name() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_SDK=$1 |
| local GX_RESULT=$2 |
| get_canonical_platform_name "${GX_SDK}" GX_SDK |
| local GX_INTERNAL_SDK="${GX_SDK}.internal" |
| |
| get_sdks |
| |
| # Prefer an internal SDK if one exists. |
| |
| [[ " ${GX_SDKS[@]} " =~ " ${GX_INTERNAL_SDK} " ]] && { eval $GX_RESULT="${GX_INTERNAL_SDK}"; return; } |
| [[ " ${GX_SDKS[@]} " =~ " ${GX_SDK} " ]] && { eval $GX_RESULT="${GX_SDK}"; return; } |
| |
| die "Unsupported SDK: ${GX_SDK}." |
| } |
| |
| |
| function invoke_each_action() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_ACTION |
| for GX_ACTION in "$@" |
| do |
| eval "${GX_ACTION}" |
| done |
| } |
| |
| |
| function for_each_configuration() |
| { |
| log_callstack_and_parameters "$@" |
| |
| if [[ -z "${GX_CONFIGURATION}" ]] |
| then |
| for GX_CONFIGURATION in "${GX_CONFIGURATIONS[@]}" |
| do |
| eval "$@" |
| done |
| |
| GX_CONFIGURATION= |
| else |
| eval "$@" |
| fi |
| } |
| |
| |
| function for_each_platform() |
| { |
| log_callstack_and_parameters "$@" |
| |
| if [[ -z "${GX_PLATFORM_NAME}" ]] |
| then |
| for GX_PLATFORM_NAME in "${GX_PS_PLATFORM_NAMES[@]}" |
| do |
| eval "$@" |
| done |
| |
| GX_PLATFORM_NAME= |
| else |
| eval "$@" |
| fi |
| } |
| |
| |
| function for_each_project() |
| { |
| log_callstack_and_parameters "$@" |
| |
| if [[ -z "${GX_PROJECT_TAG}" ]] |
| then |
| for GX_PROJECT_TAG in "${GX_PROJECT_TAGS[@]}" |
| do |
| set_project_settings |
| eval "$@" |
| done |
| |
| GX_PROJECT_TAG= |
| else |
| set_project_settings |
| eval "$@" |
| fi |
| } |
| |
| |
| function generate_derivedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| create_empty_files "${GX_TEMP_INPUT_XCFILELIST}" "${GX_TEMP_OUTPUT_XCFILELIST}" |
| |
| local GX_DERIVEDSOURCES_EXTRACTOR="${GX_HERE}/extract-dependencies-from-makefile" |
| |
| [[ -n "${GX_DERIVEDSOURCES_GENERATOR}" ]] || die "GX_DERIVEDSOURCES_GENERATOR is not defined." |
| [[ -x "${GX_DERIVEDSOURCES_GENERATOR}" ]] || die "${GX_DERIVEDSOURCES_GENERATOR} does not exist or is not executable." |
| [[ -x "${GX_DERIVEDSOURCES_EXTRACTOR}" ]] || die "${GX_DERIVEDSOURCES_EXTRACTOR} does not exist or is not executable." |
| |
| log_debug "Creating derived .xcfilelists for ${PROJECT_NAME}/${PLATFORM_NAME}/${CONFIGURATION}" |
| |
| "${GX_DERIVEDSOURCES_GENERATOR}" \ |
| NO_SUPPLEMENTAL_FILES=1 \ |
| --no-builtin-rules \ |
| --dry-run \ |
| --always-make \ |
| --debug=abvijm all \ |
| 1> "${GX_TEMP}/std.out" 2> "${GX_TEMP}/std.err" |
| local GX_RESULT=$? |
| |
| if (( ${GX_RESULT} )) |
| then |
| sed -E -e 's/^/GXCF: /' < "${GX_TEMP}/std.err" |
| die "Error generating derived sources: error = ${GX_RESULT}" ${GX_RESULT} |
| fi |
| |
| cat "${GX_TEMP}/std.out" \ |
| | "${GX_DERIVEDSOURCES_EXTRACTOR}" \ |
| --input "${GX_TEMP_INPUT_XCFILELIST}" \ |
| --output "${GX_TEMP_OUTPUT_XCFILELIST}" |
| local GX_RESULT=$? |
| |
| (( ${GX_RESULT} )) && die "Error extracting dependencies from DerivedSources.make: error = ${GX_RESULT}" |
| [[ -f "${GX_TEMP_INPUT_XCFILELIST}" ]] || die "${GX_TEMP_INPUT_XCFILELIST} was not generated." |
| [[ -f "${GX_TEMP_OUTPUT_XCFILELIST}" ]] || die "${GX_TEMP_OUTPUT_XCFILELIST} was not generated." |
| |
| replace "${GX_TEMP_INPUT_XCFILELIST}" '^WebCore/' '$(PROJECT_DIR)/' |
| replace "${GX_TEMP_INPUT_XCFILELIST}" '^JavaScriptCore/' '$(PROJECT_DIR)/' |
| replace "${GX_TEMP_INPUT_XCFILELIST}" '^JavaScriptCorePrivateHeaders/' '$(JAVASCRIPTCORE_PRIVATE_HEADERS_DIR)/' |
| replace "${GX_TEMP_INPUT_XCFILELIST}" '^WebKit2PrivateHeaders/' '$(WEBKIT2_PRIVATE_HEADERS_DIR)/' |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" PROJECT_DIR |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" WEBKITADDITIONS_HEADERS_FOLDER_PATH |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" WEBCORE_PRIVATE_HEADERS_DIR |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" WEBKIT2_PRIVATE_HEADERS_DIR |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" JAVASCRIPTCORE_PRIVATE_HEADERS_DIR |
| unexpand "${GX_TEMP_INPUT_XCFILELIST}" BUILT_PRODUCTS_DIR |
| |
| replace "${GX_TEMP_OUTPUT_XCFILELIST}" "^" "${GX_PS_DERIVED_SOURCES_DIR}/" |
| unexpand "${GX_TEMP_OUTPUT_XCFILELIST}" BUILT_PRODUCTS_DIR |
| |
| merge_xcfilelists_helper "${GX_TEMP_INPUT_XCFILELIST}" "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" |
| merge_xcfilelists_helper "${GX_TEMP_OUTPUT_XCFILELIST}" "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" |
| } |
| |
| |
| function generate_unifiedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| create_empty_files "${GX_TEMP_OUTPUT_XCFILELIST}" |
| |
| [[ -n "${GX_UNIFIEDSOURCES_GENERATOR}" ]] || die "GX_UNIFIEDSOURCES_GENERATOR is not defined." |
| [[ -x "${GX_UNIFIEDSOURCES_GENERATOR}" ]] || die "${GX_UNIFIEDSOURCES_GENERATOR} does not exist or is not executable." |
| |
| local GX_BUILD_SCRIPTS_DIR="${GX_OPENSOURCE_DIR}/Source/WTF/Scripts" |
| [[ -d "${GX_BUILD_SCRIPTS_DIR}" ]] || die "${GX_BUILD_SCRIPTS_DIR} does not exist or is not a directory." |
| [[ -f "${GX_BUILD_SCRIPTS_DIR}/generate-unified-source-bundles.rb" ]] || die "${GX_BUILD_SCRIPTS_DIR}/generate-unified-source-bundles.rb does not exist or is not a file." |
| |
| log_debug "Creating unified .xcfilelists for ${PROJECT_NAME}/${PLATFORM_NAME}/${CONFIGURATION}" |
| |
| BUILD_SCRIPTS_DIR="${GX_BUILD_SCRIPTS_DIR}" \ |
| "${GX_UNIFIEDSOURCES_GENERATOR}" \ |
| --generate-xcfilelists \ |
| --output-xcfilelist-path "${GX_TEMP_OUTPUT_XCFILELIST}" |
| GX_RESULT=$? |
| |
| (( ${GX_RESULT} )) && die "Error generating unified sources: error = ${GX_RESULT}" |
| [[ -f "${GX_TEMP_OUTPUT_XCFILELIST}" ]] || die "${GX_TEMP_OUTPUT_XCFILELIST} was not generated." |
| |
| unexpand "${GX_TEMP_OUTPUT_XCFILELIST}" BUILT_PRODUCTS_DIR |
| |
| merge_xcfilelists_helper "${GX_TEMP_OUTPUT_XCFILELIST}" "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH}" |
| } |
| |
| |
| function subgenerate_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| invoke_each_action "${GX_SUBGENERATE_ACTIONS[@]}" |
| } |
| |
| |
| function sublaunch_under_xcode() |
| { |
| log_callstack_and_parameters "$@" |
| |
| # Sublaunch the script for the given project, for each platform for which |
| # the project is built, and for Debug and Release configurations. |
| |
| local GX_ARGS=("$@") |
| (( ${GX_DRY_RUN} )) && GX_ARGS+=("--dry-run") |
| (( ${GX_DEBUG} )) && { for n in $(seq $GX_DEBUG); do GX_ARGS+=("--debug"); done; } |
| (( ${GX_QUIET} )) && GX_ARGS+=("--quiet") |
| |
| local GX_SDK_NAME |
| get_sdk_name "${GX_PLATFORM_NAME}" GX_SDK_NAME |
| |
| log_debug "Sublaunching for: ${GX_PROJECT_TAG}/${GX_PLATFORM_NAME}/${GX_CONFIGURATION}" |
| |
| local GX_XCODE_PARAMETERS=( |
| -project "${GX_PS_PROJECT_FILE_PATH}" |
| -sdk "${GX_SDK_NAME}" |
| -configuration "${GX_CONFIGURATION}" |
| -target "Apply Configuration to XCFileLists" |
| ) |
| |
| if (( ${GX_USE_WEBKITBUILD_BUILD_OUTPUT} )) |
| then |
| local GX_WEBKITBUILD_DIR="${WEBKIT_OUTPUTDIR:-${GX_OPENSOURCE_DIR}/WebKitBuild}" |
| [[ -d "${GX_WEBKITBUILD_DIR}" ]] || die "${GX_WEBKITBUILD_DIR} does not exist." |
| |
| GX_XCODE_PARAMETERS+=( |
| SYMROOT="${GX_WEBKITBUILD_DIR}" |
| OBJROOT="${GX_WEBKITBUILD_DIR}" |
| SHARED_PRECOMPS_DIR="${GX_WEBKITBUILD_DIR}/PrecompiledHeaders" |
| ) |
| fi |
| |
| if (( $GX_DEBUG > 0 )) |
| then |
| WK_SUBLAUNCH_SCRIPT_PARAMETERS=("${GX_ARGS[@]}") xcodebuild "${GX_XCODE_PARAMETERS[@]}" |
| else |
| WK_SUBLAUNCH_SCRIPT_PARAMETERS=("${GX_ARGS[@]}") xcodebuild "${GX_XCODE_PARAMETERS[@]}" | grep '^\.\.\. ' |
| fi |
| |
| local GX_RESULT=${PIPESTATUS[0]} |
| (( ${GX_RESULT} )) && die "Error sub-launching under xcode: error = ${GX_RESULT}" |
| } |
| |
| |
| function reset_project_specific_temp_files() |
| { |
| log_callstack_and_parameters "$@" |
| |
| create_empty_files \ |
| "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" \ |
| "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH}" |
| } |
| |
| |
| function generate_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| reset_project_specific_temp_files |
| |
| for_each_platform \ |
| for_each_configuration \ |
| sublaunch_under_xcode \ |
| "${GX_SUBEXECUTE_SCRIPT}" subgenerate --nocleanup --project "${GX_PROJECT_TAG}" |
| } |
| |
| |
| function merge_xcfilelists_helper() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_SOURCE="$1" |
| local GX_DEST="$2" |
| local GX_ADDITIONS="${GX_TEMP}/diff_added.tmp" |
| |
| append_xcfilelist_header "${GX_SOURCE}" |
| sort_and_unique_in_place "${GX_SOURCE}" |
| |
| find_additions "${GX_SOURCE}" "${GX_DEST}" "${GX_ADDITIONS}" |
| |
| if [[ -s "${GX_ADDITIONS}" ]] |
| then |
| cat "${GX_SOURCE}" >> "${GX_DEST}" |
| sort_and_unique_in_place "${GX_DEST}" |
| return 0 |
| fi |
| |
| return 1 |
| } |
| |
| |
| function merge_derivedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| log_debug "Merging ${GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH} into ${GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| log_debug "Merging ${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH} into ${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| |
| if (( ! ${GX_DRY_RUN} )) |
| then |
| merge_xcfilelists_helper "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH}" && GX_DEFERRED_EXIT_CODE=3 |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| |
| merge_xcfilelists_helper "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH}" && GX_DEFERRED_EXIT_CODE=3 |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| fi |
| } |
| |
| |
| function merge_unifiedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| log_debug "Merging ${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH} into ${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH}" |
| |
| if (( ! ${GX_DRY_RUN} )) |
| then |
| merge_xcfilelists_helper "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH}" && GX_DEFERRED_EXIT_CODE=3 |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| fi |
| } |
| |
| |
| function merge_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| invoke_each_action "${GX_MERGE_ACTIONS[@]}" |
| |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| } |
| |
| |
| function check_xcfilelists_helper() |
| { |
| log_callstack_and_parameters "$@" |
| |
| local GX_NEW="$1" |
| local GX_ORIG="$2" |
| local GX_ADDITIONS="${GX_TEMP}/diff_added.tmp" |
| |
| log_debug "Checking ${GX_NEW} against ${GX_ORIG}" |
| |
| find_additions "${GX_NEW}" "${GX_ORIG}" "${GX_ADDITIONS}" |
| |
| if [[ -s "${GX_ADDITIONS}" ]] |
| then |
| log_progress |
| log_progress "------------------------------------------------------------------------------" |
| log_progress "Found added files for ${GX_ORIG}:" |
| log_progress "------------------------------------------------------------------------------" |
| |
| local GX_LINE |
| while IFS='' read -r GX_LINE |
| do |
| log_progress "${GX_LINE}" |
| done < "${GX_ADDITIONS}" |
| |
| log_progress "------------------------------------------------------------------------------" |
| |
| GX_DEFERRED_EXIT_CODE=2 |
| fi |
| } |
| |
| |
| function check_derivedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| check_xcfilelists_helper "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_INPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| check_xcfilelists_helper "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_OUTPUT_DERIVED_XCFILELIST_PROJECT_PATH}" |
| } |
| |
| |
| function check_unifiedsources_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| check_xcfilelists_helper "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_TEMP_PATH}" "${GX_OUTPUT_UNIFIED_XCFILELIST_PROJECT_PATH}" |
| } |
| |
| |
| function check_xcfilelists() |
| { |
| log_callstack_and_parameters "$@" |
| |
| invoke_each_action "${GX_CHECK_ACTIONS[@]}" |
| } |
| |
| |
| function report_merge_results() |
| { |
| log_callstack_and_parameters "$@" |
| |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| |
| if (( ${GX_DEFERRED_EXIT_CODE} )) |
| then |
| log_progress |
| |
| local GX_MESSAGE='".xcfilelist" files tell the build system what files |
| are consumed and produced by the "Run Script" build phases in |
| Xcode. At least one of these .xcfilelist files was out of date and |
| has been updated. You now need to restart your build.' |
| |
| log_progress_long "${GX_MESSAGE}" |
| fi |
| } |
| |
| |
| function report_remediation_steps() |
| { |
| log_callstack_and_parameters "$@" |
| |
| if (( ${GX_DEFERRED_EXIT_CODE} )) |
| then |
| log_progress |
| |
| # We can either be called from within an xcodebuild context (meaning |
| # that we are being called during a build to validate the .xcfilelists |
| # for the current build configuration) or from the command line (to |
| # validate all .xcfilelists). We'll determine which of these is the |
| # case by checking $GX_PROJECT_TAG (which will have been set via the |
| # --project <TAG> option passed in to us when we're invoked in this |
| # context). |
| # |
| # Further, if called from within xcodebuild, it's important to know if |
| # we're being called from within Xcode or being invoked by a Makefile. |
| # If the former, the output/build files we are looking for are found in |
| # ~/Library/Developer/Xcode/DerivedData. Otherwise, they'll be found in |
| # OpenSource/WebKitBuild (or whatever $WEBKIT_OUTPUTDIR points to). We |
| # need to distinguish between these so that we can tell the user how to |
| # invoke us in a way that finds the right output/build files. |
| # |
| # If invoked from the command line, we really can't tell where the |
| # output files are, so give the user advice in this area. |
| |
| local GX_MESSAGE='".xcfilelist" files tell the build system what files |
| are consumed and produced by the "Run Script" build phases in |
| Xcode. At least one of these .xcfilelist files are out of date and |
| need to be regenerated. Regenerate these files by running |
| `Tools/Scripts/generate-xcfilelists generate' |
| |
| if [[ -n "${GX_PROJECT_TAG}" ]] |
| then |
| local GX_MESSAGE+=" --project ${GX_PROJECT_TAG}" |
| if [[ "${SYMROOT}" =~ Library/Developer/Xcode/DerivedData ]] |
| then |
| local GX_MESSAGE+=" --xcode" |
| fi |
| else |
| if (( ${GX_USE_XCODE_BUILD_OUTPUT} )) |
| then |
| local GX_MESSAGE+=" --xcode" |
| fi |
| fi |
| |
| local GX_MESSAGE+='`, or manually add the file or files shown above to |
| the indicated .xcfilelist files. Then restart your build. When |
| submitting, include the updated .xcfilelist files.' |
| |
| log_progress_long "${GX_MESSAGE}" |
| fi |
| } |
| |
| |
| function do_generate() |
| { |
| # Invoked from the command line to generate .xcfilelist files. Use any |
| # specified project, platform, and/or configuration. Any of those that |
| # aren't specified results in our iterating over all possible values for |
| # the unspecified value. |
| |
| log_callstack_and_parameters "$@" |
| |
| if [[ -z "${GX_PROJECT_TAG}" ]] |
| then |
| log_progress "=== Generating all .xcfilelists ===" |
| else |
| log_progress "=== Generating .xcfilelists for ${GX_PROJECT_TAG} ===" |
| fi |
| |
| for_each_project \ |
| generate_xcfilelists |
| } |
| |
| |
| function do_merge() |
| { |
| # Implicitly invoked for generate and generate-xcode operations to move the |
| # temporary results into the Xcode project. |
| |
| log_callstack_and_parameters "$@" |
| |
| if [[ -z "${GX_PROJECT_TAG}" ]] |
| then |
| log_progress "=== Merging all .xcfilelists into place ===" |
| else |
| log_progress "=== Merging .xcfilelists for ${GX_PROJECT_TAG} ===" |
| fi |
| |
| for_each_project \ |
| merge_xcfilelists |
| |
| log_debug "GX_DEFERRED_EXIT_CODE = $GX_DEFERRED_EXIT_CODE" |
| } |
| |
| |
| function do_check() |
| { |
| # Implicitly invoked for check and check-xcode operations to check the |
| # temporary results against the Xcode project. |
| |
| log_callstack_and_parameters "$@" |
| |
| # Being invoked from the command-line to check everything. |
| |
| if [[ -z "${GX_PROJECT_TAG}" ]] |
| then |
| log_progress "=== Checking all .xcfilelists ===" |
| else |
| log_progress "=== Checking .xcfilelists for ${GX_PROJECT_TAG} ===" |
| fi |
| |
| for_each_project \ |
| check_xcfilelists |
| } |
| |
| |
| function do_subgenerate() |
| { |
| # Invoked from within an Xcode context to generate .xcfilelist files. Use |
| # the project, platform, an configuration established in the environment. |
| |
| log_callstack_and_parameters "$@" |
| |
| [[ -n "${GX_PROJECT_TAG}" ]] || die "GX_PROJECT_TAG is not defined." |
| [[ -n "${PROJECT_NAME}" ]] || die "subgenerate should only be invoked in an Xcode context." |
| |
| log_progress "=== Generating .xcfilelists for ${PROJECT_NAME}/${PLATFORM_NAME}/${CONFIGURATION} ===" |
| |
| set_project_settings |
| |
| # We're called during generate-xcode, check-xcode, and subgenerate |
| # operations. We need to reset our project-specific temp files for the |
| # first two, but not the last one. |
| |
| (( ${GX_DO_SUBGENERATE} )) || reset_project_specific_temp_files |
| |
| subgenerate_xcfilelists |
| } |
| |
| |
| function main() |
| { |
| log_callstack_and_parameters "$@" |
| |
| log_debug_var GX_ME |
| log_debug_var GX_HERE |
| log_debug_var GX_ROOT_DIR |
| log_debug_var GX_OPENSOURCE_DIR |
| log_debug_var GX_TEMP |
| log_debug_var GX_PROJECT_TAGS |
| log_debug_var GX_CONFIGURATIONS |
| log_debug_var GX_SUBEXECUTE_SCRIPT |
| log_debug_var GX_DO_GENERATE |
| log_debug_var GX_DO_GENERATE_XCODE |
| log_debug_var GX_DO_CHECK |
| log_debug_var GX_DO_CHECK_XCODE |
| log_debug_var GX_DO_SUBGENERATE |
| log_debug_var GX_DO_CLEANUP |
| log_debug_var GX_USE_XCODE_BUILD_OUTPUT |
| log_debug_var GX_USE_WEBKITBUILD_BUILD_OUTPUT |
| log_debug_var GX_DRY_RUN |
| log_debug_var GX_DEBUG |
| log_debug_var GX_QUIET |
| log_debug_var GX_ORIG_ARGS |
| |
| if (( ${GX_DO_HELP} )) |
| then |
| usage |
| my_exit 0 |
| fi |
| |
| if (( GX_DO_GENERATE + GX_DO_GENERATE_XCODE + GX_DO_CHECK + GX_DO_CHECK_XCODE + GX_DO_SUBGENERATE + GX_DO_HELP < 1 )) |
| then |
| stderr "### One of generate, generate-xcode, check, check-xcode, subgenerate, or --help must be specified." |
| my_exit 1 |
| fi |
| |
| if (( GX_DO_GENERATE + GX_DO_GENERATE_XCODE + GX_DO_CHECK + GX_DO_CHECK_XCODE + GX_DO_SUBGENERATE + GX_DO_HELP > 1 )) |
| then |
| stderr "### Only one of generate, generate-xcode, check, check-xcode, subgenerate, or --help can be specified." |
| my_exit 1 |
| fi |
| |
| [[ -z "${GX_PROJECT_TAG}" || ( " ${GX_PROJECT_TAGS[@]} " =~ " ${GX_PROJECT_TAG} " ) ]] || { die "Unrecognized project: ${GX_PROJECT_TAG}"; } |
| get_canonical_platform_name "${GX_PLATFORM_NAME}" GX_PLATFORM_NAME |
| get_canonical_configuration "${GX_CONFIGURATION}" GX_CONFIGURATION |
| |
| if (( ${GX_DO_GENERATE} )) |
| then |
| do_generate |
| call post_generate_hook |
| |
| do_merge |
| call post_merge_hook |
| |
| report_merge_results |
| elif (( ${GX_DO_GENERATE_XCODE} )) |
| then |
| do_subgenerate |
| call post_generate_hook |
| |
| do_merge |
| call post_merge_hook |
| |
| report_merge_results |
| elif (( ${GX_DO_CHECK} )) |
| then |
| do_generate |
| call post_generate_hook |
| |
| do_check |
| call post_check_hook |
| |
| report_remediation_steps |
| elif (( ${GX_DO_CHECK_XCODE} )) |
| then |
| do_subgenerate |
| call post_generate_hook |
| |
| do_check |
| call post_check_hook |
| |
| report_remediation_steps |
| elif (( ${GX_DO_SUBGENERATE} )) |
| then |
| do_subgenerate |
| else |
| stderr "### No subcommand provided" |
| usage |
| my_exit 1 |
| fi |
| |
| my_exit ${GX_DEFERRED_EXIT_CODE} |
| } |
| |
| |
| # Initialize and sanity check |
| |
| GX_ORIG_ARGS=("$@") |
| |
| GX_DO_GENERATE=0 |
| GX_DO_GENERATE_XCODE=0 |
| GX_DO_CHECK=0 |
| GX_DO_CHECK_XCODE=0 |
| GX_DO_SUBGENERATE=0 |
| GX_DO_HELP=0 |
| GX_DO_CLEANUP=0 |
| GX_USE_XCODE_BUILD_OUTPUT=0 |
| GX_USE_WEBKITBUILD_BUILD_OUTPUT=1 |
| GX_DRY_RUN=0 |
| GX_DEBUG=0 |
| GX_QUIET=0 |
| |
| GX_DEFERRED_EXIT_CODE=0 |
| GX_PROJECT_TAG= |
| GX_PLATFORM_NAME= |
| GX_CONFIGURATION= |
| GX_SDKS=() |
| |
| GX_ME=$(normalize_file_path "${BASH_SOURCE[0]}") |
| GX_HERE=$(dirname "${GX_ME}") |
| GX_ROOT_DIR=$(normalize_directory_path "${GX_HERE}/../../..") |
| GX_OPENSOURCE_DIR="${GX_ROOT_DIR}/OpenSource" |
| GX_TEMP=$(normalize_directory_path /tmp/generate-xcfilelists) |
| GX_PROJECT_TAGS=(JavaScriptCore WebCore WebKit DumpRenderTree WebKitTestRunner) |
| GX_CONFIGURATIONS=(Release Debug) |
| GX_SUBEXECUTE_SCRIPT="${GX_ME}" |
| |
| [[ -n "${GX_ROOT_DIR}" ]] || die "Could not find GX_ROOT_DIR." |
| [[ -n "${GX_OPENSOURCE_DIR}" ]] || die "Could not find GX_OPENSOURCE_DIR." |
| [[ -d "${GX_ROOT_DIR}" ]] || die "${GX_ROOT_DIR} does not exist." |
| [[ -d "${GX_OPENSOURCE_DIR}" ]] || die "${GX_OPENSOURCE_DIR} does not exist." |
| |
| trap cleanup EXIT |
| |
| ensure_directories_exist "${GX_TEMP}" |
| |
| |
| # Process command-line parameters. |
| |
| while [[ "${1:+x}" ]] |
| do |
| case "${1}" in |
| generate) GX_DO_GENERATE=1 ;; |
| generate-xcode) GX_DO_GENERATE_XCODE=1 ;; |
| check) GX_DO_CHECK=1 ;; |
| check-xcode) GX_DO_CHECK_XCODE=1 ;; |
| subgenerate) GX_DO_SUBGENERATE=1 ;; |
| help) GX_DO_HELP=1 ;; |
| |
| --project) shift; GX_PROJECT_TAG="$1" ;; |
| --platform) shift; GX_PLATFORM_NAME="$1" ;; |
| --configuration)shift; GX_CONFIGURATION="$1" ;; |
| --xcode) GX_USE_XCODE_BUILD_OUTPUT=1; GX_USE_WEBKITBUILD_BUILD_OUTPUT=0 ;; |
| --webkitbuild) GX_USE_XCODE_BUILD_OUTPUT=0; GX_USE_WEBKITBUILD_BUILD_OUTPUT=1 ;; |
| --nocleanup) GX_DO_CLEANUP=0 ;; |
| |
| -n | --dry-run) GX_DRY_RUN=1 ;; |
| -d | --debug) GX_DEBUG=$(( $GX_DEBUG + 1 )) ;; |
| -q | --quiet) GX_QUIET=1 ;; |
| -h | --help) GX_DO_HELP=1 ;; |
| |
| *) stderr "### Unknown command: $1" |
| usage |
| my_exit 1 ;; |
| esac |
| shift |
| done |
| |
| |
| GX_SOURCED=$([[ "$0" == "${BASH_SOURCE[@]}" ]] && echo 0 || echo 1) |
| if (( ! ${GX_SOURCED} )) |
| then |
| GX_INTERNAL_ME="${GX_ROOT_DIR}/Internal/Tools/Scripts/generate-xcfilelists" |
| if [[ -x "${GX_INTERNAL_ME}" ]] |
| then |
| "${GX_INTERNAL_ME}" "${GX_ORIG_ARGS[@]}" |
| else |
| main |
| fi |
| fi |