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