2006-03-03 Eric Seidel <eseidel@apple.com>
[WebKit-https.git] / WebKitTools / Scripts / webkitdirs.pm
1 # Copyright (C) 2005, 2006 Apple Computer, 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
33 BEGIN {
34    use Exporter   ();
35    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
36    $VERSION     = 1.00;
37    @ISA         = qw(Exporter);
38    @EXPORT      = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks);
39    %EXPORT_TAGS = ( );
40    @EXPORT_OK   = ();
41 }
42
43 our @EXPORT_OK;
44
45 my $baseProductDir;
46 my @baseProductDirOption;
47 my $configuration;
48 my $configurationProductDir;
49 my $sourceDir;
50
51 # Variables for Win32 support
52 my $devenvPath;
53 my $windowsTmpPath;
54
55 sub determineSourceDir
56 {
57     return if $sourceDir;
58     $sourceDir = $FindBin::Bin;
59     if ($sourceDir !~ s|/[^/]+/[^/]+$||) {
60         die "Could not find two levels above source directory using FindBin.\n";
61     }
62 }
63
64 # used for scripts which are stored in a non-standard location
65 sub setSourceDir($)
66 {
67     $sourceDir = $_;
68 }
69
70 sub determineBaseProductDir
71 {
72     return if defined $baseProductDir;
73     determineSourceDir();
74     if (isOSX()) {
75         open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die;
76         $baseProductDir = <PRODUCT>;
77         close PRODUCT;
78         if ($baseProductDir) {
79             chomp $baseProductDir;
80         }
81     } else {
82         $baseProductDir = $ENV{"WebKitOutputDir"};
83         if (isCygwin() && $baseProductDir) {
84             my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
85             chomp $unixBuildPath;
86             $baseProductDir = $unixBuildPath;
87         }
88     }
89
90     if ($baseProductDir && isOSX()) {
91         $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
92         $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
93         $baseProductDir =~ s|^~/|$ENV{HOME}/|;
94         die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
95         die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
96         @baseProductDirOption = ();
97     }
98
99     if (!defined($baseProductDir)) {
100         $baseProductDir = "$sourceDir/WebKitBuild";
101         @baseProductDirOption = ("SYMROOT=$baseProductDir") if (isOSX());
102         if (isCygwin()) {
103             my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
104             chomp $dosBuildPath;
105             $ENV{"WebKitOutputDir"} = $dosBuildPath;
106         }
107     }
108 }
109
110 sub determineConfiguration
111 {
112     return if defined $configuration;
113     determineBaseProductDir();
114     if (open CONFIGURATION, "$baseProductDir/Configuration") {
115         $configuration = <CONFIGURATION>;
116         close CONFIGURATION;
117     }
118     if ($configuration) {
119         chomp $configuration;
120         # compatibility for people who have old Configuration files
121         $configuration = "Release" if $configuration eq "Deployment";
122         $configuration = "Debug" if $configuration eq "Development";
123     } else {
124         $configuration = "Release";
125     }
126 }
127
128 sub determineConfigurationProductDir
129 {
130     return if defined $configurationProductDir;
131     determineBaseProductDir();
132     determineConfiguration();
133     $configurationProductDir = "$baseProductDir/$configuration";
134 }
135
136 sub chdirWebKit
137 {
138     determineSourceDir();
139     chdir $sourceDir or die;
140 }
141
142 sub baseProductDir
143 {
144     determineBaseProductDir();
145     return $baseProductDir;
146 }
147
148 sub productDir
149 {
150     determineConfigurationProductDir();
151     return $configurationProductDir;
152 }
153
154 sub configuration()
155 {
156     determineConfiguration();
157     return $configuration;
158 }
159
160 sub XcodeOptions
161 {
162     determineBaseProductDir();
163     determineConfiguration();
164     return (@baseProductDirOption, "-configuration", $configuration);
165 }
166
167 sub XcodeOptionString
168 {
169     return join " ", XcodeOptions();
170 }
171
172 sub XcodeOptionStringNoConfig
173 {
174     return join " ", @baseProductDirOption;
175 }
176
177 my $passedConfiguration;
178 my $searchedForPassedConfiguration;
179 sub determinePassedConfiguration
180 {
181     return if $searchedForPassedConfiguration;
182     $searchedForPassedConfiguration = 1;
183     for my $i (0 .. $#ARGV) {
184         my $opt = $ARGV[$i];
185         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
186             splice(@ARGV, $i, 1);
187             $passedConfiguration = "Debug";
188             return;
189         }
190         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
191             splice(@ARGV, $i, 1);
192             $passedConfiguration = "Release";
193             return;
194         }
195     }
196     $passedConfiguration = undef;
197 }
198
199 sub passedConfiguration
200 {
201     determinePassedConfiguration();
202     return $passedConfiguration;
203 }
204
205 sub setConfiguration
206 {
207     determinePassedConfiguration();
208     $configuration = $passedConfiguration if $passedConfiguration;
209 }
210
211 # Locate Safari.
212 sub safariPath
213 {
214     # Use WEBKIT_SAFARI environment variable if present.
215     my $safariBundle = $ENV{WEBKIT_SAFARI};
216     if (!$safariBundle) {
217         determineConfigurationProductDir();
218         # Use Safari.app in product directory if present (good for Safari development team).
219         if (-d "$configurationProductDir/Safari.app") {
220             $safariBundle = "$configurationProductDir/Safari.app";
221         } else {
222             # Otherwise use Safari.app in Applications directory.
223             $safariBundle = "/Applications/Safari.app";
224         }
225     }
226     my $safariPath = "$safariBundle/Contents/MacOS/Safari";
227     die "Can't find executable at $safariPath.\n" unless -x $safariPath;
228     return $safariPath;
229 }
230
231 sub builtDylibPathForName
232 {
233     my $framework = shift;
234     determineConfigurationProductDir();
235     if (isOSX()) {
236         return "$configurationProductDir/$framework.framework/Versions/A/$framework";
237     }
238     if (isCygwin()) {
239         return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib";
240     }
241     die "Unsupported platform, can't determine built library locations.";
242 }
243
244 # Check to see that all the frameworks are built.
245 sub checkFrameworks
246 {
247     my @frameworks = ("JavaScriptCore", "WebCore");
248     push(@frameworks, "WebKit") if isOSX();
249     for my $framework (@frameworks) {
250         my $path = builtDylibPathForName($framework);
251         die "Can't find built framework at \"$path\".\n" unless -x $path;
252     }
253 }
254
255 sub hasSVGSupport
256 {
257     return 0 if isCygwin(); 
258     my $path = shift;
259     open NM, "-|", "nm", $path or die;
260     my $hasSVGSupport = 0;
261     while (<NM>) {
262         $hasSVGSupport = 1 if /SVGElement/;
263     }
264     close NM;
265     return $hasSVGSupport;
266 }
267
268 sub removeLibraryDependingOnSVG
269 {
270     my $frameworkName = shift;
271     my $shouldHaveSVG = shift;
272     
273     my $path = builtDylibPathForName($frameworkName);
274     return unless -x $path;
275     
276     my $hasSVG = hasSVGSupport($path);
277     system "rm -f $path" if ($shouldHaveSVG xor $hasSVG);
278 }
279
280 sub checkWebCoreSVGSupport
281 {
282     my $required = shift;
283     my $framework = "WebCore";
284     my $path = builtDylibPathForName($framework);
285     my $hasSVG = hasSVGSupport($path);
286     if ($required && !$hasSVG) {
287         die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n";
288     }
289     return $hasSVG;
290 }
291
292
293 sub isCygwin()
294 {
295     return ($^O eq "cygwin");
296 }
297
298 sub isOSX()
299 {
300     return ($^O eq "darwin");
301 }
302
303 sub checkRequiredSystemConfig
304 {
305     if (isOSX()) {
306         chomp(my $productVersion = `sw_vers -productVersion`);
307         if ($productVersion lt "10.4") {
308             print "*************************************************************\n";
309             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
310             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
311             print "*************************************************************\n";
312         }
313         my $xcodeVersion = `xcodebuild -version`;
314         if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 620) {
315             print "*************************************************************\n";
316             print "Xcode Version 2.1 or later is required to build WebKit.\n";
317             print "You have an earlier version of Xcode, thus the build will\n";
318             print "most likely fail.  The latest Xcode is available from the web:\n";
319             print "http://developer.apple.com/tools/xcode\n";
320             print "*************************************************************\n";
321         }
322     }
323     # Win32 and other platforms may want to check for minimum config
324 }
325
326 sub setupCygwinEnv()
327 {
328     return if !isCygwin();
329     return if $devenvPath;
330
331     my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`;
332     chomp $programFilesPath;
333     $devenvPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.exe";
334     $windowsTmpPath = `cygpath -w /tmp`;
335     chomp $windowsTmpPath;
336     print "Building results into: ", baseProductDir(), "\n";
337     print "WebKitOutputDir is set to: ", $ENV{"WebKitOutputDir"}, "\n";
338 }
339
340 sub buildVisualStudioProject($)
341 {
342     my ($project) = @_;
343     setupCygwinEnv();
344
345     chdir "$project.vcproj" or die "Failed to cd into $project.vcproj\n";
346     my $config = configuration();
347
348     my $resultsFile = "$windowsTmpPath\\buildresults.txt";
349     unlink($resultsFile);
350     print "$devenvPath $project.sln /build $config /Out $resultsFile\n";
351     my $result = system $devenvPath, "$project.sln", "/build", $config, "/Out", $resultsFile;
352     system "cat", $resultsFile;
353     chdir ".." or die;
354     return $result;
355 }
356
357 1;