build-webkit 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #!/usr/bin/perl -w
  2. # Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
  3. # Copyright (C) 2009 Google Inc. All rights reserved.
  4. # Copyright (C) 2010 moiji-mobile.com All rights reserved.
  5. # Copyright (C) 2011 Research In Motion Limited. All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. #
  11. # 1. Redistributions of source code must retain the above copyright
  12. # notice, this list of conditions and the following disclaimer.
  13. # 2. Redistributions in binary form must reproduce the above copyright
  14. # notice, this list of conditions and the following disclaimer in the
  15. # documentation and/or other materials provided with the distribution.
  16. # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  17. # its contributors may be used to endorse or promote products derived
  18. # from this software without specific prior written permission.
  19. #
  20. # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  21. # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  24. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  27. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. # Build script wrapper for the WebKit Open Source Project.
  31. use strict;
  32. use File::Basename;
  33. use File::Find;
  34. use File::Spec;
  35. use FindBin;
  36. use Getopt::Long qw(:config pass_through);
  37. use lib $FindBin::Bin;
  38. use webkitdirs;
  39. use webkitperl::FeatureList qw(getFeatureOptionList);
  40. use POSIX;
  41. sub cMakeArgsFromFeatures();
  42. sub formatBuildTime($);
  43. sub writeCongrats();
  44. my $originalWorkingDirectory = getcwd();
  45. chdirWebKit();
  46. my $showHelp = 0;
  47. my $clean = 0;
  48. my $minimal = 0;
  49. my $installHeaders;
  50. my $installLibs;
  51. my $prefixPath;
  52. my $makeArgs = "";
  53. my $cmakeArgs = "";
  54. my $onlyWebKitProject = 0;
  55. my $noWebKit1 = 0;
  56. my $noWebKit2 = 0;
  57. my $coverageSupport = 0;
  58. my $startTime = time();
  59. my @features = getFeatureOptionList();
  60. # Update defaults from Qt's project file
  61. if (isQt()) {
  62. # Take a sneek peek at the arguments, since we will need the qmake binary early
  63. # on to do profile parsing. We also need to know if we're showing the help-text.
  64. foreach (@ARGV) {
  65. if (/^--qmake=(.*)/) {
  66. setQmakeBinaryPath($1);
  67. } elsif (/^--help$/) {
  68. $showHelp = 1;
  69. }
  70. }
  71. my %qtDefaults;
  72. if ($showHelp) {
  73. %qtDefaults = qtFeatureDefaults();
  74. }
  75. foreach (@features) {
  76. $_->{default} = (%qtDefaults ? $qtDefaults{$_->{define}} || 0 : -1);
  77. }
  78. }
  79. # Additional environment parameters
  80. push @ARGV, split(/ /, $ENV{'BUILD_WEBKIT_ARGS'}) if ($ENV{'BUILD_WEBKIT_ARGS'});
  81. # Initialize values from defaults
  82. foreach (@ARGV) {
  83. if ($_ eq '--minimal') {
  84. $minimal = 1;
  85. }
  86. }
  87. # Initialize values from defaults
  88. foreach (@features) {
  89. ${$_->{value}} = ($minimal ? 0 : $_->{default});
  90. }
  91. my $programName = basename($0);
  92. my $usage = <<EOF;
  93. Usage: $programName [options] [options to pass to build system]
  94. --help Show this help message
  95. --clean Cleanup the build directory
  96. --debug Compile with Debug configuration
  97. --release Compile with Release configuration
  98. --sdk=<sdk> Use a specific Xcode SDK (iOS and Mac only)
  99. --device Use the current iphoneos.internal SDK (iOS only)
  100. --simulator Use the current iphonesimulator SDK (iOS only)
  101. --coverage Enable Code Coverage support (Mac only)
  102. --blackberry Build the BlackBerry port on Mac/Linux
  103. --efl Build the EFL port
  104. --gtk Build the GTK+ port
  105. --qt Build the Qt port
  106. --wincairo Build using Cairo (rather than CoreGraphics) on Windows
  107. --wince Build the WinCE port
  108. --inspector-frontend Copy changes to the inspector front-end files to the build directory
  109. --install-headers=<path> Set installation path for the headers (Qt only)
  110. --install-libs=<path> Set installation path for the libraries (Qt only)
  111. --prefix=<path> Set installation prefix to the given path (Gtk/Efl/BlackBerry only)
  112. --makeargs=<arguments> Optional Makefile flags
  113. --qmakearg=<arguments> Optional qmake flags (Qt only, e.g. --qmakearg="CONFIG+=webkit2" to build WebKit2)
  114. --cmakeargs=<arguments> Optional CMake flags (e.g. --cmakeargs="-DFOO=bar -DCMAKE_PREFIX_PATH=/usr/local")
  115. --minimal No optional features, unless explicitly enabled
  116. --only-webkit Build only the WebKit project
  117. --no-webkit1 Omit WebKit1 code from the build (Qt/EFL/GTK only)
  118. --no-webkit2 Omit WebKit2 code from the build
  119. EOF
  120. my %options = (
  121. 'help' => \$showHelp,
  122. 'clean' => \$clean,
  123. 'install-headers=s' => \$installHeaders,
  124. 'install-libs=s' => \$installLibs,
  125. 'prefix=s' => \$prefixPath,
  126. 'makeargs=s' => \$makeArgs,
  127. 'cmakeargs=s' => \$cmakeArgs,
  128. 'minimal' => \$minimal,
  129. 'only-webkit' => \$onlyWebKitProject,
  130. 'no-webkit1' => \$noWebKit1,
  131. 'no-webkit2' => \$noWebKit2,
  132. 'coverage' => \$coverageSupport,
  133. );
  134. # Build usage text and options list from features
  135. foreach (@features) {
  136. my $opt = sprintf("%-35s", " --[no-]$_->{option}");
  137. $usage .= "$opt $_->{desc} (default: $_->{default})\n";
  138. $options{"$_->{option}!"} = $_->{value};
  139. }
  140. GetOptions(%options);
  141. if ($showHelp) {
  142. print STDERR $usage;
  143. exit 1;
  144. }
  145. checkRequiredSystemConfig();
  146. setConfiguration();
  147. my $productDir = productDir();
  148. # Remove 0 byte sized files from productDir after slave lost for Qt buildbots.
  149. File::Find::find(\&unlinkZeroFiles, $productDir) if (isQt() && -e $productDir);
  150. sub unlinkZeroFiles()
  151. {
  152. my $file = $File::Find::name;
  153. # Remove 0 byte sized files, except
  154. # - directories (Because they are always 0 byte sized on Windows)
  155. # - .d files used for dependency tracking
  156. if (! -d $file && ! -s $file && $file !~ m/\.d$/) {
  157. unlink $file;
  158. print "0 byte sized file removed from build directory: $file\n";
  159. }
  160. }
  161. # Check that all the project directories are there.
  162. my @projects = ("Source/JavaScriptCore", "Source/WebCore", "Source/WebKit");
  163. # Build WTF as a separate static library on ports which support it.
  164. splice @projects, 0, 0, "Source/WTF" if isAppleMacWebKit() or isAppleWinWebKit();
  165. for my $dir (@projects) {
  166. if (! -d $dir) {
  167. die "Error: No $dir directory found. Please do a fresh checkout.\n";
  168. }
  169. }
  170. if (!isQt() && !-d "WebKitLibraries") {
  171. die "Error: No WebKitLibraries directory found. Please do a fresh checkout.\n";
  172. }
  173. my @options = ();
  174. if (isAppleMacWebKit()) {
  175. push @options, XcodeOptions();
  176. sub option($$$)
  177. {
  178. my ($feature, $isEnabled, $defaultValue) = @_;
  179. return "" if $defaultValue == $isEnabled;
  180. return $feature . "=" . ($isEnabled ? $feature : "");
  181. }
  182. foreach (@features) {
  183. my $option = option($_->{define}, ${$_->{value}}, $_->{default});
  184. push @options, $option unless $option eq "";
  185. }
  186. # ANGLE must come before WebCore
  187. splice @projects, 0, 0, "Source/ThirdParty/ANGLE";
  188. # WebKit2 is only supported in SnowLeopard and later at present.
  189. push @projects, ("Source/WebKit2", "Tools/MiniBrowser") if osXVersion()->{"minor"} >= 6 and !$noWebKit2;
  190. # WebInspectorUI must come before WebKit and WebKit2
  191. unshift @projects, ("Source/WebInspectorUI");
  192. # Build Tools needed for Apple ports
  193. push @projects, ("Tools/DumpRenderTree", "Tools/WebKitTestRunner", "Source/ThirdParty/gtest", "Tools/TestWebKitAPI");
  194. # Copy library and header from WebKitLibraries to a findable place in the product directory.
  195. (system("perl", "Tools/Scripts/copy-webkitlibraries-to-product-directory", $productDir) == 0) or die;
  196. } elsif (isWinCairo()) {
  197. (system("perl Tools/Scripts/update-webkit-wincairo-libs") == 0) or die;
  198. } elsif (isAppleWinWebKit()) {
  199. # Copy WebKitSupportLibrary to the correct location in WebKitLibraries so it can be found.
  200. # Will fail if WebKitSupportLibrary.zip is not in source root.
  201. (system("perl Tools/Scripts/update-webkit-support-libs") == 0) or die;
  202. } elsif (isQt()) {
  203. push @options, "--install-headers=" . $installHeaders if defined($installHeaders);
  204. push @options, "--install-libs=" . $installLibs if defined($installLibs);
  205. push @options, "--makeargs=" . $makeArgs if $makeArgs;
  206. push @options, "WEBKIT_CONFIG-=build_webkit1" if $noWebKit1;
  207. push @options, "WEBKIT_CONFIG-=build_webkit2" if $noWebKit2;
  208. if (checkForArgumentAndRemoveFromARGV("-2")) {
  209. print "Note: WebKit2 is now built by default, you don't need to pass -2. Disable using --no-webkit2\n";
  210. }
  211. @options = (@ARGV, @options);
  212. foreach (@features) {
  213. if ($_->{define} && ${$_->{value}} != $_->{default}) {
  214. my $define = lc($_->{define});
  215. $define =~ s/^enable_//;
  216. push @options, "WEBKIT_CONFIG" . (${$_->{value}} == 1 ? "+" : "-") . "=" . $define;
  217. }
  218. }
  219. }
  220. # If asked to build just the WebKit project, overwrite the projects
  221. # list after all of the port specific tweaks have been made to
  222. # build options, etc.
  223. @projects = ("Source/WebKit") if $onlyWebKitProject;
  224. if (isInspectorFrontend()) {
  225. exit exitStatus(copyInspectorFrontendFiles());
  226. }
  227. my $result = 0;
  228. if (isEfl()) {
  229. # By default we build using all of the available CPUs.
  230. $makeArgs .= ($makeArgs ? " " : "") . "-j" . numberOfCPUs() if $makeArgs !~ /-j\s*\d+/;
  231. $cmakeArgs = "-DENABLE_WEBKIT=OFF " . $cmakeArgs if $noWebKit1;
  232. $cmakeArgs = "-DENABLE_WEBKIT2=OFF " . $cmakeArgs if $noWebKit2;
  233. # We remove CMakeCache to avoid the bots to reuse cached flags when
  234. # we enable new features. This forces a reconfiguration.
  235. removeCMakeCache();
  236. buildCMakeProjectOrExit($clean, "Efl", $prefixPath, $makeArgs, (cmakeBasedPortArguments(), cMakeArgsFromFeatures()), $cmakeArgs);
  237. }
  238. if (isWinCE()) {
  239. buildCMakeProjectOrExit($clean, "WinCE", $prefixPath, $makeArgs, (cmakeBasedPortArguments(), cMakeArgsFromFeatures()), $cmakeArgs);
  240. }
  241. if (isBlackBerry()) {
  242. my $numberOfJobs;
  243. if ($ENV{"USE_ICECC"}) {
  244. $numberOfJobs = 50; # 50 is the number we choose for internal development
  245. } else {
  246. $numberOfJobs = numberOfCPUs();
  247. }
  248. $makeArgs .= ($makeArgs ? " " : "") . "-j" . $numberOfJobs if $makeArgs !~ /-j\s*\d+/;
  249. $prefixPath = $ENV{"STAGE_DIR"} unless $prefixPath;
  250. buildCMakeProjectOrExit($clean, "BlackBerry", $prefixPath, $makeArgs, (cmakeBasedPortArguments(), cMakeArgsFromFeatures()), $cmakeArgs);
  251. }
  252. if (isQt()) {
  253. @projects = (); # An empty projects list will build the default projects
  254. $result = buildQMakeProjects(\@projects, $clean, @options);
  255. exit exitStatus($result) if exitStatus($result);
  256. }
  257. # Build, and abort if the build fails.
  258. for my $dir (@projects) {
  259. chdir $dir or die;
  260. $result = 0;
  261. # For Gtk the WebKit project builds all others
  262. if (isGtk() && $dir ne "Source/WebKit") {
  263. chdirWebKit();
  264. next;
  265. }
  266. my $project = basename($dir);
  267. my $baseProductDir = baseProductDir();
  268. if (isGtk()) {
  269. $result = buildGtkProject($project, $clean, $prefixPath, $makeArgs, $noWebKit1, $noWebKit2, @features);
  270. } elsif (isAppleMacWebKit()) {
  271. my @local_options = @options;
  272. push @local_options, XcodeCoverageSupportOptions() if $coverageSupport && $project ne "ANGLE";
  273. my $projectPath = $project =~ /gtest/ ? "xcode/gtest" : $project;
  274. $result = buildXCodeProject($projectPath, $clean, @local_options, @ARGV);
  275. } elsif (isAppleWinWebKit()) {
  276. if ($project eq "WebKit") {
  277. my $webkitSolutionPath = "WebKit.vcxproj/WebKit.sln";
  278. $result = buildVisualStudioProject($webkitSolutionPath, $clean);
  279. my $vsConfiguration = configurationForVisualStudio();
  280. if (usingVisualStudioExpress()) {
  281. # Visual Studio Express is so lame it can't stdout build failures.
  282. # So we find its logs and dump them to the console ourselves.
  283. open(my $OUTPUT_HANDLE, '<', "$baseProductDir/$vsConfiguration/BuildOutput.htm") or die "Could not open build log file at $baseProductDir/$vsConfiguration/BuildOutput.htm";
  284. print while (<$OUTPUT_HANDLE>);
  285. }
  286. }
  287. } elsif (isPS3()) {
  288. $result = buildPS3Project($project);
  289. } elsif (isPSVita()) {
  290. $result = buildPSVitaProject($project);
  291. }
  292. # Various build* calls above may change the CWD.
  293. chdirWebKit();
  294. if (exitStatus($result)) {
  295. my $scriptDir = relativeScriptsDir();
  296. if (isAppleWinWebKit()) {
  297. print "\n\n===== BUILD FAILED ======\n\n";
  298. print "Please ensure you have run $scriptDir/update-webkit to install dependencies.\n\n";
  299. print "You can view build errors by checking the BuildLog.htm files located at:\n$baseProductDir/obj/<project>/<config>.\n";
  300. }
  301. exit exitStatus($result);
  302. }
  303. }
  304. # Don't report the "WebKit is now built" message after a clean operation.
  305. exit if $clean;
  306. # Don't report congrats message if build was interrupted by the user.
  307. exit if ($result & 127) == SIGINT;
  308. # Explicitly chdir back to where exit will take us anyway, since the following "launcher"
  309. # message is relative to that directory.
  310. chdir $originalWorkingDirectory;
  311. # Write out congratulations message.
  312. writeCongrats();
  313. exit 0;
  314. sub cMakeArgsFromFeatures()
  315. {
  316. my @args;
  317. foreach (@features) {
  318. my $featureName = $_->{define};
  319. if ($featureName) {
  320. my $featureEnabled = ${$_->{value}} ? "ON" : "OFF";
  321. push @args, "-D$featureName=$featureEnabled";
  322. }
  323. }
  324. return @args;
  325. }
  326. sub formatBuildTime($)
  327. {
  328. my ($buildTime) = @_;
  329. my $buildHours = int($buildTime / 3600);
  330. my $buildMins = int(($buildTime - $buildHours * 3600) / 60);
  331. my $buildSecs = $buildTime - $buildHours * 3600 - $buildMins * 60;
  332. if ($buildHours) {
  333. return sprintf("%dh:%02dm:%02ds", $buildHours, $buildMins, $buildSecs);
  334. }
  335. return sprintf("%02dm:%02ds", $buildMins, $buildSecs);
  336. }
  337. sub writeCongrats()
  338. {
  339. my $launcherPath = launcherPath();
  340. my $launcherName = launcherName();
  341. my $endTime = time();
  342. my $buildTime = formatBuildTime($endTime - $startTime);
  343. print "\n";
  344. print "====================================================================\n";
  345. print " WebKit is now built ($buildTime). \n";
  346. print " To run $launcherName with this newly-built code, use the\n";
  347. print " \"$launcherPath\" script.\n";
  348. print "====================================================================\n";
  349. }