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