Rewrite generate-xcfilelists in Python
[WebKit-https.git] / Tools / Scripts / generate-xcfilelists
index 0d86978..042a66c 100755 (executable)
@@ -1,6 +1,7 @@
-#!/bin/bash
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
 #
-# Copyright (C) 2018-2019 Apple Inc.  All rights reserved.
+# Copyright (C) 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
 #
 # 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_".
+# particular, it does this in order to set needed environment variables.
 
+import sys
 
-function stdout()
-{
-    (( ${GX_QUIET} )) || echo "$@" >&1
-}
+from webkitpy.generate_xcfilelists_lib.application import Application
+from webkitpy.port.config import apple_additions
 
-
-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
+if __name__ == "__main__":
+    application_class = apple_additions().get_generate_xcfilelists_application() if apple_additions() else Application
+    sys.exit(application_class(__file__).run())