Index: llvm/utils/gn/.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/.gn
@@ -0,0 +1,16 @@
+# FIXME: Once it's possible to add files to the root directory of the
+# monorepo, move this file to there. Until then, you need to pass
+# `--dotfile=llvm/utils/gn/.gn --root=.` to the `gn gen` command.
+
+buildconfig = "//llvm/utils/gn/build/BUILDCONFIG.gn"
+
+# Disallow all calls to exec_script. We should be very conservative about
+# whitelisting things here.
+exec_script_whitelist = []
+
+# The normal GN setup is to have BUILD.gn files in-tree and a root BUILD.gn
+# file. Since LLVM's GN build is unofficial, set secondary_source to tell GN
+# that e.g. llvm/lib/Demangle/BUILD.gn is found at
+# llvm/utils/gn/secondary/llvm/lib/Demangle/BUILD.gn and that the root BUILD.gn
+# file is at llvm/utils/gn/secondary/BUILD.gn
+secondary_source = "//llvm/utils/gn/secondary/"
Index: llvm/utils/gn/README.rst
===================================================================
--- /dev/null
+++ llvm/utils/gn/README.rst
@@ -0,0 +1,129 @@
+=====================
+Building LLVM with GN
+=====================
+
+.. contents::
+ :local:
+
+.. _Introduction:
+
+Introduction
+============
+
+*Warning* The GN build is experimental and best-effort. It might not work,
+and if you use it you're expected to feel comfortable to unbreak it if
+necessary. LLVM's official build system is CMake, if in doubt use that.
+If you add files, you're expected to update the CMake build but you don't need
+to update GN build files. Reviewers should not ask authors to update GN build
+files. Keeping the GN build files up-to-date is on the people who use the GN
+build.
+
+*Another Warning* Right now, we're in the process of getting the GN build
+checked in. As of this writing, it's not yet functional at all. Check back
+in a week!
+
+`GN `_ is another metabuild system. It always
+creates ninja files, but it can create some IDE projects (MSVC, Xcode, ...)
+which then shell out to ninja for the actual build.
+
+Its main features are that GN is very fast (it currently produces ninja files
+for LLVM's build in 35ms on the author's laptop, compared to 66s for CMake) --
+a 2000x difference), and since it's so fast it doesn't aggressively cache,
+making it possible to switch e.g. between release and debug builds in one build
+directory.
+
+It is arguable easier to configure than the CMake build, and has native support
+for building with multiple toolchains in one build directory. The build
+description is declarative-ish, allowing GN to print it in a json format that
+can fairly easily be converted to other metabuild system inputs.
+
+The main motivation behind the GN build is that some people find it more
+convenient for day-to-day hacking on LLVM than CMake. Distribution, building
+just parts of LLVM, and embedding the LLVM GN build from other builds are a
+non-goal for the GN build.
+
+This is a `good overview of GN `_.
+
+.. _Quick start:
+
+Quick start
+===========
+
+*Warning* Right now, we're in the process of getting the GN build checked in.
+As of this writing, it's not yet functional at all.
+
+GN only works in the monorepo layout.
+
+#. Obtain a `gn binary `_.
+
+#. In the root of the monorepo, run
+ `gn gen --dotfile=$PWD/llvm/utils/gn/.gn --root=. out/gn` (`out/gn` is the
+ build directory, it can have any name, and you can have as many as you want,
+ each with different build settings).
+
+#. Run e.g. `ninja -C out/gn check-lld` to build all prerequisites for and
+ run the LLD tests.
+
+By default, you get a release build with assertions enabled that targets
+the host arch. You can set various build options by editing `out/gn/args.gn`,
+for example putting `is_debug = true` in there gives you a debug build. Run
+`gn args --list out/gn` to see a list of all possible options. After touching
+`out/gn/args.gn`, just run ninja, it will re-invoke gn before starting the
+build.
+
+GN has extensive built-in help; try e.g. `gn help gen` to see the help
+for the `gen` command. The full GN reference is also `available online
+`_.
+
+GN has an autoformatter: `git ls-files '*.gn' '*.gni' | xargs -n 1 gn format`
+after making GN build changes is your friend.
+
+To not put `BUILD.gn` into the main tree, they are all below `utils/gn/tree`.
+For example, the build file for `llvm/lib/Support` is in
+`utils/gn/tree/llvm/lib/Support`.
+
+.. _Philosophy:
+
+Philosophy
+==========
+
+GN believes in using GN arguments to configure the build explicitly, instead
+of implicitly figuring out what to do based on what's available on the current
+system.
+
+configure is used for three classes of feature checks:
+
+- compiler checks. In GN, these could use exec_script to identify the host
+ compiler at GN time. For now the build has explicit toggles for compiler
+ features. (Maybe there could be a script that writes args.gn based on the
+ host compiler). It's possible we'll use exec_script() for this going forward,
+ but we'd have one exec_script call to identify compiler id and version,
+ and then base GN arg default values of compiler id and version instead of
+ doing one exec_script per feature check.
+ (In theory, the config approach means a new os / compiler just needs to tweak
+ the checks and not the code, but in practice a) new os's / compilers are rare
+ b) they will require code changes anyhow, so the configure tradeoff seems
+ not worth it.)
+
+- library checks. For e.g. like zlib, GN thinks it's better to say "we require
+ zlib, else we error at build time" than silently omitting features. People
+ who really don't want to install zlib can explicitly set the GN arg to turn
+ off zlib.
+
+- header checks (does system header X exist). These are generally not needed
+ (just keying this off the host OS works fine), but if they should become
+ necessary in the future, they should be done at build time and the few
+ targets that need to know if header X exists then depend on that build-time
+ check while everything else can build parallel with it.
+
+- LLVM-specific build toggles (assertions on/off, debug on/off, targets to
+ build, ...). These map cleanly to GN args (which then get copied into
+ config.h in a build step).
+
+For the last two points, it would be nice if LLVM didn't have a single
+`config.h` header, but one header per toggle. That way, when e.g.
+`llvm_enable_terminfo` is toggled, only the 3 files caring about that setting
+would need to be rebuilt, instead of everything including `config.h`.
+
+GN doesn't believe in users setting arbitrary cflags from an environment
+variable, it wants the build to be controlled by .gn files.
Index: llvm/utils/gn/build/BUILD.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/BUILD.gn
@@ -0,0 +1,153 @@
+import("//llvm/utils/gn/build/buildflags.gni")
+import("//llvm/utils/gn/build/mac_sdk.gni")
+import("//llvm/utils/gn/build/toolchain/compiler.gni")
+import("//llvm/utils/gn/build/enable_threads.gni")
+
+config("compiler_defaults") {
+ # FIXME: Don't define this globally here.
+ if (host_os != "win") {
+ defines = [ "LLVM_ON_UNIX" ]
+ }
+
+ if (!llvm_enable_assertions) {
+ defines += [ "NDEBUG" ]
+ }
+
+ cflags = []
+
+ if (host_os == "mac" && clang_base_path != "") {
+ cflags += [
+ "-isysroot",
+ mac_sdk_path,
+ ]
+ }
+
+ if (host_os != "win") {
+ if (is_debug) {
+ cflags += [ "-g" ]
+ } else {
+ cflags += [ "-O3" ]
+ }
+ cflags += [ "-fdiagnostics-color" ]
+ cflags_cc = [
+ "-std=c++11",
+ "-fno-exceptions",
+ "-fno-rtti",
+ "-fvisibility-inlines-hidden",
+ ]
+ } else {
+ if (is_debug) {
+ cflags += [ "/Zi" ]
+ } else {
+ cflags += [
+ "/O2",
+ "/Zc:inline",
+ ]
+ }
+ defines += [
+ "_CRT_SECURE_NO_DEPRECATE",
+ "_CRT_SECURE_NO_WARNINGS",
+ "_CRT_NONSTDC_NO_DEPRECATE",
+ "_CRT_NONSTDC_NO_WARNINGS",
+ "_SCL_SECURE_NO_DEPRECATE",
+ "_SCL_SECURE_NO_WARNINGS",
+
+ "_HAS_EXCEPTIONS=0",
+ "_UNICODE",
+ "UNICODE",
+ ]
+ cflags += [
+ "/EHs-c-",
+ "/GR-",
+ ]
+
+ # The MSVC default value (1 MB) is not enough for parsing recursive C++
+ # templates in Clang.
+ ldflags = [ "/STACK:10000000" ]
+ }
+
+ # Warning setup.
+ if (host_os == "win" && !is_clang) {
+ cflags += [
+ # Suppress ''modifier' : used more than once' (__forceinline and inline).
+ "-wd4141",
+
+ # Suppress 'conversion from 'type1' to 'type2', possible loss of data'.
+ "-wd4244",
+
+ # Suppress 'conversion from 'size_t' to 'type', possible loss of data'.
+ "-wd4267",
+
+ # Suppress 'no matching operator delete found'.
+ "-wd4291",
+
+ # Suppress 'noexcept used with no exception handling mode specified'.
+ "-wd4577",
+
+ # Suppress 'destructor was implicitly defined as deleted'.
+ "-wd4624",
+
+ # Suppress 'unsafe mix of type and type in operation'.
+ "-wd4805",
+ ]
+ } else {
+ if (host_os == "win") {
+ cflags += [ "/W4" ]
+ } else {
+ cflags += [
+ "-Wall",
+ "-Wextra",
+ ]
+ }
+ cflags += [
+ "-Wno-unused-parameter",
+ "-Wstring-conversion",
+ ]
+ if (is_clang) {
+ cflags += [ "-Wdelete-non-virtual-dtor" ]
+ }
+ if (is_clang && use_goma) {
+ # goma converts all paths to lowercase on the server, breaking this
+ # warning.
+ cflags += [ "-Wno-nonportable-include-path" ]
+ }
+ }
+}
+
+config("llvm_code") {
+ include_dirs = [
+ "//llvm/include",
+ "$root_gen_dir/llvm/include",
+ ]
+}
+
+config("lld_code") {
+ include_dirs = [
+ "//lld/include",
+ "$root_gen_dir/lld/include",
+ ]
+}
+
+config("clang_code") {
+ include_dirs = [
+ "//clang/include",
+ "$root_gen_dir/clang/include",
+ ]
+}
+
+config("warn_covered_switch_default") {
+ if (is_clang) {
+ cflags = [ "-Wcovered-switch-default" ]
+ }
+}
+
+config("pthread_config") {
+ visibility = [ ":pthread" ]
+ libs = [ "pthread" ]
+}
+
+group("pthread") {
+ if (llvm_enable_threads && host_os != "win") {
+ public_configs = [ ":pthread_config" ]
+ }
+}
Index: llvm/utils/gn/build/BUILDCONFIG.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/BUILDCONFIG.gn
@@ -0,0 +1,32 @@
+# All targets will get this list of configs by default.
+# Targets can opt out of a config by removing it from their local configs list.
+# If you're adding global flags and don't need targets to be able to opt out,
+# add the flags to compiler_defaults, not to a new config.
+_shared_binary_target_configs = [
+ "//llvm/utils/gn/build:compiler_defaults",
+ "//llvm/utils/gn/build:llvm_code",
+ "//llvm/utils/gn/build:warn_covered_switch_default",
+]
+
+# Apply that default list to the binary target types.
+set_defaults("executable") {
+ configs = _shared_binary_target_configs
+}
+set_defaults("loadable_module") {
+ configs = _shared_binary_target_configs
+}
+set_defaults("static_library") {
+ configs = _shared_binary_target_configs
+}
+set_defaults("shared_library") {
+ configs = _shared_binary_target_configs
+}
+set_defaults("source_set") {
+ configs = _shared_binary_target_configs
+}
+
+if (host_os == "win") {
+ set_default_toolchain("//llvm/utils/gn/build/toolchain:win")
+} else {
+ set_default_toolchain("//llvm/utils/gn/build/toolchain:posix")
+}
Index: llvm/utils/gn/build/buildflags.gni
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/buildflags.gni
@@ -0,0 +1,10 @@
+declare_args() {
+ # Whether to build with debug information and without optimizations.
+ is_debug = false
+}
+
+# args that depend on other args must live in a later declare_args() block.
+declare_args() {
+ # Whether to enable assertions.
+ llvm_enable_assertions = true
+}
Index: llvm/utils/gn/build/enable_threads.gni
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/enable_threads.gni
@@ -0,0 +1,4 @@
+declare_args() {
+ # Whether to enable threading.
+ llvm_enable_threads = true
+}
Index: llvm/utils/gn/build/mac_sdk.gni
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/mac_sdk.gni
@@ -0,0 +1,4 @@
+# Location of the mac sdk.
+# If that's not fixed, might want to shell out to xcrun at gn time to
+# retrieve this, but for now this seems to do the trick.
+mac_sdk_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
Index: llvm/utils/gn/build/toolchain/BUILD.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/toolchain/BUILD.gn
@@ -0,0 +1,231 @@
+import("//llvm/utils/gn/build/toolchain/compiler.gni")
+
+declare_args() {
+ # If is_goma is true, the location of the goma client install.
+ if (host_os == "win") {
+ goma_dir = "c:\src\goma\goma-win64"
+ } else {
+ goma_dir = getenv("HOME") + "/goma"
+ }
+}
+
+toolchain("posix") {
+ cc = "cc"
+ cxx = "c++"
+
+ if (clang_base_path != "") {
+ cc = "$clang_base_path/bin/clang"
+ cxx = "$clang_base_path/bin/clang++"
+ }
+
+ ld = cxx # Don't use goma wrapper for linking.
+ if (use_goma) {
+ cc = "$goma_dir/gomacc $cc"
+ cxx = "$goma_dir/gomacc $cxx"
+ }
+
+ tool("cc") {
+ depfile = "{{output}}.d"
+ command = "$cc -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
+ depsformat = "gcc"
+ description = "CC {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("cxx") {
+ depfile = "{{output}}.d"
+ command = "$cxx -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
+ depsformat = "gcc"
+ description = "CXX {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("alink") {
+ if (host_os == "mac") {
+ command = "libtool -static -no_warning_for_no_symbols {{arflags}} -o {{output}} {{inputs}}"
+ } else {
+ # Remove the output file first so that ar doesn't try to modify the
+ # existing file.
+ command = "rm -f {{output}} && ar rcsDT {{arflags}} -o {{output}} {{inputs}}"
+ }
+ description = "AR {{output}}"
+ outputs = [
+ "{{output_dir}}/{{target_output_name}}.a",
+ ]
+ output_prefix = "lib"
+ default_output_dir = "{{root_out_dir}}/lib"
+ }
+
+ tool("solink") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ if (host_os == "mac") {
+ command = "$ld -shared {{ldflags}} -o $outfile {{libs}} {{inputs}}"
+ default_output_extension = ".dylib"
+ } else {
+ command =
+ "$ld -shared {{ldflags}} -Wl,-z,defs -o $outfile {{libs}} {{inputs}}"
+ default_output_extension = ".so"
+ }
+ description = "SOLINK $outfile"
+ outputs = [
+ outfile,
+ ]
+ lib_switch = "-l"
+ output_prefix = "lib"
+ default_output_dir = "{{root_out_dir}}/lib"
+ }
+
+ tool("solink_module") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ if (host_os == "mac") {
+ command = "$ld -shared {{ldflags}} -Wl,-flat_namespace -Wl,-undefined,suppress -o $outfile {{libs}} {{inputs}}"
+ default_output_extension = ".dylib"
+ } else {
+ command = "$ld -shared {{ldflags}} -o $outfile {{libs}} {{inputs}}"
+ default_output_extension = ".so"
+ }
+ description = "SOLINK $outfile"
+ outputs = [
+ outfile,
+ ]
+ lib_switch = "-l"
+ default_output_dir = "{{root_out_dir}}/lib"
+ }
+
+ tool("link") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ if (host_os == "mac") {
+ command = "$ld {{ldflags}} -o $outfile {{libs}} {{inputs}}"
+ } else {
+ command = "$ld {{ldflags}} -o $outfile {{libs}} -Wl,--start-group {{inputs}} -Wl,--end-group"
+ }
+ description = "LINK $outfile"
+ outputs = [
+ outfile,
+ ]
+ lib_switch = "-l"
+
+ # Setting this allows targets to override the default executable output by
+ # setting output_dir.
+ default_output_dir = "{{root_out_dir}}/bin"
+ }
+
+ tool("copy") {
+ command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})"
+ description = "COPY {{source}} {{output}}"
+ }
+
+ tool("stamp") {
+ command = "touch {{output}}"
+ description = "STAMP {{output}}"
+ }
+}
+
+toolchain("win") {
+ cl = "cl"
+ link = "link"
+
+ if (clang_base_path != "") {
+ cl = "$clang_base_path/bin/clang-cl"
+ link = "$clang_base_path/bin/lld-link"
+ }
+
+ if (use_goma) {
+ cl = "$goma_dir/gomacc $cl"
+ }
+
+ tool("cc") {
+ command = "$cl /nologo /showIncludes /Fo{{output}} /c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
+ depsformat = "msvc"
+ description = "CC {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
+ ]
+ }
+
+ tool("cxx") {
+ command = "$cl /nologo /showIncludes /Fo{{output}} /c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
+ depsformat = "msvc"
+ description = "CXX {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
+ ]
+ }
+
+ tool("alink") {
+ command = "lib /nologo {{arflags}} /out:{{output}} {{inputs}}"
+ description = "LIB {{output}}"
+ outputs = [
+ "{{output_dir}}/{{target_output_name}}.lib",
+ ]
+ default_output_dir = "{{root_out_dir}}/lib"
+ }
+
+ tool("solink") {
+ dllfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ libfile = "$dllfile.lib"
+ command = "$link /nologo /dll {{ldflags}} /out:$dllfile /implib:$libfile {{libs}} /pdb:$dllfile.pdb {{inputs}}"
+ description = "LINK $dllfile"
+ link_output = libfile
+ depend_output = libfile
+ runtime_outputs = [ dllfile ]
+ outputs = [
+ dllfile,
+ libfile,
+ ]
+ default_output_extension = ".dll"
+ restat = true
+
+ # Put dlls next to the executables in bin/ on Windows, since Windows
+ # doesn't have a configurable rpath. This matches initialization of
+ # module_dir to bin/ in AddLLVM.cmake's set_output_directory().
+ default_output_dir = "{{root_out_dir}}/bin"
+ }
+
+ # Plugins for opt and clang and so on don't work in LLVM's Windows build
+ # since the code doesn't have export annotations, but there are a few
+ # standalone loadable modules used for unit-testing LLVM's dynamic library
+ # loading code.
+ tool("solink_module") {
+ dllfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ command = "$link /nologo /dll {{ldflags}} /out:$dllfile {{libs}} /pdb:$dllfile.pdb {{inputs}}"
+ description = "LINK_MODULE $dllfile"
+ outputs = [
+ dllfile,
+ ]
+ runtime_outputs = outputs
+ default_output_extension = ".dll"
+
+ # No default_output_dir, all clients set output_dir.
+ }
+
+ tool("link") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ command = "$link /nologo {{ldflags}} /out:$outfile {{libs}} /pdb:$outfile.pdb {{inputs}}"
+ description = "LINK $outfile"
+ outputs = [
+ outfile,
+ ]
+ default_output_extension = ".exe"
+
+ # Setting this allows targets to override the default executable output by
+ # setting output_dir.
+ default_output_dir = "{{root_out_dir}}/bin"
+ }
+
+ tool("copy") {
+ # GN hands out slash-using paths, but cmd's copy needs backslashes.
+ # Use cmd's %foo:a=b% substitution feature to convert.
+ command = "cmd /c set source=\"{{source}}\" & set output=\"{{output}}\" & call copy /Y %source:/=\% %output:\=/% > nul"
+ description = "COPY {{source}} {{output}}"
+ }
+
+ tool("stamp") {
+ command = "cmd /c type nul > {{output}}"
+ description = "STAMP {{output}}"
+ }
+}
Index: llvm/utils/gn/build/toolchain/compiler.gni
===================================================================
--- /dev/null
+++ llvm/utils/gn/build/toolchain/compiler.gni
@@ -0,0 +1,18 @@
+declare_args() {
+ # Whether to use goma (https://chromium.googlesource.com/infra/goma/client/)
+ use_goma = false
+
+ # Set this to a clang build directory. If set, that clang is used as compiler.
+ # goma only works with compiler binaries it knows about, so useful both for
+ # using a goma-approved compiler and for compiling clang with a locally-built
+ # clang in a different build directory.
+ # On Windows, setting this also causes lld-link to be used as linker.
+ # Example value: getenv("HOME") + "/src/llvm-build/Release+Asserts"
+ clang_base_path = ""
+}
+
+declare_args() {
+ # Set if the host compiler is clang. On by default on Mac or if
+ # clang_base_path is set.
+ is_clang = host_os == "mac" || clang_base_path != ""
+}
Index: llvm/utils/gn/secondary/BUILD.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/secondary/BUILD.gn
@@ -0,0 +1,11 @@
+group("default") {
+ deps = [
+ "//llvm/lib/Demangle",
+ ]
+}
+
+# A pool called "console" in the root BUILD.gn is magic and represents ninja's
+# built-in console pool. (Requires a GN with `gn --version` >= 552353.)
+pool("console") {
+ depth = 1
+}
Index: llvm/utils/gn/secondary/llvm/lib/Demangle/BUILD.gn
===================================================================
--- /dev/null
+++ llvm/utils/gn/secondary/llvm/lib/Demangle/BUILD.gn
@@ -0,0 +1,9 @@
+static_library("Demangle") {
+ output_name = "LLVMDemangle"
+
+ sources = [
+ "ItaniumDemangle.cpp",
+ "MicrosoftDemangle.cpp",
+ "MicrosoftDemangleNodes.cpp",
+ ]
+}