1 # Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
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.
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.
27 # Module to share code to get to WebKit directories.
37 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
40 @EXPORT = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks ¤tSVNRevision);
48 my @baseProductDirOption;
50 my $configurationForVisualStudio;
51 my $configurationProductDir;
53 my $currentSVNRevision;
58 # Variables for Win32 support
62 sub determineSourceDir
65 $sourceDir = $FindBin::Bin;
67 # walks up path checking each directory to see if it is the main WebKit project dir,
68 # defined by containing JavaScriptCore, WebCore, and WebKit
69 until ((-d "$sourceDir/JavaScriptCore" && -d "$sourceDir/WebCore" && -d "$sourceDir/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
71 if ($sourceDir !~ s|/[^/]+$||) {
72 die "Could not find top level webkit directory above source directory using FindBin.\n";
76 $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
79 # used for scripts which are stored in a non-standard location
85 sub determineBaseProductDir
87 return if defined $baseProductDir;
90 open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> /dev/null |" or die;
91 $baseProductDir = join '', <PRODUCT>;
94 $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
95 undef $baseProductDir unless $baseProductDir =~ /^\//;
97 if (!defined($baseProductDir)) {
98 open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die;
99 $baseProductDir = <PRODUCT>;
101 if ($baseProductDir) {
102 chomp $baseProductDir;
103 undef $baseProductDir unless $baseProductDir =~ /^\//;
107 $baseProductDir = $ENV{"WEBKITOUTPUTDIR"};
108 if (isCygwin() && $baseProductDir) {
109 my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
110 chomp $unixBuildPath;
111 $baseProductDir = $unixBuildPath;
115 if ($baseProductDir && isOSX()) {
116 $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
117 $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
118 $baseProductDir =~ s|^~/|$ENV{HOME}/|;
119 die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
120 die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
121 @baseProductDirOption = ();
124 if (!defined($baseProductDir)) {
125 $baseProductDir = "$sourceDir/WebKitBuild";
126 @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir") if (isOSX());
128 my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
130 $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath;
135 sub setBaseProductDir($)
137 ($baseProductDir) = @_;
140 sub determineConfiguration
142 return if defined $configuration;
143 determineBaseProductDir();
144 if (open CONFIGURATION, "$baseProductDir/Configuration") {
145 $configuration = <CONFIGURATION>;
148 if ($configuration) {
149 chomp $configuration;
150 # compatibility for people who have old Configuration files
151 $configuration = "Release" if $configuration eq "Deployment";
152 $configuration = "Debug" if $configuration eq "Development";
154 $configuration = "Release";
158 sub determineConfigurationForVisualStudio
160 return if defined $configurationForVisualStudio;
161 determineConfiguration();
162 $configurationForVisualStudio = $configuration;
163 return unless $configuration eq "Debug";
165 chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`);
166 $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll";
169 sub determineConfigurationProductDir
171 return if defined $configurationProductDir;
172 determineBaseProductDir();
174 $configurationProductDir = "$baseProductDir/bin";
176 determineConfiguration();
177 $configurationProductDir = "$baseProductDir/$configuration";
181 sub setConfigurationProductDir($)
183 ($configurationProductDir) = @_;
186 sub determineCurrentSVNRevision
188 return if defined $currentSVNRevision;
189 determineSourceDir();
190 my $svnInfo = `LC_ALL=C svn info $sourceDir | grep Revision:`;
191 ($currentSVNRevision) = ($svnInfo =~ m/Revision: (\d+).*/g);
192 die "Unable to determine current SVN revision in $sourceDir" unless (defined $currentSVNRevision);
193 return $currentSVNRevision;
199 determineSourceDir();
200 chdir $sourceDir or die;
205 determineBaseProductDir();
206 return $baseProductDir;
211 determineSourceDir();
217 determineConfigurationProductDir();
218 return $configurationProductDir;
223 determineConfiguration();
224 return $configuration;
227 sub configurationForVisualStudio()
229 determineConfigurationForVisualStudio();
230 return $configurationForVisualStudio;
233 sub currentSVNRevision
235 determineCurrentSVNRevision();
236 return $currentSVNRevision;
241 determineBaseProductDir();
242 determineConfiguration();
243 return (@baseProductDirOption, "-configuration", $configuration);
246 sub XcodeOptionString
248 return join " ", XcodeOptions();
251 sub XcodeOptionStringNoConfig
253 return join " ", @baseProductDirOption;
256 my $passedConfiguration;
257 my $searchedForPassedConfiguration;
258 sub determinePassedConfiguration
260 return if $searchedForPassedConfiguration;
261 $searchedForPassedConfiguration = 1;
262 for my $i (0 .. $#ARGV) {
264 if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
265 splice(@ARGV, $i, 1);
266 $passedConfiguration = "Debug";
269 if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
270 splice(@ARGV, $i, 1);
271 $passedConfiguration = "Release";
275 $passedConfiguration = undef;
278 sub passedConfiguration
280 determinePassedConfiguration();
281 return $passedConfiguration;
286 if (my $config = shift @_) {
287 $configuration = $config;
291 determinePassedConfiguration();
292 $configuration = $passedConfiguration if $passedConfiguration;
295 sub safariPathFromSafariBundle
297 my ($safariBundle) = @_;
299 return "$safariBundle/Contents/MacOS/Safari" if isOSX();
300 return $safariBundle if isCygwin();
303 sub installedSafariPath
308 $safariBundle = "/Applications/Safari.app";
309 } elsif (isCygwin()) {
310 $safariBundle = `"$configurationProductDir/FindSafari.exe"`;
311 $safariBundle =~ s/[\r\n]+$//;
312 $safariBundle = `cygpath -u '$safariBundle'`;
313 $safariBundle =~ s/[\r\n]+$//;
314 $safariBundle .= "Safari.exe";
317 return safariPathFromSafariBundle($safariBundle);
323 # Use WEBKIT_SAFARI environment variable if present.
324 my $safariBundle = $ENV{WEBKIT_SAFARI};
325 if (!$safariBundle) {
326 determineConfigurationProductDir();
327 # Use Safari.app in product directory if present (good for Safari development team).
328 if (isOSX() && -d "$configurationProductDir/Safari.app") {
329 $safariBundle = "$configurationProductDir/Safari.app";
330 } elsif (isCygwin() && -x "$configurationProductDir/bin/Safari.exe") {
331 $safariBundle = "$configurationProductDir/bin/Safari.exe";
333 return installedSafariPath();
336 my $safariPath = safariPathFromSafariBundle($safariBundle);
337 die "Can't find executable at $safariPath.\n" if isOSX() && !-x $safariPath;
341 sub builtDylibPathForName
343 my $framework = shift;
344 determineConfigurationProductDir();
345 if (isQt() or isGtk()) {
346 return "$configurationProductDir/$framework";
349 return "$configurationProductDir/$framework.framework/Versions/A/$framework";
352 if ($framework eq "JavaScriptCore") {
353 return "$baseProductDir/lib/$framework.lib";
355 return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib";
359 die "Unsupported platform, can't determine built library locations.";
362 # Check to see that all the frameworks are built.
365 return if isCygwin();
366 my @frameworks = ("JavaScriptCore", "WebCore");
367 push(@frameworks, "WebKit") if isOSX();
368 for my $framework (@frameworks) {
369 my $path = builtDylibPathForName($framework);
370 die "Can't find built framework at \"$path\".\n" unless -x $path;
376 return 0 if isCygwin();
384 if (isGtk() and $path =~ /WebCore/) {
385 $path .= "/../lib/libWebKitGtk.so";
388 open NM, "-|", "nm", $path or die;
389 my $hasSVGSupport = 0;
391 $hasSVGSupport = 1 if /SVGElement/;
394 return $hasSVGSupport;
397 sub removeLibraryDependingOnSVG
399 my $frameworkName = shift;
400 my $shouldHaveSVG = shift;
402 my $path = builtDylibPathForName($frameworkName);
403 return unless -x $path;
405 my $hasSVG = hasSVGSupport($path);
406 system "rm -f $path" if ($shouldHaveSVG xor $hasSVG);
409 sub checkWebCoreSVGSupport
411 my $required = shift;
412 my $framework = "WebCore";
413 my $path = builtDylibPathForName($framework);
414 my $hasSVG = hasSVGSupport($path);
415 if ($required && !$hasSVG) {
416 die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n";
429 my $argToCheck = shift;
430 foreach my $opt (@ARGV) {
431 if ($opt =~ /^$argToCheck/i ) {
432 @ARGV = grep(!/^$argToCheck/i, @ARGV);
441 return if defined($isQt);
443 # Allow override in case QTDIR is not set.
444 if (checkArgv("--qt")) {
449 # The presence of QTDIR only means Qt if --gtk is not on the command-line
455 $isQt = defined($ENV{'QTDIR'});
466 return if defined($isGtk);
468 if (checkArgv("--gtk")) {
477 return ($^O eq "cygwin");
482 return ($^O eq "darwin");
487 return isDarwin() unless (isQt() or isGtk());
491 sub determineOSXVersion()
493 return if $osXVersion;
500 my $version = `sw_vers -productVersion`;
501 my @splitVersion = split(/\./, $version);
502 @splitVersion >= 2 or die "Invalid version $version";
504 "major" => $splitVersion[0],
505 "minor" => $splitVersion[1],
506 "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
512 determineOSXVersion();
518 return isOSX() && osXVersion()->{"minor"} == 4;
523 return isOSX() && osXVersion()->{"minor"} == 5;
526 sub relativeScriptsDir()
528 my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel(dirname($0), getcwd()), "");
529 if ($scriptDir eq "") {
537 my $relativeScriptsPath = relativeScriptsDir();
538 if (isGtk() || isQt()) {
539 return "$relativeScriptsPath/run-launcher";
540 } elsif (isOSX() || isCygwin()) {
541 return "$relativeScriptsPath/run-safari";
548 return "GtkLauncher";
551 } elsif (isOSX() || isCygwin()) {
556 sub checkRequiredSystemConfig
559 chomp(my $productVersion = `sw_vers -productVersion`);
560 if ($productVersion lt "10.4") {
561 print "*************************************************************\n";
562 print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
563 print "You have " . $productVersion . ", thus the build will most likely fail.\n";
564 print "*************************************************************\n";
566 my $xcodeVersion = `xcodebuild -version`;
567 if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) {
568 print "*************************************************************\n";
569 print "Xcode Version 2.3 or later is required to build WebKit.\n";
570 print "You have an earlier version of Xcode, thus the build will\n";
571 print "most likely fail. The latest Xcode is available from the web:\n";
572 print "http://developer.apple.com/tools/xcode\n";
573 print "*************************************************************\n";
575 } elsif (isGtk() or isQt()) {
576 my @cmds = qw(flex bison gperf);
578 foreach my $cmd (@cmds) {
579 if (not `$cmd --version`) {
584 my $list = join ", ", @missing;
585 die "ERROR: $list missing but required to build WebKit.\n";
588 # Win32 and other platforms may want to check for minimum config
593 return if !isCygwin();
594 return if $vcBuildPath;
596 my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`;
597 chomp $programFilesPath;
598 $vcBuildPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com";
599 if (! -e $vcBuildPath) {
600 # VC++ not found, try VC++ Express
602 if ($ENV{'VSINSTALLDIR'}) {
603 $vsInstallDir = $ENV{'VSINSTALLDIR'};
605 $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
606 $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
608 $vsInstallDir = `cygpath "$vsInstallDir"`;
610 $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe";
611 if (! -e $vcBuildPath) {
612 print "*************************************************************\n";
613 print "Cannot find '$vcBuildPath'\n";
614 print "Please execute the file 'vcvars32.bat' from\n";
615 print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
616 print "to setup the necessary environment variables.\n";
617 print "*************************************************************\n";
622 chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'};
624 $windowsTmpPath = `cygpath -w /tmp`;
625 chomp $windowsTmpPath;
626 print "Building results into: ", baseProductDir(), "\n";
627 print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n";
628 print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n";
631 sub buildVisualStudioProject($)
636 my $config = configurationForVisualStudio();
638 chomp(my $winProjectPath = `cygpath -w "$project"`);
640 print "$vcBuildPath $winProjectPath /build $config\n";
641 return system $vcBuildPath, $winProjectPath, "/build", $config;
647 chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`);
648 $mkspec .= "/default";
651 open SPEC, "<$mkspec/qmake.conf" or return "make";
653 if ($_ =~ /QMAKE_CC\s*=\s*([^\s]+)/) {
659 #print "default spec: " . $mkspec . "\n";
660 #print "compiler found: " . $compiler . "\n";
662 if ($compiler eq "cl") {
669 sub buildQMakeProject(@)
673 push @buildArgs, "-r";
675 my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH
676 for my $i (0 .. $#ARGV) {
678 if ($opt =~ /^--qmake=(.*)/i ) {
680 } elsif ($opt =~ /^--qmakearg=(.*)/i ) {
685 my $make = qtMakeCommand($qmakebin);
686 my $config = configuration();
687 my $prefix = $ENV{"WebKitInstallationPrefix"};
689 push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config";
690 push @buildArgs, sourceDir() . "/WebKit.pro";
691 if ($config =~ m/debug/i) {
692 push @buildArgs, "CONFIG-=release";
693 push @buildArgs, "CONFIG+=debug";
695 push @buildArgs, "CONFIG+=release";
696 push @buildArgs, "CONFIG-=debug";
699 my $dir = baseProductDir();
701 mkdir $dir or die "Failed to create product directory " . $dir;
703 $dir = $dir . "/$config";
705 mkdir $dir or die "Failed to create build directory " . $dir;
708 chdir $dir or die "Failed to cd into " . $dir . "\n";
710 print "Calling '$qmakebin @buildArgs' in " . $dir . " ...\n\n";
711 print "Installation directory: $prefix\n" if(defined($prefix));
713 my $result = system $qmakebin, @buildArgs;
715 die "Failed to setup build environment using $qmakebin!\n";
718 my $clean = $ENV{"WEBKIT_FULLBUILD"};
720 if (defined $clean) {
721 system "$make clean";
724 $result = system "$make";
729 sub buildQMakeQtProject($)
733 my @buildArgs = ("CONFIG+=qt-port");
734 return buildQMakeProject(@buildArgs);
737 sub buildQMakeGtkProject($)
741 if ($project ne "WebKit") {
742 die "The Gtk portbuilds JavaScriptCore/WebCore/WebKitQt in one shot! Only call it for 'WebKit'.\n";
745 my @buildArgs = ("CONFIG+=gtk-port");
746 push @buildArgs, "CONFIG-=qt";
748 return buildQMakeProject(@buildArgs);
751 sub setPathForRunningWebKitApp
755 return unless isCygwin();
757 $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), $env->{PATH} || "");
762 my ($returnvalue) = @_;
763 if ($^O eq "MSWin32") {
764 return $returnvalue >> 8;
766 return WEXITSTATUS($returnvalue);