Home | History | Annotate | Download | only in Scripts
      1 # Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
      2 # Copyright (C) 2009 Google Inc. All rights reserved.
      3 #
      4 # Redistribution and use in source and binary forms, with or without
      5 # modification, are permitted provided that the following conditions
      6 # are met:
      7 #
      8 # 1.  Redistributions of source code must retain the above copyright
      9 #     notice, this list of conditions and the following disclaimer. 
     10 # 2.  Redistributions in binary form must reproduce the above copyright
     11 #     notice, this list of conditions and the following disclaimer in the
     12 #     documentation and/or other materials provided with the distribution. 
     13 # 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14 #     its contributors may be used to endorse or promote products derived
     15 #     from this software without specific prior written permission. 
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 # Module to share code to get to WebKit directories.
     29 
     30 use strict;
     31 use warnings;
     32 use Config;
     33 use FindBin;
     34 use File::Basename;
     35 use File::Path;
     36 use File::Spec;
     37 use POSIX;
     38 use VCSUtils;
     39 
     40 BEGIN {
     41    use Exporter   ();
     42    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
     43    $VERSION     = 1.00;
     44    @ISA         = qw(Exporter);
     45    @EXPORT      = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks &currentSVNRevision);
     46    %EXPORT_TAGS = ( );
     47    @EXPORT_OK   = ();
     48 }
     49 
     50 our @EXPORT_OK;
     51 
     52 my $architecture;
     53 my $baseProductDir;
     54 my @baseProductDirOption;
     55 my $configuration;
     56 my $configurationForVisualStudio;
     57 my $configurationProductDir;
     58 my $sourceDir;
     59 my $currentSVNRevision;
     60 my $osXVersion;
     61 my $isQt;
     62 my $isSymbian;
     63 my %qtFeatureDefaults;
     64 my $isGtk;
     65 my $isWx;
     66 my @wxArgs;
     67 my $isChromium;
     68 my $isInspectorFrontend;
     69 
     70 # Variables for Win32 support
     71 my $vcBuildPath;
     72 my $windowsTmpPath;
     73 my $windowsSourceDir;
     74 
     75 # Defined in VCSUtils.
     76 sub exitStatus($);
     77 
     78 sub determineSourceDir
     79 {
     80     return if $sourceDir;
     81     $sourceDir = $FindBin::Bin;
     82     $sourceDir =~ s|/+$||; # Remove trailing '/' as we would die later
     83 
     84     # walks up path checking each directory to see if it is the main WebKit project dir, 
     85     # defined by containing JavaScriptCore, WebCore, and WebKit
     86     until ((-d "$sourceDir/JavaScriptCore" && -d "$sourceDir/WebCore" && -d "$sourceDir/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
     87     {
     88         if ($sourceDir !~ s|/[^/]+$||) {
     89             die "Could not find top level webkit directory above source directory using FindBin.\n";
     90         }
     91     }
     92 
     93     $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
     94 }
     95 
     96 sub currentPerlPath()
     97 {
     98     my $thisPerl = $^X;
     99     if ($^O ne 'VMS') {
    100         $thisPerl .= $Config{_exe} unless $thisPerl =~ m/$Config{_exe}$/i;
    101     }
    102     return $thisPerl;
    103 }
    104 
    105 # used for scripts which are stored in a non-standard location
    106 sub setSourceDir($)
    107 {
    108     ($sourceDir) = @_;
    109 }
    110 
    111 sub determineBaseProductDir
    112 {
    113     return if defined $baseProductDir;
    114     determineSourceDir();
    115 
    116     if (isAppleMacWebKit()) {
    117         # Silently remove ~/Library/Preferences/xcodebuild.plist which can
    118         # cause build failure. The presence of
    119         # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from
    120         # respecting global settings such as a custom build products directory
    121         # (<rdar://problem/5585899>).
    122         my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist";
    123         if (-e $personalPlistFile) {
    124             unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!";
    125         }
    126 
    127         open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> " . File::Spec->devnull() . " |" or die;
    128         $baseProductDir = join '', <PRODUCT>;
    129         close PRODUCT;
    130 
    131         $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
    132         undef $baseProductDir unless $baseProductDir =~ /^\//;
    133 
    134         if (!defined($baseProductDir)) {
    135             open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> " . File::Spec->devnull() . " |" or die;
    136             $baseProductDir = <PRODUCT>;
    137             close PRODUCT;
    138             if ($baseProductDir) {
    139                 chomp $baseProductDir;
    140                 undef $baseProductDir unless $baseProductDir =~ /^\//;
    141             }
    142         }
    143     } elsif (isSymbian()) {
    144         # Shadow builds are not supported on Symbian
    145         $baseProductDir = $sourceDir;
    146     }
    147 
    148     if (!defined($baseProductDir)) { # Port-spesific checks failed, use default
    149         $baseProductDir = $ENV{"WEBKITOUTPUTDIR"} || "$sourceDir/WebKitBuild";
    150     }
    151 
    152     if (isGit() && isGitBranchBuild()) {
    153         my $branch = gitBranch();
    154         $baseProductDir = "$baseProductDir/$branch";
    155     }
    156 
    157     if (isAppleMacWebKit()) {
    158         $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
    159         $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
    160         $baseProductDir =~ s|^~/|$ENV{HOME}/|;
    161         die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
    162         die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
    163         @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir");
    164     }
    165 
    166     if (isCygwin()) {
    167         my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
    168         chomp $dosBuildPath;
    169         $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath;
    170     }
    171 
    172     if (isAppleWinWebKit()) {
    173         my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
    174         chomp $unixBuildPath;
    175         $baseProductDir = $unixBuildPath;
    176     }
    177 }
    178 
    179 sub setBaseProductDir($)
    180 {
    181     ($baseProductDir) = @_;
    182 }
    183 
    184 sub determineConfiguration
    185 {
    186     return if defined $configuration;
    187     determineBaseProductDir();
    188     if (open CONFIGURATION, "$baseProductDir/Configuration") {
    189         $configuration = <CONFIGURATION>;
    190         close CONFIGURATION;
    191     }
    192     if ($configuration) {
    193         chomp $configuration;
    194         # compatibility for people who have old Configuration files
    195         $configuration = "Release" if $configuration eq "Deployment";
    196         $configuration = "Debug" if $configuration eq "Development";
    197     } else {
    198         $configuration = "Release";
    199     }
    200 }
    201 
    202 sub determineArchitecture
    203 {
    204     return if defined $architecture;
    205     # make sure $architecture is defined for non-apple-mac builds
    206     $architecture = "";
    207     return unless isAppleMacWebKit();
    208 
    209     determineBaseProductDir();
    210     if (open ARCHITECTURE, "$baseProductDir/Architecture") {
    211         $architecture = <ARCHITECTURE>;
    212         close ARCHITECTURE;
    213     }
    214     if ($architecture) {
    215         chomp $architecture;
    216     } else {
    217         if (isTiger() or isLeopard()) {
    218             $architecture = `arch`;
    219         } else {
    220             my $supports64Bit = `sysctl -n hw.optional.x86_64`;
    221             chomp $supports64Bit;
    222             $architecture = $supports64Bit ? 'x86_64' : `arch`;
    223         }
    224         chomp $architecture;
    225     }
    226 }
    227 
    228 sub jscPath($)
    229 {
    230     my ($productDir) = @_;
    231     my $jscName = "jsc";
    232     $jscName .= "_debug"  if (isCygwin() && ($configuration eq "Debug"));
    233     return "$productDir/$jscName";
    234 }
    235 
    236 sub argumentsForConfiguration()
    237 {
    238     determineConfiguration();
    239     determineArchitecture();
    240 
    241     my @args = ();
    242     push(@args, '--debug') if $configuration eq "Debug";
    243     push(@args, '--release') if $configuration eq "Release";
    244     push(@args, '--32-bit') if $architecture ne "x86_64";
    245     push(@args, '--qt') if isQt();
    246     push(@args, '--symbian') if isSymbian();
    247     push(@args, '--gtk') if isGtk();
    248     push(@args, '--wx') if isWx();
    249     push(@args, '--chromium') if isChromium();
    250     push(@args, '--inspector-frontend') if isInspectorFrontend();
    251     return @args;
    252 }
    253 
    254 sub determineConfigurationForVisualStudio
    255 {
    256     return if defined $configurationForVisualStudio;
    257     determineConfiguration();
    258     $configurationForVisualStudio = $configuration;
    259     return unless $configuration eq "Debug";
    260     setupCygwinEnv();
    261     chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`);
    262     $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll";
    263 }
    264 
    265 sub determineConfigurationProductDir
    266 {
    267     return if defined $configurationProductDir;
    268     determineBaseProductDir();
    269     determineConfiguration();
    270     if (isAppleWinWebKit() && !isWx()) {
    271         $configurationProductDir = "$baseProductDir/bin";
    272     } else {
    273         # [Gtk] We don't have Release/Debug configurations in straight
    274         # autotool builds (non build-webkit). In this case and if
    275         # WEBKITOUTPUTDIR exist, use that as our configuration dir. This will
    276         # allows us to run run-webkit-tests without using build-webkit.
    277         if ($ENV{"WEBKITOUTPUTDIR"} && isGtk()) {
    278             $configurationProductDir = "$baseProductDir";
    279         } else {
    280             $configurationProductDir = "$baseProductDir/$configuration";
    281         }
    282     }
    283 }
    284 
    285 sub setConfigurationProductDir($)
    286 {
    287     ($configurationProductDir) = @_;
    288 }
    289 
    290 sub determineCurrentSVNRevision
    291 {
    292     return if defined $currentSVNRevision;
    293     determineSourceDir();
    294     $currentSVNRevision = svnRevisionForDirectory($sourceDir);
    295     return $currentSVNRevision;
    296 }
    297 
    298 
    299 sub chdirWebKit
    300 {
    301     determineSourceDir();
    302     chdir $sourceDir or die;
    303 }
    304 
    305 sub baseProductDir
    306 {
    307     determineBaseProductDir();
    308     return $baseProductDir;
    309 }
    310 
    311 sub sourceDir
    312 {
    313     determineSourceDir();
    314     return $sourceDir;
    315 }
    316 
    317 sub productDir
    318 {
    319     determineConfigurationProductDir();
    320     return $configurationProductDir;
    321 }
    322 
    323 sub jscProductDir
    324 {
    325     my $productDir = productDir();
    326     $productDir .= "/JavaScriptCore" if isQt();
    327     $productDir .= "/$configuration" if (isQt() && isWindows());
    328     $productDir .= "/Programs" if isGtk();
    329 
    330     return $productDir;
    331 }
    332 
    333 sub configuration()
    334 {
    335     determineConfiguration();
    336     return $configuration;
    337 }
    338 
    339 sub configurationForVisualStudio()
    340 {
    341     determineConfigurationForVisualStudio();
    342     return $configurationForVisualStudio;
    343 }
    344 
    345 sub currentSVNRevision
    346 {
    347     determineCurrentSVNRevision();
    348     return $currentSVNRevision;
    349 }
    350 
    351 sub XcodeOptions
    352 {
    353     determineBaseProductDir();
    354     determineConfiguration();
    355     determineArchitecture();
    356     return (@baseProductDirOption, "-configuration", $configuration, "ARCHS=$architecture");
    357 }
    358 
    359 sub XcodeOptionString
    360 {
    361     return join " ", XcodeOptions();
    362 }
    363 
    364 sub XcodeOptionStringNoConfig
    365 {
    366     return join " ", @baseProductDirOption;
    367 }
    368 
    369 sub XcodeCoverageSupportOptions()
    370 {
    371     my @coverageSupportOptions = ();
    372     push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES";
    373     push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES";
    374     push @coverageSupportOptions, "EXTRA_LINK= \$(EXTRA_LINK) -ftest-coverage -fprofile-arcs";
    375     push @coverageSupportOptions, "OTHER_CFLAGS= \$(OTHER_CFLAGS) -DCOVERAGE -MD";
    376     push @coverageSupportOptions, "OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -ftest-coverage -fprofile-arcs -framework AppKit";
    377     return @coverageSupportOptions;
    378 }
    379 
    380 my $passedConfiguration;
    381 my $searchedForPassedConfiguration;
    382 sub determinePassedConfiguration
    383 {
    384     return if $searchedForPassedConfiguration;
    385     $searchedForPassedConfiguration = 1;
    386 
    387     my $isWinCairo = checkForArgumentAndRemoveFromARGV("--cairo-win32");
    388 
    389     for my $i (0 .. $#ARGV) {
    390         my $opt = $ARGV[$i];
    391         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
    392             splice(@ARGV, $i, 1);
    393             $passedConfiguration = "Debug";
    394             $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin());
    395             return;
    396         }
    397         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
    398             splice(@ARGV, $i, 1);
    399             $passedConfiguration = "Release";
    400             $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin());
    401             return;
    402         }
    403         if ($opt =~ /^--profil(e|ing)$/i) {
    404             splice(@ARGV, $i, 1);
    405             $passedConfiguration = "Profiling";
    406             $passedConfiguration .= "_Cairo" if ($isWinCairo && isCygwin());
    407             return;
    408         }
    409     }
    410     $passedConfiguration = undef;
    411 }
    412 
    413 sub passedConfiguration
    414 {
    415     determinePassedConfiguration();
    416     return $passedConfiguration;
    417 }
    418 
    419 sub setConfiguration
    420 {
    421     setArchitecture();
    422 
    423     if (my $config = shift @_) {
    424         $configuration = $config;
    425         return;
    426     }
    427 
    428     determinePassedConfiguration();
    429     $configuration = $passedConfiguration if $passedConfiguration;
    430 }
    431 
    432 
    433 my $passedArchitecture;
    434 my $searchedForPassedArchitecture;
    435 sub determinePassedArchitecture
    436 {
    437     return if $searchedForPassedArchitecture;
    438     $searchedForPassedArchitecture = 1;
    439 
    440     for my $i (0 .. $#ARGV) {
    441         my $opt = $ARGV[$i];
    442         if ($opt =~ /^--32-bit$/i) {
    443             splice(@ARGV, $i, 1);
    444             if (isAppleMacWebKit()) {
    445                 $passedArchitecture = `arch`;
    446                 chomp $passedArchitecture;
    447             }
    448             return;
    449         }
    450     }
    451     $passedArchitecture = undef;
    452 }
    453 
    454 sub passedArchitecture
    455 {
    456     determinePassedArchitecture();
    457     return $passedArchitecture;
    458 }
    459 
    460 sub architecture()
    461 {
    462     determineArchitecture();
    463     return $architecture;
    464 }
    465 
    466 sub setArchitecture
    467 {
    468     if (my $arch = shift @_) {
    469         $architecture = $arch;
    470         return;
    471     }
    472 
    473     determinePassedArchitecture();
    474     $architecture = $passedArchitecture if $passedArchitecture;
    475 }
    476 
    477 
    478 sub safariPathFromSafariBundle
    479 {
    480     my ($safariBundle) = @_;
    481 
    482     return "$safariBundle/Contents/MacOS/Safari" if isAppleMacWebKit();
    483     return $safariBundle if isAppleWinWebKit();
    484 }
    485 
    486 sub installedSafariPath
    487 {
    488     my $safariBundle;
    489 
    490     if (isAppleMacWebKit()) {
    491         $safariBundle = "/Applications/Safari.app";
    492     } elsif (isAppleWinWebKit()) {
    493         $safariBundle = `"$configurationProductDir/FindSafari.exe"`;
    494         $safariBundle =~ s/[\r\n]+$//;
    495         $safariBundle = `cygpath -u '$safariBundle'`;
    496         $safariBundle =~ s/[\r\n]+$//;
    497         $safariBundle .= "Safari.exe";
    498     }
    499 
    500     return safariPathFromSafariBundle($safariBundle);
    501 }
    502 
    503 # Locate Safari.
    504 sub safariPath
    505 {
    506     # Use WEBKIT_SAFARI environment variable if present.
    507     my $safariBundle = $ENV{WEBKIT_SAFARI};
    508     if (!$safariBundle) {
    509         determineConfigurationProductDir();
    510         # Use Safari.app in product directory if present (good for Safari development team).
    511         if (isAppleMacWebKit() && -d "$configurationProductDir/Safari.app") {
    512             $safariBundle = "$configurationProductDir/Safari.app";
    513         } elsif (isAppleWinWebKit()) {
    514             my $path = "$configurationProductDir/Safari.exe";
    515             my $debugPath = "$configurationProductDir/Safari_debug.exe";
    516 
    517             if (configurationForVisualStudio() =~ /Debug/ && -x $debugPath) {
    518                 $safariBundle = $debugPath;
    519             } elsif (-x $path) {
    520                 $safariBundle = $path;
    521             }
    522         }
    523         if (!$safariBundle) {
    524             return installedSafariPath();
    525         }
    526     }
    527     my $safariPath = safariPathFromSafariBundle($safariBundle);
    528     die "Can't find executable at $safariPath.\n" if isAppleMacWebKit() && !-x $safariPath;
    529     return $safariPath;
    530 }
    531 
    532 sub builtDylibPathForName
    533 {
    534     my $libraryName = shift;
    535     determineConfigurationProductDir();
    536     if (isChromium()) {
    537         return "$configurationProductDir/$libraryName";
    538     }
    539     if (isQt()) {
    540         $libraryName = "QtWebKit";
    541         if (isDarwin() and -d "$configurationProductDir/lib/$libraryName.framework") {
    542             return "$configurationProductDir/lib/$libraryName.framework/$libraryName";
    543         } elsif (isWindows()) {
    544             my $mkspec = `qmake -query QMAKE_MKSPECS`;
    545             $mkspec =~ s/[\n|\r]$//g;
    546             my $qtMajorVersion = retrieveQMakespecVar("$mkspec/qconfig.pri", "QT_MAJOR_VERSION");
    547             if (not $qtMajorVersion) {
    548                 $qtMajorVersion = "";
    549             }
    550             return "$configurationProductDir/lib/$libraryName$qtMajorVersion.dll";
    551         } else {
    552             return "$configurationProductDir/lib/lib$libraryName.so";
    553         }
    554     }
    555     if (isWx()) {
    556         return "$configurationProductDir/libwxwebkit.dylib";
    557     }
    558     if (isGtk()) {
    559         return "$configurationProductDir/$libraryName/../.libs/libwebkit-1.0.so";
    560     }
    561     if (isAppleMacWebKit()) {
    562         return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName";
    563     }
    564     if (isAppleWinWebKit()) {
    565         if ($libraryName eq "JavaScriptCore") {
    566             return "$baseProductDir/lib/$libraryName.lib";
    567         } else {
    568             return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib";
    569         }
    570     }
    571 
    572     die "Unsupported platform, can't determine built library locations.";
    573 }
    574 
    575 # Check to see that all the frameworks are built.
    576 sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework.
    577 {
    578     return if isCygwin();
    579     my @frameworks = ("JavaScriptCore", "WebCore");
    580     push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days.
    581     for my $framework (@frameworks) {
    582         my $path = builtDylibPathForName($framework);
    583         die "Can't find built framework at \"$path\".\n" unless -e $path;
    584     }
    585 }
    586 
    587 sub isInspectorFrontend()
    588 {
    589     determineIsInspectorFrontend();
    590     return $isInspectorFrontend;
    591 }
    592 
    593 sub determineIsInspectorFrontend()
    594 {
    595     return if defined($isInspectorFrontend);
    596     $isInspectorFrontend = checkForArgumentAndRemoveFromARGV("--inspector-frontend");
    597 }
    598 
    599 sub isQt()
    600 {
    601     determineIsQt();
    602     return $isQt;
    603 }
    604 
    605 sub isSymbian()
    606 {
    607     determineIsSymbian();
    608     return $isSymbian;
    609 }
    610 
    611 sub qtFeatureDefaults()
    612 {
    613     determineQtFeatureDefaults();
    614     return %qtFeatureDefaults;
    615 }
    616 
    617 sub determineQtFeatureDefaults()
    618 {
    619     return if %qtFeatureDefaults;
    620     my $originalCwd = getcwd();
    621     chdir File::Spec->catfile(sourceDir(), "WebCore");
    622     my $defaults = `qmake CONFIG+=compute_defaults 2>&1`;
    623     chdir $originalCwd;
    624 
    625     while ($defaults =~ m/(\S*?)=(.*?)( |$)/gi) {
    626         $qtFeatureDefaults{$1}=$2;
    627     }
    628 }
    629 
    630 sub checkForArgumentAndRemoveFromARGV
    631 {
    632     my $argToCheck = shift;
    633     foreach my $opt (@ARGV) {
    634         if ($opt =~ /^$argToCheck$/i ) {
    635             @ARGV = grep(!/^$argToCheck$/i, @ARGV);
    636             return 1;
    637         }
    638     }
    639     return 0;
    640 }
    641 
    642 sub determineIsQt()
    643 {
    644     return if defined($isQt);
    645 
    646     # Allow override in case QTDIR is not set.
    647     if (checkForArgumentAndRemoveFromARGV("--qt")) {
    648         $isQt = 1;
    649         return;
    650     }
    651 
    652     # The presence of QTDIR only means Qt if --gtk is not on the command-line
    653     if (isGtk() || isWx()) {
    654         $isQt = 0;
    655         return;
    656     }
    657     
    658     $isQt = defined($ENV{'QTDIR'});
    659 }
    660 
    661 sub determineIsSymbian()
    662 {
    663     return if defined($isSymbian);
    664 
    665     if (checkForArgumentAndRemoveFromARGV("--symbian")) {
    666         $isSymbian = 1;
    667         return;
    668     }
    669 
    670     $isSymbian = defined($ENV{'EPOCROOT'});
    671 }
    672 
    673 sub isGtk()
    674 {
    675     determineIsGtk();
    676     return $isGtk;
    677 }
    678 
    679 sub determineIsGtk()
    680 {
    681     return if defined($isGtk);
    682     $isGtk = checkForArgumentAndRemoveFromARGV("--gtk");
    683 }
    684 
    685 sub isWx()
    686 {
    687     determineIsWx();
    688     return $isWx;
    689 }
    690 
    691 sub determineIsWx()
    692 {
    693     return if defined($isWx);
    694     $isWx = checkForArgumentAndRemoveFromARGV("--wx");
    695 }
    696 
    697 sub getWxArgs()
    698 {
    699     if (!@wxArgs) {
    700         @wxArgs = ("");
    701         my $rawWxArgs = "";
    702         foreach my $opt (@ARGV) {
    703             if ($opt =~ /^--wx-args/i ) {
    704                 @ARGV = grep(!/^--wx-args/i, @ARGV);
    705                 $rawWxArgs = $opt;
    706                 $rawWxArgs =~ s/--wx-args=//i;
    707             }
    708         }
    709         @wxArgs = split(/,/, $rawWxArgs);
    710     }
    711     return @wxArgs;
    712 }
    713 
    714 # Determine if this is debian, ubuntu, linspire, or something similar.
    715 sub isDebianBased()
    716 {
    717     return -e "/etc/debian_version";
    718 }
    719 
    720 sub isFedoraBased()
    721 {
    722     return -e "/etc/fedora-release";
    723 }
    724 
    725 sub isChromium()
    726 {
    727     determineIsChromium();
    728     return $isChromium;
    729 }
    730 
    731 sub determineIsChromium()
    732 {
    733     return if defined($isChromium);
    734     $isChromium = checkForArgumentAndRemoveFromARGV("--chromium");
    735 }
    736 
    737 sub isCygwin()
    738 {
    739     return ($^O eq "cygwin") || 0;
    740 }
    741 
    742 sub isDarwin()
    743 {
    744     return ($^O eq "darwin") || 0;
    745 }
    746 
    747 sub isWindows()
    748 {
    749     return ($^O eq "MSWin32") || 0;
    750 }
    751 
    752 sub isMsys()
    753 {
    754     return ($^O eq "msys") || 0;
    755 }
    756 
    757 sub isLinux()
    758 {
    759     return ($^O eq "linux") || 0;
    760 }
    761 
    762 sub isAppleWebKit()
    763 {
    764     return !(isQt() or isGtk() or isWx() or isChromium());
    765 }
    766 
    767 sub isAppleMacWebKit()
    768 {
    769     return isAppleWebKit() && isDarwin();
    770 }
    771 
    772 sub isAppleWinWebKit()
    773 {
    774     return isAppleWebKit() && isCygwin();
    775 }
    776 
    777 sub isPerianInstalled()
    778 {
    779     if (!isAppleWebKit()) {
    780         return 0;
    781     }
    782 
    783     if (-d "/Library/QuickTime/Perian.component") {
    784         return 1;
    785     }
    786 
    787     if (-d "$ENV{HOME}/Library/QuickTime/Perian.component") {
    788         return 1;
    789     }
    790 
    791     return 0;
    792 }
    793 
    794 sub determineOSXVersion()
    795 {
    796     return if $osXVersion;
    797 
    798     if (!isDarwin()) {
    799         $osXVersion = -1;
    800         return;
    801     }
    802 
    803     my $version = `sw_vers -productVersion`;
    804     my @splitVersion = split(/\./, $version);
    805     @splitVersion >= 2 or die "Invalid version $version";
    806     $osXVersion = {
    807             "major" => $splitVersion[0],
    808             "minor" => $splitVersion[1],
    809             "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
    810     };
    811 }
    812 
    813 sub osXVersion()
    814 {
    815     determineOSXVersion();
    816     return $osXVersion;
    817 }
    818 
    819 sub isTiger()
    820 {
    821     return isDarwin() && osXVersion()->{"minor"} == 4;
    822 }
    823 
    824 sub isLeopard()
    825 {
    826     return isDarwin() && osXVersion()->{"minor"} == 5;
    827 }
    828 
    829 sub isSnowLeopard()
    830 {
    831     return isDarwin() && osXVersion()->{"minor"} == 6;
    832 }
    833 
    834 sub isWindowsNT()
    835 {
    836     return $ENV{'OS'} eq 'Windows_NT';
    837 }
    838 
    839 sub relativeScriptsDir()
    840 {
    841     my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel(dirname($0), getcwd()), "");
    842     if ($scriptDir eq "") {
    843         $scriptDir = ".";
    844     }
    845     return $scriptDir;
    846 }
    847 
    848 sub launcherPath()
    849 {
    850     my $relativeScriptsPath = relativeScriptsDir();
    851     if (isGtk() || isQt() || isWx()) {
    852         return "$relativeScriptsPath/run-launcher";
    853     } elsif (isAppleWebKit()) {
    854         return "$relativeScriptsPath/run-safari";
    855     }
    856 }
    857 
    858 sub launcherName()
    859 {
    860     if (isGtk()) {
    861         return "GtkLauncher";
    862     } elsif (isQt()) {
    863         return "QtLauncher";
    864     } elsif (isWx()) {
    865         return "wxBrowser";
    866     } elsif (isAppleWebKit()) {
    867         return "Safari";
    868     }
    869 }
    870 
    871 sub checkRequiredSystemConfig
    872 {
    873     if (isDarwin()) {
    874         chomp(my $productVersion = `sw_vers -productVersion`);
    875         if ($productVersion lt "10.4") {
    876             print "*************************************************************\n";
    877             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
    878             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
    879             print "*************************************************************\n";
    880         }
    881         my $xcodeVersion = `xcodebuild -version`;
    882         if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) {
    883             print "*************************************************************\n";
    884             print "Xcode Version 2.3 or later is required to build WebKit.\n";
    885             print "You have an earlier version of Xcode, thus the build will\n";
    886             print "most likely fail.  The latest Xcode is available from the web:\n";
    887             print "http://developer.apple.com/tools/xcode\n";
    888             print "*************************************************************\n";
    889         }
    890     } elsif (isGtk() or isQt() or isWx()) {
    891         my @cmds = qw(flex bison gperf);
    892         my @missing = ();
    893         foreach my $cmd (@cmds) {
    894             if (not `$cmd --version`) {
    895                 push @missing, $cmd;
    896             }
    897         }
    898         if (@missing) {
    899             my $list = join ", ", @missing;
    900             die "ERROR: $list missing but required to build WebKit.\n";
    901         }
    902     }
    903     # Win32 and other platforms may want to check for minimum config
    904 }
    905 
    906 sub determineWindowsSourceDir()
    907 {
    908     return if $windowsSourceDir;
    909     my $sourceDir = sourceDir();
    910     chomp($windowsSourceDir = `cygpath -w '$sourceDir'`);
    911 }
    912 
    913 sub windowsSourceDir()
    914 {
    915     determineWindowsSourceDir();
    916     return $windowsSourceDir;
    917 }
    918 
    919 sub windowsLibrariesDir()
    920 {
    921     return windowsSourceDir() . "\\WebKitLibraries\\win";
    922 }
    923 
    924 sub windowsOutputDir()
    925 {
    926     return windowsSourceDir() . "\\WebKitBuild";
    927 }
    928 
    929 sub setupAppleWinEnv()
    930 {
    931     return unless isAppleWinWebKit();
    932 
    933     if (isWindowsNT()) {
    934         my $restartNeeded = 0;
    935         my %variablesToSet = ();
    936 
    937         # Setting the environment variable 'CYGWIN' to 'tty' makes cygwin enable extra support (i.e., termios)
    938         # for UNIX-like ttys in the Windows console
    939         $variablesToSet{CYGWIN} = "tty" unless $ENV{CYGWIN};
    940         
    941         # Those environment variables must be set to be able to build inside Visual Studio.
    942         $variablesToSet{WEBKITLIBRARIESDIR} = windowsLibrariesDir() unless $ENV{WEBKITLIBRARIESDIR};
    943         $variablesToSet{WEBKITOUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKITOUTPUTDIR};
    944 
    945         foreach my $variable (keys %variablesToSet) {
    946             print "Setting the Environment Variable '" . $variable . "' to '" . $variablesToSet{$variable} . "'\n\n";
    947             system qw(regtool -s set), '\\HKEY_CURRENT_USER\\Environment\\' . $variable, $variablesToSet{$variable};
    948             $restartNeeded ||= $variable eq "WEBKITLIBRARIESDIR" || $variable eq "WEBKITOUTPUTDIR";
    949         }
    950 
    951         if ($restartNeeded) {
    952             print "Please restart your computer before attempting to build inside Visual Studio.\n\n";
    953         }
    954     } else {
    955         if (!$ENV{'WEBKITLIBRARIESDIR'}) {
    956             print "Warning: You must set the 'WebKitLibrariesDir' environment variable\n";
    957             print "         to be able build WebKit from within Visual Studio.\n";
    958             print "         Make sure that 'WebKitLibrariesDir' points to the\n";
    959             print "         'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n";
    960         }
    961         if (!$ENV{'WEBKITOUTPUTDIR'}) {
    962             print "Warning: You must set the 'WebKitOutputDir' environment variable\n";
    963             print "         to be able build WebKit from within Visual Studio.\n\n";
    964         }
    965     }
    966 }
    967 
    968 sub setupCygwinEnv()
    969 {
    970     return if !isCygwin();
    971     return if $vcBuildPath;
    972 
    973     my $vsInstallDir;
    974     my $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
    975     if ($ENV{'VSINSTALLDIR'}) {
    976         $vsInstallDir = $ENV{'VSINSTALLDIR'};
    977     } else {
    978         $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
    979     }
    980     $vsInstallDir = `cygpath "$vsInstallDir"`;
    981     chomp $vsInstallDir;
    982     $vcBuildPath = "$vsInstallDir/Common7/IDE/devenv.com";
    983     if (-e $vcBuildPath) {
    984         # Visual Studio is installed; we can use pdevenv to build.
    985         $vcBuildPath = File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts pdevenv));
    986     } else {
    987         # Visual Studio not found, try VC++ Express
    988         $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe";
    989         if (! -e $vcBuildPath) {
    990             print "*************************************************************\n";
    991             print "Cannot find '$vcBuildPath'\n";
    992             print "Please execute the file 'vcvars32.bat' from\n";
    993             print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
    994             print "to setup the necessary environment variables.\n";
    995             print "*************************************************************\n";
    996             die;
    997         }
    998     }
    999 
   1000     my $qtSDKPath = "$programFilesPath/QuickTime SDK";
   1001     if (0 && ! -e $qtSDKPath) {
   1002         print "*************************************************************\n";
   1003         print "Cannot find '$qtSDKPath'\n";
   1004         print "Please download the QuickTime SDK for Windows from\n";
   1005         print "http://developer.apple.com/quicktime/download/\n";
   1006         print "*************************************************************\n";
   1007         die;
   1008     }
   1009     
   1010     chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'};
   1011 
   1012     $windowsTmpPath = `cygpath -w /tmp`;
   1013     chomp $windowsTmpPath;
   1014     print "Building results into: ", baseProductDir(), "\n";
   1015     print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n";
   1016     print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n";
   1017 }
   1018 
   1019 sub copyInspectorFrontendFiles
   1020 {
   1021     my $productDir = productDir();
   1022     my $sourceInspectorPath = sourceDir() . "/WebCore/inspector/front-end/";
   1023     my $inspectorResourcesDirPath = $ENV{"WEBKITINSPECTORRESOURCESDIR"};
   1024 
   1025     if (!defined($inspectorResourcesDirPath)) {
   1026         $inspectorResourcesDirPath = "";
   1027     }
   1028 
   1029     if (isAppleMacWebKit()) {
   1030         $inspectorResourcesDirPath = $productDir . "/WebCore.framework/Resources/inspector";
   1031     } elsif (isAppleWinWebKit()) {
   1032         $inspectorResourcesDirPath = $productDir . "/WebKit.resources/inspector";
   1033     } elsif (isQt() || isGtk()) {
   1034         my $prefix = $ENV{"WebKitInstallationPrefix"};
   1035         $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/webkit-1.0/webinspector";
   1036     }
   1037 
   1038     if (! -d $inspectorResourcesDirPath) {
   1039         print "*************************************************************\n";
   1040         print "Cannot find '$inspectorResourcesDirPath'.\n" if (defined($inspectorResourcesDirPath));
   1041         print "Make sure that you have built WebKit first.\n" if (! -d $productDir || defined($inspectorResourcesDirPath));
   1042         print "Optionally, set the environment variable 'WebKitInspectorResourcesDir'\n";
   1043         print "to point to the directory that contains the WebKit Inspector front-end\n";
   1044         print "files for the built WebCore framework.\n";
   1045         print "*************************************************************\n";
   1046         die;
   1047     }
   1048     return system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=.svn/", !isQt() ? "--exclude=/WebKit.qrc" : "", $sourceInspectorPath, $inspectorResourcesDirPath;
   1049 }
   1050 
   1051 sub buildXCodeProject($$@)
   1052 {
   1053     my ($project, $clean, @extraOptions) = @_;
   1054 
   1055     if ($clean) {
   1056         push(@extraOptions, "-alltargets");
   1057         push(@extraOptions, "clean");
   1058     }
   1059 
   1060     return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions;
   1061 }
   1062 
   1063 sub buildVisualStudioProject
   1064 {
   1065     my ($project, $clean) = @_;
   1066     setupCygwinEnv();
   1067 
   1068     my $config = configurationForVisualStudio();
   1069 
   1070     chomp(my $winProjectPath = `cygpath -w "$project"`);
   1071     
   1072     my $action = "/build";
   1073     if ($clean) {
   1074         $action = "/clean";
   1075     }
   1076 
   1077     my @command = ($vcBuildPath, $winProjectPath, $action, $config);
   1078 
   1079     print join(" ", @command), "\n";
   1080     return system @command;
   1081 }
   1082 
   1083 sub downloadWafIfNeeded
   1084 {
   1085     # get / update waf if needed
   1086     my $waf = "$sourceDir/WebKitTools/wx/waf";
   1087     my $wafURL = 'http://wxwebkit.wxcommunity.com/downloads/deps/waf';
   1088     if (!-f $waf) {
   1089         my $result = system "curl -o $waf $wafURL";
   1090         chmod 0755, $waf;
   1091     }
   1092 }
   1093 
   1094 sub buildWafProject
   1095 {
   1096     my ($project, $shouldClean, @options) = @_;
   1097     
   1098     # set the PYTHONPATH for waf
   1099     my $pythonPath = $ENV{'PYTHONPATH'};
   1100     if (!defined($pythonPath)) {
   1101         $pythonPath = '';
   1102     }
   1103     my $sourceDir = sourceDir();
   1104     my $newPythonPath = "$sourceDir/WebKitTools/wx/build:$pythonPath";
   1105     if (isCygwin()) {
   1106         $newPythonPath = `cygpath --mixed --path $newPythonPath`;
   1107     }
   1108     $ENV{'PYTHONPATH'} = $newPythonPath;
   1109     
   1110     print "Building $project\n";
   1111 
   1112     my $wafCommand = "$sourceDir/WebKitTools/wx/waf";
   1113     if ($ENV{'WXWEBKIT_WAF'}) {
   1114         $wafCommand = $ENV{'WXWEBKIT_WAF'};
   1115     }
   1116     if (isCygwin()) {
   1117         $wafCommand = `cygpath --windows "$wafCommand"`;
   1118         chomp($wafCommand);
   1119     }
   1120     if ($shouldClean) {
   1121         return system $wafCommand, "clean", "distclean";
   1122     }
   1123     
   1124     return system $wafCommand, 'configure', 'build', 'install', @options;
   1125 }
   1126 
   1127 sub retrieveQMakespecVar
   1128 {
   1129     my $mkspec = $_[0];
   1130     my $varname = $_[1];
   1131 
   1132     my $varvalue = undef;
   1133     #print "retrieveMakespecVar " . $mkspec . ", " . $varname . "\n";
   1134 
   1135     local *SPEC;
   1136     open SPEC, "<$mkspec" or return $varvalue;
   1137     while (<SPEC>) {
   1138         if ($_ =~ /\s*include\((.+)\)/) {
   1139             # open the included mkspec
   1140             my $oldcwd = getcwd();
   1141             (my $volume, my $directories, my $file) = File::Spec->splitpath($mkspec);
   1142             my $newcwd = "$volume$directories";
   1143             chdir $newcwd if $newcwd;
   1144             $varvalue = retrieveQMakespecVar($1, $varname);
   1145             chdir $oldcwd;
   1146         } elsif ($_ =~ /$varname\s*=\s*([^\s]+)/) {
   1147             $varvalue = $1;
   1148             last;
   1149         }
   1150     }
   1151     close SPEC;
   1152     return $varvalue;
   1153 }
   1154 
   1155 sub qtMakeCommand($)
   1156 {
   1157     my ($qmakebin) = @_;
   1158     chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`);
   1159     $mkspec .= "/default";
   1160     my $compiler = retrieveQMakespecVar("$mkspec/qmake.conf", "QMAKE_CC");
   1161 
   1162     #print "default spec: " . $mkspec . "\n";
   1163     #print "compiler found: " . $compiler . "\n";
   1164 
   1165     if ($compiler eq "cl") {
   1166         return "nmake";
   1167     }
   1168 
   1169     return "make";
   1170 }
   1171 
   1172 sub autotoolsFlag($$)
   1173 {
   1174     my ($flag, $feature) = @_;
   1175     my $prefix = $flag ? "--enable" : "--disable";
   1176 
   1177     return $prefix . '-' . $feature;
   1178 }
   1179 
   1180 sub buildAutotoolsProject($@)
   1181 {
   1182     my ($clean, @buildParams) = @_;
   1183 
   1184     my $make = 'make';
   1185     my $dir = productDir();
   1186     my $config = passedConfiguration() || configuration();
   1187     my $prefix = $ENV{"WebKitInstallationPrefix"};
   1188 
   1189     my @buildArgs = ();
   1190     my $makeArgs = $ENV{"WebKitMakeArguments"} || "";
   1191     for my $i (0 .. $#buildParams) {
   1192         my $opt = $buildParams[$i];
   1193         if ($opt =~ /^--makeargs=(.*)/i ) {
   1194             $makeArgs = $makeArgs . " " . $1;
   1195         } else {
   1196             push @buildArgs, $opt;
   1197         }
   1198     }
   1199 
   1200     push @buildArgs, "--prefix=" . $prefix if defined($prefix);
   1201 
   1202     # check if configuration is Debug
   1203     if ($config =~ m/debug/i) {
   1204         push @buildArgs, "--enable-debug";
   1205     } else {
   1206         push @buildArgs, "--disable-debug";
   1207     }
   1208 
   1209     # Use rm to clean the build directory since distclean may miss files
   1210     if ($clean && -d $dir) {
   1211         system "rm", "-rf", "$dir";
   1212     }
   1213 
   1214     if (! -d $dir) {
   1215         system "mkdir", "-p", "$dir";
   1216         if (! -d $dir) {
   1217             die "Failed to create build directory " . $dir;
   1218         }
   1219     }
   1220 
   1221     chdir $dir or die "Failed to cd into " . $dir . "\n";
   1222 
   1223     my $result;
   1224     if ($clean) {
   1225         #$result = system $make, "distclean";
   1226         return 0;
   1227     }
   1228 
   1229     print "Calling configure in " . $dir . "\n\n";
   1230     print "Installation directory: $prefix\n" if(defined($prefix));
   1231 
   1232     # Make the path relative since it will appear in all -I compiler flags.
   1233     # Long argument lists cause bizarre slowdowns in libtool.
   1234     my $relSourceDir = File::Spec->abs2rel($sourceDir);
   1235     $relSourceDir = "." if !$relSourceDir;
   1236 
   1237     $result = system "$relSourceDir/autogen.sh", @buildArgs;
   1238     if ($result ne 0) {
   1239         die "Failed to setup build environment using 'autotools'!\n";
   1240     }
   1241 
   1242     $result = system "$make $makeArgs";
   1243     if ($result ne 0) {
   1244         die "\nFailed to build WebKit using '$make'!\n";
   1245     }
   1246 
   1247     chdir ".." or die;
   1248     return $result;
   1249 }
   1250 
   1251 sub buildQMakeProject($@)
   1252 {
   1253     my ($clean, @buildParams) = @_;
   1254 
   1255     my @buildArgs = ("-r");
   1256 
   1257     my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH
   1258     my $makeargs = "";
   1259     for my $i (0 .. $#buildParams) {
   1260         my $opt = $buildParams[$i];
   1261         if ($opt =~ /^--qmake=(.*)/i ) {
   1262             $qmakebin = $1;
   1263         } elsif ($opt =~ /^--qmakearg=(.*)/i ) {
   1264             push @buildArgs, $1;
   1265         } elsif ($opt =~ /^--makeargs=(.*)/i ) {
   1266             $makeargs = $1;
   1267         } else {
   1268             push @buildArgs, $opt;
   1269         }
   1270     }
   1271 
   1272     my $make = qtMakeCommand($qmakebin);
   1273     my $config = configuration();
   1274     my $prefix = $ENV{"WebKitInstallationPrefix"};
   1275     my $dir = File::Spec->canonpath(baseProductDir());
   1276     $dir = File::Spec->catfile($dir, $config) unless isSymbian();
   1277     File::Path::mkpath($dir);
   1278     chdir $dir or die "Failed to cd into " . $dir . "\n";
   1279 
   1280     print "Generating derived sources\n\n";
   1281 
   1282     my @dsQmakeArgs = @buildArgs;
   1283     push @dsQmakeArgs, "-r";
   1284     push @dsQmakeArgs, sourceDir() . "/DerivedSources.pro";
   1285     push @dsQmakeArgs, "-o Makefile.DerivedSources";
   1286     print "Calling '$qmakebin @dsQmakeArgs' in " . $dir . "\n\n";
   1287     my $result = system "$qmakebin @dsQmakeArgs";
   1288     if ($result ne 0) {
   1289         die "Failed while running $qmakebin to generate derived sources!\n";
   1290     }
   1291 
   1292     my $dsMakefile = "Makefile.DerivedSources";
   1293 
   1294     # Iterate over different source directories manually to workaround a problem with qmake+extraTargets+s60
   1295     for my $subdir ("JavaScriptCore", "WebCore", "WebKit/qt/Api") {
   1296         print "Calling '$make $makeargs -f $dsMakefile generated_files' in " . $dir . "/$subdir\n\n";
   1297         if ($make eq "nmake") {
   1298             my $subdirWindows = $subdir;
   1299             $subdirWindows =~ s:/:\\:g;
   1300             $result = system "pushd $subdirWindows && $make $makeargs -f $dsMakefile generated_files && popd";
   1301         } else {
   1302             $result = system "$make $makeargs -C $subdir -f $dsMakefile generated_files";
   1303         }
   1304         if ($result ne 0) {
   1305             die "Failed to generate ${subdir}'s derived sources!\n";
   1306         }
   1307     }
   1308 
   1309     push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config";
   1310     push @buildArgs, sourceDir() . "/WebKit.pro";
   1311     if ($config =~ m/debug/i) {
   1312         push @buildArgs, "CONFIG-=release";
   1313         push @buildArgs, "CONFIG+=debug";
   1314     } else {
   1315         my $passedConfig = passedConfiguration() || "";
   1316         if (!isDarwin() || $passedConfig =~ m/release/i) {
   1317             push @buildArgs, "CONFIG+=release";
   1318             push @buildArgs, "CONFIG-=debug";
   1319         } else {
   1320             push @buildArgs, "CONFIG+=debug";
   1321             push @buildArgs, "CONFIG+=debug_and_release";
   1322         }
   1323     }
   1324 
   1325     print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n";
   1326     print "Installation directory: $prefix\n" if(defined($prefix));
   1327 
   1328     $result = system "$qmakebin @buildArgs";
   1329     if ($result ne 0) {
   1330        die "Failed to setup build environment using $qmakebin!\n";
   1331     }
   1332 
   1333     if ($clean) {
   1334       print "Calling '$make $makeargs distclean' in " . $dir . "\n\n";
   1335       $result = system "$make $makeargs distclean";
   1336     } elsif (isSymbian()) {
   1337       print "\n\nWebKit is now configured for building, but you have to make\n";
   1338       print "a choice about the target yourself. To start the build run:\n\n";
   1339       print "    make release-armv5|debug-winscw|etc.\n\n";
   1340     } else {
   1341       print "Calling '$make $makeargs' in " . $dir . "\n\n";
   1342       $result = system "$make $makeargs";
   1343     }
   1344 
   1345     chdir ".." or die;
   1346     return $result;
   1347 }
   1348 
   1349 sub buildQMakeQtProject($$@)
   1350 {
   1351     my ($project, $clean, @buildArgs) = @_;
   1352 
   1353     return buildQMakeProject($clean, @buildArgs);
   1354 }
   1355 
   1356 sub buildGtkProject($$@)
   1357 {
   1358     my ($project, $clean, @buildArgs) = @_;
   1359 
   1360     if ($project ne "WebKit") {
   1361         die "The Gtk port builds JavaScriptCore, WebCore and WebKit in one shot! Only call it for 'WebKit'.\n";
   1362     }
   1363 
   1364     return buildAutotoolsProject($clean, @buildArgs);
   1365 }
   1366 
   1367 sub buildChromiumMakefile($$$)
   1368 {
   1369     my ($dir, $target, $clean) = @_;
   1370     chdir $dir;
   1371     if ($clean) {
   1372         return system qw(rm -rf out);
   1373     }
   1374     my $config = configuration();
   1375     my @command = ("make", "-j4", "BUILDTYPE=$config", $target);
   1376     print join(" ", @command) . "\n";
   1377     return system @command;
   1378 }
   1379 
   1380 sub buildChromiumVisualStudioProject($$)
   1381 {
   1382     my ($projectPath, $clean) = @_;
   1383 
   1384     my $config = configuration();
   1385     my $action = "/build";
   1386     $action = "/clean" if $clean;
   1387 
   1388     # Find Visual Studio installation.
   1389     my $vsInstallDir;
   1390     my $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
   1391     if ($ENV{'VSINSTALLDIR'}) {
   1392         $vsInstallDir = $ENV{'VSINSTALLDIR'};
   1393     } else {
   1394         $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
   1395     }
   1396     $vsInstallDir = `cygpath "$vsInstallDir"` if isCygwin();
   1397     chomp $vsInstallDir;
   1398     $vcBuildPath = "$vsInstallDir/Common7/IDE/devenv.com";
   1399 
   1400     # Create command line and execute it.
   1401     my @command = ($vcBuildPath, $projectPath, $action, $config);
   1402     print "Building results into: ", baseProductDir(), "\n";
   1403     print join(" ", @command), "\n";
   1404     return system @command;
   1405 }
   1406 
   1407 sub buildChromium($@)
   1408 {
   1409     my ($clean, @options) = @_;
   1410 
   1411     my $result = 1;
   1412     if (isDarwin()) {
   1413         # Mac build - builds the root xcode project.
   1414         $result = buildXCodeProject("WebKit/chromium/WebKit", $clean, (@options));
   1415     } elsif (isCygwin() || isWindows()) {
   1416         # Windows build - builds the root visual studio solution.
   1417         $result = buildChromiumVisualStudioProject("WebKit/chromium/WebKit.sln", $clean);
   1418     } elsif (isLinux()) {
   1419         # Linux build - build using make.
   1420         $ result = buildChromiumMakefile("WebKit/chromium/", "all", $clean);
   1421     } else {
   1422         print STDERR "This platform is not supported by chromium.\n";
   1423     }
   1424     return $result;
   1425 }
   1426 
   1427 sub appleApplicationSupportPath
   1428 {
   1429     open INSTALL_DIR, "</proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Apple\ Inc./Apple\ Application\ Support/InstallDir";
   1430     my $path = <INSTALL_DIR>;
   1431     $path =~ s/[\r\n\x00].*//;
   1432     close INSTALL_DIR;
   1433 
   1434     my $unixPath = `cygpath -u '$path'`;
   1435     chomp $unixPath;
   1436     return $unixPath;
   1437 }
   1438 
   1439 sub setPathForRunningWebKitApp
   1440 {
   1441     my ($env) = @_;
   1442 
   1443     if (isAppleWinWebKit()) {
   1444         $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), appleApplicationSupportPath(), $env->{PATH} || "");
   1445     } elsif (isQt()) {
   1446         my $qtLibs = `qmake -query QT_INSTALL_LIBS`;
   1447         $qtLibs =~ s/[\n|\r]$//g;
   1448         $env->{PATH} = join(';', $qtLibs, productDir() . "/lib", $env->{PATH} || "");
   1449     }
   1450 }
   1451 
   1452 sub runSafari
   1453 {
   1454     my ($debugger) = @_;
   1455 
   1456     if (isAppleMacWebKit()) {
   1457         return system "$FindBin::Bin/gdb-safari", @ARGV if $debugger;
   1458 
   1459         my $productDir = productDir();
   1460         print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
   1461         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
   1462         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
   1463         if (!isTiger() && architecture()) {
   1464             return system "arch", "-" . architecture(), safariPath(), @ARGV;
   1465         } else {
   1466             return system safariPath(), @ARGV;
   1467         }
   1468     }
   1469 
   1470     if (isAppleWinWebKit()) {
   1471         my $script = "run-webkit-nightly.cmd";
   1472         my $result = system "cp", "$FindBin::Bin/$script", productDir();
   1473         return $result if $result;
   1474 
   1475         my $cwd = getcwd();
   1476         chdir productDir();
   1477 
   1478         my $debuggerFlag = $debugger ? "/debugger" : "";
   1479         $result = system "cmd", "/c", "call $script $debuggerFlag";
   1480         chdir $cwd;
   1481         return $result;
   1482     }
   1483 
   1484     return 1;
   1485 }
   1486 
   1487 1;
   1488