1 # Copyright (C) 2005, 2006, 2007, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
2 # Copyright (C) 2009 Google Inc. All rights reserved.
3 # Copyright (C) 2011 Research In Motion Limited. All rights reserved.
4 # Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
15 # 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 # its contributors may be used to endorse or promote products derived
17 # from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 # Module to share code to get to WebKit directories.
36 use Digest::MD5 qw(md5_hex);
39 use File::Path qw(mkpath rmtree);
47 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
52 &XcodeOptionStringNoConfig
57 &cmakeBasedPortArguments
63 &printHelpAndExitForRunAndDebugWebKitAppIfNeeded
74 use constant USE_OPEN_COMMAND => 1; # Used in runMacWebKitApp().
75 use constant INCLUDE_OPTIONS_FOR_DEBUGGING => 1;
83 my @baseProductDirOption;
86 my $configurationForVisualStudio;
87 my $configurationProductDir;
89 my $currentSVNRevision;
91 my $iPhoneSimulatorVersion;
100 my $isInspectorFrontend;
102 my $shouldTargetWebProcess;
103 my $shouldUseXPCServiceForWebProcess;
104 my $shouldUseGuardMalloc;
107 # Variables for Win32 support
108 my $programFilesPath;
112 my $windowsSourceDir;
114 my $willUseVCExpressWhenBuilding = 0;
116 # Defined in VCSUtils.
119 sub findMatchingArguments($$);
122 sub determineSourceDir
124 return if $sourceDir;
125 $sourceDir = $FindBin::Bin;
126 $sourceDir =~ s|/+$||; # Remove trailing '/' as we would die later
128 # walks up path checking each directory to see if it is the main WebKit project dir,
129 # defined by containing Sources, WebCore, and WebKit
130 until ((-d "$sourceDir/Source" && -d "$sourceDir/Source/WebCore" && -d "$sourceDir/Source/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
132 if ($sourceDir !~ s|/[^/]+$||) {
133 die "Could not find top level webkit directory above source directory using FindBin.\n";
137 $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
140 sub currentPerlPath()
144 $thisPerl .= $Config{_exe} unless $thisPerl =~ m/$Config{_exe}$/i;
149 # used for scripts which are stored in a non-standard location
155 sub determineXcodeVersion
157 return if defined $xcodeVersion;
158 my $xcodebuildVersionOutput = `xcodebuild -version`;
159 $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : "3.0";
162 sub readXcodeUserDefault($)
164 my ($unprefixedKey) = @_;
166 determineXcodeVersion();
168 my $xcodeDefaultsDomain = (eval "v$xcodeVersion" lt v4) ? "com.apple.Xcode" : "com.apple.dt.Xcode";
169 my $xcodeDefaultsPrefix = (eval "v$xcodeVersion" lt v4) ? "PBX" : "IDE";
170 my $devnull = File::Spec->devnull();
172 my $value = `defaults read $xcodeDefaultsDomain ${xcodeDefaultsPrefix}${unprefixedKey} 2> ${devnull}`;
179 sub determineBaseProductDir
181 return if defined $baseProductDir;
182 determineSourceDir();
184 my $setSharedPrecompsDir;
185 $baseProductDir = $ENV{"WEBKIT_OUTPUTDIR"};
187 if (!defined($baseProductDir) and isAppleMacWebKit()) {
188 # Silently remove ~/Library/Preferences/xcodebuild.plist which can
189 # cause build failure. The presence of
190 # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from
191 # respecting global settings such as a custom build products directory
192 # (<rdar://problem/5585899>).
193 my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist";
194 if (-e $personalPlistFile) {
195 unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!";
198 determineXcodeVersion();
200 if (eval "v$xcodeVersion" ge v4) {
201 my $buildLocationStyle = join '', readXcodeUserDefault("BuildLocationStyle");
202 if ($buildLocationStyle eq "Custom") {
203 my $buildLocationType = join '', readXcodeUserDefault("CustomBuildLocationType");
204 # FIXME: Read CustomBuildIntermediatesPath and set OBJROOT accordingly.
205 $baseProductDir = readXcodeUserDefault("CustomBuildProductsPath") if $buildLocationType eq "Absolute";
208 # DeterminedByTargets corresponds to a setting of "Legacy" in Xcode.
209 # It is the only build location style for which SHARED_PRECOMPS_DIR is not
210 # overridden when building from within Xcode.
211 $setSharedPrecompsDir = 1 if $buildLocationStyle ne "DeterminedByTargets";
214 if (!defined($baseProductDir)) {
215 $baseProductDir = join '', readXcodeUserDefault("ApplicationwideBuildSettings");
216 $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
219 undef $baseProductDir unless $baseProductDir =~ /^\//;
222 if (!defined($baseProductDir)) { # Port-specific checks failed, use default
223 $baseProductDir = "$sourceDir/WebKitBuild";
226 if (isGit() && isGitBranchBuild()) {
227 my $branch = gitBranch();
228 $baseProductDir = "$baseProductDir/$branch";
231 if (isAppleMacWebKit()) {
232 $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
233 $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
234 $baseProductDir =~ s|^~/|$ENV{HOME}/|;
235 die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
236 die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
237 @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir");
238 push(@baseProductDirOption, "SHARED_PRECOMPS_DIR=${baseProductDir}/PrecompiledHeaders") if $setSharedPrecompsDir;
242 my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
244 $ENV{"WEBKIT_OUTPUTDIR"} = $dosBuildPath;
245 my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
246 chomp $unixBuildPath;
247 $baseProductDir = $unixBuildPath;
251 sub setBaseProductDir($)
253 ($baseProductDir) = @_;
256 sub determineConfiguration
258 return if defined $configuration;
259 determineBaseProductDir();
260 if (open CONFIGURATION, "$baseProductDir/Configuration") {
261 $configuration = <CONFIGURATION>;
264 if ($configuration) {
265 chomp $configuration;
266 # compatibility for people who have old Configuration files
267 $configuration = "Release" if $configuration eq "Deployment";
268 $configuration = "Debug" if $configuration eq "Development";
270 $configuration = "Release";
273 if ($configuration && isWinCairo()) {
274 unless ($configuration =~ /_WinCairo$/) {
275 $configuration .= "_WinCairo";
280 sub determineArchitecture
282 return if defined $architecture;
283 # make sure $architecture is defined in all cases
286 determineBaseProductDir();
289 if (isAppleMacWebKit()) {
290 if (open ARCHITECTURE, "$baseProductDir/Architecture") {
291 $architecture = <ARCHITECTURE>;
297 if (not defined $xcodeSDK or $xcodeSDK =~ /^(\/$|macosx)/) {
298 my $supports64Bit = `sysctl -n hw.optional.x86_64`;
299 chomp $supports64Bit;
300 $architecture = 'x86_64' if $supports64Bit;
301 } elsif ($xcodeSDK =~ /^iphonesimulator/) {
302 $architecture = 'x86_64';
303 } elsif ($xcodeSDK =~ /^iphoneos/) {
304 $architecture = 'armv7';
307 } elsif (isEfl() || isGtk()) {
308 my $host_processor = "";
309 $host_processor = `cmake --system-information | grep CMAKE_SYSTEM_PROCESSOR`;
310 if ($host_processor =~ m/^CMAKE_SYSTEM_PROCESSOR \"([^"]+)\"/) {
311 # We have a configured build tree; use it.
313 $architecture = 'x86_64' if $architecture eq 'amd64';
317 if (!$architecture && (isGtk() || isAppleMacWebKit() || isEfl())) {
318 # Fall back to output of `arch', if it is present.
319 $architecture = `arch`;
323 if (!$architecture && (isGtk() || isAppleMacWebKit() || isEfl())) {
324 # Fall back to output of `uname -m', if it is present.
325 $architecture = `uname -m`;
329 $architecture = 'x86_64' if ($architecture =~ /amd64/ && isBSD());
332 sub determineNumberOfCPUs
334 return if defined $numberOfCPUs;
335 if (defined($ENV{NUMBER_OF_PROCESSORS})) {
336 $numberOfCPUs = $ENV{NUMBER_OF_PROCESSORS};
337 } elsif (isLinux()) {
338 # First try the nproc utility, if it exists. If we get no
339 # results fall back to just interpretting /proc directly.
340 chomp($numberOfCPUs = `nproc --all 2> /dev/null`);
341 if ($numberOfCPUs eq "") {
342 $numberOfCPUs = (grep /processor/, `cat /proc/cpuinfo`);
344 } elsif (isWindows() || isCygwin()) {
346 $numberOfCPUs = `ls /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor | wc -w`;
347 } elsif (isDarwin() || isBSD()) {
348 chomp($numberOfCPUs = `sysctl -n hw.ncpu`);
352 sub determineMaxCPULoad
354 return if defined $maxCPULoad;
355 if (defined($ENV{MAX_CPU_LOAD})) {
356 $maxCPULoad = $ENV{MAX_CPU_LOAD};
362 my ($productDir) = @_;
364 $jscName .= "_debug" if configuration() eq "Debug_All";
365 $jscName .= ".exe" if (isWindows() || isCygwin());
366 return "$productDir/$jscName" if -e "$productDir/$jscName";
367 return "$productDir/JavaScriptCore.framework/Resources/$jscName";
370 sub argumentsForConfiguration()
372 determineConfiguration();
373 determineArchitecture();
376 push(@args, '--debug') if ($configuration =~ "^Debug");
377 push(@args, '--release') if ($configuration =~ "^Release");
378 push(@args, '--32-bit') if ($architecture ne "x86_64" and !isWin64());
379 push(@args, '--64-bit') if (isWin64());
380 push(@args, '--gtk') if isGtk();
381 push(@args, '--efl') if isEfl();
382 push(@args, '--wincairo') if isWinCairo();
383 push(@args, '--wince') if isWinCE();
384 push(@args, '--inspector-frontend') if isInspectorFrontend();
388 sub determineXcodeSDK
390 return if defined $xcodeSDK;
392 if (checkForArgumentAndRemoveFromARGVGettingValue("--sdk", \$sdk)) {
394 } elsif (checkForArgumentAndRemoveFromARGV("--device")) {
395 $xcodeSDK = 'iphoneos.internal';
396 } elsif (checkForArgumentAndRemoveFromARGV("--sim") ||
397 checkForArgumentAndRemoveFromARGV("--simulator")) {
398 $xcodeSDK = 'iphonesimulator';
408 sub xcodeSDKPlatformName()
411 return "" if !defined $xcodeSDK;
412 return "iphoneos" if $xcodeSDK =~ /iphoneos/i;
413 return "iphonesimulator" if $xcodeSDK =~ /iphonesimulator/i;
414 return "macosx" if $xcodeSDK =~ /macosx/i;
415 die "Couldn't determine platform name from Xcode SDK";
422 die "Can't find the SDK path because no Xcode SDK was specified" if not $xcodeSDK;
424 my $sdkPath = `xcrun --sdk $xcodeSDK --show-sdk-path` if $xcodeSDK;
425 die 'Failed to get SDK path from xcrun' if $?;
434 return $programFilesPath if defined $programFilesPath;
436 $programFilesPath = $ENV{'PROGRAMFILES(X86)'} || $ENV{'PROGRAMFILES'} || "C:\\Program Files";
438 return $programFilesPath;
441 sub visualStudioInstallDir
443 return $vsInstallDir if defined $vsInstallDir;
445 if ($ENV{'VSINSTALLDIR'}) {
446 $vsInstallDir = $ENV{'VSINSTALLDIR'};
447 $vsInstallDir =~ s|[\\/]$||;
449 $vsInstallDir = File::Spec->catdir(programFilesPath(), "Microsoft Visual Studio 12.0");
451 chomp($vsInstallDir = `cygpath "$vsInstallDir"`) if isCygwin();
453 return $vsInstallDir;
456 sub visualStudioVersion
458 return $vsVersion if defined $vsVersion;
460 my $installDir = visualStudioInstallDir();
462 $vsVersion = ($installDir =~ /Microsoft Visual Studio ([0-9]+\.[0-9]*)/) ? $1 : "12";
467 sub determineConfigurationForVisualStudio
469 return if defined $configurationForVisualStudio;
470 determineConfiguration();
471 # FIXME: We should detect when Debug_All or Production has been chosen.
472 $configurationForVisualStudio = $configuration . (isWin64() ? "|x64" : "|Win32");
475 sub usesPerConfigurationBuildDirectory
477 # [Gtk] We don't have Release/Debug configurations in straight
478 # autotool builds (non build-webkit). In this case and if
479 # WEBKIT_OUTPUTDIR exist, use that as our configuration dir. This will
480 # allows us to run run-webkit-tests without using build-webkit.
481 return ($ENV{"WEBKIT_OUTPUTDIR"} && isGtk()) || isAppleWinWebKit();
484 sub determineConfigurationProductDir
486 return if defined $configurationProductDir;
487 determineBaseProductDir();
488 determineConfiguration();
489 if (isAppleWinWebKit() || isWinCairo()) {
490 my $binDir = isWin64() ? "bin64" : "bin32";
491 $configurationProductDir = File::Spec->catdir($baseProductDir, $configuration, $binDir);
493 if (usesPerConfigurationBuildDirectory()) {
494 $configurationProductDir = "$baseProductDir";
496 $configurationProductDir = "$baseProductDir/$configuration";
497 $configurationProductDir .= "-" . xcodeSDKPlatformName() if isIOSWebKit();
502 sub setConfigurationProductDir($)
504 ($configurationProductDir) = @_;
507 sub determineCurrentSVNRevision
509 # We always update the current SVN revision here, and leave the caching
510 # to currentSVNRevision(), so that changes to the SVN revision while the
511 # script is running can be picked up by calling this function again.
512 determineSourceDir();
513 $currentSVNRevision = svnRevisionForDirectory($sourceDir);
514 return $currentSVNRevision;
520 determineSourceDir();
521 chdir $sourceDir or die;
526 determineBaseProductDir();
527 return $baseProductDir;
532 determineSourceDir();
538 determineConfigurationProductDir();
539 return $configurationProductDir;
544 my $productDir = productDir();
545 $productDir .= "/bin" if (isEfl() || isGtk());
552 determineConfiguration();
553 return $configuration;
556 sub configurationForVisualStudio()
558 determineConfigurationForVisualStudio();
559 return $configurationForVisualStudio;
562 sub currentSVNRevision
564 determineCurrentSVNRevision() if not defined $currentSVNRevision;
565 return $currentSVNRevision;
570 determineGenerateDsym();
571 return $generateDsym;
574 sub determineGenerateDsym()
576 return if defined($generateDsym);
577 $generateDsym = checkForArgumentAndRemoveFromARGV("--dsym");
580 sub argumentsForXcode()
583 push @args, "DEBUG_INFORMATION_FORMAT=dwarf-with-dsym" if generateDsym();
589 determineBaseProductDir();
590 determineConfiguration();
591 determineArchitecture();
594 my @sdkOption = ($xcodeSDK ? "SDKROOT=$xcodeSDK" : ());
595 my @architectureOption = ($architecture ? "ARCHS=$architecture" : ());
597 return (@baseProductDirOption, "-configuration", $configuration, @architectureOption, @sdkOption, argumentsForXcode());
600 sub XcodeOptionString
602 return join " ", XcodeOptions();
605 sub XcodeOptionStringNoConfig
607 return join " ", @baseProductDirOption;
610 sub XcodeCoverageSupportOptions()
612 my @coverageSupportOptions = ();
613 push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES";
614 push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES";
615 return @coverageSupportOptions;
618 my $passedConfiguration;
619 my $searchedForPassedConfiguration;
620 sub determinePassedConfiguration
622 return if $searchedForPassedConfiguration;
623 $searchedForPassedConfiguration = 1;
624 $passedConfiguration = undef;
626 if (checkForArgumentAndRemoveFromARGV("--debug")) {
627 $passedConfiguration = "Debug";
628 } elsif(checkForArgumentAndRemoveFromARGV("--release")) {
629 $passedConfiguration = "Release";
630 } elsif (checkForArgumentAndRemoveFromARGV("--profile") || checkForArgumentAndRemoveFromARGV("--profiling")) {
631 $passedConfiguration = "Profiling";
634 $passedConfiguration .= "_WinCairo" if (defined($passedConfiguration) && isWinCairo() && isCygwin());
637 sub passedConfiguration
639 determinePassedConfiguration();
640 return $passedConfiguration;
647 if (my $config = shift @_) {
648 $configuration = $config;
652 determinePassedConfiguration();
653 $configuration = $passedConfiguration if $passedConfiguration;
657 my $passedArchitecture;
658 my $searchedForPassedArchitecture;
659 sub determinePassedArchitecture
661 return if $searchedForPassedArchitecture;
662 $searchedForPassedArchitecture = 1;
664 $passedArchitecture = undef;
665 if (checkForArgumentAndRemoveFromARGV("--32-bit")) {
666 if (isAppleMacWebKit()) {
667 # PLATFORM_IOS: Don't run `arch` command inside Simulator environment
669 delete $ENV{DYLD_ROOT_PATH};
670 delete $ENV{DYLD_FRAMEWORK_PATH};
672 $passedArchitecture = `arch`;
673 chomp $passedArchitecture;
678 sub passedArchitecture
680 determinePassedArchitecture();
681 return $passedArchitecture;
686 determineArchitecture();
687 return $architecture;
692 determineNumberOfCPUs();
693 return $numberOfCPUs;
698 determineMaxCPULoad();
704 if (my $arch = shift @_) {
705 $architecture = $arch;
709 determinePassedArchitecture();
710 $architecture = $passedArchitecture if $passedArchitecture;
713 sub skipSafariExecutableEntitlementChecks
715 return `defaults read /Library/Preferences/org.webkit.BuildConfiguration SkipSafariExecutableEntitlementChecks 2>/dev/null` eq "1\n";
718 sub executableHasEntitlements
720 my $executablePath = shift;
721 return (`codesign -d --entitlements - $executablePath 2>&1` =~ /<key>/);
724 sub safariPathFromSafariBundle
726 my ($safariBundle) = @_;
728 if (isAppleMacWebKit()) {
729 my $safariPath = "$safariBundle/Contents/MacOS/Safari";
730 return $safariPath if skipSafariExecutableEntitlementChecks();
732 my $safariForWebKitDevelopmentPath = "$safariBundle/Contents/MacOS/SafariForWebKitDevelopment";
733 return $safariForWebKitDevelopmentPath if -f $safariForWebKitDevelopmentPath && executableHasEntitlements($safariPath);
737 return $safariBundle if isAppleWinWebKit();
740 sub installedSafariPath
744 if (isAppleMacWebKit()) {
745 $safariBundle = "/Applications/Safari.app";
746 } elsif (isAppleWinWebKit()) {
747 $safariBundle = readRegistryString("/HKLM/SOFTWARE/Apple Inc./Safari/InstallDir");
748 $safariBundle =~ s/[\r\n]+$//;
749 $safariBundle = `cygpath -u '$safariBundle'` if isCygwin();
750 $safariBundle =~ s/[\r\n]+$//;
751 $safariBundle .= "Safari.exe";
754 return safariPathFromSafariBundle($safariBundle);
760 # Use WEBKIT_SAFARI environment variable if present.
761 my $safariBundle = $ENV{WEBKIT_SAFARI};
762 if (!$safariBundle) {
763 determineConfigurationProductDir();
764 # Use Safari.app in product directory if present (good for Safari development team).
765 if (isAppleMacWebKit() && -d "$configurationProductDir/Safari.app") {
766 $safariBundle = "$configurationProductDir/Safari.app";
767 } elsif (isAppleWinWebKit()) {
768 my $path = "$configurationProductDir/Safari.exe";
769 my $debugPath = "$configurationProductDir/Safari_debug.exe";
771 if (configuration() eq "Debug_All" && -x $debugPath) {
772 $safariBundle = $debugPath;
774 $safariBundle = $path;
777 if (!$safariBundle) {
778 return installedSafariPath();
781 my $safariPath = safariPathFromSafariBundle($safariBundle);
782 die "Can't find executable at $safariPath.\n" if isAppleMacWebKit() && !-x $safariPath;
786 sub builtDylibPathForName
788 my $libraryName = shift;
789 determineConfigurationProductDir();
792 # WebKitGTK+ for GTK2, WebKitGTK+ for GTK3, and WebKit2 respectively.
793 my @libraries = ("libwebkitgtk-1.0", "libwebkitgtk-3.0", "libwebkit2gtk-3.0");
794 my $extension = isDarwin() ? ".dylib" : ".so";
795 my $builtLibraryPath = "$configurationProductDir/lib/";
797 foreach $libraryName (@libraries) {
798 my $libraryPath = "$builtLibraryPath" . $libraryName . $extension;
799 return $libraryPath if -e $libraryPath;
805 return "$configurationProductDir/lib/libewebkit2.so";
807 return "$configurationProductDir/lib/libewebkit.so";
810 return "$configurationProductDir/$libraryName";
813 return "$configurationProductDir/$libraryName.framework/$libraryName";
815 if (isAppleMacWebKit()) {
816 return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName";
818 if (isAppleWinWebKit()) {
819 if ($libraryName eq "JavaScriptCore") {
820 return "$baseProductDir/lib/$libraryName.lib";
822 return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib";
826 die "Unsupported platform, can't determine built library locations.\nTry `build-webkit --help` for more information.\n";
829 # Check to see that all the frameworks are built.
830 sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework.
832 return if isCygwin() || isWindows();
833 my @frameworks = ("JavaScriptCore", "WebCore");
834 push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days.
835 for my $framework (@frameworks) {
836 my $path = builtDylibPathForName($framework);
837 die "Can't find built framework at \"$path\".\n" unless -e $path;
841 sub isInspectorFrontend()
843 determineIsInspectorFrontend();
844 return $isInspectorFrontend;
847 sub determineIsInspectorFrontend()
849 return if defined($isInspectorFrontend);
850 $isInspectorFrontend = checkForArgumentAndRemoveFromARGV("--inspector-frontend");
856 my $devnull = File::Spec->devnull();
857 return `$command --version 2> $devnull`;
860 sub checkForArgumentAndRemoveFromARGV($)
862 my $argToCheck = shift;
863 return checkForArgumentAndRemoveFromArrayRef($argToCheck, \@ARGV);
866 sub checkForArgumentAndRemoveFromArrayRefGettingValue($$$)
868 my ($argToCheck, $valueRef, $arrayRef) = @_;
869 my $argumentStartRegEx = qr#^$argToCheck(?:=\S|$)#;
871 for (; $i < @$arrayRef; ++$i) {
872 last if $arrayRef->[$i] =~ $argumentStartRegEx;
874 if ($i >= @$arrayRef) {
875 return $$valueRef = undef;
877 my ($key, $value) = split("=", $arrayRef->[$i]);
878 splice(@$arrayRef, $i, 1);
879 if (defined($value)) {
880 # e.g. --sdk=iphonesimulator
881 return $$valueRef = $value;
883 return $$valueRef = splice(@$arrayRef, $i, 1); # e.g. --sdk iphonesimulator
886 sub checkForArgumentAndRemoveFromARGVGettingValue($$)
888 my ($argToCheck, $valueRef) = @_;
889 return checkForArgumentAndRemoveFromArrayRefGettingValue($argToCheck, $valueRef, \@ARGV);
892 sub findMatchingArguments($$)
894 my ($argToCheck, $arrayRef) = @_;
896 foreach my $index (0 .. $#$arrayRef) {
897 my $opt = $$arrayRef[$index];
898 if ($opt =~ /^$argToCheck$/i ) {
899 push(@matchingIndices, $index);
902 return @matchingIndices;
907 my ($argToCheck, $arrayRef) = @_;
908 my @matchingIndices = findMatchingArguments($argToCheck, $arrayRef);
909 return scalar @matchingIndices > 0;
912 sub checkForArgumentAndRemoveFromArrayRef
914 my ($argToCheck, $arrayRef) = @_;
915 my @indicesToRemove = findMatchingArguments($argToCheck, $arrayRef);
916 my $removeOffset = 0;
917 foreach my $index (@indicesToRemove) {
918 splice(@$arrayRef, $index - $removeOffset++, 1);
920 return scalar @indicesToRemove > 0;
925 if (defined($isWK2)) {
928 if (checkForArgumentAndRemoveFromARGV("-2")) {
938 return if defined($isEfl);
939 $isEfl = checkForArgumentAndRemoveFromARGV("--efl");
950 return if defined($isGtk);
951 $isGtk = checkForArgumentAndRemoveFromARGV("--gtk");
966 sub determineIsWinCE()
968 return if defined($isWinCE);
969 $isWinCE = checkForArgumentAndRemoveFromARGV("--wince");
972 # Determine if this is debian, ubuntu, linspire, or something similar.
975 return -e "/etc/debian_version";
980 return -e "/etc/fedora-release";
985 determineIsWinCairo();
989 sub determineIsWinCairo()
991 return if defined($isWinCairo);
992 $isWinCairo = checkForArgumentAndRemoveFromARGV("--wincairo");
1001 sub determineIsWin64()
1003 return if defined($isWin64);
1004 $isWin64 = checkForArgumentAndRemoveFromARGV("--64-bit");
1009 return ($^O eq "cygwin") || 0;
1014 return isWindows() || isCygwin();
1017 sub determineWinVersion()
1019 return if $winVersion;
1021 if (!isAnyWindows()) {
1026 my $versionString = `cmd /c ver`;
1027 $versionString =~ /(\d)\.(\d)\.(\d+)/;
1038 determineWinVersion();
1044 return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 1 && winVersion()->{build} == 7600;
1047 sub isWindowsVista()
1049 return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 0;
1054 return isAnyWindows() && winVersion()->{major} == 5 && winVersion()->{minor} == 1;
1059 return ($^O eq "darwin") || 0;
1064 return ($^O eq "MSWin32") || 0;
1069 return ($^O eq "linux") || 0;
1074 return ($^O eq "freebsd") || ($^O eq "openbsd") || ($^O eq "netbsd") || 0;
1079 return ($Config{archname} =~ /^arm[v\-]/) || ($Config{archname} =~ /^aarch64[v\-]/);
1082 sub isCrossCompilation()
1085 $compiler = $ENV{'CC'} if (defined($ENV{'CC'}));
1086 if ($compiler =~ /gcc/) {
1087 my $compiler_options = `$compiler -v 2>&1`;
1088 my @host = $compiler_options =~ m/--host=(.*?)\s/;
1089 my @target = $compiler_options =~ m/--target=(.*?)\s/;
1091 return ($host[0] ne "" && $target[0] ne "" && $host[0] ne $target[0]);
1098 return isAppleMacWebKit() || isAppleWinWebKit();
1101 sub isAppleMacWebKit()
1103 return isDarwin() && !isGtk();
1106 sub isAppleWinWebKit()
1108 return (isCygwin() || isWindows()) && !isWinCairo() && !isGtk() && !isWinCE();
1111 sub willUseIOSDeviceSDKWhenBuilding()
1113 return xcodeSDKPlatformName() eq "iphoneos";
1116 sub willUseIOSSimulatorSDKWhenBuilding()
1118 return xcodeSDKPlatformName() eq "iphonesimulator";
1123 determineXcodeSDK();
1124 return isAppleMacWebKit() && (willUseIOSDeviceSDKWhenBuilding() || willUseIOSSimulatorSDKWhenBuilding());
1127 sub isPerianInstalled()
1129 if (!isAppleWebKit()) {
1133 if (-d "/Library/QuickTime/Perian.component") {
1137 if (-d "$ENV{HOME}/Library/QuickTime/Perian.component") {
1144 sub determineIPhoneSimulatorVersion()
1146 return if $iPhoneSimulatorVersion;
1148 if (!isIOSWebKit()) {
1149 $iPhoneSimulatorVersion = -1;
1153 my $version = `/usr/local/bin/psw_vers -productVersion`;
1154 my @splitVersion = split(/\./, $version);
1155 @splitVersion >= 2 or die "Invalid version $version";
1156 $iPhoneSimulatorVersion = {
1157 "major" => $splitVersion[0],
1158 "minor" => $splitVersion[1],
1159 "subminor" => defined($splitVersion[2] ? $splitVersion[2] : 0),
1163 sub iPhoneSimulatorVersion()
1165 determineIPhoneSimulatorVersion();
1166 return $iPhoneSimulatorVersion;
1169 sub determineNmPath()
1173 if (isAppleMacWebKit()) {
1174 $nmPath = `xcrun -find nm`;
1177 $nmPath = "nm" if !$nmPath;
1186 sub determineOSXVersion()
1188 return if $osXVersion;
1195 my $version = `sw_vers -productVersion`;
1196 my @splitVersion = split(/\./, $version);
1197 @splitVersion >= 2 or die "Invalid version $version";
1199 "major" => $splitVersion[0],
1200 "minor" => $splitVersion[1],
1201 "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
1207 determineOSXVersion();
1213 return isDarwin() && osXVersion()->{"minor"} == 6;
1218 return isDarwin() && osXVersion()->{"minor"} == 7;
1223 return $ENV{'OS'} eq 'Windows_NT';
1226 sub shouldTargetWebProcess
1228 determineShouldTargetWebProcess();
1229 return $shouldTargetWebProcess;
1232 sub determineShouldTargetWebProcess
1234 return if defined($shouldTargetWebProcess);
1235 $shouldTargetWebProcess = checkForArgumentAndRemoveFromARGV("--target-web-process");
1238 sub shouldUseXPCServiceForWebProcess
1240 determineShouldUseXPCServiceForWebProcess();
1241 return $shouldUseXPCServiceForWebProcess;
1244 sub determineShouldUseXPCServiceForWebProcess
1246 return if defined($shouldUseXPCServiceForWebProcess);
1247 $shouldUseXPCServiceForWebProcess = checkForArgumentAndRemoveFromARGV("--use-web-process-xpc-service");
1252 determineDebugger();
1256 sub determineDebugger
1258 return if defined($debugger);
1260 determineXcodeVersion();
1261 if (eval "v$xcodeVersion" ge v4.5) {
1267 if (checkForArgumentAndRemoveFromARGV("--use-lldb")) {
1271 if (checkForArgumentAndRemoveFromARGV("--use-gdb")) {
1276 sub appendToEnvironmentVariableList
1278 my ($environmentVariableName, $value) = @_;
1280 if (defined($ENV{$environmentVariableName})) {
1281 $ENV{$environmentVariableName} .= ":" . $value;
1283 $ENV{$environmentVariableName} = $value;
1287 sub setUpGuardMallocIfNeeded
1293 if (!defined($shouldUseGuardMalloc)) {
1294 $shouldUseGuardMalloc = checkForArgumentAndRemoveFromARGV("--guard-malloc");
1297 if ($shouldUseGuardMalloc) {
1298 appendToEnvironmentVariableList("DYLD_INSERT_LIBRARIES", "/usr/lib/libgmalloc.dylib");
1302 sub relativeScriptsDir()
1304 my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel($FindBin::Bin, getcwd()), "");
1305 if ($scriptDir eq "") {
1313 my $relativeScriptsPath = relativeScriptsDir();
1314 if (isGtk() || isEfl() || isWinCE()) {
1315 return "$relativeScriptsPath/run-launcher";
1316 } elsif (isAppleWebKit()) {
1317 return "$relativeScriptsPath/run-safari";
1324 return "GtkLauncher";
1325 } elsif (isAppleMacWebKit()) {
1327 } elsif (isAppleWinWebKit()) {
1328 return "WinLauncher";
1330 return "EWebLauncher/MiniBrowser";
1331 } elsif (isWinCE()) {
1332 return "WinCELauncher";
1336 sub checkRequiredSystemConfig
1339 chomp(my $productVersion = `sw_vers -productVersion`);
1340 if (eval "v$productVersion" lt v10.7.5) {
1341 print "*************************************************************\n";
1342 print "Mac OS X Version 10.7.5 or later is required to build WebKit.\n";
1343 print "You have " . $productVersion . ", thus the build will most likely fail.\n";
1344 print "*************************************************************\n";
1346 my $xcodebuildVersionOutput = `xcodebuild -version`;
1347 my $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : undef;
1348 if (!$xcodeVersion || $xcodeVersion && eval "v$xcodeVersion" lt v4.6) {
1349 print "*************************************************************\n";
1350 print "Xcode Version 4.6 or later is required to build WebKit.\n";
1351 print "You have an earlier version of Xcode, thus the build will\n";
1352 print "most likely fail. The latest Xcode is available from the App Store.\n";
1353 print "*************************************************************\n";
1355 } elsif (isGtk() or isEfl() or isWindows()) {
1356 my @cmds = qw(bison gperf flex);
1358 my $oldPath = $ENV{PATH};
1359 foreach my $cmd (@cmds) {
1360 push @missing, $cmd if not commandExists($cmd);
1364 my $list = join ", ", @missing;
1365 die "ERROR: $list missing but required to build WebKit.\n";
1368 # Win32 and other platforms may want to check for minimum config
1371 sub determineWindowsSourceDir()
1373 return if $windowsSourceDir;
1374 $windowsSourceDir = sourceDir();
1375 chomp($windowsSourceDir = `cygpath -w '$windowsSourceDir'`) if isCygwin();
1378 sub windowsSourceDir()
1380 determineWindowsSourceDir();
1381 return $windowsSourceDir;
1384 sub windowsSourceSourceDir()
1386 return windowsSourceDir() . "\\Source";
1389 sub windowsLibrariesDir()
1391 return windowsSourceDir() . "\\WebKitLibraries\\win";
1394 sub windowsOutputDir()
1396 return windowsSourceDir() . "\\WebKitBuild";
1402 my $val = system qw(regtool get), '\\HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\' . $font . ' (TrueType)';
1406 sub checkInstalledTools()
1408 # SVN 1.7.10 is known to be compatible with current servers. SVN 1.8.x seems to be missing some authentication
1409 # protocols we use for svn.webkit.org:
1410 my $svnVersion = `svn --version | grep "\\sversion"`;
1412 if (!$? and $svnVersion =~ /1\.8\./) {
1413 print "svn 1.7.10 is known to be compatible with our servers. You are running $svnVersion,\nwhich may not work properly.\n"
1416 # Python 2.7.3 as shipped by Cygwin prevents the build from completing due to some issue with handling of
1417 # environment variables. Avoid until this is corrected.
1418 my $pythonVer = `python --version 2>&1`;
1419 die "You must have Python installed to build WebKit.\n" if ($?);
1420 die "Python 2.7.3 is not compatible with the WebKit build. Please downgrade to Python 2.6.8.\n" if ($pythonVer =~ /2\.7\.3/);
1422 # MathML requires fonts that do not ship with Windows (at least through Windows 8). Warn the user if they are missing
1423 my @fonts = qw(STIXGeneral-Regular MathJax_Main-Regular);
1425 foreach my $font (@fonts) {
1426 push @missing, $font if not fontExists($font);
1429 if (scalar @missing > 0) {
1430 print "*************************************************************\n";
1431 print "Mathematical fonts, such as STIX and MathJax, are needed to\n";
1432 print "use the MathML feature. You do not appear to have these fonts\n";
1433 print "on your system.\n\n";
1434 print "You can download a suitable set of fonts from the following URL:\n";
1435 print "https://developer.mozilla.org/Mozilla/MathML_Projects/Fonts\n";
1436 print "*************************************************************\n";
1439 print "Installed tools are correct for the WebKit build.\n";
1442 sub setupAppleWinEnv()
1444 return unless isAppleWinWebKit();
1446 checkInstalledTools();
1448 if (isWindowsNT()) {
1449 my $restartNeeded = 0;
1450 my %variablesToSet = ();
1452 # FIXME: We should remove this explicit version check for cygwin once we stop supporting Cygwin 1.7.9 or older versions.
1453 # https://bugs.webkit.org/show_bug.cgi?id=85791
1454 my $uname_version = (POSIX::uname())[2];
1455 $uname_version =~ s/\(.*\)//; # Remove the trailing cygwin version, if any.
1456 if (version->parse($uname_version) < version->parse("1.7.10")) {
1457 # Setting the environment variable 'CYGWIN' to 'tty' makes cygwin enable extra support (i.e., termios)
1458 # for UNIX-like ttys in the Windows console
1459 $variablesToSet{CYGWIN} = "tty" unless $ENV{CYGWIN};
1462 # Those environment variables must be set to be able to build inside Visual Studio.
1463 $variablesToSet{WEBKIT_LIBRARIES} = windowsLibrariesDir() unless $ENV{WEBKIT_LIBRARIES};
1464 $variablesToSet{WEBKIT_OUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKIT_OUTPUTDIR};
1465 $variablesToSet{MSBUILDDISABLENODEREUSE} = "1" unless $ENV{MSBUILDDISABLENODEREUSE};
1467 foreach my $variable (keys %variablesToSet) {
1468 print "Setting the Environment Variable '" . $variable . "' to '" . $variablesToSet{$variable} . "'\n\n";
1469 system qw(regtool -s set), '\\HKEY_CURRENT_USER\\Environment\\' . $variable, $variablesToSet{$variable};
1470 $restartNeeded ||= $variable eq "WEBKIT_LIBRARIES" || $variable eq "WEBKIT_OUTPUTDIR";
1473 if ($restartNeeded) {
1474 print "Please restart your computer before attempting to build inside Visual Studio.\n\n";
1477 if (!defined $ENV{'WEBKIT_LIBRARIES'} || !$ENV{'WEBKIT_LIBRARIES'}) {
1478 print "Warning: You must set the 'WebKit_Libraries' environment variable\n";
1479 print " to be able build WebKit from within Visual Studio 2013 and newer.\n";
1480 print " Make sure that 'WebKit_Libraries' points to the\n";
1481 print " 'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n";
1483 if (!defined $ENV{'WEBKIT_OUTPUTDIR'} || !$ENV{'WEBKIT_OUTPUTDIR'}) {
1484 print "Warning: You must set the 'WebKit_OutputDir' environment variable\n";
1485 print " to be able build WebKit from within Visual Studio 2013 and newer.\n\n";
1487 if (!defined $ENV{'MSBUILDDISABLENODEREUSE'} || !$ENV{'MSBUILDDISABLENODEREUSE'}) {
1488 print "Warning: You should set the 'MSBUILDDISABLENODEREUSE' environment variable to '1'\n";
1489 print " to avoid periodic locked log files when building.\n\n";
1492 # FIXME (125180): Remove the following temporary 64-bit support once official support is available.
1493 if (isWin64() and !$ENV{'WEBKIT_64_SUPPORT'}) {
1494 print "Warning: You must set the 'WEBKIT_64_SUPPORT' environment variable\n";
1495 print " to be able run WebKit or JavaScriptCore tests.\n\n";
1499 sub setupCygwinEnv()
1501 return if !isCygwin() && !isWindows();
1502 return if $vcBuildPath;
1504 my $programFilesPath = programFilesPath();
1505 $vcBuildPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE devenv.com));
1506 if (-e $vcBuildPath) {
1507 # Visual Studio is installed;
1508 if (visualStudioVersion() eq "12") {
1509 $vcBuildPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE devenv.exe));
1512 # Visual Studio not found, try VC++ Express
1513 $vcBuildPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE WDExpress.exe));
1514 if (! -e $vcBuildPath) {
1515 print "*************************************************************\n";
1516 print "Cannot find '$vcBuildPath'\n";
1517 print "Please execute the file 'vcvars32.bat' from\n";
1518 print "'$programFilesPath\\Microsoft Visual Studio 12.0\\VC\\bin\\'\n";
1519 print "to setup the necessary environment variables.\n";
1520 print "*************************************************************\n";
1523 $willUseVCExpressWhenBuilding = 1;
1526 print "Building results into: ", baseProductDir(), "\n";
1527 print "WEBKIT_OUTPUTDIR is set to: ", $ENV{"WEBKIT_OUTPUTDIR"}, "\n";
1528 print "WEBKIT_LIBRARIES is set to: ", $ENV{"WEBKIT_LIBRARIES"}, "\n";
1529 # FIXME (125180): Remove the following temporary 64-bit support once official support is available.
1530 print "WEBKIT_64_SUPPORT is set to: ", $ENV{"WEBKIT_64_SUPPORT"}, "\n" if isWin64();
1533 sub dieIfWindowsPlatformSDKNotInstalled
1535 my $registry32Path = "/proc/registry/";
1536 my $registry64Path = "/proc/registry64/";
1537 my @windowsPlatformSDKRegistryEntries = (
1538 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v8.0A",
1539 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v8.0",
1540 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v7.1A",
1541 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v7.0A",
1542 "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/InstalledSDKs/D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1",
1545 # FIXME: It would be better to detect whether we are using 32- or 64-bit Windows
1546 # and only check the appropriate entry. But for now we just blindly check both.
1547 my $recommendedPlatformSDK = $windowsPlatformSDKRegistryEntries[0];
1549 while (@windowsPlatformSDKRegistryEntries) {
1550 my $windowsPlatformSDKRegistryEntry = shift @windowsPlatformSDKRegistryEntries;
1551 return if (-e $registry32Path . $windowsPlatformSDKRegistryEntry) || (-e $registry64Path . $windowsPlatformSDKRegistryEntry);
1554 print "*************************************************************\n";
1555 print "Cannot find registry entry '$recommendedPlatformSDK'.\n";
1556 print "Please download and install the Microsoft Windows SDK\n";
1557 print "from <http://www.microsoft.com/en-us/download/details.aspx?id=8279>.\n\n";
1558 print "Then follow step 2 in the Windows section of the \"Installing Developer\n";
1559 print "Tools\" instructions at <http://www.webkit.org/building/tools.html>.\n";
1560 print "*************************************************************\n";
1564 sub copyInspectorFrontendFiles
1566 my $productDir = productDir();
1567 my $sourceInspectorPath = sourceDir() . "/Source/WebCore/inspector/front-end/";
1568 my $inspectorResourcesDirPath = $ENV{"WEBKITINSPECTORRESOURCESDIR"};
1570 if (!defined($inspectorResourcesDirPath)) {
1571 $inspectorResourcesDirPath = "";
1574 if (isAppleMacWebKit()) {
1575 if (isIOSWebKit()) {
1576 $inspectorResourcesDirPath = $productDir . "/WebCore.framework/inspector";
1578 $inspectorResourcesDirPath = $productDir . "/WebCore.framework/Resources/inspector";
1580 } elsif (isAppleWinWebKit() || isWinCairo()) {
1581 $inspectorResourcesDirPath = $productDir . "/WebKit.resources/inspector";
1583 my $prefix = $ENV{"WebKitInstallationPrefix"};
1584 $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/webkit-1.0/webinspector";
1586 my $prefix = $ENV{"WebKitInstallationPrefix"};
1587 $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/ewebkit/webinspector";
1590 if (! -d $inspectorResourcesDirPath) {
1591 print "*************************************************************\n";
1592 print "Cannot find '$inspectorResourcesDirPath'.\n" if (defined($inspectorResourcesDirPath));
1593 print "Make sure that you have built WebKit first.\n" if (! -d $productDir || defined($inspectorResourcesDirPath));
1594 print "Optionally, set the environment variable 'WebKitInspectorResourcesDir'\n";
1595 print "to point to the directory that contains the WebKit Inspector front-end\n";
1596 print "files for the built WebCore framework.\n";
1597 print "*************************************************************\n";
1601 if (isAppleMacWebKit()) {
1602 my $sourceLocalizedStrings = sourceDir() . "/Source/WebCore/English.lproj/localizedStrings.js";
1603 my $destinationLocalizedStrings;
1604 if (isIOSWebKit()) {
1605 $destinationLocalizedStrings = $productDir . "/WebCore.framework/English.lproj/localizedStrings.js";
1607 $destinationLocalizedStrings = $productDir . "/WebCore.framework/Resources/English.lproj/localizedStrings.js";
1609 system "ditto", $sourceLocalizedStrings, $destinationLocalizedStrings;
1612 my $exitStatus = system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=*.re2js", "--exclude=.svn/", $sourceInspectorPath, $inspectorResourcesDirPath;
1613 return $exitStatus if $exitStatus;
1615 if (isIOSWebKit()) {
1616 chdir($productDir . "/WebCore.framework");
1617 return system "zip", "--quiet", "--exclude=*.qrc", "-r", "inspector-remote.zip", "inspector";
1620 return 0; # Success; did copy files.
1623 sub buildXCodeProject($$@)
1625 my ($project, $clean, @extraOptions) = @_;
1628 push(@extraOptions, "-alltargets");
1629 push(@extraOptions, "clean");
1632 return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions;
1635 sub usingVisualStudioExpress()
1638 return $willUseVCExpressWhenBuilding;
1641 sub buildVisualStudioProject
1643 my ($project, $clean) = @_;
1646 my $config = configurationForVisualStudio();
1648 dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding;
1650 chomp($project = `cygpath -w "$project"`) if isCygwin();
1652 my $action = "/build";
1657 my @command = ($vcBuildPath, $project, $action, $config);
1659 print join(" ", @command), "\n";
1660 return system @command;
1663 sub getJhbuildPath()
1665 my @jhbuildPath = File::Spec->splitdir(baseProductDir());
1666 if (isGit() && isGitBranchBuild() && gitBranch()) {
1669 push(@jhbuildPath, "Dependencies");
1670 return File::Spec->catdir(@jhbuildPath);
1673 sub isCachedArgumentfileOutOfDate($@)
1675 my ($filename, $currentContents) = @_;
1677 if (! -e $filename) {
1681 open(CONTENTS_FILE, $filename);
1682 chomp(my $previousContents = <CONTENTS_FILE>);
1683 close(CONTENTS_FILE);
1685 if ($previousContents ne $currentContents) {
1686 print "Contents for file $filename have changed.\n";
1687 print "Previous contents were: $previousContents\n\n";
1688 print "New contents are: $currentContents\n";
1695 sub jhbuildWrapperPrefixIfNeeded()
1697 if (-e getJhbuildPath()) {
1698 my @prefix = (File::Spec->catfile(sourceDir(), "Tools", "jhbuild", "jhbuild-wrapper"));
1700 push(@prefix, "--efl");
1702 push(@prefix, "--gtk");
1704 push(@prefix, "run");
1712 sub cmakeCachePath()
1714 return File::Spec->catdir(baseProductDir(), configuration(), "CMakeCache.txt");
1717 sub shouldRemoveCMakeCache(@)
1719 my ($cacheFilePath, @buildArgs) = @_;
1728 # We check this first, because we always want to create this file for a fresh build.
1729 my $productDir = File::Spec->catdir(baseProductDir(), configuration());
1730 my $optionsCache = File::Spec->catdir($productDir, "build-webkit-options.txt");
1731 my $joinedBuildArgs = join(" ", @buildArgs);
1732 if (isCachedArgumentfileOutOfDate($optionsCache, $joinedBuildArgs)) {
1733 File::Path::mkpath($productDir) unless -d $productDir;
1734 open(CACHED_ARGUMENTS, ">", $optionsCache);
1735 print CACHED_ARGUMENTS $joinedBuildArgs;
1736 close(CACHED_ARGUMENTS);
1741 my $cmakeCache = cmakeCachePath();
1742 unless (-e $cmakeCache) {
1746 my $cacheFileModifiedTime = stat($cmakeCache)->mtime;
1747 my $platformConfiguration = File::Spec->catdir(sourceDir(), "Source", "cmake", "Options" . cmakeBasedPortName() . ".cmake");
1748 if ($cacheFileModifiedTime < stat($platformConfiguration)->mtime) {
1752 my $globalConfiguration = File::Spec->catdir(sourceDir(), "Source", "cmake", "OptionsCommon.cmake");
1753 if ($cacheFileModifiedTime < stat($globalConfiguration)->mtime) {
1760 sub removeCMakeCache(@)
1762 my (@buildArgs) = @_;
1763 if (shouldRemoveCMakeCache(@buildArgs)) {
1764 my $cmakeCache = cmakeCachePath();
1765 unlink($cmakeCache) if -e $cmakeCache;
1771 # Test both ninja and ninja-build. Fedora uses ninja-build and has patched CMake to also call ninja-build.
1772 system('which ninja > /dev/null || which ninja-build > /dev/null');
1776 sub cmakeGeneratedBuildfile(@)
1778 my ($willUseNinja) = @_;
1779 if ($willUseNinja) {
1780 return File::Spec->catfile(baseProductDir(), configuration(), "build.ninja")
1782 return File::Spec->catfile(baseProductDir(), configuration(), "Makefile")
1786 sub generateBuildSystemFromCMakeProject
1788 my ($port, $prefixPath, @cmakeArgs, $additionalCMakeArgs) = @_;
1789 my $config = configuration();
1790 my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1791 File::Path::mkpath($buildPath) unless -d $buildPath;
1792 my $originalWorkingDirectory = getcwd();
1793 chdir($buildPath) or die;
1795 # For GTK+ we try to be smart about when to rerun cmake, so that we can have faster incremental builds.
1796 my $willUseNinja = isGtk() && canUseNinja();
1797 if (isGtk() && -e cmakeCachePath() && -e cmakeGeneratedBuildfile($willUseNinja)) {
1802 push @args, "-DPORT=\"$port\"";
1803 push @args, "-DCMAKE_INSTALL_PREFIX=\"$prefixPath\"" if $prefixPath;
1804 push @args, "-DSHARED_CORE=ON" if isEfl() && $ENV{"ENABLE_DRT"};
1805 if ($config =~ /release/i) {
1806 push @args, "-DCMAKE_BUILD_TYPE=Release";
1807 } elsif ($config =~ /debug/i) {
1808 push @args, "-DCMAKE_BUILD_TYPE=Debug";
1811 if ($willUseNinja) {
1813 push @args, "Ninja";
1816 # Don't warn variables which aren't used by cmake ports.
1817 push @args, "--no-warn-unused-cli";
1818 push @args, @cmakeArgs if @cmakeArgs;
1819 push @args, $additionalCMakeArgs if $additionalCMakeArgs;
1821 push @args, '"' . sourceDir() . '"';
1823 # Compiler options to keep floating point values consistent
1824 # between 32-bit and 64-bit architectures.
1825 determineArchitecture();
1826 if ($architecture ne "x86_64" && !isARM() && !isCrossCompilation()) {
1827 $ENV{'CXXFLAGS'} = "-march=pentium4 -msse2 -mfpmath=sse " . ($ENV{'CXXFLAGS'} || "");
1830 # We call system("cmake @args") instead of system("cmake", @args) so that @args is
1831 # parsed for shell metacharacters.
1832 my $wrapper = join(" ", jhbuildWrapperPrefixIfNeeded()) . " ";
1833 my $returnCode = system($wrapper . "cmake @args");
1835 chdir($originalWorkingDirectory);
1839 sub buildCMakeGeneratedProject($)
1841 my ($makeArgs) = @_;
1842 my $config = configuration();
1843 my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1844 if (! -d $buildPath) {
1845 die "Must call generateBuildSystemFromCMakeProject() before building CMake project.";
1848 my $command = "cmake";
1849 my @args = ("--build", $buildPath, "--config", $config);
1850 push @args, ("--", $makeArgs) if $makeArgs;
1852 # GTK uses a build script to preserve colors and pretty-printing.
1854 chdir "$buildPath" or die;
1855 $command = "$buildPath/build.sh";
1856 @args = ($makeArgs);
1859 # We call system("cmake @args") instead of system("cmake", @args) so that @args is
1860 # parsed for shell metacharacters. In particular, $makeArgs may contain such metacharacters.
1861 my $wrapper = join(" ", jhbuildWrapperPrefixIfNeeded()) . " ";
1862 return system($wrapper . "$command @args");
1866 sub cleanCMakeGeneratedProject()
1868 my $config = configuration();
1869 my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1870 if (-d $buildPath) {
1871 return system("cmake", "--build", $buildPath, "--config", $config, "--target", "clean");
1876 sub buildCMakeProjectOrExit($$$$@)
1878 my ($clean, $port, $prefixPath, $makeArgs, @cmakeArgs) = @_;
1881 exit(exitStatus(cleanCMakeGeneratedProject())) if $clean;
1883 if (isEfl() && checkForArgumentAndRemoveFromARGV("--update-efl")) {
1884 system("perl", "$sourceDir/Tools/Scripts/update-webkitefl-libs") == 0 or die $!;
1887 if (isGtk() && checkForArgumentAndRemoveFromARGV("--update-gtk")) {
1888 system("perl", "$sourceDir/Tools/Scripts/update-webkitgtk-libs") == 0 or die $!;
1891 $returnCode = exitStatus(generateBuildSystemFromCMakeProject($port, $prefixPath, @cmakeArgs));
1892 exit($returnCode) if $returnCode;
1894 $returnCode = exitStatus(buildCMakeGeneratedProject($makeArgs));
1895 exit($returnCode) if $returnCode;
1899 sub cmakeBasedPortArguments()
1901 return ('-G "Visual Studio 8 2005 STANDARDSDK_500 (ARMV4I)"') if isWinCE();
1905 sub cmakeBasedPortName()
1907 return "Efl" if isEfl();
1908 return "WinCE" if isWinCE();
1909 return "GTK" if isGtk();
1915 return isEfl() || isWinCE() || isGtk();
1920 my ($prompt, $default) = @_;
1921 my $defaultValue = $default ? "[$default]" : "";
1922 print "$prompt $defaultValue: ";
1923 chomp(my $input = <STDIN>);
1924 return $input ? $input : $default;
1927 sub appleApplicationSupportPath
1930 # FIXME (125180): Remove the following once official 64-bit Windows support is available.
1931 return $ENV{"WEBKIT_64_SUPPORT"}, "\n" if isWin64();
1934 open INSTALL_DIR, "</proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Apple\ Inc./Apple\ Application\ Support/InstallDir";
1935 my $path = <INSTALL_DIR>;
1936 $path =~ s/[\r\n\x00].*//;
1939 my $unixPath = `cygpath -u '$path'`;
1944 sub setPathForRunningWebKitApp
1948 if (isAppleWinWebKit()) {
1949 $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), appleApplicationSupportPath(), $env->{PATH} || "");
1950 } elsif (isWinCairo()) {
1951 my $winCairoBin = sourceDir() . "/WebKitLibraries/win/" . (isWin64() ? "bin64/" : "bin32/");
1952 my $gstreamerBin = isWin64() ? $ENV{"GSTREAMER_1_0_ROOT_X86_64"} . "bin" : $ENV{"GSTREAMER_1_0_ROOT_X86"} . "bin";
1953 $env->{PATH} = join(':', productDir(), $winCairoBin, $gstreamerBin, $env->{PATH} || "");
1957 sub printHelpAndExitForRunAndDebugWebKitAppIfNeeded
1959 return unless checkForArgumentAndRemoveFromARGV("--help");
1961 my ($includeOptionsForDebugging) = @_;
1964 Usage: @{[basename($0)]} [options] [args ...]
1965 --help Show this help message
1966 --no-saved-state Launch the application without state restoration (OS X 10.7 and later)
1967 --guard-malloc Enable Guard Malloc (OS X only)
1968 --use-web-process-xpc-service Launch the Web Process as an XPC Service (OS X only)
1971 if ($includeOptionsForDebugging) {
1973 --target-web-process Debug the web process
1974 --use-gdb Use GDB (this is the default when using Xcode 4.4 or earlier)
1975 --use-lldb Use LLDB (this is the default when using Xcode 4.5 or later)
1982 sub argumentsForRunAndDebugMacWebKitApp()
1985 if (checkForArgumentAndRemoveFromARGV("--no-saved-state")) {
1986 push @args, ("-ApplePersistenceIgnoreStateQuietly", "YES");
1987 # FIXME: Don't set ApplePersistenceIgnoreState once all supported OS versions respect ApplePersistenceIgnoreStateQuietly (rdar://15032886).
1988 push @args, ("-ApplePersistenceIgnoreState", "YES");
1990 push @args, ("-WebKit2UseXPCServiceForWebProcess", "YES") if shouldUseXPCServiceForWebProcess();
1991 unshift @args, @ARGV;
1996 sub runMacWebKitApp($;$)
1998 my ($appPath, $useOpenCommand) = @_;
1999 my $productDir = productDir();
2000 print "Starting @{[basename($appPath)]} with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
2001 $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
2002 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
2004 setUpGuardMallocIfNeeded();
2006 if (defined($useOpenCommand) && $useOpenCommand == USE_OPEN_COMMAND) {
2007 return system("open", "-W", "-a", $appPath, "--args", argumentsForRunAndDebugMacWebKitApp());
2009 if (architecture()) {
2010 return system "arch", "-" . architecture(), $appPath, argumentsForRunAndDebugMacWebKitApp();
2012 return system { $appPath } $appPath, argumentsForRunAndDebugMacWebKitApp();
2015 sub execMacWebKitAppForDebugging($)
2018 my $architectureSwitch;
2019 my $argumentsSeparator;
2021 if (debugger() eq "lldb") {
2022 $architectureSwitch = "--arch";
2023 $argumentsSeparator = "--";
2024 } elsif (debugger() eq "gdb") {
2025 $architectureSwitch = "-arch";
2026 $argumentsSeparator = "--args";
2028 die "Unknown debugger $debugger.\n";
2031 my $debuggerPath = `xcrun -find $debugger`;
2032 chomp $debuggerPath;
2033 die "Can't find the $debugger executable.\n" unless -x $debuggerPath;
2035 my $productDir = productDir();
2036 $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
2037 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
2039 setUpGuardMallocIfNeeded();
2041 my @architectureFlags = ($architectureSwitch, architecture());
2042 if (!shouldTargetWebProcess()) {
2043 print "Starting @{[basename($appPath)]} under $debugger with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
2044 exec { $debuggerPath } $debuggerPath, @architectureFlags, $argumentsSeparator, $appPath, argumentsForRunAndDebugMacWebKitApp() or die;
2046 if (shouldUseXPCServiceForWebProcess()) {
2047 die "Targetting the Web Process is not compatible with using an XPC Service for the Web Process at this time.";
2050 my $webProcessShimPath = File::Spec->catfile($productDir, "SecItemShim.dylib");
2051 my $webProcessPath = File::Spec->catdir($productDir, "WebProcess.app");
2052 my $webKit2ExecutablePath = File::Spec->catfile($productDir, "WebKit2.framework", "WebKit2");
2054 appendToEnvironmentVariableList("DYLD_INSERT_LIBRARIES", $webProcessShimPath);
2056 print "Starting WebProcess under $debugger with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
2057 exec { $debuggerPath } $debuggerPath, @architectureFlags, $argumentsSeparator, $webProcessPath, $webKit2ExecutablePath, "-type", "webprocess", "-client-executable", $appPath or die;
2063 if (isAppleMacWebKit()) {
2065 execMacWebKitAppForDebugging(safariPath());
2068 return 1; # Unsupported platform; can't debug Safari on this platform.
2074 if (isAppleMacWebKit()) {
2075 return runMacWebKitApp(safariPath());
2078 if (isAppleWinWebKit()) {
2080 my $productDir = productDir();
2081 my $webKitLauncherPath = File::Spec->catfile(productDir(), "WinLauncher.exe");
2082 return system { $webKitLauncherPath } $webKitLauncherPath, @ARGV;
2085 return 1; # Unsupported platform; can't run Safari on this platform.
2090 if (isAppleMacWebKit()) {
2091 return runMacWebKitApp(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser"));
2097 sub debugMiniBrowser
2099 if (isAppleMacWebKit()) {
2100 execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser"));
2106 sub runWebKitTestRunner
2108 if (isAppleMacWebKit()) {
2109 return runMacWebKitApp(File::Spec->catfile(productDir(), "WebKitTestRunner"));
2115 sub debugWebKitTestRunner
2117 if (isAppleMacWebKit()) {
2118 execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "WebKitTestRunner"));
2124 sub readRegistryString
2126 my ($valueName) = @_;
2127 chomp(my $string = `regtool --wow32 get "$valueName"`);
2131 sub writeRegistryString
2133 my ($valueName, $string) = @_;
2135 my $error = system "regtool", "--wow32", "set", "-s", $valueName, $string;
2137 # On Windows Vista/7 with UAC enabled, regtool will fail to modify the registry, but will still
2138 # return a successful exit code. So we double-check here that the value we tried to write to the
2139 # registry was really written.
2140 return !$error && readRegistryString($valueName) eq $string;