| #!/usr/bin/env perl | |
| # Copyright (C) 2005-2023 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. | |
| # 3. Neither the name of Apple Inc. ("Apple") nor the names of | |
| # its contributors may be used to endorse or promote products derived | |
| # from this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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. | |
| use strict; | |
| use warnings; | |
| use Cwd qw(realpath); | |
| use File::Basename; | |
| use File::Path qw(make_path); | |
| use File::Spec; | |
| use FindBin; | |
| use lib $FindBin::Bin; | |
| use webkitdirs; | |
| my $programName = basename($0); | |
| my $usage = <<EOF; | |
| Usage: $programName [options] | |
| --[no-]asan Enable or disable clang address sanitizer | |
| --[no-]tsan Enable or disable clang thread sanitizer | |
| --[no-]ubsan Enable or disable clang undefined behavior sanitizer | |
| --[no-]libFuzzer Enable or disable clang libFuzzer | |
| --[no-]coverage Enable or disable LLVM Source-based Code Coverage | |
| --[no-]fuzzilli Enable or disable Fuzzilli support; enabling Fuzzilli | |
| implies disabling clang libFuzzer | |
| --force-optimization-level=<level> Optimization level: O3, O2, O1, O0, Os, Ofast, Og, or none | |
| --lto-mode=<mode> Set LTO mode: full, thin, or none | |
| --debug Set the default configuration to debug | |
| --release Set the default configuration to release | |
| --cmake Build with CMake, into WebKitBuild/cmake-<platform>/<configuration> | |
| --xcode Build with Xcode, into WebKitBuild/<configuration> | |
| --workspace=<workspace> Set the default Xcode workspace to build from | |
| --reset Reset configurations | |
| -h, --help Show this message and exit | |
| EOF | |
| sub printCurrentSettings(); | |
| sub printUsage(); | |
| sub updateOrDeleteConfigurationFile($$$); | |
| my $configuration = passedConfiguration(); | |
| # Read before the isCMakeBuild() call below, which consumes --cmake and --xcode. | |
| my $buildSystem = passedBuildSystem(); | |
| my $enableASAN = checkForArgumentAndRemoveFromARGV("--asan"); | |
| my $disableASAN = checkForArgumentAndRemoveFromARGV("--no-asan"); | |
| my $enableTSAN = checkForArgumentAndRemoveFromARGV("--tsan"); | |
| my $disableTSAN = checkForArgumentAndRemoveFromARGV("--no-tsan"); | |
| my $enableUBSAN = checkForArgumentAndRemoveFromARGV("--ubsan"); | |
| my $disableUBSAN = checkForArgumentAndRemoveFromARGV("--no-ubsan"); | |
| my $enableLibFuzzer = checkForArgumentAndRemoveFromARGV("--libFuzzer"); | |
| my $disableLibFuzzer = checkForArgumentAndRemoveFromARGV("--no-libFuzzer"); | |
| my $enableCoverage = checkForArgumentAndRemoveFromARGV("--coverage"); | |
| my $disableCoverage = checkForArgumentAndRemoveFromARGV("--no-coverage"); | |
| my $enableFuzzilli = checkForArgumentAndRemoveFromARGV("--fuzzilli"); | |
| $enableLibFuzzer = 0 if ($enableFuzzilli); | |
| my $disableFuzzilli = checkForArgumentAndRemoveFromARGV("--no-fuzzilli"); | |
| my $ltoMode; | |
| if (!checkForArgumentAndRemoveFromARGVGettingValue("--lto-mode", \$ltoMode)) { | |
| $ltoMode=""; | |
| } | |
| my $forceOptimizationLevel = passedForceOptimizationLevel(); | |
| my $workspace; | |
| if (!checkForArgumentAndRemoveFromARGVGettingValue("--workspace", \$workspace)) { | |
| $workspace=""; | |
| } | |
| if (checkForArgumentAndRemoveFromARGV("-h") || checkForArgumentAndRemoveFromARGV("--help")) { | |
| printUsage(); | |
| exit 1; | |
| } | |
| my $baseProductDir = baseProductDir(); | |
| # Reset before anything reads a marker file, so that printCurrentSettings() | |
| # below reports the defaults rather than the settings just deleted. | |
| if (checkForArgumentAndRemoveFromARGV("--reset")) { | |
| for my $fileName (qw(ASan BuildSystem BuildSystem.xcconfig Configuration Coverage ForceOptimizationLevel Fuzzilli LibFuzzer LTO TSan UBSan Workspace)) { | |
| unlink File::Spec->catfile($baseProductDir, $fileName); | |
| } | |
| printCurrentSettings(); | |
| exit 0; | |
| } | |
| if (isAppleCocoaWebKit() && !isCMakeBuild()) { | |
| markBaseProductDirectoryAsCreatedByXcodeBuildSystem(); | |
| } else { | |
| make_path($baseProductDir); | |
| } | |
| # Record this even for a CMake build, or a later Xcode build in the same directory would use a stale workspace. | |
| if (isAppleCocoaWebKit() && $workspace) { | |
| open WORKSPACE, ">", "$baseProductDir/Workspace"; | |
| print WORKSPACE realpath($workspace); | |
| close WORKSPACE; | |
| } | |
| if ($enableASAN && $enableTSAN) { | |
| print STDERR "ERROR: Address Sanitizer and Thread Sanitzer can't be enabled together.\n"; | |
| printUsage(); | |
| exit 1; | |
| } | |
| if ($ltoMode && $ltoMode ne "full" && $ltoMode ne "thin" && $ltoMode ne "none") { | |
| printUsage(); | |
| exit 1; | |
| } | |
| if ($forceOptimizationLevel && !isValidForceOptimizationLevel($forceOptimizationLevel)) { | |
| printUsage(); | |
| exit 1; | |
| } | |
| if ($configuration) { | |
| writeBuildSetting("Configuration", $configuration); | |
| } | |
| # Only Apple's Cocoa ports have a choice of build system. | |
| if ($buildSystem && isAppleCocoaWebKit()) { | |
| writeBuildSetting("BuildSystem", $buildSystem); | |
| } | |
| updateOrDeleteConfigurationFile("ASan", $enableASAN, $disableASAN); | |
| updateOrDeleteConfigurationFile("Coverage", $enableCoverage, $disableCoverage); | |
| updateOrDeleteConfigurationFile("Fuzzilli", $enableFuzzilli, $disableFuzzilli); | |
| updateOrDeleteConfigurationFile("TSan", $enableTSAN, $disableTSAN); | |
| updateOrDeleteConfigurationFile("UBSan", $enableUBSAN, $disableUBSAN); | |
| updateOrDeleteConfigurationFile("LibFuzzer", $enableLibFuzzer, $disableLibFuzzer); | |
| if ($forceOptimizationLevel) { | |
| recordForceOptimizationLevel($forceOptimizationLevel); | |
| } | |
| if ($ltoMode) { | |
| open LTO, ">", File::Spec->catfile($baseProductDir, "LTO") or die; | |
| print LTO "$ltoMode"; | |
| close LTO; | |
| } | |
| # Written last, so that it describes every setting recorded above. | |
| recordBuildSystemXcodeConfiguration(); | |
| printCurrentSettings(); | |
| exit 0; | |
| sub printCurrentSettings() | |
| { | |
| my $result = "Current settings:"; | |
| $result .= " Configuration:" . configuration(); | |
| $result .= " BuildSystem:" . buildSystem() if isAppleCocoaWebKit(); | |
| $result .= " ASan" if asanIsEnabled(); | |
| $result .= " TSan" if tsanIsEnabled(); | |
| $result .= " UBSan" if ubsanIsEnabled(); | |
| $result .= " Fuzzilli" if fuzzilliIsEnabled(); | |
| $result .= " LibFuzzer" if libFuzzerIsEnabled(); | |
| $result .= " Coverage" if coverageIsEnabled(); | |
| $result .= " LTOMode:" . ltoMode() if ltoMode(); | |
| $result .= " ForceOptimizationLevel:O" . forceOptimizationLevel() if defined forceOptimizationLevel(); | |
| $result .= " Workspace:" . configuredXcodeWorkspace() if configuredXcodeWorkspace(); | |
| print STDERR $result, "\n"; | |
| } | |
| sub printUsage() | |
| { | |
| print STDERR $usage, "\n"; | |
| printCurrentSettings(); | |
| } | |
| sub updateOrDeleteConfigurationFile($$$) | |
| { | |
| my ($fileName, $shouldEnable, $shouldDisable) = @_; | |
| my $filePath = File::Spec->catfile($baseProductDir, $fileName); | |
| if ($shouldEnable) { | |
| open FILE, ">", $filePath or die; | |
| print FILE "YES"; | |
| close FILE; | |
| } elsif ($shouldDisable) { | |
| unlink $filePath; | |
| } | |
| } |