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