2006-10-02 Nikolas Zimmermann <zimmermann@kde.org>
[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
130 sub determineConfigurationProductDir
131 {
132     return if defined $configurationProductDir;
133     determineBaseProductDir();
134     determineConfiguration();
135     $configurationProductDir = "$baseProductDir/$configuration";
136 }
137
138 sub determineCurrentSVNRevision
139 {
140     return if defined $currentSVNRevision;
141     determineSourceDir();
142     my $svnInfo = `svn info $sourceDir | grep Revision:`;
143     ($currentSVNRevision) = ($svnInfo =~ m/Revision: (\d+).*/g);
144     die "Unable to determine current SVN revision in $sourceDir" unless (defined $currentSVNRevision);
145     return $currentSVNRevision;
146 }
147
148
149 sub chdirWebKit
150 {
151     determineSourceDir();
152     chdir $sourceDir or die;
153 }
154
155 sub baseProductDir
156 {
157     determineBaseProductDir();
158     return $baseProductDir;
159 }
160
161 sub productDir
162 {
163     determineConfigurationProductDir();
164     return $configurationProductDir;
165 }
166
167 sub configuration()
168 {
169     determineConfiguration();
170     return $configuration;
171 }
172
173 sub currentSVNRevision
174 {
175     determineCurrentSVNRevision();
176     return $currentSVNRevision;
177 }
178
179 sub XcodeOptions
180 {
181     determineBaseProductDir();
182     determineConfiguration();
183     return (@baseProductDirOption, "-configuration", $configuration);
184 }
185
186 sub XcodeOptionString
187 {
188     return join " ", XcodeOptions();
189 }
190
191 sub XcodeOptionStringNoConfig
192 {
193     return join " ", @baseProductDirOption;
194 }
195
196 my $passedConfiguration;
197 my $searchedForPassedConfiguration;
198 sub determinePassedConfiguration
199 {
200     return if $searchedForPassedConfiguration;
201     $searchedForPassedConfiguration = 1;
202     for my $i (0 .. $#ARGV) {
203         my $opt = $ARGV[$i];
204         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
205             splice(@ARGV, $i, 1);
206             $passedConfiguration = "Debug";
207             return;
208         }
209         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
210             splice(@ARGV, $i, 1);
211             $passedConfiguration = "Release";
212             return;
213         }
214     }
215     $passedConfiguration = undef;
216 }
217
218 sub passedConfiguration
219 {
220     determinePassedConfiguration();
221     return $passedConfiguration;
222 }
223
224 sub setConfiguration
225 {
226     determinePassedConfiguration();
227     $configuration = $passedConfiguration if $passedConfiguration;
228 }
229
230 # Locate Safari.
231 sub safariPath
232 {
233     # Use WEBKIT_SAFARI environment variable if present.
234     my $safariBundle = $ENV{WEBKIT_SAFARI};
235     if (!$safariBundle) {
236         determineConfigurationProductDir();
237         # Use Safari.app in product directory if present (good for Safari development team).
238         if (-d "$configurationProductDir/Safari.app") {
239             $safariBundle = "$configurationProductDir/Safari.app";
240         } else {
241             # Otherwise use Safari.app in Applications directory.
242             $safariBundle = "/Applications/Safari.app";
243         }
244     }
245     my $safariPath = "$safariBundle/Contents/MacOS/Safari";
246     die "Can't find executable at $safariPath.\n" unless -x $safariPath;
247     return $safariPath;
248 }
249
250 sub builtDylibPathForName
251 {
252     my $framework = shift;
253     determineConfigurationProductDir();
254     if (isOSX()) {
255         return "$configurationProductDir/$framework.framework/Versions/A/$framework";
256     }
257     if (isCygwin()) {
258         if ($framework eq "JavaScriptCore") {
259                 return "$baseProductDir/lib/$framework.lib";
260         } else {
261             return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib";
262         }
263     }
264     if (isQt()) {
265         return "$baseProductDir/../../../$framework";
266     }
267
268     die "Unsupported platform, can't determine built library locations.";
269 }
270
271 # Check to see that all the frameworks are built.
272 sub checkFrameworks
273 {
274     my @frameworks = ("JavaScriptCore", "WebCore");
275     push(@frameworks, "WebKit") if isOSX();
276     for my $framework (@frameworks) {
277         my $path = builtDylibPathForName($framework);
278         die "Can't find built framework at \"$path\".\n" unless -x $path;
279     }
280 }
281
282 sub hasSVGSupport
283 {
284     return 0 if isCygwin();
285
286     my $path = shift;
287
288     if ((isQt()) and ($path =~ /WebCore/)) {
289         $path .= "/../lib/libWebCore-unity.so";
290     }
291
292     open NM, "-|", "nm", $path or die;
293     my $hasSVGSupport = 0;
294     while (<NM>) {
295         $hasSVGSupport = 1 if /SVGElement/;
296     }
297     close NM;
298     return $hasSVGSupport;
299 }
300
301 sub removeLibraryDependingOnSVG
302 {
303     my $frameworkName = shift;
304     my $shouldHaveSVG = shift;
305
306     my $path = builtDylibPathForName($frameworkName);
307     return unless -x $path;
308
309     my $hasSVG = hasSVGSupport($path);
310     system "rm -f $path" if ($shouldHaveSVG xor $hasSVG);
311 }
312
313 sub checkWebCoreSVGSupport
314 {
315     my $required = shift;
316     my $framework = "WebCore";
317     my $path = builtDylibPathForName($framework);
318     my $hasSVG = hasSVGSupport($path);
319     if ($required && !$hasSVG) {
320         die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n";
321     }
322     return $hasSVG;
323 }
324
325 sub isQt()
326 {
327     return ($^O eq "linux") and defined($ENV{'QTDIR'})
328 }
329
330 sub isCygwin()
331 {
332     return ($^O eq "cygwin");
333 }
334
335 sub isOSX()
336 {
337     return ($^O eq "darwin");
338 }
339
340 sub checkRequiredSystemConfig
341 {
342     if (isOSX()) {
343         chomp(my $productVersion = `sw_vers -productVersion`);
344         if ($productVersion lt "10.4") {
345             print "*************************************************************\n";
346             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
347             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
348             print "*************************************************************\n";
349         }
350         my $xcodeVersion = `xcodebuild -version`;
351         if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) {
352             print "*************************************************************\n";
353             print "Xcode Version 2.3 or later is required to build WebKit.\n";
354             print "You have an earlier version of Xcode, thus the build will\n";
355             print "most likely fail.  The latest Xcode is available from the web:\n";
356             print "http://developer.apple.com/tools/xcode\n";
357             print "*************************************************************\n";
358         }
359     }
360     # Win32 and other platforms may want to check for minimum config
361 }
362
363 sub setupCygwinEnv()
364 {
365     return if !isCygwin();
366     return if $devenvPath;
367
368     my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`;
369     chomp $programFilesPath;
370     $devenvPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com";
371     $windowsTmpPath = `cygpath -w /tmp`;
372     chomp $windowsTmpPath;
373     print "Building results into: ", baseProductDir(), "\n";
374     print "WebKitOutputDir is set to: ", $ENV{"WebKitOutputDir"}, "\n";
375 }
376
377 sub buildVisualStudioProject($)
378 {
379     my ($project) = @_;
380     setupCygwinEnv();
381
382     chdir "$project.vcproj" or die "Failed to cd into $project.vcproj\n";
383     my $config = configuration();
384
385     print "$devenvPath $project.sln /build $config";
386     my $result = system $devenvPath, "$project.sln", "/build", $config;
387     chdir ".." or die;
388     return $result;
389 }
390
391 sub buildCMakeProject($)
392 {
393     my ($project) = @_;
394
395     if ($project ne "WebKit") { 
396         die "Qt/Linux builds JavaScriptCore/WebCore/WebKitQt in one shot! Only call it for 'WebKit'.\n";
397     }
398
399     my $config = configuration();
400     print "Calling 'cmake -DCMAKE_BUILD_TYPE=$config ../' in " . baseProductDir() . " ...\n\n";
401
402     system "mkdir -p " . baseProductDir();
403     chdir baseProductDir() or die "Failed to cd into " . baseProductDir() . "\n";
404
405     my $result = system "cmake", "-DCMAKE_BUILD_TYPE=$config", "../";
406     if($result ne 0) {
407        die "Failed to setup build environment using cmake!\n";
408     }
409
410     $result = system "make";
411     chdir ".." or die;
412     return $result;
413 }
414
415 1;