look for the Qt library in the installed location
[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 $vcBuildPath;
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") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
64     {
65         if ($sourceDir !~ s|/[^/]+$||) {
66             die "Could not find top level webkit directory above source directory using FindBin.\n";
67         }
68     }
69
70     $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
71 }
72
73 # used for scripts which are stored in a non-standard location
74 sub setSourceDir($)
75 {
76     ($sourceDir) = @_;
77 }
78
79 sub determineBaseProductDir
80 {
81     return if defined $baseProductDir;
82     determineSourceDir();
83     if (isOSX()) {
84         open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die;
85         $baseProductDir = <PRODUCT>;
86         close PRODUCT;
87         if ($baseProductDir) {
88             chomp $baseProductDir;
89             undef $baseProductDir unless $baseProductDir =~ /^\//;
90         }
91     } else {
92         $baseProductDir = $ENV{"WEBKITOUTPUTDIR"};
93         if (isCygwin() && $baseProductDir) {
94             my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
95             chomp $unixBuildPath;
96             $baseProductDir = $unixBuildPath;
97         }
98     }
99
100     if ($baseProductDir && isOSX()) {
101         $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
102         $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
103         $baseProductDir =~ s|^~/|$ENV{HOME}/|;
104         die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
105         die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
106         @baseProductDirOption = ();
107     }
108
109     if (!defined($baseProductDir)) {
110         $baseProductDir = "$sourceDir/WebKitBuild";
111         @baseProductDirOption = ("SYMROOT=$baseProductDir") if (isOSX());
112         if (isCygwin()) {
113             my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
114             chomp $dosBuildPath;
115             $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath;
116         }
117     }
118 }
119
120 sub determineConfiguration
121 {
122     return if defined $configuration;
123     determineBaseProductDir();
124     if (open CONFIGURATION, "$baseProductDir/Configuration") {
125         $configuration = <CONFIGURATION>;
126         close CONFIGURATION;
127     }
128     if ($configuration) {
129         chomp $configuration;
130         # compatibility for people who have old Configuration files
131         $configuration = "Release" if $configuration eq "Deployment";
132         $configuration = "Debug" if $configuration eq "Development";
133     } else {
134         $configuration = "Release";
135     }
136 }
137
138 sub determineConfigurationProductDir
139 {
140     return if defined $configurationProductDir;
141     determineBaseProductDir();
142     if(isCygwin()) {
143         $configurationProductDir = "$baseProductDir/bin";
144     } else {
145         determineConfiguration();
146         $configurationProductDir = "$baseProductDir/$configuration";
147     }
148 }
149
150 sub determineCurrentSVNRevision
151 {
152     return if defined $currentSVNRevision;
153     determineSourceDir();
154     my $svnInfo = `LC_ALL=C svn info $sourceDir | grep Revision:`;
155     ($currentSVNRevision) = ($svnInfo =~ m/Revision: (\d+).*/g);
156     die "Unable to determine current SVN revision in $sourceDir" unless (defined $currentSVNRevision);
157     return $currentSVNRevision;
158 }
159
160
161 sub chdirWebKit
162 {
163     determineSourceDir();
164     chdir $sourceDir or die;
165 }
166
167 sub baseProductDir
168 {
169     determineBaseProductDir();
170     return $baseProductDir;
171 }
172
173 sub sourceDir
174 {
175     determineSourceDir();
176     return $sourceDir;
177 }
178
179 sub productDir
180 {
181     determineConfigurationProductDir();
182     return $configurationProductDir;
183 }
184
185 sub configuration()
186 {
187     determineConfiguration();
188     return $configuration;
189 }
190
191 sub currentSVNRevision
192 {
193     determineCurrentSVNRevision();
194     return $currentSVNRevision;
195 }
196
197 sub XcodeOptions
198 {
199     determineBaseProductDir();
200     determineConfiguration();
201     return (@baseProductDirOption, "-configuration", $configuration);
202 }
203
204 sub XcodeOptionString
205 {
206     return join " ", XcodeOptions();
207 }
208
209 sub XcodeOptionStringNoConfig
210 {
211     return join " ", @baseProductDirOption;
212 }
213
214 my $passedConfiguration;
215 my $searchedForPassedConfiguration;
216 sub determinePassedConfiguration
217 {
218     return if $searchedForPassedConfiguration;
219     $searchedForPassedConfiguration = 1;
220     for my $i (0 .. $#ARGV) {
221         my $opt = $ARGV[$i];
222         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
223             splice(@ARGV, $i, 1);
224             $passedConfiguration = "Debug";
225             return;
226         }
227         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
228             splice(@ARGV, $i, 1);
229             $passedConfiguration = "Release";
230             return;
231         }
232     }
233     $passedConfiguration = undef;
234 }
235
236 sub passedConfiguration
237 {
238     determinePassedConfiguration();
239     return $passedConfiguration;
240 }
241
242 sub setConfiguration
243 {
244     if (my $config = shift @_) {
245         $configuration = $config;
246         return;
247     }
248
249     determinePassedConfiguration();
250     $configuration = $passedConfiguration if $passedConfiguration;
251 }
252
253 # Locate Safari.
254 sub safariPath
255 {
256     # Use WEBKIT_SAFARI environment variable if present.
257     my $safariBundle = $ENV{WEBKIT_SAFARI};
258     if (!$safariBundle) {
259         determineConfigurationProductDir();
260         # Use Safari.app in product directory if present (good for Safari development team).
261         if (isOSX() && -d "$configurationProductDir/Safari.app") {
262             $safariBundle = "$configurationProductDir/Safari.app";
263         } elsif (isCygwin() && -x "$configurationProductDir/bin/Safari.exe") {
264             $safariBundle = "$configurationProductDir/bin/Safari.exe";
265         } else {
266             # Otherwise use the installed Safari
267             if (isOSX()) {
268                 $safariBundle = "/Applications/Safari.app";
269             } elsif (isCygwin()) {
270                 chomp(my $programFiles = `cygpath -u '$ENV{"PROGRAMFILES"}'`);
271                 $safariBundle = "$programFiles/Safari/Safari.exe";
272             }
273         }
274     }
275     my $safariPath;
276     if (isOSX()) {
277         $safariPath = "$safariBundle/Contents/MacOS/Safari";
278     } elsif (isCygwin()) {
279         $safariPath = $safariBundle;
280     }
281     die "Can't find executable at $safariPath.\n" if isOSX() && !-x $safariPath;
282     return $safariPath;
283 }
284
285 sub builtDylibPathForName
286 {
287     my $framework = shift;
288     determineConfigurationProductDir();
289     if (isQt() or isGdk()) {
290         return "$configurationProductDir/$framework";
291     }
292     if (isOSX()) {
293         return "$configurationProductDir/$framework.framework/Versions/A/$framework";
294     }
295     if (isCygwin()) {
296         if ($framework eq "JavaScriptCore") {
297                 return "$baseProductDir/lib/$framework.lib";
298         } else {
299             return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib";
300         }
301     }
302
303     die "Unsupported platform, can't determine built library locations.";
304 }
305
306 # Check to see that all the frameworks are built.
307 sub checkFrameworks
308 {
309     return if isCygwin();
310     my @frameworks = ("JavaScriptCore", "WebCore");
311     push(@frameworks, "WebKit") if isOSX();
312     for my $framework (@frameworks) {
313         my $path = builtDylibPathForName($framework);
314         die "Can't find built framework at \"$path\".\n" unless -x $path;
315     }
316 }
317
318 sub hasSVGSupport
319 {
320     return 0 if isCygwin();
321
322     my $path = shift;
323
324     if (isQt() and $path =~ /WebCore/) {
325         $path = $ENV{QTDIR}."/lib/libQtWebKit.so";
326     }
327
328     if (isGdk() and $path =~ /WebCore/) {
329         $path .= "/../lib/libWebKitGdk.so";
330     }
331
332     open NM, "-|", "nm", $path or die;
333     my $hasSVGSupport = 0;
334     while (<NM>) {
335         $hasSVGSupport = 1 if /SVGElement/;
336     }
337     close NM;
338     return $hasSVGSupport;
339 }
340
341 sub removeLibraryDependingOnSVG
342 {
343     my $frameworkName = shift;
344     my $shouldHaveSVG = shift;
345
346     my $path = builtDylibPathForName($frameworkName);
347     return unless -x $path;
348
349     my $hasSVG = hasSVGSupport($path);
350     system "rm -f $path" if ($shouldHaveSVG xor $hasSVG);
351 }
352
353 sub checkWebCoreSVGSupport
354 {
355     my $required = shift;
356     my $framework = "WebCore";
357     my $path = builtDylibPathForName($framework);
358     my $hasSVG = hasSVGSupport($path);
359     if ($required && !$hasSVG) {
360         die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n";
361     }
362     return $hasSVG;
363 }
364
365 sub isQt()
366 {
367     return defined($ENV{'QTDIR'})
368 }
369
370 sub isGdk()
371 {
372     for my $i (0 .. $#ARGV) {
373         my $opt = $ARGV[$i];
374         if ($opt =~ /^--gdk$/i ) {
375             return 1;
376         }
377     }
378     return 0;
379 }
380
381 sub isCygwin()
382 {
383     return ($^O eq "cygwin");
384 }
385
386 sub isOSX()
387 {
388     return ($^O eq "darwin");
389 }
390
391 sub checkRequiredSystemConfig
392 {
393     if (isOSX()) {
394         chomp(my $productVersion = `sw_vers -productVersion`);
395         if ($productVersion lt "10.4") {
396             print "*************************************************************\n";
397             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
398             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
399             print "*************************************************************\n";
400         }
401         my $xcodeVersion = `xcodebuild -version`;
402         if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) {
403             print "*************************************************************\n";
404             print "Xcode Version 2.3 or later is required to build WebKit.\n";
405             print "You have an earlier version of Xcode, thus the build will\n";
406             print "most likely fail.  The latest Xcode is available from the web:\n";
407             print "http://developer.apple.com/tools/xcode\n";
408             print "*************************************************************\n";
409         }
410     }
411     # Win32 and other platforms may want to check for minimum config
412 }
413
414 sub setupCygwinEnv()
415 {
416     return if !isCygwin();
417     return if $vcBuildPath;
418
419     my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`;
420     chomp $programFilesPath;
421     $vcBuildPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com";
422     if (! -e $vcBuildPath) {
423         # VC++ not found, try VC++ Express
424         my $vsInstallDir;
425         if ($ENV{'VSINSTALLDIR'}) {
426             $vsInstallDir = $ENV{'VSINSTALLDIR'};
427         } else {
428             $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
429             $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
430         }
431         $vsInstallDir = `cygpath "$vsInstallDir"`;
432         chomp $vsInstallDir;
433         $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe";
434         if (! -e $vcBuildPath) {
435             print "*************************************************************\n";
436             print "Cannot find '$vcBuildPath'\n";
437             print "Please execute the file 'vcvars32.bat' from\n";
438             print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
439             print "to setup the necessary environment variables.\n";
440             print "*************************************************************\n";
441             die;
442         }
443     }
444
445     chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'};
446
447     $windowsTmpPath = `cygpath -w /tmp`;
448     chomp $windowsTmpPath;
449     print "Building results into: ", baseProductDir(), "\n";
450     print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n";
451     print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n";
452 }
453
454 sub buildVisualStudioProject($)
455 {
456     my ($project) = @_;
457     setupCygwinEnv();
458
459     my $config = configuration();
460
461     chomp(my $winProjectPath = `cygpath -w "$project"`);
462
463     print "$vcBuildPath $winProjectPath /build $config";
464     my $result = system $vcBuildPath, $winProjectPath, "/build", $config;
465     return $result;
466 }
467
468 sub buildQMakeProject($$)
469 {
470     my ($project, $colorize) = @_;
471
472     if ($project ne "WebKit") {
473         die "Qt/Linux builds JavaScriptCore/WebCore/WebKitQt in one shot! Only call it for 'WebKit'.\n";
474     }
475
476     my $config = configuration();
477     my $prefix = $ENV{"WebKitInstallationPrefix"};
478
479     my @buildArgs = ("-r");
480     push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config";
481     push @buildArgs, "CONFIG+=qt-port";
482     push @buildArgs, sourceDir() . "/WebKit.pro";
483
484     print "Calling 'qmake @buildArgs' in " . baseProductDir() . "/$config ...\n\n";
485     print "Installation directory: $prefix\n" if(defined($prefix));
486
487     system "mkdir -p " . baseProductDir() . "/$config";
488     chdir baseProductDir() . "/$config" or die "Failed to cd into " . baseProductDir() . "/$config \n";
489
490     my $result = system "qmake", @buildArgs;
491     if($result ne 0) {
492        die "Failed to setup build environment using qmake!\n";
493     }
494
495     my $clean = $ENV{"WEBKIT_FULLBUILD"};
496
497     if(defined $clean) {
498       system "make clean";
499     }
500
501     $result = system "make";
502     chdir ".." or die;
503     return $result;
504 }
505
506 sub buildQMakeGdkProject($$)
507 {
508     my ($project, $colorize) = @_;
509
510     if ($project ne "WebKit") {
511         die "The Gdk portbuilds JavaScriptCore/WebCore/WebKitQt in one shot! Only call it for 'WebKit'.\n";
512     }
513
514     my $config = configuration();
515     my $prefix = $ENV{"WebKitInstallationPrefix"};
516
517     my @buildArgs = ("-r");
518     push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config";
519     push @buildArgs, "CONFIG-=qt";
520     push @buildArgs, "CONFIG+=gdk-port";
521     push @buildArgs, sourceDir() . "/WebKit.pro";
522
523     print "Calling 'qmake @buildArgs' in " . baseProductDir() . "/$config ...\n\n";
524     print "Installation directory: $prefix\n" if(defined($prefix));
525
526     system "mkdir -p " . baseProductDir() . "/$config";
527     chdir baseProductDir() . "/$config" or die "Failed to cd into " . baseProductDir() . "/$config \n";
528
529     my $result = system "qmake-qt4", @buildArgs;
530     $result =  system "qmake", @buildArgs if ($result ne 0);
531     if ($result ne 0) {
532        die "Failed to setup build environment using qmake!\n";
533     }
534
535     my $clean = $ENV{"WEBKIT_FULLBUILD"};
536
537     if (defined $clean) {
538       system "make clean";
539     }
540
541     $result = system "make";
542     chdir ".." or die;
543     return $result;
544 }
545
546 1;