0e4d2cd2b704de23d5af8d5c3e0f876485eb2157
[WebKit-https.git] / WebKitTools / Scripts / webkitdirs.pm
1 # Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 #
7 # 1.  Redistributions of source code must retain the above copyright
8 #     notice, this list of conditions and the following disclaimer. 
9 # 2.  Redistributions in binary form must reproduce the above copyright
10 #     notice, this list of conditions and the following disclaimer in the
11 #     documentation and/or other materials provided with the distribution. 
12 # 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
13 #     its contributors may be used to endorse or promote products derived
14 #     from this software without specific prior written permission. 
15 #
16 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
17 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
20 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 # Module to share code to get to WebKit directories.
28
29 use strict;
30 use warnings;
31 use FindBin;
32 use File::Basename;
33 use POSIX;
34 use VCSUtils;
35
36 BEGIN {
37    use Exporter   ();
38    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
39    $VERSION     = 1.00;
40    @ISA         = qw(Exporter);
41    @EXPORT      = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks &currentSVNRevision);
42    %EXPORT_TAGS = ( );
43    @EXPORT_OK   = ();
44 }
45
46 our @EXPORT_OK;
47
48 my $baseProductDir;
49 my @baseProductDirOption;
50 my $configuration;
51 my $configurationForVisualStudio;
52 my $configurationProductDir;
53 my $sourceDir;
54 my $currentSVNRevision;
55 my $osXVersion;
56 my $isQt;
57 my $isGtk;
58 my $isWx;
59
60 # Variables for Win32 support
61 my $vcBuildPath;
62 my $windowsTmpPath;
63
64 sub determineSourceDir
65 {
66     return if $sourceDir;
67     $sourceDir = $FindBin::Bin;
68     
69     # walks up path checking each directory to see if it is the main WebKit project dir, 
70     # defined by containing JavaScriptCore, WebCore, and WebKit
71     until ((-d "$sourceDir/JavaScriptCore" && -d "$sourceDir/WebCore" && -d "$sourceDir/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
72     {
73         if ($sourceDir !~ s|/[^/]+$||) {
74             die "Could not find top level webkit directory above source directory using FindBin.\n";
75         }
76     }
77
78     $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
79 }
80
81 # used for scripts which are stored in a non-standard location
82 sub setSourceDir($)
83 {
84     ($sourceDir) = @_;
85 }
86
87 sub determineBaseProductDir
88 {
89     return if defined $baseProductDir;
90     determineSourceDir();
91     if (isOSX()) {
92         open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> /dev/null |" or die;
93         $baseProductDir = join '', <PRODUCT>;
94         close PRODUCT;
95
96         $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
97         undef $baseProductDir unless $baseProductDir =~ /^\//;
98
99         if (!defined($baseProductDir)) {
100             open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die;
101             $baseProductDir = <PRODUCT>;
102             close PRODUCT;
103             if ($baseProductDir) {
104                 chomp $baseProductDir;
105                 undef $baseProductDir unless $baseProductDir =~ /^\//;
106             }
107         }
108     } else {
109         $baseProductDir = $ENV{"WEBKITOUTPUTDIR"};
110         if (isCygwin() && $baseProductDir) {
111             my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
112             chomp $unixBuildPath;
113             $baseProductDir = $unixBuildPath;
114         }
115     }
116
117     if ($baseProductDir && isOSX()) {
118         $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
119         $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
120         $baseProductDir =~ s|^~/|$ENV{HOME}/|;
121         die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
122         die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
123         @baseProductDirOption = ();
124     }
125
126     if (!defined($baseProductDir)) {
127         $baseProductDir = "$sourceDir/WebKitBuild";
128
129         if (isGit() && isGitBranchBuild()) {
130             my $branch = gitBranch();
131             $baseProductDir = "$baseProductDir/$branch";
132         }
133
134         @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir") if (isOSX());
135         if (isCygwin()) {
136             my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
137             chomp $dosBuildPath;
138             $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath;
139         }
140     }
141 }
142
143 sub setBaseProductDir($)
144 {
145     ($baseProductDir) = @_;
146 }
147
148 sub determineConfiguration
149 {
150     return if defined $configuration;
151     determineBaseProductDir();
152     if (open CONFIGURATION, "$baseProductDir/Configuration") {
153         $configuration = <CONFIGURATION>;
154         close CONFIGURATION;
155     }
156     if ($configuration) {
157         chomp $configuration;
158         # compatibility for people who have old Configuration files
159         $configuration = "Release" if $configuration eq "Deployment";
160         $configuration = "Debug" if $configuration eq "Development";
161     } else {
162         $configuration = "Release";
163     }
164 }
165
166 sub determineConfigurationForVisualStudio
167 {
168     return if defined $configurationForVisualStudio;
169     determineConfiguration();
170     $configurationForVisualStudio = $configuration;
171     return unless $configuration eq "Debug";
172     setupCygwinEnv();
173     chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`);
174     $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll";
175 }
176
177 sub determineConfigurationProductDir
178 {
179     return if defined $configurationProductDir;
180     determineBaseProductDir();
181     if(isCygwin() && !isWx()) {
182         $configurationProductDir = "$baseProductDir/bin";
183     } else {
184         determineConfiguration();
185         $configurationProductDir = "$baseProductDir/$configuration";
186     }
187 }
188
189 sub setConfigurationProductDir($)
190 {
191     ($configurationProductDir) = @_;
192 }
193
194 sub determineCurrentSVNRevision
195 {
196     return if defined $currentSVNRevision;
197     determineSourceDir();
198     my $svnInfo = `LC_ALL=C svn info $sourceDir | grep Revision:`;
199     ($currentSVNRevision) = ($svnInfo =~ m/Revision: (\d+).*/g);
200     die "Unable to determine current SVN revision in $sourceDir" unless (defined $currentSVNRevision);
201     return $currentSVNRevision;
202 }
203
204
205 sub chdirWebKit
206 {
207     determineSourceDir();
208     chdir $sourceDir or die;
209 }
210
211 sub baseProductDir
212 {
213     determineBaseProductDir();
214     return $baseProductDir;
215 }
216
217 sub sourceDir
218 {
219     determineSourceDir();
220     return $sourceDir;
221 }
222
223 sub productDir
224 {
225     determineConfigurationProductDir();
226     return $configurationProductDir;
227 }
228
229 sub configuration()
230 {
231     determineConfiguration();
232     return $configuration;
233 }
234
235 sub configurationForVisualStudio()
236 {
237     determineConfigurationForVisualStudio();
238     return $configurationForVisualStudio;
239 }
240
241 sub currentSVNRevision
242 {
243     determineCurrentSVNRevision();
244     return $currentSVNRevision;
245 }
246
247 sub XcodeOptions
248 {
249     determineBaseProductDir();
250     determineConfiguration();
251     return (@baseProductDirOption, "-configuration", $configuration);
252 }
253
254 sub XcodeOptionString
255 {
256     return join " ", XcodeOptions();
257 }
258
259 sub XcodeOptionStringNoConfig
260 {
261     return join " ", @baseProductDirOption;
262 }
263
264 my $passedConfiguration;
265 my $searchedForPassedConfiguration;
266 sub determinePassedConfiguration
267 {
268     return if $searchedForPassedConfiguration;
269     $searchedForPassedConfiguration = 1;
270     for my $i (0 .. $#ARGV) {
271         my $opt = $ARGV[$i];
272         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
273             splice(@ARGV, $i, 1);
274             $passedConfiguration = "Debug";
275             return;
276         }
277         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
278             splice(@ARGV, $i, 1);
279             $passedConfiguration = "Release";
280             return;
281         }
282     }
283     $passedConfiguration = undef;
284 }
285
286 sub passedConfiguration
287 {
288     determinePassedConfiguration();
289     return $passedConfiguration;
290 }
291
292 sub setConfiguration
293 {
294     if (my $config = shift @_) {
295         $configuration = $config;
296         return;
297     }
298
299     determinePassedConfiguration();
300     $configuration = $passedConfiguration if $passedConfiguration;
301 }
302
303 sub safariPathFromSafariBundle
304 {
305     my ($safariBundle) = @_;
306
307     return "$safariBundle/Contents/MacOS/Safari" if isOSX();
308     return $safariBundle if isCygwin();
309 }
310
311 sub installedSafariPath
312 {
313     my $safariBundle;
314
315     if (isOSX()) {
316         $safariBundle = "/Applications/Safari.app";
317     } elsif (isCygwin()) {
318         $safariBundle = `"$configurationProductDir/FindSafari.exe"`;
319         $safariBundle =~ s/[\r\n]+$//;
320         $safariBundle = `cygpath -u '$safariBundle'`;
321         $safariBundle =~ s/[\r\n]+$//;
322         $safariBundle .= "Safari.exe";
323     }
324
325     return safariPathFromSafariBundle($safariBundle);
326 }
327
328 # Locate Safari.
329 sub safariPath
330 {
331     # Use WEBKIT_SAFARI environment variable if present.
332     my $safariBundle = $ENV{WEBKIT_SAFARI};
333     if (!$safariBundle) {
334         determineConfigurationProductDir();
335         # Use Safari.app in product directory if present (good for Safari development team).
336         if (isOSX() && -d "$configurationProductDir/Safari.app") {
337             $safariBundle = "$configurationProductDir/Safari.app";
338         } elsif (isCygwin() && -x "$configurationProductDir/bin/Safari.exe") {
339             $safariBundle = "$configurationProductDir/bin/Safari.exe";
340         } else {
341             return installedSafariPath();
342         }
343     }
344     my $safariPath = safariPathFromSafariBundle($safariBundle);
345     die "Can't find executable at $safariPath.\n" if isOSX() && !-x $safariPath;
346     return $safariPath;
347 }
348
349 sub builtDylibPathForName
350 {
351     my $framework = shift;
352     determineConfigurationProductDir();
353     if (isQt() or isGtk()) {
354         return "$configurationProductDir/$framework";
355     }
356     if (isOSX()) {
357         return "$configurationProductDir/$framework.framework/Versions/A/$framework";
358     }
359     if (isCygwin()) {
360         if ($framework eq "JavaScriptCore") {
361                 return "$baseProductDir/lib/$framework.lib";
362         } else {
363             return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib";
364         }
365     }
366
367     die "Unsupported platform, can't determine built library locations.";
368 }
369
370 # Check to see that all the frameworks are built.
371 sub checkFrameworks
372 {
373     return if isCygwin();
374     my @frameworks = ("JavaScriptCore", "WebCore");
375     push(@frameworks, "WebKit") if isOSX();
376     for my $framework (@frameworks) {
377         my $path = builtDylibPathForName($framework);
378         die "Can't find built framework at \"$path\".\n" unless -x $path;
379     }
380 }
381
382 sub hasSVGSupport
383 {
384     return 0 if isCygwin();
385
386     my $path = shift;
387
388     if (isQt()) {
389         return 1;
390     }
391
392     if (isGtk() and $path =~ /WebCore/) {
393         if (useQmake()) {
394             $path .= "/../lib/libWebKitGtk.so";
395         } else {
396             $path .= "/../.libs/webkit-1.0.so";
397         }
398     }
399
400     my $hasSVGSupport = 0;
401     if (-e $path) {
402         open NM, "-|", "nm", $path or die;
403         while (<NM>) {
404             $hasSVGSupport = 1 if /SVGElement/;
405         }
406         close NM;
407     }
408     return $hasSVGSupport;
409 }
410
411 sub removeLibraryDependingOnSVG
412 {
413     my $frameworkName = shift;
414     my $shouldHaveSVG = shift;
415
416     my $path = builtDylibPathForName($frameworkName);
417     return unless -x $path;
418
419     my $hasSVG = hasSVGSupport($path);
420     system "rm -f $path" if ($shouldHaveSVG xor $hasSVG);
421 }
422
423 sub checkWebCoreSVGSupport
424 {
425     my $required = shift;
426     my $framework = "WebCore";
427     my $path = builtDylibPathForName($framework);
428     my $hasSVG = hasSVGSupport($path);
429     if ($required && !$hasSVG) {
430         die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n";
431     }
432     return $hasSVG;
433 }
434
435 sub isQt()
436 {
437     determineIsQt();
438     return $isQt;
439 }
440
441 sub checkArgv($)
442 {
443     my $argToCheck = shift;
444     foreach my $opt (@ARGV) {
445         if ($opt =~ /^$argToCheck/i ) {
446             @ARGV = grep(!/^$argToCheck/i, @ARGV);
447             return 1;
448         }
449     }
450     return 0;
451 }
452
453 sub determineIsQt()
454 {
455     return if defined($isQt);
456
457     # Allow override in case QTDIR is not set.
458     if (checkArgv("--qt")) {
459         $isQt = 1;
460         return;
461     }
462
463     # The presence of QTDIR only means Qt if --gtk is not on the command-line
464     if (isGtk()) {
465         $isQt = 0;
466         return;
467     }
468     
469     $isQt = defined($ENV{'QTDIR'});
470 }
471
472 sub useQmake()
473 {
474     return 1 if isQt();
475     return 0 if !defined($ENV{WEBKIT_BUILD_SYSTEM});
476     return $ENV{WEBKIT_BUILD_SYSTEM} eq "qmake";
477 }
478
479 sub isGtk()
480 {
481     determineIsGtk();
482     return $isGtk;
483 }
484
485 sub determineIsGtk()
486 {
487     return if defined($isGtk);
488
489     if (checkArgv("--gtk")) {
490         $isGtk = 1;
491     } else {
492         $isGtk = 0;
493     }
494 }
495
496 sub isWx()
497 {
498     determineIsWx();
499     return $isWx;
500 }
501
502 sub determineIsWx()
503 {
504     return if defined($isWx);
505
506     if (checkArgv("--wx")) {
507         $isWx = 1;
508     } else {
509         $isWx = 0;
510     }
511 }
512
513 # Determine if this is debian, ubuntu, linspire, or something similar.
514 sub isDebianBased()
515 {
516     return -e "/etc/debian_version";
517 }
518
519 sub isCygwin()
520 {
521     return ($^O eq "cygwin");
522 }
523
524 sub isDarwin()
525 {
526     return ($^O eq "darwin");
527 }
528
529 sub isOSX()
530 {
531     return isDarwin() unless (isQt() or isGtk() or isWx());
532     return 0;
533 }
534
535 sub determineOSXVersion()
536 {
537     return if $osXVersion;
538
539     if (!isOSX()) {
540         $osXVersion = -1;
541         return;
542     }
543
544     my $version = `sw_vers -productVersion`;
545     my @splitVersion = split(/\./, $version);
546     @splitVersion >= 2 or die "Invalid version $version";
547     $osXVersion = {
548             "major" => $splitVersion[0],
549             "minor" => $splitVersion[1],
550             "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
551     };
552 }
553
554 sub osXVersion()
555 {
556     determineOSXVersion();
557     return $osXVersion;
558 }
559
560 sub isTiger()
561 {
562     return isOSX() && osXVersion()->{"minor"} == 4;
563 }
564
565 sub isLeopard()
566 {
567     return isOSX() && osXVersion()->{"minor"} == 5;
568 }
569
570 sub relativeScriptsDir()
571 {
572     my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel(dirname($0), getcwd()), "");
573     if ($scriptDir eq "") {
574         $scriptDir = ".";
575     }
576     return $scriptDir;
577 }
578
579 sub launcherPath()
580 {
581     my $relativeScriptsPath = relativeScriptsDir();
582     if (isGtk() || isQt()) {
583         return "$relativeScriptsPath/run-launcher";
584     } elsif (isOSX() || isCygwin()) {
585         return "$relativeScriptsPath/run-safari";
586     }
587 }
588
589 sub launcherName()
590 {
591     if (isGtk()) {
592         return "GtkLauncher";
593     } elsif (isQt()) {
594         return "QtLauncher";
595     } elsif (isOSX() || isCygwin()) {
596         return "Safari";
597     }
598 }
599
600 sub checkRequiredSystemConfig
601 {
602     if (isOSX()) {
603         chomp(my $productVersion = `sw_vers -productVersion`);
604         if ($productVersion lt "10.4") {
605             print "*************************************************************\n";
606             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
607             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
608             print "*************************************************************\n";
609         }
610         my $xcodeVersion = `xcodebuild -version`;
611         if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) {
612             print "*************************************************************\n";
613             print "Xcode Version 2.3 or later is required to build WebKit.\n";
614             print "You have an earlier version of Xcode, thus the build will\n";
615             print "most likely fail.  The latest Xcode is available from the web:\n";
616             print "http://developer.apple.com/tools/xcode\n";
617             print "*************************************************************\n";
618         }
619     } elsif (isGtk() or isQt() or isWx()) {
620         my @cmds = qw(flex bison gperf);
621         my @missing = ();
622         foreach my $cmd (@cmds) {
623             if (not `$cmd --version`) {
624                 push @missing, $cmd;
625             }
626         }
627         if (@missing) {
628             my $list = join ", ", @missing;
629             die "ERROR: $list missing but required to build WebKit.\n";
630         }
631     }
632     # Win32 and other platforms may want to check for minimum config
633 }
634
635 sub setupCygwinEnv()
636 {
637     return if !isCygwin();
638     return if $vcBuildPath;
639
640     my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`;
641     chomp $programFilesPath;
642     $vcBuildPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com";
643     if (! -e $vcBuildPath) {
644         # VC++ not found, try VC++ Express
645         my $vsInstallDir;
646         if ($ENV{'VSINSTALLDIR'}) {
647             $vsInstallDir = $ENV{'VSINSTALLDIR'};
648         } else {
649             $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
650             $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
651         }
652         $vsInstallDir = `cygpath "$vsInstallDir"`;
653         chomp $vsInstallDir;
654         $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe";
655         if (! -e $vcBuildPath) {
656             print "*************************************************************\n";
657             print "Cannot find '$vcBuildPath'\n";
658             print "Please execute the file 'vcvars32.bat' from\n";
659             print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
660             print "to setup the necessary environment variables.\n";
661             print "*************************************************************\n";
662             die;
663         }
664     }
665
666     my $qtSDKPath = "$programFilesPath/QuickTime SDK";
667     if (0 && ! -e $qtSDKPath) {
668         print "*************************************************************\n";
669         print "Cannot find '$qtSDKPath'\n";
670         print "Please download the QuickTime SDK for Windows from\n";
671         print "http://developer.apple.com/quicktime/download/\n";
672         print "*************************************************************\n";
673         die;
674     }
675     
676     chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'};
677
678     $windowsTmpPath = `cygpath -w /tmp`;
679     chomp $windowsTmpPath;
680     print "Building results into: ", baseProductDir(), "\n";
681     print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n";
682     print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n";
683 }
684
685 sub buildVisualStudioProject
686 {
687     my ($project, $clean) = @_;
688     setupCygwinEnv();
689
690     my $config = configurationForVisualStudio();
691
692     chomp(my $winProjectPath = `cygpath -w "$project"`);
693     
694     my $command = "/build";
695     if ($clean) {
696         $command = "/clean";
697     }
698
699     print "$vcBuildPath $winProjectPath /build $config\n";
700     return system $vcBuildPath, $winProjectPath, $command, $config;
701 }
702
703 sub qtMakeCommand($)
704 {
705     my ($qmakebin) = @_;
706     chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`);
707     $mkspec .= "/default";
708
709     my $compiler = "";
710     open SPEC, "<$mkspec/qmake.conf" or return "make";
711     while (<SPEC>) {
712         if ($_ =~ /QMAKE_CC\s*=\s*([^\s]+)/) {
713             $compiler = $1;
714         }
715     }
716     close SPEC;
717
718     #print "default spec: " . $mkspec . "\n";
719     #print "compiler found: " . $compiler . "\n";
720
721     if ($compiler eq "cl") {
722         return "nmake";
723     }
724
725     return "make";
726 }
727
728 sub autotoolsFlag($$)
729 {
730     my ($flag, $feature) = @_;
731     my $prefix = $flag ? "--enable" : "--disable";
732
733     return $prefix . '-' . $feature;
734 }
735
736 sub buildAutotoolsProject($@)
737 {
738     my ($clean, @buildArgs) = @_;
739
740     my $make = 'make';
741     my $dir = productDir();
742     my $config = passedConfiguration() || configuration();
743     my $prefix = $ENV{"WebKitInstallationPrefix"};
744
745     # check if configuration is Debug
746     if ($config =~ m/debug/i) {
747         push @buildArgs, "--enable-debug";
748     } else {
749         push @buildArgs, "--disable-debug";
750     }
751
752     if (! -d $dir) {
753         system "mkdir", "-p", "$dir";
754         if (! -d $dir) {
755             die "Failed to create build directory " . $dir;
756         }
757     }
758
759     chdir $dir or die "Failed to cd into " . $dir . "\n";
760
761     my $result;
762     if ($clean) {
763         $result = system $make, "distclean";
764         return 0;
765     }
766
767     print "Calling autogen.sh in " . $dir . "\n\n";
768     print "Installation directory: $prefix\n" if(defined($prefix));
769
770     $result = system "$sourceDir/autogen.sh --help";
771     if ($result ne 0) {
772         die "Failed to setup build environment using 'autotools'!\n";
773     }
774
775     print "Calling configure in " . $dir . "\n\n";
776     print "Installation directory: $prefix\n" if(defined($prefix));
777
778     # The autotools configure script requires bash explicitly at time of writing
779     $result = system "/bin/bash", "$sourceDir/configure", "SHELL=/bin/bash", @buildArgs;
780     if ($result ne 0) {
781         die "Failed to setup build environment using 'autotools'!\n";
782     }
783
784     $result = system $make;
785     if ($result ne 0) {
786         die "\nFailed to build WebKit using '$make'!\n";
787     }
788
789     chdir ".." or die;
790     return $result;
791 }
792
793 sub buildQMakeProject($@)
794 {
795     my ($clean, @buildArgs) = @_;
796
797     push @buildArgs, "-r";
798
799     my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH
800     for my $i (0 .. $#ARGV) {
801         my $opt = $ARGV[$i];
802         if ($opt =~ /^--qmake=(.*)/i ) {
803             $qmakebin = $1;
804         } elsif ($opt =~ /^--qmakearg=(.*)/i ) {
805             push @buildArgs, $1;
806         }
807     }
808
809     my $make = qtMakeCommand($qmakebin);
810     my $config = configuration();
811     my $prefix = $ENV{"WebKitInstallationPrefix"};
812
813     push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config";
814     push @buildArgs, sourceDir() . "/WebKit.pro";
815     if ($config =~ m/debug/i) {
816         push @buildArgs, "CONFIG-=release";
817         push @buildArgs, "CONFIG+=debug";
818     } else {
819         push @buildArgs, "CONFIG+=release";
820         push @buildArgs, "CONFIG-=debug";
821     }
822
823     my $dir = baseProductDir();
824     if (! -d $dir) {
825         system "mkdir", "-p", "$dir";
826         if (! -d $dir) {
827             die "Failed to create product directory " . $dir;
828         }
829     }
830     $dir = $dir . "/$config";
831     if (! -d $dir) {
832         system "mkdir", "-p", "$dir";
833         if (! -d $dir) {
834             die "Failed to create build directory " . $dir;
835         }
836     }
837
838     chdir $dir or die "Failed to cd into " . $dir . "\n";
839
840     print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n";
841     print "Installation directory: $prefix\n" if(defined($prefix));
842
843     my $result = system $qmakebin, @buildArgs;
844     if ($result ne 0) {
845        die "Failed to setup build environment using $qmakebin!\n";
846     }
847
848     if ($clean) {
849       $result = system "$make distclean";
850     } else {
851       $result = system "$make";
852     }
853
854     chdir ".." or die;
855     return $result;
856 }
857
858 sub buildQMakeQtProject($$)
859 {
860     my ($project, $clean) = @_;
861
862     my @buildArgs = ("CONFIG+=qt-port");
863     return buildQMakeProject($clean, @buildArgs);
864 }
865
866 sub buildGtkProject($$@)
867 {
868     my ($project, $clean, @buildArgs) = @_;
869
870     if ($project ne "WebKit") {
871         die "The Gtk port builds JavaScriptCore, WebCore and WebKit in one shot! Only call it for 'WebKit'.\n";
872     }
873
874     if (useQmake()) {
875         my @buildArgs = ("CONFIG+=gtk-port", "CONFIG-=qt");
876         return buildQMakeProject($clean, @buildArgs);
877     } else {
878         return buildAutotoolsProject($clean, @buildArgs);
879     }
880 }
881
882 sub setPathForRunningWebKitApp
883 {
884     my ($env) = @_;
885
886     return unless isCygwin();
887
888     $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), $env->{PATH} || "");
889 }
890
891 sub exitStatus($)
892 {
893     my ($returnvalue) = @_;
894     if ($^O eq "MSWin32") {
895         return $returnvalue >> 8;
896     }
897     return WEXITSTATUS($returnvalue);
898 }
899
900 sub runSafari
901 {
902     my ($debugger) = @_;
903
904     if (isOSX()) {
905         return system "$FindBin::Bin/gdb-safari", @ARGV if $debugger;
906
907         my $productDir = productDir();
908         print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
909         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
910         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
911         return system safariPath(), @ARGV;
912     }
913
914     if (isCygwin()) {
915         my $script = "run-webkit-nightly.cmd";
916         my $result = system "cp", "$FindBin::Bin/$script", productDir();
917         return $result if $result;
918
919         my $cwd = getcwd();
920         chdir productDir();
921
922         my $debuggerFlag = $debugger ? "/debugger" : "";
923         $result = system "cmd", "/c", "call $script $debuggerFlag";
924         chdir $cwd;
925         return $result;
926     }
927
928     return 1;
929 }
930
931 sub runDrosera
932 {
933     my ($debugger) = @_;
934
935     if (isOSX()) {
936         return system "$FindBin::Bin/gdb-drosera", @ARGV if $debugger;
937
938         my $productDir = productDir();
939         print "Starting Drosera with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
940         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
941         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
942
943         my $droseraPath = "$productDir/Drosera.app/Contents/MacOS/Drosera";
944         return system $droseraPath, @ARGV;
945     }
946
947     if (isCygwin()) {
948         print "Running Drosera\n";
949         my $script = "run-drosera-nightly.cmd";
950         my $prodDir = productDir();
951         my $result = system "cp", "$FindBin::Bin/$script", $prodDir;
952         return $result if $result;
953
954         my $cwd = getcwd();
955         chdir $prodDir;
956
957         my $debuggerFlag = $debugger ? "/debugger" : "";
958         $result = system "cmd", "/c", "call $script $debuggerFlag";
959         chdir $cwd;
960         return $result;
961     }
962
963     return 1;
964 }
965
966 1;