pax_global_header00006660000000000000000000000064147171476700014530gustar00rootroot0000000000000052 comment=24e92acb847233a9c0753c12cb82c98fc084e3db generate-ninja-0.0~git20241119.24e92ac/000077500000000000000000000000001471714767000170545ustar00rootroot00000000000000generate-ninja-0.0~git20241119.24e92ac/.clang-format000066400000000000000000000000471471714767000214300ustar00rootroot00000000000000BasedOnStyle: Chromium Standard: c++17 generate-ninja-0.0~git20241119.24e92ac/.editorconfig000066400000000000000000000000541471714767000215300ustar00rootroot00000000000000[*.py] indent_style = space indent_size = 2 generate-ninja-0.0~git20241119.24e92ac/.git-blame-ignore-revs000066400000000000000000000001211471714767000231460ustar00rootroot00000000000000# apply clang-format to all C++ sources 8bd36a27c0764c869d40ac4102a24720b781b389 generate-ninja-0.0~git20241119.24e92ac/.gitattributes000066400000000000000000000005431471714767000217510ustar00rootroot00000000000000# We expect files to have Unix line endings. *.c text eol=lf *.cc text eol=lf *.cpp text eol=lf *.gn text eol=lf *.gni text eol=lf *.h text eol=lf *.md text eol=lf *.py text eol=lf *.txt text eol=lf .clang-format text eol=lf .gitattributes text eol=lf .gitignore text eol=lf AUTHORS text eol=lf LICENSE text eol=lf OWNERS text eol=lf README.* text eol=lf generate-ninja-0.0~git20241119.24e92ac/.gitignore000066400000000000000000000013131471714767000210420ustar00rootroot00000000000000*.bak *.gypcmd *.mk *.ncb *.opensdf *.orig *.pdb *.props *.pyc *.pyproj *.rules *.sdf *.sln *.sublime-project *.sublime-workspace *.suo *.targets *.user *.vc.opendb *.vcproj *.vcxproj *.vcxproj.filters *.vpj *.vpw *.vpwhistu *.vtg *.xcodeproj *.xcworkspace *.VC.db *_proto.xml *_proto_cpp.xml *~ !Android.mk .*.sw? .DS_Store .cache .cipd .classpath .cproject .gdb_history .gdbinit .landmines .metadata .project .pydevproject .recipe_deps .checkstyle /clang compile_commands.json cscope.* out/ GPATH GRTAGS GSYMS GTAGS Session.vim tags Thumbs.db # Settings directories for eclipse /.externalToolBuilders/ /.settings/ /.vs/ # Visual Studio Code /.vscode/ /_out # VSChromium configuration file vs-chromium-project.txt generate-ninja-0.0~git20241119.24e92ac/.mailmap000066400000000000000000000015221471714767000204750ustar00rootroot00000000000000# This file allows mapping several author and committer email addresses and # names to a single canonical one for `git shortlog`, `git log --author`, # or `git check-mailmap`. # # For example, if you commit as `random.person@example.com` but sometimes use # "Rañdom Person" and sometimes "Random Person" as name and you want the former # to be your canonical name, add # # Rañdom Person # # If you commit as both `random.person@example.com` and `ranp@example.com` and # you want the former to be your canonical email address, add # # # # Combinations of both are possible too, see # https://git-scm.com/docs/gitmailmap for format details. Nico Weber Nico Weber generate-ninja-0.0~git20241119.24e92ac/.style.yapf000066400000000000000000000000361471714767000211520ustar00rootroot00000000000000[style] based_on_style = yapf generate-ninja-0.0~git20241119.24e92ac/AUTHORS000066400000000000000000000035101471714767000201230ustar00rootroot00000000000000# Names should be added to this file with this pattern: # # For individuals: # Name # # For organizations: # Organization # # See python fnmatch module documentation for more information. Google Inc. <*@google.com> HyperConnect Inc. <*@hpcnt.com> IBM Inc. <*@*.ibm.com> Loongson Technology Corporation Limited. <*@loongson.cn> MIPS Technologies, Inc. <*@mips.com> NVIDIA Corporation <*@nvidia.com> Opera Software ASA <*@opera.com> Red Hat Inc. <*@redhat.com> The Chromium Authors <*@chromium.org> Vewd Software AS <*@vewd.com> Vivaldi Technologies AS <*@vivaldi.com> Yandex LLC <*@yandex-team.ru> Aleksei Khoroshilov Alexis Menard Alfredo Mazzinghi Andrew Boyarshin Anuj Kumar Sharma DanCraft99 Evangelos Foutras Gergely Nagy Ilia K Ivan Naydonov Joe Armstrong Julien Brianceau Kal Conley Kamil Rytarowski Ma Aiguo Martijn Croonen Matej Knopp Michael Gilbert Milko Leporis Mohan Reddy Raphael Kubo da Costa Riku Voipio Saikrishna Arcot Stephan Hartmann Tim Niederhausen Tomas Popela Tripta Gupta Wink Saville Yuriy Taraday Zhongwei Wang Oleksandr Motsok Ihor Karavan generate-ninja-0.0~git20241119.24e92ac/LICENSE000066400000000000000000000030271471714767000200630ustar00rootroot00000000000000// Copyright 2015 The Chromium Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. generate-ninja-0.0~git20241119.24e92ac/OWNERS000066400000000000000000000002051471714767000200110ustar00rootroot00000000000000brettw@chromium.org brettw@google.com digit@google.com dpranke@google.com phosek@google.com sdefresne@chromium.org tikuta@google.com generate-ninja-0.0~git20241119.24e92ac/README.md000066400000000000000000000234051471714767000203370ustar00rootroot00000000000000# GN GN is a meta-build system that generates build files for [Ninja](https://ninja-build.org). Related resources: * Documentation in [docs/](https://gn.googlesource.com/gn/+/main/docs/). In particular: * [GN quick start guide](https://gn.googlesource.com/gn/+/main/docs/quick_start.md). * [Frequently asked questions](https://gn.googlesource.com/gn/+/main/docs/faq.md) * [Reference](https://gn.googlesource.com/gn/+/main/docs/reference.md) (all builtin help converted to a single file). * An introductory [presentation](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing). * The [mailing list](https://groups.google.com/a/chromium.org/forum/#!forum/gn-dev). * The [bug database](https://gn.issues.chromium.org/issues?q=status:open). ## What GN is for GN is currently used as the build system for Chromium, Fuchsia, and related projects. Some strengths of GN are: * It is designed for large projects and large teams. It scales efficiently to many thousands of build files and tens of thousands of source files. * It has a readable, clean syntax. Once a build is set-up, it is generally easy for people with no backround in GN to make basic edits to the build. * It is designed for multi-platform projects. It can cleanly express many complicated build variants across different platforms. A single build invocation can target multiple platforms. * It supports multiple parallel output directories, each with their own configuration. This allows a developer to maintain builds targeting debug, release, or different platforms in parallel without forced rebuilds when switching. * It has a focus on correctness. GN checks for the correct dependencies, inputs, and outputs to the extent possible, and has a number of tools to allow developers to ensure the build evolves as desired (for example, `gn check`, `testonly`, `assert_no_deps`). * It has comprehensive build-in help available from the command-line. Although small projects successfully use GN, the focus on large projects has some disadvanages: * GN has the goal of being minimally expressive. Although it can be quite flexible, a design goal is to direct members of a large team (who may not have much knowledge about the build) down an easy-to-understand, well-lit path. This isn't necessarily the correct trade-off for smaller projects. * The minimal build configuration is relatively heavyweight. There are several files required and the exact way all compilers and linkers are run must be specified in the configuration (see "Examples" below). There is no default compiler configuration. * It is not easily composable. GN is designed to compile a single large project with relatively uniform settings and rules. Projects like Chromium do bring together multiple repositories from multiple teams, but the projects must agree on some conventions in the build files to allow this to work. * GN is designed with the expectation that the developers building a project want to compile an identical configuration. So while builds can integrate with the user's environment like the CXX and CFLAGS variables if they want, this is not the default and most project's builds do not do this. The result is that many GN projects do not integrate well with other systems like ebuild. * There is no simple release scheme (see "Versioning and distribution" below). Projects are expected to manage the version of GN they require. Getting an appropriate GN binary can be a hurdle for new contributors to a project. Since GN is relatively uncommon, it can be more difficult to find information and examples. GN can generate Ninja build files for C, C++, Rust, Objective C, and Swift source on most popular platforms. Other languages can be compiled using the general "action" rules which are executed by Python or another scripting language (Google does this to compile Java and Go). But because this is not as clean, generally GN is only used when the bulk of the build is in one of the main built-in languages. ## Getting a binary You can download the latest version of GN binary for [Linux](https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/latest), [macOS](https://chrome-infra-packages.appspot.com/dl/gn/gn/mac-amd64/+/latest) and [Windows](https://chrome-infra-packages.appspot.com/dl/gn/gn/windows-amd64/+/latest) from Google's build infrastructure (see "Versioning and distribution" below for how this is expected to work). Alternatively, you can build GN from source with a C++17 compiler: git clone https://gn.googlesource.com/gn cd gn python build/gen.py # --allow-warning if you want to build with warnings. ninja -C out # To run tests: out/gn_unittests On Windows, it is expected that `cl.exe`, `link.exe`, and `lib.exe` can be found in `PATH`, so you'll want to run from a Visual Studio command prompt, or similar. On Linux, Mac and z/OS, the default compiler is `clang++`, a recent version is expected to be found in `PATH`. This can be overridden by setting the `CC`, `CXX`, and `AR` environment variables. On MSYS and MinGW, the default compiler is `g++`, a recent version is expected to be found in `PATH`. This can be overridden by setting the `CC`, `CXX`, `LD` and `AR` environment variables. On z/OS, building GN requires [ZOSLIB](https://github.com/ibmruntimes/zoslib) to be installed, as described at that URL. When building with `build/gen.py`, use the option `--zoslib-dir` to specify the path to [ZOSLIB](https://github.com/ibmruntimes/zoslib): cd gn python build/gen.py --zoslib-dir /path/to/zoslib By default, if you don't specify `--zoslib-dir`, `gn/build/gen.py` expects to find `zoslib` directory under `gn/third_party/`. ## Examples There is a simple example in [examples/simple_build](examples/simple_build) directory that is a good place to get started with the minimal configuration. To build and run the simple example with the default gcc compiler: cd examples/simple_build ../../out/gn gen -C out ninja -C out ./out/hello For a maximal configuration see the Chromium setup: * [.gn](https://cs.chromium.org/chromium/src/.gn) * [BUILDCONFIG.gn](https://cs.chromium.org/chromium/src/build/config/BUILDCONFIG.gn) * [Toolchain setup](https://cs.chromium.org/chromium/src/build/toolchain/) * [Compiler setup](https://cs.chromium.org/chromium/src/build/config/compiler/BUILD.gn) and the Fuchsia setup: * [.gn](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/.gn) * [BUILDCONFIG.gn](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/build/config/BUILDCONFIG.gn) * [Toolchain setup](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/build/toolchain/) * [Compiler setup](https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/build/config/BUILD.gn) ## Reporting bugs If you find a bug, you can see if it is known or report it in the [bug database](https://bugs.chromium.org/p/gn/issues/list). ## Sending patches GN uses [Gerrit](https://www.gerritcodereview.com/) for code review hosted at [gn-review.googlesource.com](https://gn-review.googlesource.com/). The short version of how to patch is: Register at https://gn-review.googlesource.com. ... edit code ... ninja -C out && out/gn_unittests Then, to upload a change for review: git commit git push origin HEAD:refs/for/main The first time you do this you'll get an error from the server about a missing change-ID. Follow the directions in the error message to install the change-ID hook and run `git commit --amend` to apply the hook to the current commit. When revising a change, use: git commit --amend git push origin HEAD:refs/for/main which will add the new changes to the existing code review, rather than creating a new one. We ask that all contributors [sign Google's Contributor License Agreement](https://cla.developers.google.com/) (either individual or corporate as appropriate, select 'any other Google project'). ## Community You may ask questions and follow along with GN's development on Chromium's [gn-dev@](https://groups.google.com/a/chromium.org/forum/#!forum/gn-dev) Google Group. ## Versioning and distribution Most open-source projects are designed to use the developer's computer's current toolchain such as compiler, linker, and build tool. But the large centrally controlled projects that GN is designed for typically want a more hermetic environment. They will ensure that developers are using a specific compatible toolchain that is versioned with the code. As a result, GN expects that the project choose the appropriate version of GN that will work with each version of the project. There is no "current stable version" of GN that is expected to work for all projects. As a result, the GN developers do not maintain any packages in any of the various packaging systems (Debian, RedHat, HomeBrew, etc.). Some of these systems to have GN packages, but they are maintained by third parties and you should use them at your own risk. Instead, we recommend you refer your checkout tooling to download binaries for a specific hash from [Google's build infrastructure](https://chrome-infra-packages.appspot.com/p/gn/gn) or compile your own. GN does not guarantee the backwards-compatibility of new versions and has no branches or versioning scheme beyond the sequence of commits to the main git branch (which is expected to be stable). In practice, however, GN is very backwards-compatible. The core functionality has been stable for many years and there is enough GN code at Google alone to make non-backwards-compatible changes very difficult, even if they were desirable. There have been discussions about adding a versioning scheme with some guarantees about backwards-compatibility, but nothing has yet been implemented. generate-ninja-0.0~git20241119.24e92ac/build/000077500000000000000000000000001471714767000201535ustar00rootroot00000000000000generate-ninja-0.0~git20241119.24e92ac/build/build_aix.ninja.template000066400000000000000000000004611471714767000247470ustar00rootroot00000000000000rule cxx command = $cxx -MMD -MF $out.d $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = rm -f $out && $ar rcsT $out $in description = AR $out rule link command = $ld $ldflags -o $out $in $libs $solibs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_haiku.ninja.template000066400000000000000000000005231471714767000252660ustar00rootroot00000000000000rule cxx command = $cxx -MMD -MF $out.d $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = rm -f $out && $ar rcsT $out $in description = AR $out rule link command = $ld $ldflags -o $out -Wl,--start-group $in $libs -Wl,--end-group $solibs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_linux.ninja.template000066400000000000000000000005051471714767000253240ustar00rootroot00000000000000rule cxx command = $cxx -MMD -MF $out.d $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = $ar rcsT $out $in description = AR $out rule link command = $ld $ldflags -o $out -Wl,--start-group $in $libs -Wl,--end-group $solibs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_mac.ninja.template000066400000000000000000000004601471714767000247250ustar00rootroot00000000000000rule cxx command = $cxx -MMD -MF $out.d $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = rm -f $out && $ar rcs $out $in description = AR $out rule link command = $ld $ldflags -o $out $in $solibs $libs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_openbsd.ninja.template000066400000000000000000000005221471714767000256160ustar00rootroot00000000000000rule cxx command = $cxx -MMD -MF $out.d $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = rm -f $out && $ar rcs $out $in description = AR $out rule link command = $ld $ldflags -o $out -Wl,--start-group $in $libs -Wl,--end-group $solibs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_win.ninja.template000066400000000000000000000005231471714767000247620ustar00rootroot00000000000000rule cxx command = $cxx /nologo /showIncludes /FC $includes $cflags /c $in /Fo$out description = CXX $out deps = msvc rule alink_thin command = $ar /nologo /ignore:4221 $libflags /OUT:$out $in description = LIB $out rule link command = $ld /nologo $ldflags /OUT:$out /PDB:$out.pdb $in $solibs $libs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/build_zos.ninja.template000066400000000000000000000004411471714767000247770ustar00rootroot00000000000000rule cxx command = $cxx $includes $cflags -c $in -o $out description = CXX $out depfile = $out.d deps = gcc rule alink_thin command = rm -f $out && $ar rcsT $out $in description = AR $out rule link command = $ld $ldflags -o $out $in $libs $solibs description = LINK $out generate-ninja-0.0~git20241119.24e92ac/build/full_test.py000077500000000000000000000047201471714767000225340ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import os import shutil import subprocess import sys import timeit IS_WIN = sys.platform.startswith('win') def RemoveDir(d): if os.path.isdir(d): shutil.rmtree(d) def Trial(gn_path_to_use, save_out_dir=None): bin_path = os.path.join('out', 'gntrial') if not os.path.isdir(bin_path): os.makedirs(bin_path) gn_to_run = os.path.join(bin_path, 'gn' + ('.exe' if IS_WIN else '')) shutil.copy2(gn_path_to_use, gn_to_run) comp_dir = os.path.join('out', 'COMP') subprocess.check_call([gn_to_run, 'gen', comp_dir, '-q', '--check']) if save_out_dir: RemoveDir(save_out_dir) shutil.move(comp_dir, save_out_dir) def main(): if len(sys.argv) < 3 or len(sys.argv) > 4: print('Usage: full_test.py /chrome/tree/at/762a25542878 rel_gn_path [clean]') return 1 if len(sys.argv) == 4: RemoveDir('out') subprocess.check_call([sys.executable, os.path.join('build', 'gen.py')]) subprocess.check_call(['ninja', '-C', 'out']) subprocess.check_call([os.path.join('out', 'gn_unittests')]) orig_dir = os.getcwd() in_chrome_tree_gn = sys.argv[2] our_gn = os.path.join(orig_dir, 'out', 'gn' + ('.exe' if IS_WIN else '')) os.chdir(sys.argv[1]) # Check in-tree vs. ours. Uses: # - Chromium tree at 762a25542878 in argv[1] (this can be off by a bit, but # is roughly when GN was moved out of the Chrome tree, so matches in case GN # semantics/ordering change after that.) # - relative path to argv[1] built gn binary in argv[2] # First, do a comparison to make sure the output between the two gn binaries # actually matches. print('Confirming output matches...') dir_a = os.path.join('out', 'a') dir_b = os.path.join('out', 'b') Trial(in_chrome_tree_gn, dir_a) Trial(our_gn, dir_b) subprocess.check_call(['diff', '-r', dir_a, dir_b]) # Then, some time trials. TRIALS = 5 print('Comparing performance... (takes a while)') time_a = timeit.timeit('Trial("%s")' % in_chrome_tree_gn, number=TRIALS, setup='from __main__ import Trial') time_b = timeit.timeit('Trial("%s")' % our_gn, number=TRIALS, setup='from __main__ import Trial') print('In-tree gn avg: %.3fs' % (time_a / TRIALS)) print('Our gn avg: %.3fs' % (time_b / TRIALS)) return 0 if __name__ == '__main__': sys.exit(main()) generate-ninja-0.0~git20241119.24e92ac/build/gen.py000077500000000000000000001024331471714767000213040ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Generates build.ninja that will build GN.""" import argparse import os import platform import re import shlex import subprocess import sys # IMPORTANT: This script is also executed as python2 on # GN's CI builders. try: # py3 from shlex import quote as shell_quote except ImportError: # py2 from pipes import quote as shell_quote SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) REPO_ROOT = os.path.dirname(SCRIPT_DIR) class Platform(object): """Represents a host/target platform.""" def __init__(self, platform): self._platform = platform if self._platform is not None: return self._platform = sys.platform if self._platform.startswith('linux'): self._platform = 'linux' elif self._platform.startswith('darwin'): self._platform = 'darwin' elif self._platform.startswith('mingw'): self._platform = 'mingw' elif self._platform.startswith('msys'): self._platform = 'msys' elif self._platform.startswith('win'): self._platform = 'msvc' elif self._platform.startswith('aix'): self._platform = 'aix' elif self._platform.startswith('fuchsia'): self._platform = 'fuchsia' elif self._platform.startswith('freebsd'): self._platform = 'freebsd' elif self._platform.startswith('netbsd'): self._platform = 'netbsd' elif self._platform.startswith('openbsd'): self._platform = 'openbsd' elif self._platform.startswith('haiku'): self._platform = 'haiku' elif self._platform.startswith('sunos'): self._platform = 'solaris' elif self._platform.startswith('zos'): self._platform = 'zos' elif self._platform.startswith('serenity'): self._platform = 'serenity' @staticmethod def known_platforms(): return ['linux', 'darwin', 'mingw', 'msys', 'msvc', 'aix', 'fuchsia', 'freebsd', 'netbsd', 'openbsd', 'haiku', 'solaris', 'zos', 'serenity'] def platform(self): return self._platform def is_linux(self): return self._platform == 'linux' def is_mingw(self): return self._platform == 'mingw' def is_msys(self): return self._platform == 'msys' def is_msvc(self): return self._platform == 'msvc' def is_windows(self): return self.is_mingw() or self.is_msvc() def is_darwin(self): return self._platform == 'darwin' def is_aix(self): return self._platform == 'aix' def is_haiku(self): return self._platform == 'haiku' def is_solaris(self): return self._platform == 'solaris' def is_posix(self): return self._platform in ['linux', 'freebsd', 'darwin', 'aix', 'openbsd', 'haiku', 'solaris', 'msys', 'netbsd', 'serenity'] def is_zos(self): return self._platform == 'zos' def is_serenity(self): return self._platform == 'serenity' class ArgumentsList: """Helper class to accumulate ArgumentParser argument definitions and be able to regenerate a corresponding command-line to be written in the generated Ninja file for the 'regen' rule. """ def __init__(self): self._arguments = [] def add(self, *args, **kwargs): """Add an argument definition, use as argparse.ArgumentParser.add_argument().""" self._arguments.append((args, kwargs)) def add_to_parser(self, parser): """Add all known arguments to parser.""" for args, kwargs in self._arguments: parser.add_argument(*args, **kwargs) def gen_command_line_args(self, parser_arguments): """Generate a gen.py argument list to be embedded in a Ninja file.""" result = [] for args, kwargs in self._arguments: if len(args) == 2: long_option = args[1] else: long_option = args[0] dest = kwargs.get('dest', None) if dest is None: assert long_option.startswith('--') dest = long_option[2:].replace('-', '_') if getattr(parser_arguments, dest, None) is None: # This was not set on the command-line so skip it. continue action = kwargs.get('action', None) if action == 'store_true': if getattr(parser_arguments, dest): result.append(long_option) elif action == 'store' or action is None: result.append('%s=%s' % (long_option, getattr(parser_arguments, dest))) elif action == 'append': for item in getattr(parser_arguments, dest): result.append('%s=%s' % (long_option, item)) else: assert action is None, "Unsupported action " + action if platform.system() == "Windows": return ' '.join(result) else: return ' '.join(shell_quote(item) for item in result) def main(argv): parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__) args_list = ArgumentsList() args_list.add('-d', '--debug', action='store_true', help='Do a debug build. Defaults to release build.') args_list.add('--platform', help='target platform (' + '/'.join(Platform.known_platforms()) + ')', choices=Platform.known_platforms()) args_list.add('--host', help='host platform (' + '/'.join(Platform.known_platforms()) + ')', choices=Platform.known_platforms()) args_list.add('--use-lto', action='store_true', help='Enable the use of LTO') args_list.add('--use-icf', action='store_true', help='Enable the use of Identical Code Folding') args_list.add('--use-asan', action='store_true', help='Enable the use of AddressSanitizer') args_list.add('--use-ubsan', action='store_true', help='Enable the use of UndefinedBehaviorSanitizer') args_list.add('--no-last-commit-position', action='store_true', help='Do not generate last_commit_position.h.') args_list.add('--out-path', type=str, default=os.path.join(REPO_ROOT, 'out'), help='The path to generate the build files in.') args_list.add('--no-strip', action='store_true', help='Don\'t strip release build. Useful for profiling.') args_list.add('--no-static-libstdc++', action='store_true', default=False, dest='no_static_libstdcpp', help='Don\'t link libstdc++ statically') args_list.add('--link-lib', action='append', metavar='LINK_LIB', default=[], dest='link_libs', help=('Add a library to the final executable link. ' + 'LINK_LIB must be the path to a static or shared ' + 'library, or \'-l\' on POSIX systems. Can be ' + 'used multiple times. Useful to link custom malloc ' + 'or cpu profiling libraries.')) args_list.add('--allow-warnings', action='store_true', default=False, help=('Allow compiler warnings, don\'t treat them as ' 'errors.')) if sys.platform == 'zos': args_list.add('--zoslib-dir', action='store', default='../third_party/zoslib', dest='zoslib_dir', help=('Specify the path of ZOSLIB directory, to link ' + 'with /install/lib/libzoslib.a, and ' + 'add -I/install/include to the compile ' + 'commands. See README.md for details.')) args_list.add_to_parser(parser) options = parser.parse_args(argv) platform = Platform(options.platform) if options.host: host = Platform(options.host) else: host = platform out_dir = options.out_path if not os.path.isdir(out_dir): os.makedirs(out_dir) if not options.no_last_commit_position: GenerateLastCommitPosition(host, os.path.join(out_dir, 'last_commit_position.h')) WriteGNNinja(os.path.join(out_dir, 'build.ninja'), platform, host, options, args_list) return 0 def is_gcc(cxx): """Return True iff the compiler at `cxx` is GCC based.""" ret = subprocess.run( f'{cxx} -dM -E -', shell=True, stdin=subprocess.DEVNULL, text=True, capture_output=True) return ret.returncode == 0 and "#define __GNUC__" in ret.stdout and not "#define __clang__" in ret.stdout def GenerateLastCommitPosition(host, header): ROOT_TAG = 'initial-commit' describe_output = subprocess.check_output( ['git', 'describe', 'HEAD', '--abbrev=12', '--match', ROOT_TAG], shell=host.is_windows(), cwd=REPO_ROOT) mo = re.match(ROOT_TAG + r'-(\d+)-g([0-9a-f]+)', describe_output.decode()) if not mo: raise ValueError( 'Unexpected output from git describe when generating version header') contents = '''// Generated by build/gen.py. #ifndef OUT_LAST_COMMIT_POSITION_H_ #define OUT_LAST_COMMIT_POSITION_H_ #define LAST_COMMIT_POSITION_NUM %s #define LAST_COMMIT_POSITION "%s (%s)" #endif // OUT_LAST_COMMIT_POSITION_H_ ''' % (mo.group(1), mo.group(1), mo.group(2)) # Only write/touch this file if the commit position has changed. old_contents = '' if os.path.isfile(header): with open(header, 'r') as f: old_contents = f.read() if old_contents != contents: with open(header, 'w') as f: f.write(contents) def WriteGenericNinja(path, static_libraries, executables, cxx, ar, ld, platform, host, options, args_list, cflags=[], ldflags=[], libflags=[], include_dirs=[], solibs=[]): args = args_list.gen_command_line_args(options) if args: args = " " + args ninja_header_lines = [ 'cxx = ' + cxx, 'ar = ' + ar, 'ld = ' + ld, '', 'rule regen', ' command = %s ../build/gen.py%s' % (sys.executable, args), ' description = Regenerating ninja files', '', 'build build.ninja: regen', ' generator = 1', ' depfile = build.ninja.d', '', ] template_filename = os.path.join(SCRIPT_DIR, { 'msvc': 'build_win.ninja.template', 'mingw': 'build_linux.ninja.template', 'msys': 'build_linux.ninja.template', 'darwin': 'build_mac.ninja.template', 'linux': 'build_linux.ninja.template', 'freebsd': 'build_linux.ninja.template', 'aix': 'build_aix.ninja.template', 'openbsd': 'build_openbsd.ninja.template', 'haiku': 'build_haiku.ninja.template', 'solaris': 'build_linux.ninja.template', 'netbsd': 'build_linux.ninja.template', 'zos': 'build_zos.ninja.template', 'serenity': 'build_linux.ninja.template', }[platform.platform()]) with open(template_filename) as f: ninja_template = f.read() if platform.is_windows(): executable_ext = '.exe' if platform.is_msvc(): library_ext = '.lib' else: library_ext = '.a' object_ext = '.obj' else: executable_ext = '' library_ext = '.a' object_ext = '.o' def escape_path_ninja(path): return path.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') def src_to_obj(path): return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext) def library_to_a(library): return '%s%s' % (library, library_ext) ninja_lines = [] def build_source(src_file, settings): ninja_lines.extend([ 'build %s: cxx %s' % (src_to_obj(src_file), escape_path_ninja( os.path.relpath( os.path.join(REPO_ROOT, src_file), os.path.dirname(path)))), ' includes = %s' % ' '.join( ['-I' + escape_path_ninja(dirname) for dirname in include_dirs]), ' cflags = %s' % ' '.join(cflags), ]) for library, settings in static_libraries.items(): for src_file in settings['sources']: build_source(src_file, settings) ninja_lines.append('build %s: alink_thin %s' % ( library_to_a(library), ' '.join([src_to_obj(src_file) for src_file in settings['sources']]))) ninja_lines.append(' libflags = %s' % ' '.join(libflags)) for executable, settings in executables.items(): for src_file in settings['sources']: build_source(src_file, settings) ninja_lines.extend([ 'build %s%s: link %s | %s' % ( executable, executable_ext, ' '.join([src_to_obj(src_file) for src_file in settings['sources']]), ' '.join([library_to_a(library) for library in settings['libs']])), ' ldflags = %s' % ' '.join(ldflags), ' solibs = %s' % ' '.join(solibs), ' libs = %s' % ' '.join( [library_to_a(library) for library in settings['libs']]), ]) ninja_lines.append('') # Make sure the file ends with a newline. with open(path, 'w') as f: f.write('\n'.join(ninja_header_lines)) f.write(ninja_template) f.write('\n'.join(ninja_lines)) with open(path + '.d', 'w') as f: f.write('build.ninja: ' + os.path.relpath(os.path.join(SCRIPT_DIR, 'gen.py'), os.path.dirname(path)) + ' ' + os.path.relpath(template_filename, os.path.dirname(path)) + '\n') def WriteGNNinja(path, platform, host, options, args_list): if platform.is_msvc(): cxx = os.environ.get('CXX', 'cl.exe') ld = os.environ.get('LD', 'link.exe') ar = os.environ.get('AR', 'lib.exe') elif platform.is_aix(): cxx = os.environ.get('CXX', 'g++') ld = os.environ.get('LD', 'g++') ar = os.environ.get('AR', 'ar -X64') elif platform.is_msys() or platform.is_mingw(): cxx = os.environ.get('CXX', 'g++') ld = os.environ.get('LD', 'g++') ar = os.environ.get('AR', 'ar') else: cxx = os.environ.get('CXX', 'clang++') ld = cxx ar = os.environ.get('AR', 'ar') cflags = os.environ.get('CFLAGS', '').split() cflags += os.environ.get('CXXFLAGS', '').split() ldflags = os.environ.get('LDFLAGS', '').split() libflags = os.environ.get('LIBFLAGS', '').split() include_dirs = [ os.path.relpath(os.path.join(REPO_ROOT, 'src'), os.path.dirname(path)), '.', ] if platform.is_zos(): include_dirs += [ options.zoslib_dir + '/install/include' ] libs = [] if not platform.is_msvc(): if options.debug: cflags.extend(['-O0', '-g']) # Enable libc++ or libstdc++ assertions in debug mode. # Just set both macros to avoid detecting the C++ runtime being used. # Currently disabled on MacOS since this results in linking errors at the # moment, due to what looks like an XCode-specific Clang packaging error. if not platform.is_darwin(): cflags.extend(['-D_LIBCPP_DEBUG=1', '-D_GLIBCXX_DEBUG=1']) else: cflags.append('-DNDEBUG') cflags.append('-O3') if options.no_strip: cflags.append('-g') ldflags.append('-O3') # Use -fdata-sections and -ffunction-sections to place each function # or data item into its own section so --gc-sections can eliminate any # unused functions and data items. cflags.extend(['-fdata-sections', '-ffunction-sections']) ldflags.extend(['-fdata-sections', '-ffunction-sections']) if platform.is_darwin(): ldflags.append('-Wl,-dead_strip') elif not platform.is_aix() and not platform.is_solaris() and not platform.is_zos(): # Garbage collection is done by default on aix, and option is unsupported on z/OS. ldflags.append('-Wl,--gc-sections') # Omit all symbol information from the output file. if options.no_strip is None: if platform.is_darwin(): ldflags.append('-Wl,-S') elif platform.is_aix(): ldflags.append('-Wl,-s') elif platform.is_solaris(): ldflags.append('-Wl,--strip-all') elif not platform.is_zos(): # /bin/ld on z/OS doesn't have an equivalent option. ldflags.append('-Wl,-strip-all') # Enable identical code-folding. if options.use_icf and not platform.is_darwin(): ldflags.append('-Wl,--icf=all') if options.use_lto: cflags.extend(['-flto', '-fwhole-program-vtables']) ldflags.extend(['-flto', '-fwhole-program-vtables']) if options.use_asan: cflags.append('-fsanitize=address') ldflags.append('-fsanitize=address') if options.use_ubsan: cflags.append('-fsanitize=undefined') ldflags.append('-fsanitize=undefined') if not options.allow_warnings: cflags.append('-Werror') cflags.extend([ '-D_FILE_OFFSET_BITS=64', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS', '-pthread', '-pipe', '-fno-exceptions', '-fno-rtti', '-fdiagnostics-color', '-Wall', '-Wextra', '-Wno-unused-parameter', '-Wextra-semi', '-Wundef', '-std=c++20' ]) if is_gcc(cxx): cflags.append('-Wno-redundant-move') # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104336 cflags.append('-Wno-restrict') # flags not supported by gcc/g++. else: cflags.extend(['-Wrange-loop-analysis', '-Wextra-semi-stmt']) if platform.is_linux() or platform.is_mingw() or platform.is_msys(): ldflags.append('-Wl,--as-needed') if not options.no_static_libstdcpp: ldflags.append('-static-libstdc++') cflags.extend([ '-Wno-deprecated-copy', '-Wno-implicit-fallthrough', '-Wno-redundant-move', '-Wno-unused-variable', '-Wno-format', # Use of %llx, which is supported by _UCRT, false positive '-Wno-strict-aliasing', # Dereferencing punned pointer '-Wno-cast-function-type', # Casting FARPROC to RegDeleteKeyExPtr ]) elif platform.is_darwin(): min_mac_version_flag = '-mmacosx-version-min=10.9' cflags.append(min_mac_version_flag) ldflags.append(min_mac_version_flag) elif platform.is_aix(): cflags.append('-maix64') ldflags.append('-maix64') elif platform.is_haiku(): cflags.append('-fPIC') cflags.extend(['-D_BSD_SOURCE']) elif platform.is_zos(): cflags.append('-fzos-le-char-mode=ascii') cflags.append('-Wno-unused-function') cflags.append('-D_OPEN_SYS_FILE_EXT') cflags.append('-DPATH_MAX=1024') cflags.append('-DZOSLIB_OVERRIDE_CLIB') if platform.is_posix() and not platform.is_haiku(): ldflags.append('-pthread') if platform.is_mingw() or platform.is_msys(): cflags.extend(['-DUNICODE', '-DNOMINMAX', '-DWIN32_LEAN_AND_MEAN', '-DWINVER=0x0A00', '-D_CRT_SECURE_NO_DEPRECATE', '-D_SCL_SECURE_NO_DEPRECATE', '-D_UNICODE', '-D_WIN32_WINNT=0x0A00', '-D_HAS_EXCEPTIONS=0' ]) elif platform.is_msvc(): if not options.debug: cflags.extend(['/O2', '/DNDEBUG', '/Zc:inline']) ldflags.extend(['/OPT:REF']) if options.use_icf: libflags.extend(['/OPT:ICF']) if options.use_lto: cflags.extend(['/GL']) libflags.extend(['/LTCG']) ldflags.extend(['/LTCG']) if not options.allow_warnings: cflags.append('/WX') cflags.extend([ '/DNOMINMAX', '/DUNICODE', '/DWIN32_LEAN_AND_MEAN', '/DWINVER=0x0A00', '/D_CRT_SECURE_NO_DEPRECATE', '/D_SCL_SECURE_NO_DEPRECATE', '/D_UNICODE', '/D_WIN32_WINNT=0x0A00', '/FS', '/W4', '/Zi', '/wd4099', '/wd4100', '/wd4127', '/wd4244', '/wd4267', '/wd4505', '/wd4838', '/wd4996', '/std:c++20', '/GR-', '/D_HAS_EXCEPTIONS=0', ]) win_manifest = os.path.relpath( os.path.join(REPO_ROOT, "build/windows.manifest.xml"), options.out_path) ldflags.extend(['/DEBUG', '/MACHINE:x64', '/MANIFEST:EMBED', f'/MANIFESTINPUT:{win_manifest}']) static_libraries = { 'base': {'sources': [ 'src/base/command_line.cc', 'src/base/environment.cc', 'src/base/files/file.cc', 'src/base/files/file_enumerator.cc', 'src/base/files/file_path.cc', 'src/base/files/file_path_constants.cc', 'src/base/files/file_util.cc', 'src/base/files/scoped_file.cc', 'src/base/files/scoped_temp_dir.cc', 'src/base/json/json_parser.cc', 'src/base/json/json_reader.cc', 'src/base/json/json_writer.cc', 'src/base/json/string_escape.cc', 'src/base/logging.cc', 'src/base/md5.cc', 'src/base/memory/ref_counted.cc', 'src/base/memory/weak_ptr.cc', 'src/base/sha1.cc', 'src/base/strings/string_number_conversions.cc', 'src/base/strings/string_split.cc', 'src/base/strings/string_util.cc', 'src/base/strings/string_util_constants.cc', 'src/base/strings/stringprintf.cc', 'src/base/strings/utf_string_conversion_utils.cc', 'src/base/strings/utf_string_conversions.cc', 'src/base/timer/elapsed_timer.cc', 'src/base/value_iterators.cc', 'src/base/values.cc', ]}, 'gn_lib': {'sources': [ 'src/gn/action_target_generator.cc', 'src/gn/action_values.cc', 'src/gn/analyzer.cc', 'src/gn/args.cc', 'src/gn/binary_target_generator.cc', 'src/gn/build_settings.cc', 'src/gn/builder.cc', 'src/gn/builder_record.cc', 'src/gn/bundle_data.cc', 'src/gn/bundle_data_target_generator.cc', 'src/gn/bundle_file_rule.cc', 'src/gn/builtin_tool.cc', 'src/gn/c_include_iterator.cc', 'src/gn/c_substitution_type.cc', 'src/gn/c_tool.cc', 'src/gn/command_analyze.cc', 'src/gn/command_args.cc', 'src/gn/command_check.cc', 'src/gn/command_clean.cc', 'src/gn/command_clean_stale.cc', 'src/gn/command_desc.cc', 'src/gn/command_format.cc', 'src/gn/command_gen.cc', 'src/gn/command_help.cc', 'src/gn/command_ls.cc', 'src/gn/command_meta.cc', 'src/gn/command_outputs.cc', 'src/gn/command_path.cc', 'src/gn/command_refs.cc', 'src/gn/commands.cc', 'src/gn/compile_commands_writer.cc', 'src/gn/rust_project_writer.cc', 'src/gn/config.cc', 'src/gn/config_values.cc', 'src/gn/config_values_extractors.cc', 'src/gn/config_values_generator.cc', 'src/gn/copy_target_generator.cc', 'src/gn/create_bundle_target_generator.cc', 'src/gn/deps_iterator.cc', 'src/gn/desc_builder.cc', 'src/gn/eclipse_writer.cc', 'src/gn/err.cc', 'src/gn/escape.cc', 'src/gn/exec_process.cc', 'src/gn/filesystem_utils.cc', 'src/gn/file_writer.cc', 'src/gn/frameworks_utils.cc', 'src/gn/function_exec_script.cc', 'src/gn/function_filter.cc', 'src/gn/function_filter_labels.cc', 'src/gn/function_foreach.cc', 'src/gn/function_forward_variables_from.cc', 'src/gn/function_get_label_info.cc', 'src/gn/function_get_path_info.cc', 'src/gn/function_get_target_outputs.cc', 'src/gn/function_label_matches.cc', 'src/gn/function_process_file_template.cc', 'src/gn/function_read_file.cc', 'src/gn/function_rebase_path.cc', 'src/gn/function_set_default_toolchain.cc', 'src/gn/function_set_defaults.cc', 'src/gn/function_template.cc', 'src/gn/function_toolchain.cc', 'src/gn/function_write_file.cc', 'src/gn/functions.cc', 'src/gn/functions_target.cc', 'src/gn/general_tool.cc', 'src/gn/generated_file_target_generator.cc', 'src/gn/group_target_generator.cc', 'src/gn/header_checker.cc', 'src/gn/import_manager.cc', 'src/gn/input_conversion.cc', 'src/gn/input_file.cc', 'src/gn/input_file_manager.cc', 'src/gn/invoke_python.cc', 'src/gn/item.cc', 'src/gn/json_project_writer.cc', 'src/gn/label.cc', 'src/gn/label_pattern.cc', 'src/gn/lib_file.cc', 'src/gn/loader.cc', 'src/gn/location.cc', 'src/gn/metadata.cc', 'src/gn/metadata_walk.cc', 'src/gn/ninja_action_target_writer.cc', 'src/gn/ninja_binary_target_writer.cc', 'src/gn/ninja_build_writer.cc', 'src/gn/ninja_bundle_data_target_writer.cc', 'src/gn/ninja_c_binary_target_writer.cc', 'src/gn/ninja_copy_target_writer.cc', 'src/gn/ninja_create_bundle_target_writer.cc', 'src/gn/ninja_generated_file_target_writer.cc', 'src/gn/ninja_group_target_writer.cc', 'src/gn/ninja_outputs_writer.cc', 'src/gn/ninja_rust_binary_target_writer.cc', 'src/gn/ninja_target_command_util.cc', 'src/gn/ninja_target_writer.cc', 'src/gn/ninja_toolchain_writer.cc', 'src/gn/ninja_tools.cc', 'src/gn/ninja_utils.cc', 'src/gn/ninja_writer.cc', 'src/gn/operators.cc', 'src/gn/output_conversion.cc', 'src/gn/output_file.cc', 'src/gn/parse_node_value_adapter.cc', 'src/gn/parse_tree.cc', 'src/gn/parser.cc', 'src/gn/path_output.cc', 'src/gn/pattern.cc', 'src/gn/pool.cc', 'src/gn/qt_creator_writer.cc', 'src/gn/resolved_target_data.cc', 'src/gn/runtime_deps.cc', 'src/gn/rust_substitution_type.cc', 'src/gn/rust_tool.cc', 'src/gn/rust_values.cc', 'src/gn/rust_values_generator.cc', 'src/gn/rust_variables.cc', 'src/gn/scheduler.cc', 'src/gn/scope.cc', 'src/gn/scope_per_file_provider.cc', 'src/gn/settings.cc', 'src/gn/setup.cc', 'src/gn/source_dir.cc', 'src/gn/source_file.cc', 'src/gn/standard_out.cc', 'src/gn/string_atom.cc', 'src/gn/string_output_buffer.cc', 'src/gn/string_utils.cc', 'src/gn/substitution_list.cc', 'src/gn/substitution_pattern.cc', 'src/gn/substitution_type.cc', 'src/gn/substitution_writer.cc', 'src/gn/swift_values.cc', 'src/gn/swift_values_generator.cc', 'src/gn/swift_variables.cc', 'src/gn/switches.cc', 'src/gn/target.cc', 'src/gn/target_generator.cc', 'src/gn/template.cc', 'src/gn/token.cc', 'src/gn/tokenizer.cc', 'src/gn/tool.cc', 'src/gn/toolchain.cc', 'src/gn/trace.cc', 'src/gn/value.cc', 'src/gn/value_extractors.cc', 'src/gn/variables.cc', 'src/gn/version.cc', 'src/gn/visibility.cc', 'src/gn/visual_studio_utils.cc', 'src/gn/visual_studio_writer.cc', 'src/gn/xcode_object.cc', 'src/gn/xcode_writer.cc', 'src/gn/xml_element_writer.cc', 'src/util/atomic_write.cc', 'src/util/exe_path.cc', 'src/util/msg_loop.cc', 'src/util/semaphore.cc', 'src/util/sys_info.cc', 'src/util/ticks.cc', 'src/util/worker_pool.cc', ]}, } executables = { 'gn': {'sources': [ 'src/gn/gn_main.cc' ], 'libs': []}, 'gn_unittests': { 'sources': [ 'src/gn/action_target_generator_unittest.cc', 'src/gn/analyzer_unittest.cc', 'src/gn/args_unittest.cc', 'src/gn/builder_record_map_unittest.cc', 'src/gn/builder_unittest.cc', 'src/gn/bundle_data_unittest.cc', 'src/gn/c_include_iterator_unittest.cc', 'src/gn/command_format_unittest.cc', 'src/gn/commands_unittest.cc', 'src/gn/compile_commands_writer_unittest.cc', 'src/gn/config_unittest.cc', 'src/gn/config_values_extractors_unittest.cc', 'src/gn/escape_unittest.cc', 'src/gn/exec_process_unittest.cc', 'src/gn/filesystem_utils_unittest.cc', 'src/gn/file_writer_unittest.cc', 'src/gn/frameworks_utils_unittest.cc', 'src/gn/function_filter_unittest.cc', 'src/gn/function_filter_labels_unittest.cc', 'src/gn/function_foreach_unittest.cc', 'src/gn/function_forward_variables_from_unittest.cc', 'src/gn/function_get_label_info_unittest.cc', 'src/gn/function_get_path_info_unittest.cc', 'src/gn/function_get_target_outputs_unittest.cc', 'src/gn/function_label_matches_unittest.cc', 'src/gn/function_process_file_template_unittest.cc', 'src/gn/function_rebase_path_unittest.cc', 'src/gn/function_template_unittest.cc', 'src/gn/function_toolchain_unittest.cc', 'src/gn/function_write_file_unittest.cc', 'src/gn/functions_target_rust_unittest.cc', 'src/gn/functions_target_unittest.cc', 'src/gn/functions_unittest.cc', 'src/gn/hash_table_base_unittest.cc', 'src/gn/header_checker_unittest.cc', 'src/gn/input_conversion_unittest.cc', 'src/gn/json_project_writer_unittest.cc', 'src/gn/rust_project_writer_unittest.cc', 'src/gn/rust_project_writer_helpers_unittest.cc', 'src/gn/label_pattern_unittest.cc', 'src/gn/label_unittest.cc', 'src/gn/loader_unittest.cc', 'src/gn/metadata_unittest.cc', 'src/gn/metadata_walk_unittest.cc', 'src/gn/ninja_action_target_writer_unittest.cc', 'src/gn/ninja_binary_target_writer_unittest.cc', 'src/gn/ninja_build_writer_unittest.cc', 'src/gn/ninja_bundle_data_target_writer_unittest.cc', 'src/gn/ninja_c_binary_target_writer_unittest.cc', 'src/gn/ninja_copy_target_writer_unittest.cc', 'src/gn/ninja_create_bundle_target_writer_unittest.cc', 'src/gn/ninja_generated_file_target_writer_unittest.cc', 'src/gn/ninja_group_target_writer_unittest.cc', 'src/gn/ninja_outputs_writer_unittest.cc', 'src/gn/ninja_rust_binary_target_writer_unittest.cc', 'src/gn/ninja_target_command_util_unittest.cc', 'src/gn/ninja_target_writer_unittest.cc', 'src/gn/ninja_toolchain_writer_unittest.cc', 'src/gn/operators_unittest.cc', 'src/gn/output_conversion_unittest.cc', 'src/gn/parse_tree_unittest.cc', 'src/gn/parser_unittest.cc', 'src/gn/path_output_unittest.cc', 'src/gn/pattern_unittest.cc', 'src/gn/pointer_set_unittest.cc', 'src/gn/resolved_target_data_unittest.cc', 'src/gn/resolved_target_deps_unittest.cc', 'src/gn/runtime_deps_unittest.cc', 'src/gn/scope_per_file_provider_unittest.cc', 'src/gn/scope_unittest.cc', 'src/gn/setup_unittest.cc', 'src/gn/source_dir_unittest.cc', 'src/gn/source_file_unittest.cc', 'src/gn/string_atom_unittest.cc', 'src/gn/string_output_buffer_unittest.cc', 'src/gn/string_utils_unittest.cc', 'src/gn/substitution_pattern_unittest.cc', 'src/gn/substitution_writer_unittest.cc', 'src/gn/target_public_pair_unittest.cc', 'src/gn/target_unittest.cc', 'src/gn/template_unittest.cc', 'src/gn/test_with_scheduler.cc', 'src/gn/test_with_scope.cc', 'src/gn/tokenizer_unittest.cc', 'src/gn/unique_vector_unittest.cc', 'src/gn/value_unittest.cc', 'src/gn/vector_utils_unittest.cc', 'src/gn/version_unittest.cc', 'src/gn/visibility_unittest.cc', 'src/gn/visual_studio_utils_unittest.cc', 'src/gn/visual_studio_writer_unittest.cc', 'src/gn/xcode_object_unittest.cc', 'src/gn/xml_element_writer_unittest.cc', 'src/util/atomic_write_unittest.cc', 'src/util/test/gn_test.cc', ], 'libs': []}, } if platform.is_posix() or platform.is_zos(): static_libraries['base']['sources'].extend([ 'src/base/files/file_enumerator_posix.cc', 'src/base/files/file_posix.cc', 'src/base/files/file_util_posix.cc', 'src/base/posix/file_descriptor_shuffle.cc', 'src/base/posix/safe_strerror.cc', ]) if platform.is_zos(): libs.extend([ options.zoslib_dir + '/install/lib/libzoslib.a' ]) if platform.is_windows(): static_libraries['base']['sources'].extend([ 'src/base/files/file_enumerator_win.cc', 'src/base/files/file_util_win.cc', 'src/base/files/file_win.cc', 'src/base/win/registry.cc', 'src/base/win/scoped_handle.cc', 'src/base/win/scoped_process_information.cc', ]) if platform.is_msvc(): libs.extend([ 'advapi32.lib', 'dbghelp.lib', 'kernel32.lib', 'ole32.lib', 'shell32.lib', 'user32.lib', 'userenv.lib', 'version.lib', 'winmm.lib', 'ws2_32.lib', 'Shlwapi.lib', ]) else: libs.extend([ '-ladvapi32', '-ldbghelp', '-lkernel32', '-lole32', '-lshell32', '-luser32', '-luserenv', '-lversion', '-lwinmm', '-lws2_32', '-lshlwapi', ]) libs.extend(options.link_libs) # we just build static libraries that GN needs executables['gn']['libs'].extend(static_libraries.keys()) executables['gn_unittests']['libs'].extend(static_libraries.keys()) WriteGenericNinja(path, static_libraries, executables, cxx, ar, ld, platform, host, options, args_list, cflags, ldflags, libflags, include_dirs, libs) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) generate-ninja-0.0~git20241119.24e92ac/build/windows.manifest.xml000066400000000000000000000011341471714767000241730ustar00rootroot00000000000000 true generate-ninja-0.0~git20241119.24e92ac/docs/000077500000000000000000000000001471714767000200045ustar00rootroot00000000000000generate-ninja-0.0~git20241119.24e92ac/docs/cross_compiles.md000066400000000000000000000115201471714767000233510ustar00rootroot00000000000000# How GN handles cross-compiling ## As a GN user GN has robust support for doing cross compiles and building things for multiple architectures in a single build (e.g., to build some things to run locally and some things to run on an embedded device). In fact, there is no limit on the number of different architectures you can build at once; the Chromium build uses at least four in some configurations. To start, GN has the concepts of a _host_ and a _target_. The host is the platform that the build is run on, and the target is the platform where the code will actually run (This is different from [autotools](http://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html)' terminology, but uses the more common terminology for cross compiling). (Confusingly, GN also refers to each build artifact -- an executable, library, etc. -- as a target. On this page, we will use "target" only to refer to the system you want to run your code on, and use "rule" or some other synonym to refer to a specific build artifact). When GN starts up, the `host_os` and `host_cpu` variables are set automatically to match the operating system (they can be overridden in args files, which can be useful in weird corner cases). The user can specify that they want to do a cross-compile by setting either or both of `target_os` and `target_cpu`; if they are not set, the build config files will usually set them to the host's values, though the Chromium build will set target\_cpu to "arm" if target\_os is set to "android"). So, for example, running on an x64 Linux machine: ``` gn gen out/Default ``` is equivalent to: ``` gn gen out/Default --args='target_os="linux" target_cpu="x64"' ``` To do an 32-bit ARM Android cross-compile, do: ``` gn gen out/Default --args='target_os="android"' ``` (We don't have to specify target\_cpu because of the conditionals mentioned above). And, to do a 64-bit MIPS Chrome OS cross-compile: ``` gn gen out/Default --args='target_os="chromeos" target_cpu="mips64el"' ``` ## As a BUILD.gn author If you are editing build files outside of the //build directory (i.e., not directly working on toolchains, compiler configs, etc.), generally you only need to worry about a few things: The `current_toolchain`, `current_cpu`, and `current_os` variables reflect the settings that are **currently** in effect in a given rule. The `is_linux`, `is_win` etc. variables are updated to reflect the current settings, and changes to `cflags`, `ldflags` and so forth also only apply to the current toolchain and the current thing being built. You can also refer to the `target_cpu` and `target_os` variables. This is useful if you need to do something different on the host depending on which target\_arch is requested; the values are constant across all toolchains. You can do similar things for the `host_cpu` and `host_os` variables, but should generally never need to. For the default toolchain, `target_cpu` and `current_cpu` are the same. For a secondary toolchain, `current_cpu` is set based on the toolchain definition and `target_cpu` remains the same. When writing rules, **`current_cpu` should be used rather than `target_cpu` most of the time**. By default, dependencies listed in the `deps` variable of a rule use the same (currently active) toolchain. You may specify a different toolchain using the `foo(bar)` label notation as described in [the label section of the reference doc](reference.md#Toolchains). Here's an example of when to use `target_cpu` vs `current_cpu`: ``` declare_args() { # Applies only to toolchains targeting target_cpu. sysroot = "" } config("my_config") { # Uses current_cpu because compile flags are toolchain-dependent. if (current_cpu == "arm") { defines = [ "CPU_IS_32_BIT" ] } else { defines = [ "CPU_IS_64_BIT" ] } # Compares current_cpu with target_cpu to see whether current_toolchain # has the same architecture as target_toolchain. if (sysroot != "" && current_cpu == target_cpu) { cflags = [ "-isysroot", sysroot, ] } } ``` ## As a //build/config or //build/toolchain author The `default_toolchain` is declared in the `BUILDCONFIG.gn` file (in Google projects this normally is in the `//build/config` directory). Usually the `default_toolchain` should be the toolchain for the `target_os` and `target_cpu`. The `current_toolchain` reflects the toolchain that is currently in effect for a rule. Be sure you understand the differences between `host_cpu`, `target_cpu`, `current_cpu`, and `toolchain_cpu` (and the os equivalents). The first two are set as described above. You are responsible for making sure that `current_cpu` is set appropriately in your toolchain definitions; if you are using the stock templates like `gcc_toolchain` and `msvc_toolchain`, that means you are responsible for making sure that `toolchain_cpu` and `toolchain_os` are set as appropriate in the template invocations. generate-ninja-0.0~git20241119.24e92ac/docs/faq.md000066400000000000000000000263361471714767000211070ustar00rootroot00000000000000# GN Frequently Asked Questions [TOC] ## Where is the GN documentation? GN has extensive built-in help, so you can run `gn help`, but you can also see all of the help on [the reference page](reference.md). See also the [quick start](quick_start.md) guide and the [language and operation details](language.md). ## Can I generate XCode or Visual Studio projects? You can generate skeleton (or wrapper) projects for Xcode, Visual Studio, QTCreator, and Eclipse that will list the files and targets in the build, but use Ninja to do the actual build. You cannot generate "real" projects that look and compile like native ones. Run `gn help gen` for more details. ## How do I do cross-compiles? GN has robust support for doing cross compiles and building things for multiple architectures in a single build. See [GNCrossCompiles](cross_compiles.md) for more info. ## Can I control what targets are built by default? Yes! If you create a group target called "default" in the top-level (root) build file, i.e., "//:default", GN will tell Ninja to build that by default, rather than building everything. ## Are there any public presentations on GN? [There's at least one](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing), from 2015. There haven't been big changes since then apart from moving it to a standalone repo, so it should still be relevant. ## What is the order of flags and values given to the compiler? The final values of compiler flags, linker flags, defines, and include directories are collected from various sources by GN. The ordering is defined as: 1. Those set directly on the current target (not in a config). 2. Those set on the `configs` on the target in order that the configs appear in the list. 3. Those set on the `all_dependent_configs` on the target in order that the configs appear in the list. 4. Those set on the `public_configs` on the target in order that those configs appear in the list. 5. `all_dependent_configs` pulled from dependencies, in the order of the `deps` list. This is done recursively. If a config appears more than once, only the first occurrence will be used. 6. `public_configs` pulled from dependencies, in the order of the `deps` list. If a dependency is public, they will be applied recursively. If you need a specific relative ordering of values you may need to put those flags in a config and prepend or append that config in a way that produces the desired result. ## How can a target affect those that depend on it? The main way that information flows up the dependency graph is via `public_configs`. This allows a target to add preprocessor defines, compiler flags, and linker flags to targets that depend on it. A typical example is a library that requires `include_dirs` and `defines` to be set in a certain way for its headers to work. It would put its values in a config: ``` config("icu_config") { include_dirs = [ "//third_party/icu" ] defines = [ "U_USING_ICU_NAMESPACE=0" ] } ``` The library would then reference that as a `public_config` which will apply it to any target that directly depends on the `icu` target: ``` shared_library("icu") { sources = [ ... ] deps = [ ... ] public_configs = [ ":icu_config" ] # Label of config defined above. } ``` A `public_config` applies only to direct dependencies of the target. If a target wants to "republish" the `public_configs` from its dependencies, it would list those dependencies in its `public_deps`. In this example, a "browser" library might use ICU headers in its own headers, so anything that depends on it also needs to get the ICU configuration: ``` shared_library("browser") { ... # Anything that depends on this "browser" library will also get ICU's settings. public_deps = [ "//third_party/icu" ] } ``` Another way apply settings up the dependency graph is with `all_dependent_configs` which works like `public_configs` except that it is applied to all dependent targets regardless of `deps`/`public_deps`. Use of this feature is discouraged because it is easy to accumulate lots of unnecessary settings in a large project. Ideally all targets can define which information their dependencies need and can control this explicitly with `public_deps`. The last way that information can be collected across the dependency graph is with the metadata feature. This allows data (see `gn help metadata`) to be collected from targets to be written to disk (see `gn help generated_file`) for the build to use. Computed metadata values are written after all BUILD.gn files are processed and are not available to the GN script. Sometimes people want to write conditional GN code based on values of a dependency. This is not possible: GN has no defined order for loading BUILD.gn files (this allows pararellism) so GN may not have even loaded the file containing a dependency when you might want information about it. The only way information flows around the dependency graph is if GN itself is propagating that data after the targets are defined. ## How can a target affect its dependencies? Sometimes you might have a dependency graph **A 🠲 Z** or a longer chain **A 🠲 B 🠲 C 🠲 Z** and want to control some aspect of **Z** when used from **A**. This is not possible in GN: information only flows up the dependency chain. Every label in GN is compiled once per _toolchain_. This means that every target that depends on **B** gets the same version of **B**. If you need different variants of **B** there are only two options: 1. Explicitly define two similar but differently named targets encoding the variations you need. This can be done without specifying everything twice using a template or by writing things like the sources to a variable and using that variable in each version of the target. 2. Use different toolchains. This is commonly used to encode "host" versus "target" differences or to compile parts of a project with something like ASAN. It is possible to use toolchains to encode any variation you might desire but this can be difficult to manage and might be impossible or discoraged depending on how your project is set up (Chrome and Fuchsia use toolchains for specific purposes only). ## How can I recursively copy a directory as a build step? Sometimes people want to write a build action that expresses copying all files (possibly recursively, possily not) from a source directory without specifying all files in that directory in a BUILD file. This is not possible to express: correct builds must list all inputs. Most approaches people try to work around this break in some way for incremental builds, either the build step is run every time (the build is always "dirty"), file modifications will be missed, or file additions will be missed. One thing people try is to write an action that declares an input directory and an output directory and have it copy all files from the source to the destination. But incremental builds are likely going to be incorrect if you do this. Ninja determines if an output is in need of rebuilding by comparing the last modified date of the source to the last modified date of the destination. Since almost no filesystems propagate the last modified date of files to their directory, modifications to files in the source will not trigger an incremental rebuild. Beware when testing this: most filesystems update the last modified date of the parent directory (but not recursive parents) when adding to or removing a file from that directory so this will appear to work in many cases. But no modern production filesystems propagate modification times of the contents of the files to any directories because it would be very slow. The result will be that modifications to the source files will not be reflected in the output when doing incremental builds. Another thing people try is to write all of the source files to a "depfile" (see `gn help depfile`) and to write a single stamp file that tracks the modified date of the output. This approach also may appear to work but is subtly wrong: the additions of new files to the source directory will not trigger the build step and that addition will not be reflected in an incremental build. ## How can I reference all files in a directory (glob)? Sometimes people want to automatically refer to all files in a directory, typically something like `"*.cc"` for the sources. This is called a "glob." Globs are not supported in GN. In order for Ninja to know when to re-run GN, it would need to check the directory modification times of any directories being globbed. Directory modification times that reflect additions and removals of files are not as reliably implemented across platforms and filesystems as file modification times (for example, it is not supported on Windows FAT32 drives). Even if directory modification times work properly on your build systems, GN's philosophy prefers a very explicit build specification style that is contrary to globs. ## Why does "gn check" complain about conditionally included headers? The "gn check" feature (see `gn help check`) validates that the source code's use of header files follows the requirements set up in the build. It can be a very useful tool for ensuring build correctness. GN scans the source code for `#include` directives and checks that the included files are allowed given the specification of the build. But it is relatively simplistic and does not understand the preprocessor. This means that some headers that are correctly included for a different build variant might be flagged by GN. To disable checking of an include, append a "nogncheck" annotation to the include line: ``` #if defined(OS_ANDROID) #include "src/android/foo/bar.h" // nogncheck #endif ``` Correctly handling these cases requires a full preprocessor implementation because many preprocessor conditions depend on values set by other headers. Implementing this would require new code and complexity to define the toolchain and run the preprocessor, and also means that a full build be done before doing the check (since some headers will be generated at build-time). So far, the complexity and disadvantages have outweighed the advantages of a perfectly correct "gn check" implementation. ## Why does "gn check" miss my header? The "gn check" feature (see previous question) only checks for headers that have been declared in the current toolchain. So if your header never appears in a `sources` or `public` list, any file will be able to include it without "gn check" failing. As a result, targets should always list all headers they contain even though listing them does not affect the build. Sometimes a feature request is made to flag unknown headers so that people will know they should be added to the build. But the silent omission of headers outside of the current toolchain is an important feature that limits the necessity of "nogncheck" annotations (see previous question). In a large project like Chrome, many platform-specific headers will only be defined in that platform's build (for example, Android-specific headers would only be listed in the build when compiling for Android). Because the checking doesn't understand the preprocessor, checking unknown files would flag uses of these headers even if they were properly guarded by platform conditionals. By ignoring headers outside of the current toolchain, the "nogncheck" annotations can be omitted for most platform-specific files. generate-ninja-0.0~git20241119.24e92ac/docs/language.md000066400000000000000000000446351471714767000221250ustar00rootroot00000000000000# GN Language and Operation [TOC] ## Introduction This page describes many of the language details and behaviors. ### Use the built-in help! GN has an extensive built-in help system which provides a reference for every function and built-in variable. This page is more high-level. ``` gn help ``` You can also see the [slides](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing) from a March, 2016 introduction to GN. The speaker notes contain the full content. ### Design philosophy * Writing build files should not be a creative endeavour. Ideally two people should produce the same buildfile given the same requirements. There should be no flexibility unless it's absolutely needed. As many things should be fatal errors as possible. * The definition should read more like code than rules. I don't want to write or debug Prolog. But everybody on our team can write and debug C++ and Python. * The build language should be opinionated as to how the build should work. It should not necessarily be easy or even possible to express arbitrary things. We should be changing source and tooling to make the build simpler rather than making everything more complicated to conform to external requirements (within reason). * Be like Blaze when it makes sense (see "Differences and similarities to Blaze" below). ## Language GN uses an extremely simple, dynamically typed language. The types are: * Boolean (`true`, `false`). * 64-bit signed integers. * Strings. * Lists (of any other types). * Scopes (sort of like a dictionary, only for built-in stuff). There are some built-in variables whose values depend on the current environment. See `gn help` for more. There are purposefully many omissions in the language. There are no user-defined function calls, for example (templates are the closest thing). As per the above design philosophy, if you need this kind of thing you're probably doing it wrong. The full grammar for language nerds is available in `gn help grammar`. ### Strings Strings are enclosed in double-quotes and use backslash as the escape character. The only escape sequences supported are: * `\"` (for literal quote) * `\$` (for literal dollars sign) * `\\` (for literal backslash) Any other use of a backslash is treated as a literal backslash. So, for example, `\b` used in patterns does not need to be escaped, nor do most Windows paths like `"C:\foo\bar.h"`. Simple variable substitution is supported via `$`, where the word following the dollars sign is replaced with the value of the variable. You can optionally surround the name with `{}` if there is not a non-variable-name character to terminate the variable name. More complex expressions are not supported, only variable name substitution. ``` a = "mypath" b = "$a/foo.cc" # b -> "mypath/foo.cc" c = "foo${a}bar.cc" # c -> "foomypathbar.cc" ``` You can encode 8-bit characters using "$0xFF" syntax, so a string with newlines (hex 0A) would `"look$0x0Alike$0x0Athis"`. ### Lists Aside from telling empty lists from non empty lists (`a == []`), there is no way to get the length of a list. If you find yourself wanting to do this kind of thing, you're trying to do too much work in the build. Lists support appending: ``` a = [ "first" ] a += [ "second" ] # [ "first", "second" ] a += [ "third", "fourth" ] # [ "first", "second", "third", "fourth" ] b = a + [ "fifth" ] # [ "first", "second", "third", "fourth", "fifth" ] ``` Appending a list to another list appends the items in the second list rather than appending the list as a nested member. You can remove items from a list: ``` a = [ "first", "second", "third", "first" ] b = a - [ "first" ] # [ "second", "third" ] a -= [ "second" ] # [ "first", "third", "first" ] ``` The - operator on a list searches for matches and removes all matching items. Subtracting a list from another list will remove each item in the second list. If no matching items are found, an error will be thrown, so you need to know in advance that the item is there before removing it. Given that there is no way to test for inclusion, the main use-case is to set up a master list of files or flags, and to remove ones that don't apply to the current build based on various conditions. Stylistically, prefer to only add to lists and have each source file or dependency appear once. This is the opposite of the advice Chrome-team used to give for GYP (GYP would prefer to list all files, and then remove the ones you didn't want in conditionals). Lists support zero-based subscripting to extract values: ``` a = [ "first", "second", "third" ] b = a[1] # -> "second" ``` The \[\] operator is read-only and can not be used to mutate the list. The primary use-case of this is when an external script returns several known values and you want to extract them. There are some cases where it's easy to overwrite a list when you mean to append to it instead. To help catch this case, it is an error to assign a nonempty list to a variable containing an existing nonempty list. If you want to get around this restriction, first assign the destination variable to the empty list. ``` a = [ "one" ] a = [ "two" ] # Error: overwriting nonempty list with a nonempty list. a = [] # OK a = [ "two" ] # OK ``` Note that execution of the build script is done without intrinsic knowledge of the meaning of the underlying data. This means that it doesn't know that `sources` is a list of file names, for example. So if you remove an item, it must match the literal string rather than specifying a different name that will resolve to the same file name. ### Conditionals Conditionals look like C: ``` if (is_linux || (is_win && target_cpu == "x86")) { sources -= [ "something.cc" ] } else if (...) { ... } else { ... } ``` You can use them in most places, even around entire targets if the target should only be declared in certain circumstances. ### Looping You can iterate over a list with `foreach`. This is discouraged. Most things the build should do can normally be expressed without doing this, and if you find it necessary it may be an indication you're doing too much work in the metabuild. ``` foreach(i, mylist) { print(i) # Note: i is a copy of each element, not a reference to it. } ``` ### Function calls Simple function calls look like most other languages: ``` print("hello, world") assert(is_win, "This should only be executed on Windows") ``` Such functions are built-in and the user can not define new ones. Some functions take a block of code enclosed by `{ }` following them: ``` static_library("mylibrary") { sources = [ "a.cc" ] } ``` Most of these define targets. The user can define new functions like this with the template mechanism discussed below. Precisely, this expression means that the block becomes an argument to the function for the function to execute. Most of the block-style functions execute the block and treat the resulting scope as a dictionary of variables to read. ### Scoping and execution Files and function calls followed by `{ }` blocks introduce new scopes. Scopes are nested. When you read a variable, the containing scopes will be searched in reverse order until a matching name is found. Variable writes always go to the innermost scope. There is no way to modify any enclosing scope other than the innermost one. This means that when you define a target, for example, nothing you do inside of the block will "leak out" into the rest of the file. `if`/`else`/`foreach` statements, even though they use `{ }`, do not introduce a new scope so changes will persist outside of the statement. ## Naming things ### File and directory names File and directory names are strings and are interpreted as relative to the current build file's directory. There are three possible forms: Relative names: ``` "foo.cc" "src/foo.cc" "../src/foo.cc" ``` Source-tree absolute names: ``` "//net/foo.cc" "//base/test/foo.cc" ``` System absolute names (rare, normally used for include directories): ``` "/usr/local/include/" "/C:/Program Files/Windows Kits/Include" ``` ## Build configuration ## Targets A target is a node in the build graph. It usually represents some kind of executable or library file that will be generated. Targets depend on other targets. The built-in target types (see `gn help ` for more help) are: * `action`: Run a script to generate a file. * `action_foreach`: Run a script once for each source file. * `bundle_data`: Declare data to go into a Mac/iOS bundle. * `create_bundle`: Creates a Mac/iOS bundle. * `executable`: Generates an executable file. * `group`: A virtual dependency node that refers to one or more other targets. * `shared_library`: A .dll or .so. * `loadable_module`: A .dll or .so loadable only at runtime. * `source_set`: A lightweight virtual static library (usually preferrable over a real static library since it will build faster). * `static_library`: A .lib or .a file (normally you'll want a `source_set` instead). You can extend this to make custom target types using templates (see below). In Chrome some of the more commonly-used templates are: * `component`: Either a source set or shared library, depending on the build type. * `test`: A test executable. On mobile this will create the appropriate native app type for tests. * `app`: Executable or Mac/iOS application. * `android_apk`: Make an APK. There are a _lot_ of other Android ones, see `//build/config/android/rules.gni`. ## Configs Configs are named objects that specify sets of flags, include directories, and defines. They can be applied to a target and pushed to dependent targets. To define a config: ``` config("myconfig") { includes = [ "src/include" ] defines = [ "ENABLE_DOOM_MELON" ] } ``` To apply a config to a target: ``` executable("doom_melon") { configs = [ ":myconfig" ] } ``` It is common for the build config file to specify target defaults that set a default list of configs. Targets can add or remove to this list as needed. So in practice you would usually use `configs += ":myconfig"` to append to the list of defaults. See `gn help config` for more information about how configs are declared and applied. ### Public configs A target can apply settings to other targets that depend on it. The most common example is a third party target that requires some defines or include directories for its headers to compile properly. You want these settings to apply both to the compile of the third party library itself, as well as all targets that use the library. To do this, you write a config with the settings you want to apply: ``` config("my_external_library_config") { includes = "." defines = [ "DISABLE_JANK" ] } ``` Then this config is added to the target as a "public" config. It will apply both to the target as well as targets that directly depend on it. ``` shared_library("my_external_library") { ... # Targets that depend on this get this config applied. public_configs = [ ":my_external_library_config" ] } ``` Dependent targets can in turn forward this up the dependency tree another level by adding your target as a "public" dependency. ``` static_library("intermediate_library") { ... # Targets that depend on this one also get the configs from "my external library". public_deps = [ ":my_external_library" ] } ``` A target can forward a config to all dependents until a link boundary is reached by setting it as an `all_dependent_config`. This is strongly discouraged as it can spray flags and defines over more of the build than necessary. Instead, use public_deps to control which flags apply where. In Chrome, prefer the build flag header system (`build/buildflag_header.gni`) for defines which prevents most screw-ups with compiler defines. ## Templates Templates are GN's primary way to re-use code. Typically, a template would expand to one or more other target types. ``` # Declares a script that compiles IDL files to source, and then compiles those # source files. template("idl") { # Always base helper targets on target_name so they're unique. Target name # will be the string passed as the name when the template is invoked. idl_target_name = "${target_name}_generate" action_foreach(idl_target_name) { ... } # Your template should always define a target with the name target_name. # When other targets depend on your template invocation, this will be the # destination of that dependency. source_set(target_name) { ... deps = [ ":$idl_target_name" ] # Require the sources to be compiled. } } ``` Typically your template definition would go in a `.gni` file and users would import that file to see the template definition: ``` import("//tools/idl_compiler.gni") idl("my_interfaces") { sources = [ "a.idl", "b.idl" ] } ``` Declaring a template creates a closure around the variables in scope at that time. When the template is invoked, the magic variable `invoker` is used to read variables out of the invoking scope. The template would generally copy the values its interested in into its own scope: ``` template("idl") { source_set(target_name) { sources = invoker.sources } } ``` The current directory when a template executes will be that of the invoking build file rather than the template source file. This is so files passed in from the template invoker will be correct (this generally accounts for most file handling in a template). However, if the template has files itself (perhaps it generates an action that runs a script), you will want to use absolute paths ("//foo/...") to refer to these files to account for the fact that the current directory will be unpredictable during invocation. See `gn help template` for more information and more complete examples. ## Other features ### Imports You can import `.gni` files into the current scope with the `import` function. This is _not_ an include in the C++ sense. The imported file is executed independently and the resulting scope is copied into the current file (C++ executes the included file in the current context of when the include directive appeared). This allows the results of the import to be cached, and also prevents some of the more "creative" uses of includes like multiply-included files. Typically, a `.gni` would define build arguments and templates. See `gn help import` for more. Your `.gni` file can define temporary variables that are not exported files that include it by using a preceding underscore in the name like `_this`. ### Path processing Often you will want to make a file name or a list of file names relative to a different directory. This is especially common when running scripts, which are executed with the build output directory as the current directory, while build files usually refer to files relative to their containing directory. You can use `rebase_path` to convert directories. See `gn help rebase_path` for more help and examples. Typical usage to convert a file name relative to the current directory to be relative to the root build directory would be: ``` new_paths = rebase_path("myfile.c", root_build_dir) ``` ### Patterns Patterns are used to generate the output file names for a given set of inputs for custom target types, and to automatically remove files from the list values (see `gn help filter_include` and `gn help filter_exclude`). They are like simple regular expressions. See `gn help label_pattern` for more. ### Executing scripts There are two ways to execute scripts. All external scripts in GN are in Python. The first way is as a build step. Such a script would take some input and generate some output as part of the build. Targets that invoke scripts are declared with the "action" target type (see `gn help action`). The second way to execute scripts is synchronously during build file execution. This is necessary in some cases to determine the set of files to compile, or to get certain system configurations that the build file might depend on. The build file can read the stdout of the script and act on it in different ways. Synchronous script execution is done by the `exec_script` function (see `gn help exec_script` for details and examples). Because synchronously executing a script requires that the current buildfile execution be suspended until a Python process completes execution, relying on external scripts is slow and should be minimized. To prevent abuse, files permitted to call `exec_script` can be whitelisted in the toplevel `.gn` file. Chrome does this to require additional code review for such additions. See `gn help dotfile`. You can synchronously read and write files which is discouraged but occasionally necessary when synchronously running scripts. The typical use-case would be to pass a list of file names longer than the command-line limits of the current platform. See `gn help read_file` and `gn help write_file` for how to read and write files. These functions should be avoided if at all possible. Actions that exceed command-line length limits can use response files to get around this limitation without synchronously writing files. See `gn help response_file_contents`. # Differences and similarities to Blaze Blaze is Google's internal build system, now publicly released as [Bazel](http://bazel.io/). It has inspired a number of other systems such as [Pants](http://www.pantsbuild.org/) and [Buck](http://facebook.github.io/buck/). In Google's homogeneous environment, the need for conditionals is very low and they can get by with a few hacks (`abi_deps`). Chrome uses conditionals all over the place and the need to add these is the main reason for the files looking different. GN also adds the concept of "configs" to manage some of the trickier dependency and configuration problems which likewise don't arise on the server. Blaze has a concept of a "configuration" which is like a GN toolchain, but built into the tool itself. The way that toolchains work in GN is a result of trying to separate this concept out into the build files in a clean way. GN keeps some GYP concept like "all dependent" settings which work a bit differently in Blaze. This is partially to make conversion from the existing GYP code easier, and the GYP constructs generally offer more fine-grained control (which is either good or bad, depending on the situation). GN also uses GYP names like "sources" instead of "srcs" since abbreviating this seems needlessly obscure, although it uses Blaze's "deps" since "dependencies" is so hard to type. Chromium also compiles multiple languages in one target so specifying the language type on the target name prefix was dropped (e.g. from `cc_library`). generate-ninja-0.0~git20241119.24e92ac/docs/mingw.md000066400000000000000000000027121471714767000214510ustar00rootroot00000000000000# Building and using `gn` with MinGW on Windows At the time of writing: 2024-04-13 Test environment: Windows 11, intel x86_64 CPU ## Requirements 1. Install [MSYS2](https://www.msys2.org/) 1. Start a Terminal windows for MSYS2's MinGW development by opening one of `clang32.exe`, `clang64.exe`, `clangarm64.exe`,`mingw32.exe`, `mingw64.exe`, `ucrt64.exe`. 1. To download clang toolchain, Ninja and git programs, run command: `pacman -S mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-ninja git` ## Build `gn` 1. To clone `gn` source code, run command: `git clone https://gn.googlesource.com/gn` 1. Run command: `cd gn` 1. Run command: `build/gen.py --platform mingw` This configuration generates a static executable that does not depend on MSYS2, and can be run in any development environment. Use `--help` flag to check more configuration options. Use `--allow-warning` flag to build with warnings. 1. Run command: `ninja -C out` ## Testing 1. Run command: `out/gn --version` 1. Run command: `out/gn_unittests` > Notes: > > For "mingw-w64-clang-x86_64-toolchain" in the clang64 environment, g++ is a copy of clang++. > > The toolchain that builds `gn` does not use vendor lock-in compiler command flags, > so `gn` can be built with these clang++, g++. > > However the build rules in [examples/simple_build](../examples/simple_build/) require GCC-specific compiler macros, and thus only work in the `ucrt64` MSYS2 development environment. generate-ninja-0.0~git20241119.24e92ac/docs/quick_start.md000066400000000000000000000206161471714767000226640ustar00rootroot00000000000000# GN Quick Start guide [TOC] ## Running GN You just run `gn` from the command line. For large projects, GN is versioned and distributed with the source checkout. * For Chromium and Chromium-based projects, there is a script in `depot_tools`, which is presumably in your PATH, with this name. The script will find the binary in the source tree containing the current directory and run it. * For Fuchsia in-tree development, run `fx gn ...` which will find the right GN binary and run it with the given arguments. * For other projects, see your project's documentation. ## Setting up a build Unlike some other build systems, with GN you set up your own build directories with the settings you want. This lets you maintain as many different builds in parallel as you need. Once you set up a build directory, the Ninja files will be automatically regenerated if they're out of date when you build in that directory so you should not have to re-run GN. To make a build directory: ``` gn gen out/my_build ``` ## Passing build arguments Set build arguments on your build directory by running: ``` gn args out/my_build ``` This will bring up an editor. Type build args into that file like this: ``` is_component_build = true is_debug = false ``` The available variables will depend on your build (this example is from Chromium). You can see the list of available arguments and their default values by typing ``` gn args --list out/my_build ``` on the command line. Note that you have to specify the build directory for this command because the available arguments can change according to the build. Chrome developers can also read the [Chrome-specific build configuration](http://www.chromium.org/developers/gn-build-configuration) instructions for more information. ## Cross-compiling to a target OS or architecture Run `gn args out/Default` (substituting your build directory as needed) and add one or more of the following lines for common cross-compiling options. ``` target_os = "chromeos" target_os = "android" target_cpu = "arm" target_cpu = "x86" target_cpu = "x64" ``` See [GN cross compiles](cross_compiles.md) for more info. ## Step-by-step ### Adding a build file Go to the directory `examples/simple_build`. This is the root of a minimal GN repository. In that directory there is a `tutorial` directory. There is already a `tutorial.cc` file that's not hooked up to the build. Create a new `BUILD.gn` file in that directory for our new target. ``` executable("tutorial") { sources = [ "tutorial.cc", ] } ``` Now we just need to tell the build about this new target. Open the `BUILD.gn` file in the parent (`simple_build`) directory. GN starts by loading this root file, and then loads all dependencies ourward from here, so we just need to add a reference to our new target from this file. You could add our new target as a dependency from one of the existing targets in the `simple_build/BUILD.gn` file, but it usually doesn't make a lot of sense to have an executable as a depdency of another executable (they can't be linked). So let's make a "tools" group. In GN, a "group" is just a collection of dependencies that's not complied or linked: ``` group("tools") { deps = [ # This will expand to the name "//tutorial:tutorial" which is the full name # of our new target. Run "gn help labels" for more. "//tutorial", ] } ``` ### Testing your addition From the command line in the `simple_build` directory: ``` gn gen out ninja -C out tutorial out/tutorial ``` You should see "Hello, world." output to the console. Side note: GN encourages target names for static libraries that aren't globally unique. To build one of these, you can pass the label with its path (but no leading "//") to ninja: ``` ninja -C out some/path/to/target:my_target ``` ### Declaring dependencies Let's look at the targets defined in [examples/simple_build/BUILD.gn](../examples/simple_build/BUILD.gn). There is a static library that defines one function, `GetStaticText()`: ``` static_library("hello_static") { sources = [ "hello_static.cc", "hello_static.h", ] } ``` There is also a shared library that defines one function `GetSharedText()`: ``` shared_library("hello_shared") { sources = [ "hello_shared.cc", "hello_shared.h", ] defines = [ "HELLO_SHARED_IMPLEMENTATION" ] } ``` This also illustrates how to set preprocessor defines for a target. To set more than one or to assign values, use this form: ``` defines = [ "HELLO_SHARED_IMPLEMENTATION", "ENABLE_DOOM_MELON=0", ] ``` Now let's look at the executable that depends on these two libraries: ``` executable("hello") { sources = [ "hello.cc", ] deps = [ ":hello_shared", ":hello_static", ] } ``` This executable includes one source file and depends on the previous two libraries. Labels starting with a colon refer to a target with that name in the current BUILD.gn file. ### Test the binary From the command line in the `simple_build` directory: ``` ninja -C out hello out/hello ``` Note that you **didn't** need to re-run GN. GN will automatically rebuild the ninja files when any build file has changed. You know this happens when ninja prints `[1/1] Regenerating ninja files` at the beginning of execution. ### Putting settings in a config Users of a library often need compiler flags, defines, and include directories applied to them. To do this, put all such settings into a "config" which is a named collection of settings (but not sources or dependencies): ``` config("my_lib_config") { defines = [ "ENABLE_DOOM_MELON" ] include_dirs = [ "//third_party/something" ] } ``` To apply a config's settings to a target, add it to the `configs` list: ``` static_library("hello_shared") { ... # Note "+=" here is usually required, see "default configs" below. configs += [ ":my_lib_config", ] } ``` A config can be applied to all targets that depend on the current one by putting its label in the `public_configs` list: ``` static_library("hello_shared") { ... public_configs = [ ":my_lib_config", ] } ``` The `public_configs` also applies to the current target, so there's no need to list a config in both places. ### Default configs The build configuration will set up some settings that apply to every target by default. These will normally be set as a default list of configs. You can see this using the "print" command which is useful for debugging: ``` executable("hello") { print(configs) } ``` Running GN will print something like: ``` $ gn gen out ["//build:compiler_defaults", "//build:executable_ldconfig"] Done. Made 5 targets from 5 files in 9ms ``` Targets can modify this list to change their defaults. For example, the build setup might turn off exceptions by default by adding a `no_exceptions` config, but a target might re-enable them by replacing it with a different one: ``` executable("hello") { ... configs -= [ "//build:no_exceptions" ] # Remove global default. configs += [ "//build:exceptions" ] # Replace with a different one. } ``` Our print command from above could also be expressed using string interpolation. This is a way to convert values to strings. It uses the symbol "$" to refer to a variable: ``` print("The configs for the target $target_name are $configs") ``` ## Add a new build argument You declare which arguments you accept and specify default values via `declare_args`. ``` declare_args() { enable_teleporter = true enable_doom_melon = false } ``` See `gn help buildargs` for an overview of how this works. See `gn help declare_args` for specifics on declaring them. It is an error to declare a given argument more than once in a given scope, so care should be used in scoping and naming arguments. ## Don't know what's going on? You can run GN in verbose mode to see lots of messages about what it's doing. Use `-v` for this. ### The "desc" command You can run `gn desc ` to get information about a given target: ``` gn desc out/Default //foo/bar:say_hello ``` will print out lots of exciting information. You can also print just one section. Lets say you wanted to know where your `TWO_PEOPLE` define came from on the `say_hello` target: ``` > gn desc out/Default //foo/bar:say_hello defines --blame ...lots of other stuff omitted... From //foo/bar:hello_config (Added by //foo/bar/BUILD.gn:12) TWO_PEOPLE ``` Another particularly interesting variation: ``` gn desc out/Default //base:base_i18n deps --tree ``` See `gn help desc` for more. generate-ninja-0.0~git20241119.24e92ac/docs/reference.md000066400000000000000000011661421471714767000222770ustar00rootroot00000000000000# GN Reference *This page is automatically generated from* `gn help --markdown all`. ## Contents * [Commands](#commands) * [analyze: Analyze which targets are affected by a list of files.](#cmd_analyze) * [args: Display or configure arguments declared by the build.](#cmd_args) * [check: Check header dependencies.](#cmd_check) * [clean: Cleans the output directory.](#cmd_clean) * [clean_stale: Cleans the stale output files from the output directory.](#cmd_clean_stale) * [desc: Show lots of insightful information about a target or config.](#cmd_desc) * [format: Format .gn files.](#cmd_format) * [gen: Generate ninja files.](#cmd_gen) * [help: Does what you think.](#cmd_help) * [ls: List matching targets.](#cmd_ls) * [meta: List target metadata collection results.](#cmd_meta) * [outputs: Which files a source/target make.](#cmd_outputs) * [path: Find paths between two targets.](#cmd_path) * [refs: Find stuff referencing a target or file.](#cmd_refs) * [Target declarations](#targets) * [action: Declare a target that runs a script a single time.](#func_action) * [action_foreach: Declare a target that runs a script over a set of files.](#func_action_foreach) * [bundle_data: [iOS/macOS] Declare a target without output.](#func_bundle_data) * [copy: Declare a target that copies files.](#func_copy) * [create_bundle: [iOS/macOS] Build an iOS or macOS bundle.](#func_create_bundle) * [executable: Declare an executable target.](#func_executable) * [generated_file: Declare a generated_file target.](#func_generated_file) * [group: Declare a named group of targets.](#func_group) * [loadable_module: Declare a loadable module target.](#func_loadable_module) * [rust_library: Declare a Rust library target.](#func_rust_library) * [rust_proc_macro: Declare a Rust procedural macro target.](#func_rust_proc_macro) * [shared_library: Declare a shared library target.](#func_shared_library) * [source_set: Declare a source set target.](#func_source_set) * [static_library: Declare a static library target.](#func_static_library) * [target: Declare a target with the given programmatic type.](#func_target) * [Buildfile functions](#functions) * [assert: Assert an expression is true at generation time.](#func_assert) * [config: Defines a configuration object.](#func_config) * [declare_args: Declare build arguments.](#func_declare_args) * [defined: Returns whether an identifier is defined.](#func_defined) * [exec_script: Synchronously run a script and return the output.](#func_exec_script) * [filter_exclude: Remove values that match a set of patterns.](#func_filter_exclude) * [filter_include: Remove values that do not match a set of patterns.](#func_filter_include) * [filter_labels_exclude: Remove labels that match a set of patterns.](#func_filter_labels_exclude) * [filter_labels_include: Remove labels that do not match a set of patterns.](#func_filter_labels_include) * [foreach: Iterate over a list.](#func_foreach) * [forward_variables_from: Copies variables from a different scope.](#func_forward_variables_from) * [get_label_info: Get an attribute from a target's label.](#func_get_label_info) * [get_path_info: Extract parts of a file or directory name.](#func_get_path_info) * [get_target_outputs: [file list] Get the list of outputs from a target.](#func_get_target_outputs) * [getenv: Get an environment variable.](#func_getenv) * [import: Import a file into the current scope.](#func_import) * [label_matches: Returns whether a label matches any of a list of patterns.](#func_label_matches) * [not_needed: Mark variables from scope as not needed.](#func_not_needed) * [pool: Defines a pool object.](#func_pool) * [print: Prints to the console.](#func_print) * [print_stack_trace: Prints a stack trace.](#func_print_stack_trace) * [process_file_template: Do template expansion over a list of files.](#func_process_file_template) * [read_file: Read a file into a variable.](#func_read_file) * [rebase_path: Rebase a file or directory to another location.](#func_rebase_path) * [set_default_toolchain: Sets the default toolchain name.](#func_set_default_toolchain) * [set_defaults: Set default values for a target type.](#func_set_defaults) * [split_list: Splits a list into N different sub-lists.](#func_split_list) * [string_join: Concatenates a list of strings with a separator.](#func_string_join) * [string_replace: Replaces substring in the given string.](#func_string_replace) * [string_split: Split string into a list of strings.](#func_string_split) * [template: Define a template rule.](#func_template) * [tool: Specify arguments to a toolchain tool.](#func_tool) * [toolchain: Defines a toolchain.](#func_toolchain) * [write_file: Write a file to disk.](#func_write_file) * [Built-in predefined variables](#predefined_variables) * [current_cpu: [string] The processor architecture of the current toolchain.](#var_current_cpu) * [current_os: [string] The operating system of the current toolchain.](#var_current_os) * [current_toolchain: [string] Label of the current toolchain.](#var_current_toolchain) * [default_toolchain: [string] Label of the default toolchain.](#var_default_toolchain) * [gn_version: [number] The version of gn.](#var_gn_version) * [host_cpu: [string] The processor architecture that GN is running on.](#var_host_cpu) * [host_os: [string] The operating system that GN is running on.](#var_host_os) * [invoker: [string] The invoking scope inside a template.](#var_invoker) * [python_path: [string] Absolute path of Python.](#var_python_path) * [root_build_dir: [string] Directory where build commands are run.](#var_root_build_dir) * [root_gen_dir: [string] Directory for the toolchain's generated files.](#var_root_gen_dir) * [root_out_dir: [string] Root directory for toolchain output files.](#var_root_out_dir) * [target_cpu: [string] The desired cpu architecture for the build.](#var_target_cpu) * [target_gen_dir: [string] Directory for a target's generated files.](#var_target_gen_dir) * [target_name: [string] The name of the current target.](#var_target_name) * [target_os: [string] The desired operating system for the build.](#var_target_os) * [target_out_dir: [string] Directory for target output files.](#var_target_out_dir) * [Variables you set in targets](#target_variables) * [aliased_deps: [scope] Set of crate-dependency pairs.](#var_aliased_deps) * [all_dependent_configs: [label list] Configs to be forced on dependents.](#var_all_dependent_configs) * [allow_circular_includes_from: [label list] Permit includes from deps.](#var_allow_circular_includes_from) * [arflags: [string list] Arguments passed to static_library archiver.](#var_arflags) * [args: [string list] Arguments passed to an action.](#var_args) * [asmflags: [string list] Flags passed to the assembler.](#var_asmflags) * [assert_no_deps: [label pattern list] Ensure no deps on these targets.](#var_assert_no_deps) * [bridge_header: [string] Path to C/Objective-C compatibility header.](#var_bridge_header) * [bundle_contents_dir: Expansion of {{bundle_contents_dir}} in create_bundle.](#var_bundle_contents_dir) * [bundle_deps_filter: [label list] A list of labels that are filtered out.](#var_bundle_deps_filter) * [bundle_executable_dir: Expansion of {{bundle_executable_dir}} in create_bundle](#var_bundle_executable_dir) * [bundle_resources_dir: Expansion of {{bundle_resources_dir}} in create_bundle.](#var_bundle_resources_dir) * [bundle_root_dir: Expansion of {{bundle_root_dir}} in create_bundle.](#var_bundle_root_dir) * [cflags: [string list] Flags passed to all C compiler variants.](#var_cflags) * [cflags_c: [string list] Flags passed to the C compiler.](#var_cflags_c) * [cflags_cc: [string list] Flags passed to the C++ compiler.](#var_cflags_cc) * [cflags_objc: [string list] Flags passed to the Objective C compiler.](#var_cflags_objc) * [cflags_objcc: [string list] Flags passed to the Objective C++ compiler.](#var_cflags_objcc) * [check_includes: [boolean] Controls whether a target's files are checked.](#var_check_includes) * [code_signing_args: [string list] [deprecated] Args for the post-processing script.](#var_code_signing_args) * [code_signing_outputs: [file list] [deprecated] Outputs of the post-processing step.](#var_code_signing_outputs) * [code_signing_script: [file name] [deprecated] Script for the post-processing step.](#var_code_signing_script) * [code_signing_sources: [file list] [deprecated] Sources for the post-processing step.](#var_code_signing_sources) * [complete_static_lib: [boolean] Links all deps into a static library.](#var_complete_static_lib) * [configs: [label list] Configs applying to this target or config.](#var_configs) * [contents: Contents to write to file.](#var_contents) * [crate_name: [string] The name for the compiled crate.](#var_crate_name) * [crate_root: [string] The root source file for a binary or library.](#var_crate_root) * [crate_type: [string] The type of linkage to use on a shared_library.](#var_crate_type) * [data: [file list] Runtime data file dependencies.](#var_data) * [data_deps: [label list] Non-linked dependencies.](#var_data_deps) * [data_keys: [string list] Keys from which to collect metadata.](#var_data_keys) * [defines: [string list] C preprocessor defines.](#var_defines) * [depfile: [string] File name for input dependencies for actions.](#var_depfile) * [deps: [label list] Private linked dependencies.](#var_deps) * [externs: [scope] Set of Rust crate-dependency pairs.](#var_externs) * [framework_dirs: [directory list] Additional framework search directories.](#var_framework_dirs) * [frameworks: [name list] Name of frameworks that must be linked.](#var_frameworks) * [friend: [label pattern list] Allow targets to include private headers.](#var_friend) * [gen_deps: [label list] Declares targets that should generate when this one does.](#var_gen_deps) * [include_dirs: [directory list] Additional include directories.](#var_include_dirs) * [inputs: [file list] Additional compile-time dependencies.](#var_inputs) * [ldflags: [string list] Flags passed to the linker.](#var_ldflags) * [lib_dirs: [directory list] Additional library directories.](#var_lib_dirs) * [libs: [string list] Additional libraries to link.](#var_libs) * [metadata: [scope] Metadata of this target.](#var_metadata) * [mnemonic: [string] Prefix displayed when ninja runs this action.](#var_mnemonic) * [module_name: [string] The name for the compiled module.](#var_module_name) * [output_conversion: Data format for generated_file targets.](#var_output_conversion) * [output_dir: [directory] Directory to put output file in.](#var_output_dir) * [output_extension: [string] Value to use for the output's file extension.](#var_output_extension) * [output_name: [string] Name for the output file other than the default.](#var_output_name) * [output_prefix_override: [boolean] Don't use prefix for output name.](#var_output_prefix_override) * [outputs: [file list] Output files for actions and copy targets.](#var_outputs) * [partial_info_plist: [filename] Path plist from asset catalog compiler.](#var_partial_info_plist) * [pool: [string] Label of the pool used by binary targets and actions.](#var_pool) * [post_processing_args: [string list] Args for the post-processing script.](#var_post_processing_args) * [post_processing_outputs: [file list] Outputs of the post-processing step.](#var_post_processing_outputs) * [post_processing_script: [file name] Script for the post-processing step.](#var_post_processing_script) * [post_processing_sources: [file list] Sources for the post-processing step.](#var_post_processing_sources) * [precompiled_header: [string] Header file to precompile.](#var_precompiled_header) * [precompiled_header_type: [string] "gcc" or "msvc".](#var_precompiled_header_type) * [precompiled_source: [file name] Source file to precompile.](#var_precompiled_source) * [product_type: [string] Product type for the bundle.](#var_product_type) * [public: [file list] Declare public header files for a target.](#var_public) * [public_configs: [label list] Configs applied to dependents.](#var_public_configs) * [public_deps: [label list] Declare public dependencies.](#var_public_deps) * [rebase: [boolean] Rebase collected metadata as files.](#var_rebase) * [response_file_contents: [string list] Contents of .rsp file for actions.](#var_response_file_contents) * [rustflags: [string list] Flags passed to the Rust compiler.](#var_rustflags) * [script: [file name] Script file for actions.](#var_script) * [sources: [file list] Source files for a target.](#var_sources) * [swiftflags: [string list] Flags passed to the swift compiler.](#var_swiftflags) * [testonly: [boolean] Declares a target must only be used for testing.](#var_testonly) * [transparent: [bool] True if the bundle is transparent.](#var_transparent) * [visibility: [label list] A list of labels that can depend on a target.](#var_visibility) * [walk_keys: [string list] Key(s) for managing the metadata collection walk.](#var_walk_keys) * [weak_frameworks: [name list] Name of frameworks that must be weak linked.](#var_weak_frameworks) * [write_runtime_deps: Writes the target's runtime_deps to the given path.](#var_write_runtime_deps) * [xcasset_compiler_flags: [string list] Flags passed to xcassets compiler](#var_xcasset_compiler_flags) * [xcode_extra_attributes: [scope] Extra attributes for Xcode projects.](#var_xcode_extra_attributes) * [xcode_test_application_name: [string] Name for Xcode test target.](#var_xcode_test_application_name) * [Other help topics](#other) * all: Print all the help at once * [buildargs: How build arguments work.](#buildargs) * [dotfile: Info about the toplevel .gn file.](#dotfile) * [execution: Build graph and execution overview.](#execution) * [grammar: Language and grammar for GN build files.](#grammar) * [input_conversion: Processing input from exec_script and read_file.](#io_conversion) * [file_pattern: Matching more than one file.](#file_pattern) * [label_pattern: Matching more than one label.](#label_pattern) * [labels: About labels.](#labels) * [metadata_collection: About metadata and its collection.](#metadata_collection) * [ninja_rules: How Ninja build rules are named.](#ninja_rules) * [nogncheck: Annotating includes for checking.](#nogncheck) * [output_conversion: Specifies how to transform a value to output.](#io_conversion) * [runtime_deps: How runtime dependency computation works.](#runtime_deps) * [source_expansion: Map sources to outputs for scripts.](#source_expansion) * [switches: Show available command-line switches.](#switch_list) ## Commands ### **gn analyze <out_dir> <input_path> <output_path>** [Back to Top](#gn-reference) ``` Analyze which targets are affected by a list of files. This command takes three arguments: out_dir is the path to the build directory. input_path is a path to a file containing a JSON object with three fields: - "files": A list of the filenames to check. - "test_targets": A list of the labels for targets that are needed to run the tests we wish to run. - "additional_compile_targets" (optional): A list of the labels for targets that we wish to rebuild, but aren't necessarily needed for testing. The important difference between this field and "test_targets" is that if an item in the additional_compile_targets list refers to a group, then any dependencies of that group will be returned if they are out of date, but the group itself does not need to be. If the dependencies themselves are groups, the same filtering is repeated. This filtering can be used to avoid rebuilding dependencies of a group that are unaffected by the input files. The list may also contain the string "all" to refer to a pseudo-group that contains every root target in the build graph. This filtering behavior is also known as "pruning" the list of compile targets. If "additional_compile_targets" is absent, it defaults to the empty list. If input_path is -, input is read from stdin. output_path is a path indicating where the results of the command are to be written. The results will be a file containing a JSON object with one or more of following fields: - "compile_targets": A list of the labels derived from the input compile_targets list that are affected by the input files. Due to the way the filtering works for compile targets as described above, this list may contain targets that do not appear in the input list. - "test_targets": A list of the labels from the input test_targets list that are affected by the input files. This list will be a proper subset of the input list. - "invalid_targets": A list of any names from the input that do not exist in the build graph. If this list is non-empty, the "error" field will also be set to "Invalid targets". - "status": A string containing one of three values: - "Found dependency" - "No dependency" - "Found dependency (all)" In the first case, the lists returned in compile_targets and test_targets should be passed to ninja to build. In the second case, nothing was affected and no build is necessary. In the third case, GN could not determine the correct answer and returned the input as the output in order to be safe. - "error": This will only be present if an error occurred, and will contain a string describing the error. This includes cases where the input file is not in the right format, or contains invalid targets. If output_path is -, output is written to stdout. The command returns 1 if it is unable to read the input file or write the output file, or if there is something wrong with the build such that gen would also fail, and 0 otherwise. In particular, it returns 0 even if the "error" key is non-empty and a non-fatal error occurred. In other words, it tries really hard to always write something to the output JSON and convey errors that way rather than via return codes. ``` ### **gn args**: (command-line tool) [Back to Top](#gn-reference) ``` Display or configure arguments declared by the build. gn args [--list] [--short] [--args] [--overrides-only] See also "gn help buildargs" for a more high-level overview of how build arguments work. ``` #### **Usage** ``` gn args Open the arguments for the given build directory in an editor. If the given build directory doesn't exist, it will be created and an empty args file will be opened in the editor. You would type something like this into that file: enable_doom_melon=false os="android" To find your editor on Posix, GN will search the environment variables in order: GN_EDITOR, VISUAL, and EDITOR. On Windows GN will open the command associated with .txt files. Note: you can edit the build args manually by editing the file "args.gn" in the build directory and then running "gn gen ". gn args --list[=] [--short] [--overrides-only] [--json] Lists all build arguments available in the current configuration, or, if an exact_arg is specified for the list flag, just that one build argument. The output will list the declaration location, current value for the build, default value (if different than the current value), and comment preceding the declaration. If --short is specified, only the names and current values will be printed. If --overrides-only is specified, only the names and current values of arguments that have been overridden (i.e. non-default arguments) will be printed. Overrides come from the /args.gn file and //.gn If --json is specified, the output will be emitted in json format. JSON schema for output: [ { "name": variable_name, "current": { "value": overridden_value, "file": file_name, "line": line_no }, "default": { "value": default_value, "file": file_name, "line": line_no }, "comment": comment_string }, ... ] ``` #### **Examples** ``` gn args out/Debug Opens an editor with the args for out/Debug. gn args out/Debug --list --short Prints all arguments with their default values for the out/Debug build. gn args out/Debug --list --short --overrides-only Prints overridden arguments for the out/Debug build. gn args out/Debug --list=target_cpu Prints information about the "target_cpu" argument for the " "out/Debug build. gn args --list --args="os=\"android\" enable_doom_melon=true" Prints all arguments with the default values for a build with the given arguments set (which may affect the values of other arguments). ``` ### **gn check <out_dir> [<label_pattern>] [\--force] [\--check-generated]** [Back to Top](#gn-reference) ``` GN's include header checker validates that the includes for C-like source files match the build dependency graph. "gn check" is the same thing as "gn gen" with the "--check" flag except that this command does not write out any build files. It's intended to be an easy way to manually trigger include file checking. The can take exact labels or patterns that match more than one (although not general regular expressions). If specified, only those matching targets will be checked. See "gn help label_pattern" for details. ``` #### **Command-specific switches** ``` --check-generated Generated files are normally not checked since they do not exist until after a build. With this flag, those generated files that can be found on disk are also checked. --check-system Check system style includes (using ) in addition to "double quote" includes. --default-toolchain Normally wildcard targets are matched in all toolchains. This switch makes wildcard labels with no explicit toolchain reference only match targets in the default toolchain. Non-wildcard inputs with no explicit toolchain specification will always match only a target in the default toolchain if one exists. --force Ignores specifications of "check_includes = false" and checks all target's files that match the target label. ``` #### **What gets checked** ``` The .gn file may specify a list of targets to be checked in the list check_targets (see "gn help dotfile"). Alternatively, the .gn file may specify a list of targets not to be checked in no_check_targets. If a label pattern is specified on the command line, neither check_targets or no_check_targets is used. Targets can opt-out from checking with "check_includes = false" (see "gn help check_includes"). For targets being checked: - GN opens all C-like source files in the targets to be checked and scans the top for includes. - Generated files (that might not exist yet) are ignored unless the --check-generated flag is provided. - Includes with a "nogncheck" annotation are skipped (see "gn help nogncheck"). - Includes using "quotes" are always checked. If system style checking is enabled, includes using are also checked. - Include paths are assumed to be relative to any of the "include_dirs" for the target (including the implicit current dir). - GN does not run the preprocessor so will not understand conditional includes. - Only includes matching known files in the build are checked: includes matching unknown paths are ignored. For an include to be valid: - The included file must be in the current target, or there must be a path following only public dependencies to a target with the file in it ("gn path" is a good way to diagnose problems). - There can be multiple targets with an included file: only one needs to be valid for the include to be allowed. - If there are only "sources" in a target, all are considered to be public and can be included by other targets with a valid public dependency path. - If a target lists files as "public", only those files are able to be included by other targets. Anything in the sources will be considered private and will not be includable regardless of dependency paths. - Outputs from actions are treated like public sources on that target. - A target can include headers from a target that depends on it if the other target is annotated accordingly. See "gn help allow_circular_includes_from". ``` #### **Advice on fixing problems** ``` If you have a third party project that is difficult to fix or doesn't care about include checks it's generally best to exclude that target from checking altogether via "check_includes = false". If you have conditional includes, make sure the build conditions and the preprocessor conditions match, and annotate the line with "nogncheck" (see "gn help nogncheck" for an example). If two targets are hopelessly intertwined, use the "allow_circular_includes_from" annotation. Ideally each should have identical dependencies so configs inherited from those dependencies are consistent (see "gn help allow_circular_includes_from"). If you have a standalone header file or files that need to be shared between a few targets, you can consider making a source_set listing only those headers as public sources. With only header files, the source set will be a no-op from a build perspective, but will give a central place to refer to those headers. That source set's files will still need to pass "gn check" in isolation. In rare cases it makes sense to list a header in more than one target if it could be considered conceptually a member of both. ``` #### **Examples** ``` gn check out/Debug Check everything. gn check out/Default //foo:bar Check only the files in the //foo:bar target. gn check out/Default "//foo/* Check only the files in targets in the //foo directory tree. ``` ### **gn clean <out_dir>...** [Back to Top](#gn-reference) ``` Deletes the contents of the output directory except for args.gn and creates a Ninja build environment sufficient to regenerate the build. ``` ### **gn clean_stale [\--ninja-executable=...] <out_dir>...** [Back to Top](#gn-reference) ``` Removes the no longer needed output files from the build directory and prunes their records from the ninja build log and dependency database. These are output files that were generated from previous builds, but the current build graph no longer references them. This command requires a ninja executable of at least version 1.10.0. The executable must be provided by the --ninja-executable switch. ``` #### **Options** ``` --ninja-executable= Can be used to specify the ninja executable to use. ``` ### **gn desc** [Back to Top](#gn-reference) ``` gn desc