[Win] build-jsc and run-javascriptcore-tests do not work
[WebKit-https.git] / Tools / Scripts / copy-webkitlibraries-to-product-directory
1 #!/usr/bin/perl -w
2
3 # Copyright (C) 2005, 2008, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # 1.  Redistributions of source code must retain the above copyright
10 #     notice, this list of conditions and the following disclaimer. 
11 # 2.  Redistributions in binary form must reproduce the above copyright
12 #     notice, this list of conditions and the following disclaimer in the
13 #     documentation and/or other materials provided with the distribution. 
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 use strict;
27 use File::Spec;
28 use FindBin;
29 use Getopt::Long qw(:config pass_through);
30 use lib $FindBin::Bin;
31 use webkitdirs;
32
33 sub buildLLVM($);
34 sub symlinkLLVMLibrariesIfNeeded($$);
35
36 my $showHelp = 0;
37 my $llvm = 0;
38 my $wksi = 0;
39 my $clean = 0;
40 my $llvmIncludePackage = "";
41 my $llvmLibraryPackage = "";
42 my $useFullLibPaths = 0;
43 my $preferSystemLLVMOverDrops = 0;
44 my $llvmSubdirectoryName = "llvm";
45 my $llvmPrefix = willUseIOSDeviceSDKWhenBuilding() ? "/usr/local" : "/usr/local/LLVMForJavaScriptCore";
46 my $osxVersion;
47 my $force = 0;
48
49 my $programName = basename($0);
50 my $usage = <<EOF;
51 Usage: $programName [options]
52   --help                        Show this help message
53   --[no-]llvm                   Toggle copying LLVM drops (default: $llvm)
54   --[no-]wksi                   Toggle copying WebKitSystemInterface drops (default: $wksi)
55   --clean                       Clean the libraries (default: $clean)
56   --use-llvm-includes=<path>    Get the LLVM inludes package from <path>
57   --use-llvm-libraries=<path>   Get the LLVM libraries package from <path>
58   --[no-]use-full-lib-paths     Toggle using full library paths
59   --[no-]prefer-system-llvm     Toggle preferring the system LLVM over the binary drops (default: $preferSystemLLVMOverDrops)
60   --llvm-subdirectory=<name>    Set the name of the LLVM subdirectory to search for (default: $llvmSubdirectoryName)
61   --llvm-prefix=<path>          Set the prefix into which LLVM is installed (default: $llvmPrefix)
62   --sdk=<sdk>                   Use a specific Xcode SDK
63   --device                      Use the current iphoneos.internal SDK (iOS only)
64   --simulator                   Use the current iphonesimulator SDK (iOS only)
65   --osx-version=<version>       Set the OS X version to use when deciding what to copy.
66   --[no-]force                  Toggle forcing the copy - i.e. ignoring timestamps (default: $force)
67 EOF
68
69 GetOptions(
70     'help' => \$showHelp,
71     'llvm!' => \$llvm,
72     'wksi!' => \$wksi,
73     'clean' => \$clean,
74     'use-llvm-includes=s' => \$llvmIncludePackage,
75     'use-llvm-libraries=s' => \$llvmLibraryPackage,
76     'use-full-lib-paths!' => \$useFullLibPaths,
77     'prefer-system-llvm!' => \$preferSystemLLVMOverDrops,
78     'llvm-subdirectory=s' => \$llvmSubdirectoryName,
79     'llvm-prefix=s' => \$llvmPrefix,
80     'osx-version=s' => \$osxVersion,
81     'force!' => \$force
82 );
83
84 if ($showHelp) {
85    print STDERR $usage;
86    exit 1;
87 }
88
89 my $productDir = shift @ARGV;
90 if ($productDir) {
91     $productDir = File::Spec->rel2abs($productDir);
92 } else {
93     $productDir = $ENV{BUILT_PRODUCTS_DIR} || productDir();
94 }
95
96 if (!isIOSWebKit() && !$osxVersion &&!isAnyWindows()) {
97     $osxVersion = `sw_vers -productVersion | cut -d. -f-2`;
98     chomp($osxVersion);
99 }
100
101 chdirWebKit();
102
103 sub executeRanlib($)
104 {
105     my ($library) = @_;
106     my @args;
107     push @args, ("-sdk", xcodeSDK()) if xcodeSDK();
108     push @args, "ranlib";
109     push @args, "-no_warning_for_no_symbols" if isIOSWebKit();
110     system("xcrun", @args, $library) == 0 or die;
111 }
112
113 sub unpackIfNecessary
114 {
115     my ($targetDir, $sampleFile, $package, $hasLibraries) = @_;
116     if ($force || !-e $sampleFile || -M $sampleFile > -M $package) {
117         print "Unpacking $package into $targetDir\n";
118         (system("tar -C $targetDir -xmf $package") == 0) or die;
119         if ($hasLibraries) {
120             foreach my $library (`tar -tf $package`) {
121                 chomp $library;
122                 print "   Ranlib $library\n";
123                 executeRanlib($targetDir . "/" . $library);
124             }
125         }
126         return 1;
127     }
128     return 0;
129 }
130
131 sub dittoHeaders
132 {
133     my ($srcHeader, $header) = @_;
134     if ($force || !-e $header || -M $header > -M $srcHeader) {
135         print "Updating $header\n";
136         (system("ditto", $srcHeader, $header) == 0) or die;
137     }
138 }
139
140 if ($clean) {
141     print "Cleaning.\n";    
142     (system("rm", "-rf", File::Spec->catfile($productDir, "usr", "local", "include", "WebKitSystemInterface.h")) == 0) or die;
143     if (isIOSWebKit()) {
144         (system("rm", "-rf", File::Spec->catfile($productDir, "usr", "local", "include", "WebKitSystemInterfaceIOS.h")) == 0) or die;
145     }
146     (system("rm", "-rf", "$productDir$llvmPrefix") == 0) or die;
147     unlink glob "$productDir/libWebKitSystemInterface*" or die if glob "$productDir/libWebKitSystemInterface*";
148     unlink glob "$productDir/usr/local/lib/libWebKitSystemInterface*" or die if glob "$productDir/usr/local/lib/libWebKitSystemInterface*";
149     unlink glob "$productDir/libLLVM*" or die if glob "$productDir/libLLVM*";
150     unlink glob "$productDir/libLTO*" or die if glob "$productDir/libLTO*";
151 }
152
153 if ($wksi) {
154     (system("mkdir", "-p", "$productDir/usr/local/include") == 0) or die;
155     
156     my $libraryDir = $useFullLibPaths ? "$productDir/usr/local/lib" : $productDir;
157     (system("mkdir", "-p", $libraryDir) == 0) or die;
158
159     my @librariesToCopy;
160     if (isIOSWebKit()) {
161         push(@librariesToCopy, (
162             "libWebKitSystemInterfaceIOSDevice8.1.a",
163             "libWebKitSystemInterfaceIOSSimulator8.1.a",
164             "libWebKitSystemInterfaceIOSDevice8.2.a",
165             "libWebKitSystemInterfaceIOSSimulator8.2.a",
166             "libWebKitSystemInterfaceIOSDevice8.3.a",
167             "libWebKitSystemInterfaceIOSSimulator8.3.a",
168             "libWebKitSystemInterfaceIOSDevice8.4.a",
169             "libWebKitSystemInterfaceIOSSimulator8.4.a",
170             "libWebKitSystemInterfaceIOSDevice9.0.a",
171             "libWebKitSystemInterfaceIOSSimulator9.0.a",
172         ));
173     } else {
174         push(@librariesToCopy, (
175             "libWebKitSystemInterfaceMavericks.a",
176             "libWebKitSystemInterfaceYosemite.a",
177             "libWebKitSystemInterfaceElCapitan.a"
178         ));
179     }
180
181     foreach my $libraryName (@librariesToCopy) {
182         my $sourceLibrary = "WebKitLibraries/" . $libraryName;
183         my $targetLibrary = "$libraryDir/" . $libraryName;
184         if ($force || !-e $targetLibrary || -M $targetLibrary > -M $sourceLibrary) {
185             print "Updating $targetLibrary\n";
186             (system("ditto", $sourceLibrary, $targetLibrary) == 0) or die;
187             executeRanlib($targetLibrary);
188         }
189     }
190     
191     dittoHeaders("WebKitLibraries/WebKitSystemInterface.h", "$productDir/usr/local/include/WebKitSystemInterface.h");
192     dittoHeaders("WebKitLibraries/WebKitSystemInterfaceIOS.h", "$productDir/usr/local/include/WebKitSystemInterfaceIOS.h") if isIOSWebKit();
193 }
194
195 if ($llvm) {
196     (system("mkdir", "-p", "$productDir$llvmPrefix/include") == 0) or die;
197
198     my $libraryDir = $useFullLibPaths ? "$productDir$llvmPrefix/lib" : $productDir;
199     # Always create a directory at the full library path, because the JavaScriptCore build emits a warning if it's not there.
200     (system("mkdir", "-p", "$productDir$llvmPrefix/lib") == 0) or die;
201
202     (system("rm", "-f", File::Spec->catfile($productDir, "ExtraIncludesForLocalLLVMBuild")) == 0) or die;
203
204     if ($preferSystemLLVMOverDrops) {
205         print "Using system LLVM.\n";
206         exit 0;
207     }
208
209     my $llvmSourceDirectory = $ENV{LLVM_SOURCE_PATH};
210     $llvmSourceDirectory = File::Spec->catdir(sourceDir(), $llvmSubdirectoryName) unless $llvmSourceDirectory;
211     if (-d $llvmSourceDirectory) {
212         my $llvmBuildFile = File::Spec->catfile($llvmSourceDirectory, "LLVMBuild.txt");
213         if (-f $llvmBuildFile) {
214             print "Using LLVM source from $llvmSourceDirectory.\n";
215             buildLLVM($llvmSourceDirectory);
216             if (symlinkLLVMLibrariesIfNeeded($llvmSourceDirectory, $libraryDir)) {
217                 # LLVM libraries changed; make JavaScriptCore relink against the new LLVM the next time it is built.
218                 (system("touch", "Source/JavaScriptCore/llvm/library/LLVMAnchor.cpp") == 0) or die;
219             }
220             exit 0;
221         }
222         print STDERR "*************************************************************\n";
223         print STDERR "Cannot find file '$llvmBuildFile'.\n";
224         print STDERR "Please ensure that you have a complete LLVM distribution.\n";
225         print STDERR "You can check out LLVM trunk into the WebKit directory by running:\n";
226         print STDERR "svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm\n";
227         print STDERR "*************************************************************\n";
228         exit 1;
229     }
230
231     $llvmIncludePackage = $ENV{LLVM_LIBRARY_PACKAGE} unless $llvmIncludePackage;
232     $llvmIncludePackage = $ENV{LLVM_INCLUDE_PACKAGE} unless $llvmIncludePackage;
233     if (!$llvmLibraryPackage || !$llvmIncludePackage) {
234         if (isIOSWebKit()) {
235             my $majorSDKVersion = iosVersion()->{"major"};
236             $llvmLibraryPackage = "WebKitLibraries/LLVMLibrariesIOS$majorSDKVersion.tar.bz2";
237             $llvmIncludePackage = "WebKitLibraries/LLVMIncludesIOS$majorSDKVersion.tar.bz2";
238         } elsif (isAppleMacWebKit()) {
239             if ($osxVersion eq "10.9") {
240                 $llvmLibraryPackage = "WebKitLibraries/LLVMLibrariesMavericks.tar.bz2";
241                 $llvmIncludePackage = "WebKitLibraries/LLVMIncludesMavericks.tar.bz2";
242             } elsif ($osxVersion eq "10.10") {
243                 $llvmLibraryPackage = "WebKitLibraries/LLVMLibrariesYosemite.tar.bz2";
244                 $llvmIncludePackage = "WebKitLibraries/LLVMIncludesYosemite.tar.bz2";
245             } elsif ($osxVersion eq "10.11") {
246                 $llvmLibraryPackage = "WebKitLibraries/LLVMLibrariesElCapitan.tar.bz2";
247                 $llvmIncludePackage = "WebKitLibraries/LLVMIncludesElCapitan.tar.bz2";
248             }
249         }
250     }
251     if ($llvmLibraryPackage && $llvmIncludePackage) {
252         print "Using LLVM binary drops $llvmLibraryPackage and $llvmIncludePackage.\n";
253         if (unpackIfNecessary($libraryDir, "$libraryDir/libLLVMCore.a", $llvmLibraryPackage, 1)) {
254             # LLVM libraries changed; make JavaScriptCore relink against the new LLVM the next time it is built.
255             (system("touch", "Source/JavaScriptCore/llvm/library/LLVMAnchor.cpp") == 0) or die;
256         }
257         unpackIfNecessary(File::Spec->catdir("$productDir$llvmPrefix", "include"), File::Spec->catfile("$productDir$llvmPrefix", "include", "llvm-c", "Core.h"), $llvmIncludePackage, 0);
258         exit 0;
259     }
260
261     print STDERR "*************************************************************\n";
262     print STDERR "Don't know where to find LLVM!\n";
263     print STDERR "\n";
264     print STDERR "Try defining LLVM_LIBRARY_PACKAGE and LLVM_INCLUDE_PACKAGE or setting the\n";
265     print STDERR "--use-llvm-includes and --use-llvm-libraries options.\n";
266     print STDERR "\n";
267     print STDERR "Alternatively, you can check out llvm trunk into the WebKit directory:\n";
268     print STDERR "svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm\n";
269     print STDERR "*************************************************************\n";
270     exit 1;
271 }
272
273 sub fileContains
274 {
275     my ($filename, $string) = @_;
276     open my $fileHandle, '<', $filename or die;
277     while (<$fileHandle>) {
278         return 1 if /^$string$/;
279     }
280     return 0;
281 }
282
283 sub isContentOfFileEqualToString($$)
284 {
285     my ($filename, $string) = @_;
286     open my $fileHandle, '<', $filename or die;
287     binmode $fileHandle;
288     my $contents = <$fileHandle>;
289     return $contents eq $string;
290 }
291
292 sub buildLLVM($)
293 {
294     my ($llvmSourceDirectory) = @_;
295
296     my $savedWorkingDirectory = getcwd();
297     chomp(my $sdkRootEnvironmentVariable = `xcrun @{[xcodeSDK() ? "--sdk " . xcodeSDK() : ""]} --show-sdk-path`);
298     $sdkRootEnvironmentVariable = "SDKROOT=$sdkRootEnvironmentVariable";
299
300     my $llvmBaseProductDirectory = File::Spec->catdir($llvmSourceDirectory, "wkLLVMBuild");
301     if (!-e File::Spec->catfile($llvmBaseProductDirectory, "Makefile.config")) {
302         system("mkdir", "-p", $llvmBaseProductDirectory);
303         chdir($llvmBaseProductDirectory) or die;
304         my @args = qw(
305             --enable-optimized=yes
306             --enable-backtraces=no
307             --enable-libcpp=yes
308             --enable-zlib=no
309             --enable-terminfo=no
310             --enable-crash-overrides=no
311         );
312         my $targetArchitecture;
313         if (isIOSWebKit()) {
314             $targetArchitecture = "arm64";
315             push @args, "--host=arm-apple-darwin";
316             push @args, "--enable-targets=$targetArchitecture";
317         } else {
318             $targetArchitecture = "x86_64";
319             push @args, "--enable-targets=$targetArchitecture";
320         }
321
322         # Environment variables are explicitly appended after command line options so that
323         # the script configure caches them in file config.status for automatic reconfiguration.
324         if (isIOSWebKit()) {
325             # We must explicitly specify the target architecture to the compiler/preprocessor
326             # since we are cross-compiling LLVM.
327             for my $environmentVariableName (qw(CFLAGS CXXFLAGS CPPFLAGS)) {
328                 push @args, "$environmentVariableName=-arch $targetArchitecture";
329             }
330         }
331         push @args, $sdkRootEnvironmentVariable;
332         (system("../configure", @args) == 0) or die;
333     }
334
335     chdir($llvmBaseProductDirectory) or die;
336     my $savedPath = $ENV{"PATH"};
337
338     my $binariesDirectory = "binariesForLLVMBuild";
339     my $pathEnvironmentVariable = "";
340     if (-e $binariesDirectory) {
341         my $binariesPath = File::Spec->rel2abs($binariesDirectory);
342         $pathEnvironmentVariable = "PATH=" . join(":", $binariesPath, '$PATH');
343     }
344     my $makeCommand = "env -i bash -l -c \"$pathEnvironmentVariable $sdkRootEnvironmentVariable make -j `sysctl -n hw.activecpu`\"";
345     print $makeCommand . "\n";
346     (system($makeCommand) == 0) or die;
347
348     $ENV{"PATH"} = $savedPath;
349     chdir($savedWorkingDirectory);
350 }
351
352 sub symlinkLLVMLibrariesIfNeeded($$)
353 {
354     my ($llvmSourceDirectory, $libraryTargetDirectory) = @_;
355
356     my $llvmMakefileConfig = File::Spec->catfile($llvmSourceDirectory, "wkLLVMBuild", "Makefile.config");
357     my $configurationDirectoryName = "";
358     if (fileContains($llvmMakefileConfig, "ENABLE_OPTIMIZED=1")) {
359         $configurationDirectoryName .= "Release";
360     } else {
361         $configurationDirectoryName .= "Debug";
362     }
363     $configurationDirectoryName .= "+Asserts" unless fileContains($llvmMakefileConfig, "DISABLE_ASSERTIONS=1");
364     my $librarySourceDirectory = File::Spec->catdir($llvmSourceDirectory, "wkLLVMBuild", $configurationDirectoryName, "lib");
365
366     my $shouldUpdateLLVMLibraryToken = 0;
367     print("Symlinking libraries from $librarySourceDirectory to $libraryTargetDirectory\n");
368     opendir(my $dirHandle, $librarySourceDirectory);
369     while (my $filename = readdir($dirHandle)) {
370         next if $filename !~ /\.a$/;
371         next if $filename =~ /libgtest/;
372
373         print "   Symlink $filename\n";
374         my $sourceLibrary = File::Spec->catfile($librarySourceDirectory, $filename);
375         my $targetLibrary = File::Spec->catfile($libraryTargetDirectory, $filename);
376         my $ranlibToken = File::Spec->catfile($libraryTargetDirectory, ".ranlibToken-$filename");
377         unlink($targetLibrary);
378         symlink($sourceLibrary, $targetLibrary);
379         if ($force || !-e $ranlibToken || !isContentOfFileEqualToString($ranlibToken, $sourceLibrary) || -M $ranlibToken > -M $sourceLibrary) {
380             print "   Ranlib $filename\n";
381             executeRanlib($targetLibrary);
382             open(RANLIB_TOKEN, ">", $ranlibToken) or die "Failed to open $ranlibToken: $!";
383             print RANLIB_TOKEN $sourceLibrary;
384             close(RANLIB_TOKEN);
385             $shouldUpdateLLVMLibraryToken = 1;
386         }
387     }
388     closedir($dirHandle);
389
390     my $targetIncludeLLVMDirectory = File::Spec->catdir("$productDir$llvmPrefix", "include", "llvm");
391     my $targetIncludeLLVMCDirectory = File::Spec->catdir("$productDir$llvmPrefix", "include", "llvm-c");
392     (system("rm", "-rf", $targetIncludeLLVMDirectory) == 0) or die;
393     (system("rm", "-rf", $targetIncludeLLVMCDirectory) == 0) or die;
394     symlink(File::Spec->catdir($llvmSourceDirectory, "include", "llvm"), $targetIncludeLLVMDirectory) or die;
395     symlink(File::Spec->catdir($llvmSourceDirectory, "include", "llvm-c"), $targetIncludeLLVMCDirectory) or die;
396     symlink(File::Spec->catdir($llvmSourceDirectory, "wkLLVMBuild", "include"), File::Spec->catfile($productDir, "ExtraIncludesForLocalLLVMBuild")) or die;
397
398     return $shouldUpdateLLVMLibraryToken;
399 }