{"id":3318,"date":"2014-12-03T02:01:43","date_gmt":"2014-12-03T01:01:43","guid":{"rendered":"http:\/\/glandium.org\/blog\/?p=3318"},"modified":"2014-12-03T16:11:41","modified_gmt":"2014-12-03T15:11:41","slug":"mozilla-build-system-past-present-and-future","status":"publish","type":"post","link":"https:\/\/glandium.org\/blog\/?p=3318","title":{"rendered":"Mozilla Build System: past, present and future"},"content":{"rendered":"<p>The Mozilla Build System has, for most of its history, not changed much. But, for a couple years now, we've been, slowly and incrementally, modifying it in quite extensive ways. This post summarizes the progress so far, and my personal view on where we're headed.<\/p>\n<h2>Recursive make<\/h2>\n<p>The Mozilla Build System has, all along, been implemented as a set of recursively traversed Makefiles. The way it has been working for a very long time looks like the following:<\/p>\n<ul>\n<li>For each <em>tier<\/em> (group of source directories) defined at the top-level:\n<ul>\n<li>For each subdirectory in current <em>tier<\/em>:\n<ul>\n<li>Build the <code>export<\/code> target recursively for each subdirectory defined in Makefile.<\/li>\n<li>Build the <code>libs<\/code> target recursively for each subdirectory defined in Makefile.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>The typical limitation due to the above is that some compiled tests from a given directory would require a library that's not linked until after the given directory is recursed, so another target was later <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=273598\">added on top of that (<code>tools<\/code>)<\/a>.<\/p>\n<p>There was not much room for parallelism, except in individual directories, where multiple sources could be built in parallel, but never would sources from multiple directories be built at the same time. So, for a bunch of directories where it was possible, special rules were <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=461395\">added to allow that to happen<\/a>, which led to interesting recursions:<\/p>\n<ul>\n<li>For each of <code>export<\/code>, <code>libs<\/code>, and <code>tools<\/code>:\n<ul>\n<li>Build the target in the subdirectories that can be built in parallel.<\/li>\n<li>Build the target in the current directory.<\/li>\n<li>Build the target in the remaining subdirectories.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>This ensured some extra fun with dependencies between (sub)directories.<\/p>\n<p>Apart from the way things were recursed, all sorts of custom build rules had piled up, some of which relied on things in other directories having happened beforehand, and the build system implementation itself relied on some quite awful things (remember <code>allmakefiles.sh<\/code>?)<\/p>\n<h2>Gradual Overhaul<\/h2>\n<p>Around two years ago, we started a gradual overhaul of the build system.<\/p>\n<p>One of the goals was to <a href=\"https:\/\/groups.google.com\/d\/msg\/mozilla.dev.platform\/SACOnl-avMs\/73FMooBgATQJ\">move away from Makefiles<\/a>. For various reasons, we decided to go with our own kind-of-declarative (but really, sandboxed python) format (<code>moz.build<\/code>) instead of using e.g. <a href=\"https:\/\/code.google.com\/p\/gyp\/wiki\/GypLanguageSpecification \">gyp<\/a>. The more progress we make on the build system, and the more I think this was the right choice.<\/p>\n<p>Anyways, while we've come a long way and converted a lot of Makefiles to <code>moz.build<\/code>, we're not quite there yet:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/2014\/11\/makefiles.png\" width=\"600\" height=\"400\" class=\"noborder\" \/><\/p>\n<p>One interesting thing to note in the above graph is that we've also been reducing the overall number of <code>moz.build<\/code> files we use, by consolidating some declarations. For example, some <code>moz.build<\/code> files now declare source or test files from their subdirectories directly, instead of having one file per directory declare sources and test files local to their own directory.<\/p>\n<h2>Pseudo derecursifying recursive Make<\/h2>\n<p>Neologism aside, one of the ideas to help with the process of converting the build system to something that can be parallelized more massively was to <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=907365\">reduce the depth of recursion<\/a> we do with Make. So that instead of a sequence like this:<\/p>\n<ul>\n<li>Entering directory A\n<ul>\n<li>Entering directory A\/B<\/li>\n<li>Leaving directory A\/B<\/li>\n<li>Entering directory A\/C\n<ul>\n<li>Entering directory A\/C\/D<\/li>\n<li>Leaving directory A\/C\/D<\/li>\n<li>Entering directory A\/C\/E<\/li>\n<li>Leaving directory A\/C\/E<\/li>\n<li>Entering directory A\/C\/F<\/li>\n<li>Leaving directory A\/C\/F<\/li>\n<\/ul>\n<\/li>\n<li>Leaving directory A\/C<\/li>\n<li>Entering directory A\/G<\/li>\n<li>Leaving directory A\/G<\/li>\n<\/ul>\n<\/li>\n<li>Leaving directory A<\/li>\n<li>Entering directory H<\/li>\n<li>Leaving directory H<\/li>\n<\/ul>\n<p>We would have a sequence like this:<\/p>\n<ul>\n<li>Entering directory A<\/li>\n<li>Leaving directory A<\/li>\n<li>Entering directory A\/B<\/li>\n<li>Leaving directory A\/B<\/li>\n<li>Entering directory A\/C<\/li>\n<li>Leaving directory A\/C<\/li>\n<li>Entering directory A\/C\/D<\/li>\n<li>Leaving directory A\/C\/D<\/li>\n<li>Entering directory A\/C\/E<\/li>\n<li>Leaving directory A\/C\/E<\/li>\n<li>Entering directory A\/C\/F<\/li>\n<li>Leaving directory A\/C\/F<\/li>\n<li>Entering directory A\/G<\/li>\n<li>Leaving directory A\/G<\/li>\n<li>Entering directory H<\/li>\n<li>Leaving directory H<\/li>\n<\/ul>\n<p>For each directory there would be a directory-specific target per top-level target, such as <code>A\/B\/export<\/code>, <code>A\/B\/libs<\/code>, etc. Essentially those targets are defined as:<\/p>\n<blockquote>\n<pre>%\/$(target):\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(MAKE) -C $* $(target)\r\n<\/pre>\n<\/blockquote>\n<p>And each top-level target is expressed as a set of dependencies, such as, in the case above:<\/p>\n<blockquote>\n<pre>A\/B\/libs: A\/libs\r\nA\/C\/libs: A\/B\/libs\r\nA\/C\/D\/libs: A\/C\/libs\r\nA\/C\/E\/libs: A\/C\/D\/libs\r\nA\/C\/F\/libs: A\/C\/E\/libs\r\nA\/G\/libs: A\/C\/F\/libs\r\nH\/libs: A\/G\/libs\r\nlibs: H\/libs\r\n<\/pre>\n<\/blockquote>\n<p>That dependency list, instead of being declared manually, is generated from the \"traditional\" recursion declaration we had in <code>moz.build<\/code>, through the various <code>*_DIRS<\/code> variables. I'll skip the gory details about how this replicated the weird subdirectory orders I mentioned above when you had both <code>PARALLEL_DIRS<\/code> and <code>DIRS<\/code>. They are irrelevant today anyways.<\/p>\n<p>You'll also note that this also removed the notion of <em>tier<\/em>, and the entirety of the tree is dealt with for each target, instead of iterating all targets for each group of directories.<\/p>\n<p>[But note that, confusingly, but for practical reasons related to the amount of code changes required, and to how things were incrementally set in place, those targets are now called tiers]<\/p>\n<p>From there, parallelizing parts of the build only involves reorganizing those Make dependencies such that Make can go in several subdirectories at once, the ultimate goal being:<\/p>\n<blockquote>\n<pre>libs: A\/libs A\/B\/libs A\/C\/libs A\/C\/D\/libs A\/C\/E\/libs A\/C\/F\/libs A\/G\/libs A\/H\/libs\r\n<\/pre>\n<\/blockquote>\n<p>But then, things in various directories may need other things built in different directories first, such that additional dependencies can be needed, for example:<\/p>\n<blockquote>\n<pre>A\/B\/libs A\/C\/libs: A\/libs\r\nA\/H\/libs: A\/G\/libs\r\n<\/pre>\n<\/blockquote>\n<p>The trick is that those dependencies can in many cases be deduced from the contents of <code>moz.build<\/code>. That's where we are today, for example, for everything related to compilation: We added a <code>compile<\/code> target that deals with everything C\/C++ compilation, and we have dependencies between directories building objects and directories building libraries and executables that depend on those objects. You can have a taste yourself:<\/p>\n<blockquote>\n<pre>\r\n$ mach clobber\r\n$ mach configure\r\n$ mach build export\r\n$ mach build -C \/ toolkit\/library\/target\r\n<\/pre>\n<\/blockquote>\n<p>[Note, the <code>compile<\/code> target is actually composed of two sub-targets, <code>target<\/code> and <code>host<\/code>.]<\/p>\n<p>The third command runs the <code>export<\/code> target on the whole tree, because that's a prerequisite that is not expressed as a make dependency yet (it would be too broad of a dependency anyways).<\/p>\n<p>The last command runs the <code>toolkit\/library\/target<\/code> target at the top level (as opposed to <code>mach build toolkit\/library\/target<\/code>, which runs the <code>target<\/code> target in the <code>toolkit\/library<\/code> directory). That will build libxul, and everything needed to link it, but nothing else unrelated.<\/p>\n<p>All the other top-level targets have also received this treatment to some extent:<\/p>\n<ul>\n<li>The <code>export<\/code> target was made entirely parallel, although it keeps some cross-directory dependencies derived from the historical traversal data.<\/li>\n<li>The <code>libs<\/code> target is still entirely sequential, because of all the horrible rules in it that may or may not depend on the historical traversal order.<\/li>\n<li>A parallelized <code>misc<\/code> target was <a href=\"https:\/\/groups.google.com\/forum\/#!topic\/mozilla.dev.builds\/1Y6cmEwuHr8\">recently created<\/a> to receive all the things that are currently done as part of the <code>libs<\/code> target that are actually safe to be parallelized (another reason for creating this new target is that <code>libs<\/code> is now a misnomer, since everything related to libraries is now part of <code>compile<\/code>). Please feel free to participate in the effort to move <code>libs<\/code> rules there.<\/li>\n<li>The <code>tools<\/code> target is still sequential, but see below.<\/li>\n<\/ul>\n<p>Although, some interdependencies that can't be derived yet are currently <a href=\"http:\/\/hg.mozilla.org\/mozilla-central\/file\/1e024ddabbb3\/config\/recurse.mk#l141\">hardcoded in <code>config\/recurse.mk<\/code><\/a>.<\/p>\n<p>And since the mere fact of entering a directory, figuring out if there's anything to do at all, and leaving a directory takes some time on builds when only a couple things changed, we also skip some directories entirely by making them not have a <code>directory\/target<\/code> target at all:<\/p>\n<ul>\n<li><code>export<\/code> and <code>libs<\/code> only traverse directories where there is a <code>Makefile.in<\/code> file, or where the <code>moz.build<\/code> file sets variables that do require something to be done in those targets.<\/li>\n<li><code>compile<\/code> only traverses directories where there is something to compile or link.<\/li>\n<li><code>misc<\/code> only traverses directories with an explicit <code>HAS_MISC_RULE = True<\/code> when they have a <code>Makefile.in<\/code>, or with a <code>moz.build<\/code> setting variables affecting the <code>misc<\/code> target.<\/li>\n<li><code>tools<\/code> only traverses directories that contain a Makefile.in containing <code>tools::<\/code> (there's actually a regexp, but in essence, that's it).<\/li>\n<\/ul>\n<p>Those skipping rules allow to only traverse, taking numbers from a local Linux build, as of a couple weeks ago:<\/p>\n<ul>\n<li>186 directories during <code>libs<\/code>,<\/li>\n<li>472 directories during <code>compile<\/code>,<\/li>\n<li>161 directories during <code>misc<\/code>,<\/li>\n<li>382 directories during <code>libs<\/code>,<\/li>\n<li>2 directories during <code>tools<\/code>.<\/li>\n<\/ul>\n<p>instead of 850 for each.<\/p>\n<p><b>In the near future<\/b>, we may want to change <code>export<\/code> and <code>libs<\/code> to opt-ins, like <code>misc<\/code>, instead of opt-outs.<\/p>\n<h2>Alternative build backends<\/h2>\n<p>With more and more declarations in <code>moz.build<\/code>, files, we've been able to build up some alternative build backends for Eclipse and Microsoft Visual Studio. While they still are considered experimental, they seem to work well enough for people to take advantage of them in some useful ways. They however still rely on the \"traditional\" Make backend to build various things (to the best of my knowledge).<\/p>\n<p>Ultimately, we would like to support entirely different build systems such as ninja or tup, but at the moment, many things still heavily rely on the \"traditional\" Make backend. We're getting close to having everything related to compilation available from the <code>moz.build<\/code> declarations (ignoring third-party code, but see further below), but there is still a long way to go for other things.<\/p>\n<p><b>In the near future<\/b>, we may want to implement hybrid build backends where compilation would be driven by ninja or tup, and the rest of the build would be handled by Make. However, my feeling is that the Make backend is fast enough for compilation and ninja doesn't bring enough other than performance that it's not worth investing in a ninja backend. Tup is different because it does solve <a href=\"http:\/\/gittup.org\/blog\/2014\/03\/6-clobber-builds-part-1---missing-dependencies\/\">some<\/a> of the <a href=\"http:\/\/gittup.org\/blog\/2014\/05\/7-clobber-builds-part-2---fixing-missing-dependencies\/\">problems<\/a> with <a href=\"http:\/\/gittup.org\/blog\/2014\/06\/8-clobber-builds-part-3---other-clobber-causes\/\">incremental builds<\/a>.<\/p>\n<p>While on the topic of being close to having everything related to compilation available from <code>moz.build<\/code> declarations, closing in on this topic would allow, more than such hybrid build systems, to better integrate tools such as code static analyzers.<\/p>\n<h2>Unified C\/C++ sources<\/h2>\n<p>Compiling C code, and even more compiling C++ code, involves reading the same headers an important number of times. In C++, that usually also means instantiating the same templates and compiling the same inline methods numerous times.<\/p>\n<p>So we've worked around this by creating \"unified sources\" that just <code>#include<\/code> the actual source files, grouping them 16 by 16 (except when specified otherwise).<\/p>\n<p>This reduced build times drastically, and, interestingly, reduced the size of <a href=\"http:\/\/en.wikipedia.org\/wiki\/DWARF\">DWARF debugging symbols<\/a> as well. This does have a couple downsides, though. It allows <code>#include<\/code> impurity in the code in such a way that e.g. changes in the file groups can lead to subtle build failures. It also makes incremental builds significantly slower in parts of the tree where compiling one file is already somehow slow, so doing 16 at a time can be a drag for people working on that code. This is why we're considering <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=977338\">decreasing the number for the javascript engine<\/a> <b>in the near future<\/b>. We should probably investigate where else building one unified source is slow enough to be a concern. I don't think we can rely on people actively complaining about it, they've been too used to slow build times to care to file bugs about it.<\/p>\n<p>Relatedly, our story with <code>#include<\/code> is suboptimal to say the least, and several have been untangled, but <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=includehell\">there's still a long tail<\/a>. It's a hard problem to solve, even with tools like <a href=\"https:\/\/code.google.com\/p\/include-what-you-use\/\">IWYU<\/a>.<\/p>\n<h2>Fake libraries<\/h2>\n<p>For a very long time, the build system was building intermediate static libraries, and then was linking them together to form shared libraries. This is how the main components were built in the old days before libxul (remember libgklayout?), and was how libxul built when it was created. For various reasons, ranging from disk space waste to linker inefficiencies, this was replaced by <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=522770\">building fake libraries<\/a>, that only reference the objects that would normally be contained in the static library that used to be built. This later was changed to use a <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=584474\">more complex system allowing more flexibility<\/a>.<\/p>\n<p>Fast-forward to today, and with all the knowledge from <code>moz.build<\/code>, <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1077151\">one of the usecases of that more complex system was made moot<\/a>, and <b>in the future<\/b>, those fake libraries could be generated as build backend files instead of being created during the build.<\/p>\n<h2>Specialized incremental builds<\/h2>\n<p>When iterating C\/C++ code patches, one usually needs to (re)compile often. With the build system having the overhead it has, and rebuilding with no change taking many seconds (it has been around a minute for a long time on my machine and is now around half of that, although, sadly, I had got it down to 20 seconds but that regressed recently, damn <code>libs<\/code> rules), we also added a special rule that only handles header changes and rebuilding objects, libraries and executables.<\/p>\n<p>That special rule is invoked as:<\/p>\n<blockquote>\n<pre>$ mach build binaries<\/pre>\n<\/blockquote>\n<p>And takes about 3.5s on my machine when there are no changes. It used to be faster thanks to clever tricks, but that was regressed on purpose. That's a trade-off, but linking libxul, which most code changes require, takes much longer than that anyways. If deemed necessary, the same clever tricks could be restored.<\/p>\n<p>While we work to improve the overall build experience, <b>in the near future<\/b> we should have one or more special rules for non-compilation use-cases. For Firefox frontend developers, the following command may do part of the job:<\/p>\n<blockquote>\n<pre>$ mach build -C \/ chrome<\/pre>\n<\/blockquote>\n<p>but we should have some better and more complete commands for them and e.g. Firefox Android developers.<\/p>\n<p>We also currently have a build option allowing to entirely skip everything that is compilation related (<code>--disable-compile-environment<\/code>), but it is <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1063880\"> currently broken<\/a> and is only really useful in few use cases. <b>In the near future<\/b>, we need build modes that allow to use e.g. nightly builds as if they were the result of compiling C++ source. This would allow some classes of developers to skip compilations altogether, which are an unnecessary overhead for them at the moment, since they need to compile at least once (and with all the auto-clobbers we have, it's much more than that).<\/p>\n<h2>Localization<\/h2>\n<p>Related to the above, the experience of building locale packs and repacks for Firefox is dreadful. Even worse than that, it also relies on a big pile of awful Make rules. It probably is, along with the code related to the creation of Firefox tarballs and installers, the most horrifying part of the build system. Its entanglement with release automation also makes improving the situation unnecessarily difficult.<\/p>\n<p>While there are some sorts of tests running on every push, there are many occasions where those tests fail to catch regressions that lead to broken localized builds for nightlies, or worse on beta or release (which, you'll have to admit, is a sadly late a moment to find such regressions).<\/p>\n<p>Something really needs to be done about localization, and hopefully the discussions we'll have this week in Portland will lead to improvements <b>in the short to medium term<\/b>.<\/p>\n<h2>Install manifests<\/h2>\n<p>The build system copies many files during the build. From the source directory to the \"object\" directory. Sometimes in <code>$(DIST)\/somedir<\/code>, sometimes elsewhere. Sometimes in both or more. On non-Windows systems, copies are replaced by symbolic links. Sometimes not. There are also files that are preprocessed during the build.<\/p>\n<p>All those used to be handled by Make rules invoking <code>$(NSINSTALL)<\/code> on every build. Even when the files hadn't changed. Most of these were replaced by some <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=773202\">Makefile<\/a> <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=770426\">magic<\/a>, but many are now covered with so-called <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=899241\">\"install manifests\"<\/a>.<\/p>\n<p>Others, defined in <code>jar.mn<\/code> files, used to be added to jar files during the build. While those jars are not created anymore because of omni.ja, the corresponding content is still copied\/symlinked and defined in <code>jar.mn<\/code>.<\/p>\n<p><b>In the near future<\/b>, all those should be switched to install manifests somehow, and that is greatly tied to solving part of the localization problem: currently, localization relies on Make overrides that <code>moz.build<\/code> can't know about, preventing install manifests being created and used for the corresponding content.<\/p>\n<h2>Faster configure<\/h2>\n<p>One of the very first things the build system does when a build starts from scratch is to run <code>configure<\/code>. That's a part of the build system that is based on the antiquated <code>autoconf<\/code> 2.13, with 15+ years of accumulated linear m4 and shell gunk. That's what detects what kind of compiler you use, how broken it is, how broken its headers are, what options you requested, what application you want to build, etc.<\/p>\n<p>Topping that, it also invokes <code>configure<\/code> from third-party software that happen to live in the tree, like ICU or jemalloc 3. Those are also based on <code>autoconf<\/code>, but in more recent versions than 2.13. They are also third-party, so we're essentially only importing them, as opposed to actively making them bigger for those that are ours.<\/p>\n<p>While it doesn't necessarily look that bad when running on e.g. Linux, the time it takes to run all this pile of shell scripts is painfully horrible on Windows (like, taking more than 5 minutes on automation). While there's still a lot to do, various improvements were recently made:<\/p>\n<ul>\n<li>Some classes of changes (such as modifying <code>configure.in<\/code>) make the build system re-run <code>configure<\/code>. It used to trigger every <code>configure<\/code> to run again, but now only re-runs a relevant subset.<\/li>\n<li>They used to all run sequentially, but apart from the top-level one, which still needs to run before all the others, they now all run in parallel. This cut <code>configure<\/code> times almost in half on Windows clobber builds on automation.<\/li>\n<\/ul>\n<p><b>In the future<\/b>, we want to get rid of <code>autoconf<\/code> 2.13 and use smart lazy python code to only run the tests that are relevant to the configure options. How this would all exactly work has, as of writing, not been determined. It's been on my list of things to investigate for a while, but hasn't reached the top. In the near future, though, I would like to move all our <code>autoconf<\/code> code related to the build toolchain (compiler and linker) to some form of python code. <\/p>\n<h2>Zaphod beeblebuild<\/h2>\n<p>There are essentially two main projects in the mozilla-central repository: Firefox\/Gecko and the Javascript engine. They use the same build system in many ways. But for a very long time, they actually relied on different copies of the same build system files, like <code>config\/rules.mk<\/code> or <code>build\/autoconf\/*.m4<\/code>. And we had a <code>check-sync-dirs<\/code> script verifying that both projects were indeed using the same file contents. Countless times, we've had landings forgetting to synchronize the files and leading to a <code>check-sync-dirs<\/code> error during the build. I plead guilty to have landed such things multiple times, and so did many other people.<\/p>\n<p>Those days are now long gone, but we currently rely on <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=950298\">dirty tricks that still keep the Firefox\/Gecko and Javascript engine build systems half separate<\/a>. So we kind of replaced a conjoined-twins system with a biheaded system. <b>In the future<\/b>, and this is tied to the section above, both build systems would be <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=jsmerge\">completely merged<\/a>.<\/p>\n<h2>Build system interface<\/h2>\n<p>Another goal of the build system changes was to make the build and test experience better. Especially, running tests was not exactly the most pleasant experience.<\/p>\n<p>A single entry point to the build system was created in the <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=751795\">form of the <code>mach<\/code> tool<\/a>. It simplifies and self-documents many of the workflows that required arcane knowledge.<\/p>\n<p> <b>In the future<\/b>, we will deprecate the historical build system entry points, or replace their implementation to call <code>mach<\/code>. This includes <code>client.mk<\/code> and <code>testing\/testsuite-targets.mk<\/code>.<\/p>\n<h2>moz.build<\/h2>\n<p>Yet another goal of the build system changes was to improve the experience developers have when adding code to the tree. Again, while there is still a lot to be done on the subject, there have been a lot of changes in the past year that I hope have made developer's lives easier.<\/p>\n<p>As an example, adding new code to libxul previous required:<\/p>\n<ul>\n<li>Creating a <code>Makefile.in<\/code> file\n<ul>\n<li>Defining a <code>LIBRARY_NAME<\/code>.<\/li>\n<li>Defining which sources to build with <code>CPPSRCS<\/code>, <code>CSRCS<\/code>, <code>CMMSRCS<\/code>, <code>SSRCS<\/code> or <code>ASFILES<\/code>, using the right variable name for the each source type (C++ or C or Obj-C, or assembly. By the way, did you know there was a difference between <code>SSRCS<\/code> and <code>ASFILES<\/code>?).<\/li>\n<\/ul>\n<\/li>\n<li>Adding something like <code>SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,libname,$(DEPTH)\/path)<\/code> to <code>toolkit\/library\/Makefile.in.<\/code><\/li>\n<\/ul>\n<p>Now, adding new code to libxul requires:<\/p>\n<ul>\n<li>Creating a <code>moz.build<\/code> file\n<ul>\n<li>Defining which sources to build with <code>SOURCES<\/code>, whether they are C, C++ or other.<\/li>\n<li>Defining <code>FINAL_LIBRARY<\/code> to <code>'xul'<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>This is only a simple example, though. There are more things that should have gotten easier, especially since <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1041941\">support for templates landed<\/a>. Templates allowed to hide some details such as dependencies on the right combination of libxul, libnss, libmozalloc and others when building programs or XPCOM components. Combined with syntactic sugar and recent changes to how <code>moz.build<\/code> data is handled by build backends, we could, <b>in the future<\/b>, allow to define multiple targets in a single directory. Currently, if you want to build e.g. a library and a program or multiple libraries in the same directory, well, essentially, you can't.<\/p>\n<p>Relatedly, <code>moz.build<\/code> currently suffers from how it was grown from simply moving definitions from <code>Makefile.in<\/code>., and how those definitions in <code>Makefile.in<\/code> were partly tied to how Make works, and how <code>config.mk<\/code> and <code>rules.mk<\/code> work. Consolidating <code>CPPSRCS<\/code>, <code>CSRCS<\/code> and other variables into a single <code>SOURCES<\/code> variable is something that should be done more broadly, and we should bring more consistency to how things are defined (for example NO_PGO vs. no_pgo depending on the context, etc.). Incidentally, I think those changes can be made in a way that simplifies the build backend python code.<\/p>\n<h2>Multipass<\/h2>\n<p>Some build types, while unusual for developers to do locally on their machine, happen regularly on automation, and are done in awful or inefficient ways.<\/p>\n<p>First, Profile Guided Optimized (PGO) builds. The core idea for those builds is to build once with instrumentation, run the resulting instrumented binary against a profile, and rebuild with the data gathered from that. In our build system, this is what actually happens on Linux:<\/p>\n<ul>\n<li>Build everything with instrumentation.<\/li>\n<li>Run instrumented binary against profile.<\/li>\n<li>Remove half the object directory, including many non-compiled code things that are generated during a normal build.<\/li>\n<li>Rebuild with optimizations guided by the collected data.<\/li>\n<\/ul>\n<p>Yes, the last step repeats things from the second that are not necessary to be repeated.<\/p>\n<p>Second, Mac universal builds, which happen in the following manner:<\/p>\n<ul>\n<li>Build everything for i386.<\/li>\n<li>Build everything for x86-64.<\/li>\n<li>Merge the result of both builds.<\/li>\n<\/ul>\n<p>Yes, \"everything\" in both \"Build everything\" includes the same non-compiled files. Then the third step checks that those non-compiled files actually match (and for <code>buildconfig.html<\/code>, has special treatment) and merges the i386 and x86-64 binaries in Mach-o fat binaries. Not only is this inefficient, but the code behind this is terrible, although it got better with the new packager code. And reproducing universal builds locally is not an easy task.<\/p>\n<p><b>In the future<\/b>, the build system would be able to compile binaries for different targets in a way that doesn't require jumping through hoops like the above. It could even allow to build e.g. a javascript shell for the build machine during a cross-compilation for Android without involving wrapper scripts to handle the situation.<\/p>\n<h2>Third party code<\/h2>\n<p>Building Firefox involves building several third party libraries. In some cases, they use gyp, and we convert their gyp files to <code>moz.build<\/code> at import time (angle, for instance). In other cases, they use gyp, and we just use those gyp files through <code>moz.build<\/code> rules, such that the gyp processing is done during <code>configure<\/code> instead of at import time (webrtc). In yet other cases, they use <code>autoconf<\/code> and <code>automake<\/code>, but we use a <code>moz.build<\/code> file to build them, while still running their <code>configure<\/code> script (freetype and jemalloc). In all those cases, the sources are handled as if they had been Mozilla code all along.<\/p>\n<p>But in the case of NSPR, NSS and ICU, we don't necessarily build them in ways their respective build systems (were meant to) allow and rely on hacks around their build system to do our bidding. This is especially true for NSS (don't look at <code>config\/external\/nss\/Makefile.in<\/code> if you care about your sanity). On top of using atrocious hacks, that makes the build dependable on Make for compilation, in inefficient ways, at that.<\/p>\n<p><b>In the future<\/b>, we wouldn't rely on NSPR, NSS and ICU build systems, and would build them as if they were Mozilla code, like the others. We need to find ways to allow that while limiting the cost of updates to new versions. This is especially true for ICU which is entirely third party. For NSPR and NSS, we have some kind of foothold. Although it is highly unlikely we can make them switch to <code>moz.build<\/code> (and in the current state of <code>moz.build<\/code>, being very tied to Gecko, not possible without possibly significant changes), we can probably come up with schemes that would allow to e.g. easily generate <code>moz.build<\/code> files from their Makefiles and\/or manifests. I expect this to be somewhat manageable for NSS and NSPR. ICU is an entirely different story, sadly.<\/p>\n<h2>And more<\/h2>\n<p>There are many other aspects of the build system that I'm not mentioning here, but you'll excuse me as this post is already long enough (and took much longer to write than it really should).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Mozilla Build System has, for most of its history, not changed much. But, for a couple years now, we&#8217;ve been, slowly and incrementally, modifying it in quite extensive ways. This post summarizes the progress so far, and my personal view on where we&#8217;re headed. Recursive make The Mozilla Build System has, all along, been [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[23],"class_list":["post-3318","post","type-post","status-publish","format-standard","hentry","category-planet-mozilla","tag-en"],"_links":{"self":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3318"}],"version-history":[{"count":47,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3318\/revisions"}],"predecessor-version":[{"id":3376,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3318\/revisions\/3376"}],"wp:attachment":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}