From 4bfb1461811cdbc948a8f3957f83a903d1577443 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Tue, 28 Mar 2023 06:43:12 -0600 Subject: [PATCH] Meta: Add the start of a gn build based on the LLVM gn build "based on" in this context means "largely copied from" --- .gn | 4 + Meta/gn/.gitignore | 1 + Meta/gn/README.md | 9 + Meta/gn/build/BUILD.gn | 170 ++++++++ Meta/gn/build/BUILDCONFIG.gn | 44 +++ Meta/gn/build/buildflags.gni | 18 + Meta/gn/build/libs/crypt/BUILD.gn | 10 + Meta/gn/build/libs/pthread/BUILD.gn | 11 + Meta/gn/build/mac_sdk.gni | 22 ++ Meta/gn/build/sysroot.gni | 4 + Meta/gn/build/toolchain/BUILD.gn | 161 ++++++++ Meta/gn/build/toolchain/compiler.gni | 8 + Meta/gn/build/write_cmake_config.gni | 50 +++ Meta/gn/build/write_cmake_config.py | 121 ++++++ Meta/gn/secondary/AK/BUILD.gn | 371 ++++++++++++++++++ Meta/gn/secondary/BUILD.gn | 11 + .../Userland/Libraries/LibCore/BUILD.gn | 142 +++++++ .../Userland/Libraries/LibCrypt/BUILD.gn | 36 ++ .../Userland/Libraries/LibSystem/BUILD.gn | 32 ++ 19 files changed, 1225 insertions(+) create mode 100644 .gn create mode 100644 Meta/gn/.gitignore create mode 100644 Meta/gn/README.md create mode 100644 Meta/gn/build/BUILD.gn create mode 100644 Meta/gn/build/BUILDCONFIG.gn create mode 100644 Meta/gn/build/buildflags.gni create mode 100644 Meta/gn/build/libs/crypt/BUILD.gn create mode 100644 Meta/gn/build/libs/pthread/BUILD.gn create mode 100644 Meta/gn/build/mac_sdk.gni create mode 100644 Meta/gn/build/sysroot.gni create mode 100644 Meta/gn/build/toolchain/BUILD.gn create mode 100644 Meta/gn/build/toolchain/compiler.gni create mode 100644 Meta/gn/build/write_cmake_config.gni create mode 100644 Meta/gn/build/write_cmake_config.py create mode 100644 Meta/gn/secondary/AK/BUILD.gn create mode 100644 Meta/gn/secondary/BUILD.gn create mode 100644 Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn create mode 100644 Meta/gn/secondary/Userland/Libraries/LibCrypt/BUILD.gn create mode 100644 Meta/gn/secondary/Userland/Libraries/LibSystem/BUILD.gn diff --git a/.gn b/.gn new file mode 100644 index 00000000000..646516e27fa --- /dev/null +++ b/.gn @@ -0,0 +1,4 @@ +buildconfig = "//Meta/gn/build/BUILDCONFIG.gn" +exec_script_whitelist = [] +script_executable = "python3" +secondary_source = "//Meta/gn/secondary/" diff --git a/Meta/gn/.gitignore b/Meta/gn/.gitignore new file mode 100644 index 00000000000..71860a75dbf --- /dev/null +++ b/Meta/gn/.gitignore @@ -0,0 +1 @@ +!build diff --git a/Meta/gn/README.md b/Meta/gn/README.md new file mode 100644 index 00000000000..99fa224206b --- /dev/null +++ b/Meta/gn/README.md @@ -0,0 +1,9 @@ +# gn build for SerenityOS and Ladybird + +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. Serenity'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. + +GN is a 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. + +This is a good [overview of GN](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit#slide=id.g119d702868_0_12). + +For more information, motivation, philosophy, and inspriation, see the LLVM documentation on its [GN build](https://github.com/llvm/llvm-project/tree/main/llvm/utils/gn#quick-start) diff --git a/Meta/gn/build/BUILD.gn b/Meta/gn/build/BUILD.gn new file mode 100644 index 00000000000..4d149e4161d --- /dev/null +++ b/Meta/gn/build/BUILD.gn @@ -0,0 +1,170 @@ +import("//Meta/gn/build/buildflags.gni") +import("//Meta/gn/build/mac_sdk.gni") +import("//Meta/gn/build/sysroot.gni") +import("//Meta/gn/build/toolchain/compiler.gni") + +declare_args() { + # If set, puts relative paths in debug info. + # Makes the build output independent of the build directory, but makes + # most debuggers harder to use. See "Getting to local determinism" and + # "Getting debuggers to work well with locally deterministic builds" in + # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html + # for more information. + use_relative_paths_in_debug_info = false + + # The version of host gcc. Ignored if is_clang is true. + gcc_version = 12 +} + +config("compiler_defaults") { + defines = [] + asmflags = [] + cflags = [] + cflags_cc = [] + ldflags = [] + + if (symbol_level == 2) { + cflags += [ "-g" ] + + # For full debug-info -g builds, --gdb-index makes links ~15% slower, and + # gdb symbol reading time 1500% faster (lld links in 4.4 instead of 3.9s, + # and gdb loads and runs it in 2s instead of in 30s). It's likely that + # people doing symbol_level=2 want to run a debugger (since + # symbol_level=2 isn't the default). So this seems like the right + # tradeoff. + if (current_os != "mac" && use_lld) { + cflags += [ "-ggnu-pubnames" ] # llvm PR34820 + ldflags += [ "-Wl,--gdb-index" ] + + # Use debug fission. In this mode, detailed debug information is + # written to a .dwo file next to each .o file instead of into the .o + # file directly. The linker then only links the .o files, which contain + # a pointer to each .dwo file. The debugger then reads debug info out + # of all the .dwo files instead of from the binary. + # + # (The dwp tool can link all the debug info together into a single + # "debug info binary", but that's not done as part of the build.) + # + # This requires `-Wl,--gdb-index` (above) to work well. + # + # With lld, this reduces link time: + # - in release + symbol_level=2 builds: From 2.3s to 1.3s + # - in debug builds: From 5.2s to 4.6s + # + # Time needed for gdb startup and setting a breakpoint is comparable, + # the time from from `r` to hititng a breakpoint on main goes from 4s + # to 2s. + # + # (macOS's linker always keeps debug info out of its output executables + # and debuggers there also know to load debug info from the .o files. + # macOS also has a debug info linker like dwp, it's called dsymutil. + # This happens by default, so there's no need to pass a flag there.) + cflags += [ "-gsplit-dwarf" ] + ldflags += [ "-gsplit-dwarf" ] # Needed for ThinLTO builds. + } + } else if (symbol_level == 1) { + cflags += [ "-g1" ] + # For linetable-only -g1 builds, --gdb-index makes links ~8% slower, but + # links are 4x faster than -g builds so it's a fairly small absolute cost. + # On the other hand, gdb startup is well below 1s with and without the + # index, and people using -g1 likely don't use a debugger. So don't use + # the flag here. + # Linetables always go in the .o file, even with -gsplit-dwarf, so there's + # no point in passing -gsplit-dwarf here. + } + if (is_optimized) { + cflags += [ "-O3" ] + } + cflags += [ "-fdiagnostics-color" ] + + if (use_lld) { + ldflags += [ "-Wl,--color-diagnostics" ] + } + cflags_cc += [ + "-std=c++20", + "-fvisibility-inlines-hidden", + ] + + # Warning setup. + cflags += [ + "-Wall", + "-Wextra", + ] + cflags += [ "-Wno-unused-parameter" ] + if (is_clang) { + cflags += [ + "-Wdelete-non-virtual-dtor", + "-Wstring-conversion", + "-Wno-user-defined-literals", + "-fconstexpr-steps=16777216", + "-Wno-unused-private-field", + ] + } else { + cflags += [ + # Disable gcc's potentially uninitialized use analysis as it presents + # lots of false positives. + "-Wno-maybe-uninitialized", + + # Disable -Wredundant-move on GCC>=9. GCC wants to remove std::move + # in code like "A foo(ConvertibleToA a) { return std::move(a); }", + # but this code does not compile (or uses the copy constructor + # instead) on clang<=3.8. Clang also has a -Wredundant-move, but it + # only fires when the types match exactly, so we can keep it here. + "-Wno-redundant-move", + ] + } + + if (use_lld) { + ldflags += [ "-fuse-ld=lld" ] + } + + # Deterministic build setup, see + # http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html + if (is_clang) { + cflags += [ + "-no-canonical-prefixes", + "-Werror=date-time", + ] + if (use_relative_paths_in_debug_info) { + cflags += [ "-fdebug-compilation-dir=." ] + } + } + if (sysroot != "") { + if (current_os != "mac" && current_os != "android") { + cflags += [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ] + } + } + + if (current_os == "mac" && sysroot != "") { + sdk_path = mac_sdk_path + cflags += [ + "-isysroot", + rebase_path(sdk_path, root_build_dir), + ] + ldflags += [ + "-isysroot", + rebase_path(sdk_path, root_build_dir), + ] + } + if (sysroot != "" && current_os != "win" && is_clang) { + cflags += [ "-Wpoison-system-directories" ] + } + cflags_objcc = cflags_cc +} + +config("no_exceptions") { + cflags_cc = [ "-fno-exceptions" ] + cflags_objcc = cflags_cc +} + +config("zdefs") { + if (current_os != "mac" && current_os != "android") { + ldflags = [ "-Wl,-z,defs" ] + } +} + +config("pic") { + if (current_os != "mac") { + cflags_cc = [ "-fPIC" ] + } +} diff --git a/Meta/gn/build/BUILDCONFIG.gn b/Meta/gn/build/BUILDCONFIG.gn new file mode 100644 index 00000000000..67e29c1e6f9 --- /dev/null +++ b/Meta/gn/build/BUILDCONFIG.gn @@ -0,0 +1,44 @@ +# 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 = [ + "//Meta/gn/build:compiler_defaults", + "//Meta/gn/build:no_exceptions", + "//Meta/gn/build:pic", +] + +# 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 + [ "//Meta/gn/build:zdefs" ] +} +set_defaults("source_set") { + configs = shared_binary_target_configs +} + +if (target_os == "") { + target_os = host_os +} +if (current_os == "") { + current_os = target_os +} + +if (target_cpu == "") { + target_cpu = host_cpu +} +if (current_cpu == "") { + current_cpu = target_cpu +} + +host_toolchain = "//Meta/gn/build/toolchain:unix" + +set_default_toolchain(host_toolchain) diff --git a/Meta/gn/build/buildflags.gni b/Meta/gn/build/buildflags.gni new file mode 100644 index 00000000000..782cd0d79d7 --- /dev/null +++ b/Meta/gn/build/buildflags.gni @@ -0,0 +1,18 @@ +declare_args() { + # Build for debugging. Equivalent to is_optimized=false symbol_level=2. + is_debug = false +} + +# args that depend on other args must live in a later declare_args() block. +declare_args() { + # Whether to build with optimizations. + is_optimized = !is_debug + + if (is_debug) { + # Debug info symbol level. 0: No symbols; 1: Line numbers; 2: Full symbols. + symbol_level = 2 + } else { + # Debug info symbol level. 0: No symbols; 1: Line numbers; 2: Full symbols. + symbol_level = 1 + } +} diff --git a/Meta/gn/build/libs/crypt/BUILD.gn b/Meta/gn/build/libs/crypt/BUILD.gn new file mode 100644 index 00000000000..2df57fdc890 --- /dev/null +++ b/Meta/gn/build/libs/crypt/BUILD.gn @@ -0,0 +1,10 @@ +config("crypt_config") { + visibility = [ ":crypt" ] + libs = [ "crypt" ] +} + +group("crypt") { + if (current_os == "linux") { + public_configs = [ ":crypt_config" ] + } +} diff --git a/Meta/gn/build/libs/pthread/BUILD.gn b/Meta/gn/build/libs/pthread/BUILD.gn new file mode 100644 index 00000000000..76ff4ddd106 --- /dev/null +++ b/Meta/gn/build/libs/pthread/BUILD.gn @@ -0,0 +1,11 @@ +config("pthread_config") { + visibility = [ ":pthread" ] + libs = [ "pthread" ] +} + +group("pthread") { + # On Android, bionic has built-in support for pthreads. + if (current_os != "android") { + public_configs = [ ":pthread_config" ] + } +} diff --git a/Meta/gn/build/mac_sdk.gni b/Meta/gn/build/mac_sdk.gni new file mode 100644 index 00000000000..2bbb3c3f7bf --- /dev/null +++ b/Meta/gn/build/mac_sdk.gni @@ -0,0 +1,22 @@ +import("//Meta/gn/build/sysroot.gni") + +if (sysroot == "") { + declare_args() { + # Set to true if you don't have Xcode installed, but do have the commandline + # tools. + mac_use_commandline_tools_sdk = false + } + + # Location of the mac sdk. + # The correct way to do this is to call xcrun + # (https://reviews.llvm.org/D70835), but that makes `gn gen` take twice as + # long and almost everyone has Xcode installed. So require that people who + # don't have it installed set a gn arg. + if (mac_use_commandline_tools_sdk) { + mac_sdk_path = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" + } else { + mac_sdk_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" + } +} else { + mac_sdk_path = sysroot + "/MacOSX.sdk" +} diff --git a/Meta/gn/build/sysroot.gni b/Meta/gn/build/sysroot.gni new file mode 100644 index 00000000000..b1b4e74cea9 --- /dev/null +++ b/Meta/gn/build/sysroot.gni @@ -0,0 +1,4 @@ +declare_args() { + # Path of sysroot to use. + sysroot = "" +} diff --git a/Meta/gn/build/toolchain/BUILD.gn b/Meta/gn/build/toolchain/BUILD.gn new file mode 100644 index 00000000000..52e944619e6 --- /dev/null +++ b/Meta/gn/build/toolchain/BUILD.gn @@ -0,0 +1,161 @@ +unix_copy_command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})" + +template("unix_toolchain") { + toolchain(target_name) { + ar = "ar" + cc = "cc" + cxx = "c++" + ld = cxx + + forward_variables_from(invoker.toolchain_args, "*") + forward_variables_from(invoker, "*") + + 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}}/{{label_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}}/{{label_name}}.{{source_name_part}}.o" ] + } + + tool("objcxx") { + depfile = "{{output}}.d" + command = "$cxx -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_objcc}}" + depsformat = "gcc" + description = "OBJCXX {{output}}" + outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] + } + + tool("asm") { + depfile = "{{output}}.d" + command = "$cc -MMD -MF $depfile -o {{output}} -c {{source}} {{defines}} {{include_dirs}} {{asmflags}}" + depsformat = "gcc" + description = "ASM {{output}}" + outputs = [ "{{source_out_dir}}/{{label_name}}.{{source_name_part}}.o" ] + } + + tool("alink") { + if (current_os == "ios" || current_os == "mac") { + command = "libtool -D -static -no_warning_for_no_symbols {{arflags}} -o {{output}} {{inputs}}" + not_needed([ "ar" ]) + } else { + # Remove the output file first so that ar doesn't try to modify the + # existing file. + command = + "rm -f {{output}} && $ar rcsD {{arflags}} {{output}} {{inputs}}" + } + description = "AR {{output}}" + outputs = [ "{{output_dir}}/{{target_output_name}}.a" ] + output_prefix = "lib" + if (current_os != "serenity") { + output_prefix = "liblagom-" + } + default_output_dir = "{{root_out_dir}}/lib" + } + + # Make these apply to all tools below. + lib_switch = "-l" + lib_dir_switch = "-L" + + tool("solink") { + outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" + if (current_os == "ios" || current_os == "mac") { + command = "$ld -shared {{ldflags}} -o $outfile {{inputs}} {{libs}} {{frameworks}}" + default_output_extension = ".dylib" + } else { + command = "$ld -shared {{ldflags}} -Wl,-soname,{{target_output_name}}{{output_extension}} -Wl,-rpath,\\\$ORIGIN -o $outfile {{inputs}} {{libs}}" + default_output_extension = ".so" + } + description = "SOLINK $outfile" + outputs = [ outfile ] + output_prefix = "lib" + if (current_os != "serenity") { + output_prefix = "liblagom-" + } + default_output_dir = "{{root_out_dir}}/lib" + } + + tool("solink_module") { + outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" + if (current_os == "ios" || current_os == "mac") { + command = "$ld -shared {{ldflags}} -Wl,-flat_namespace -Wl,-undefined,suppress -o $outfile {{inputs}} {{libs}} {{frameworks}}" + default_output_extension = ".dylib" + } else { + command = "$ld -shared {{ldflags}} -Wl,-soname,{{target_output_name}}{{output_extension}} -Wl,-rpath,\\\$ORIGIN -o $outfile {{inputs}} {{libs}}" + default_output_extension = ".so" + } + description = "SOLINK $outfile" + outputs = [ outfile ] + if (current_os != "serenity") { + output_prefix = "lagom-" + } + default_output_dir = "{{root_out_dir}}/lib" + } + + tool("link") { + outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}" + if (current_os == "ios" || current_os == "mac") { + command = + "$ld {{ldflags}} -o $outfile {{inputs}} {{libs}} {{frameworks}}" + } else { + command = "$ld {{ldflags}} -o $outfile -Wl,--start-group {{inputs}} -Wl,--end-group -Wl,-rpath,\\\$ORIGIN/../lib {{libs}}" + } + description = "LINK $outfile" + outputs = [ outfile ] + + # Setting this allows targets to override the default executable output by + # setting output_dir. + default_output_dir = "{{root_out_dir}}/bin" + } + + tool("copy") { + command = unix_copy_command + description = "COPY {{source}} {{output}}" + } + + if (current_os == "ios" || current_os == "mac") { + tool("copy_bundle_data") { + # https://github.com/nico/hack/blob/master/notes/copydir.md + _copydir = "cd {{source}} && " + + "find . | cpio -pdl \"\$OLDPWD\"/{{output}} 2>/dev/null" + command = "rm -rf {{output}} && if [[ -d {{source}} ]]; then " + + _copydir + "; else " + unix_copy_command + "; fi" + description = "COPY_BUNDLE_DATA {{source}} {{output}}" + } + tool("compile_xcassets") { + command = "false" + description = "The serenity build doesn't use any xcasset files" + } + } + + tool("stamp") { + command = "touch {{output}}" + description = "STAMP {{output}}" + } + } +} + +declare_args() { + # C compiler for native builds + host_cc = "cc" + + # C++ compiler for native builds + host_cxx = "c++" +} + +unix_toolchain("unix") { + toolchain_args = { + current_os = host_os + cc = host_cc + cxx = host_cxx + } +} +# Note: For serenity, we can override cc and cxx etc in toolchain_args diff --git a/Meta/gn/build/toolchain/compiler.gni b/Meta/gn/build/toolchain/compiler.gni new file mode 100644 index 00000000000..5608161186b --- /dev/null +++ b/Meta/gn/build/toolchain/compiler.gni @@ -0,0 +1,8 @@ +declare_args() { + # Set to true when host compiler is clang so that clang flags will be passed to it + is_clang = host_os == "mac" + + # Enable setting -fuse-ld and other flags for using the lld linker. + # Should not be set on macOS when using the default system compiler. + use_lld = false +} diff --git a/Meta/gn/build/write_cmake_config.gni b/Meta/gn/build/write_cmake_config.gni new file mode 100644 index 00000000000..881c4aff5de --- /dev/null +++ b/Meta/gn/build/write_cmake_config.gni @@ -0,0 +1,50 @@ +# This file introduces a template for calling write_cmake_config.py. +# +# write_cmake_config behaves like CMake's configure_file(), but runs at build +# time, not at generator time. See write_cmake_config.py for details. +# +# Parameters: +# +# input (required) [string] +# +# output (required) [string] +# +# values (required) [list of strings] +# Each entry is a '='-separated key-value pair used for substitution. +# +# Example use: +# +# write_cmake_config("attributes_compat_func_gen") { +# input = "Version.inc.in" +# output = "$root_gen_dir/clang/include/clang/Basic/Version.inc", +# values = [ +# "CLANG_VERSION=$llvm_version", +# ] +# } + +template("write_cmake_config") { + assert(defined(invoker.input), "must set 'input' in $target_name") + assert(defined(invoker.output), "must set 'output' in $target_name") + assert(defined(invoker.values), "must set 'values' in $target_name") + + action(target_name) { + script = "//Meta/gn/build/write_cmake_config.py" + + sources = [ invoker.input ] + outputs = [ invoker.output ] + args = [ + "-o", + rebase_path(outputs[0], root_build_dir), + rebase_path(sources[0], root_build_dir), + ] + invoker.values + + forward_variables_from(invoker, + [ + "configs", + "deps", + "public_configs", + "public_deps", + "visibility", + ]) + } +} diff --git a/Meta/gn/build/write_cmake_config.py b/Meta/gn/build/write_cmake_config.py new file mode 100644 index 00000000000..05fbcb105b8 --- /dev/null +++ b/Meta/gn/build/write_cmake_config.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +r"""Emulates the bits of CMake's configure_file() function needed in serenity. + +The CMake build uses configure_file() for several things. This emulates that +function for the GN build. In the GN build, this runs at build time instead +of at generator time. + +Takes a list of KEY=VALUE pairs (where VALUE can be empty). + +The sequence `\` `n` in each VALUE is replaced by a newline character. + +On each line, replaces '${KEY}' or '@KEY@' with VALUE. + +Then, handles these special cases (note that FOO= sets the value of FOO to the +empty string, which is falsy, but FOO=0 sets it to '0' which is truthy): + +1.) #cmakedefine01 FOO + Checks if key FOO is set to a truthy value, and depending on that prints + one of the following two lines: + + #define FOO 1 + #define FOO 0 + +2.) #cmakedefine FOO [...] + Checks if key FOO is set to a truthy value, and depending on that prints + one of the following two lines: + + #define FOO [...] + /* #undef FOO */ + +Fails if any of the KEY=VALUE arguments aren't needed for processing the +input file, or if the input file references keys that weren't passed in. +""" + +import argparse +import os +import re +import sys + + +def main(): + parser = argparse.ArgumentParser( + epilog=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('input', help='input file') + parser.add_argument('values', nargs='*', help='several KEY=VALUE pairs') + parser.add_argument('-o', '--output', required=True, + help='output file') + args = parser.parse_args() + + values = {} + for value in args.values: + key, val = value.split('=', 1) + if key in values: + print('duplicate key "%s" in args' % key, file=sys.stderr) + return 1 + values[key] = val.replace('\\n', '\n') + unused_values = set(values.keys()) + + # Matches e.g. '${FOO}' or '@FOO@' and captures FOO in group 1 or 2. + var_re = re.compile(r'\$\{([^}]*)\}|@([^@]*)@') + + with open(args.input) as f: + in_lines = f.readlines() + out_lines = [] + for in_line in in_lines: + def repl(m): + key = m.group(1) or m.group(2) + unused_values.discard(key) + return values[key] + in_line = var_re.sub(repl, in_line) + if in_line.startswith('#cmakedefine01 ') or in_line.startswith("# cmakedefine01"): + in_line = in_line.replace('# cmakedefine01', '#cmakedefine01') + _, var = in_line.split() + if values[var] == '0': + print('error: "%s=0" used with #cmakedefine01 %s' % (var, var)) + print(" '0' evaluates as truthy with #cmakedefine01") + print(' use "%s=" instead' % var) + return 1 + in_line = '#define %s %d\n' % (var, 1 if values[var] else 0) + unused_values.discard(var) + elif in_line.startswith('#cmakedefine '): + _, var = in_line.split(None, 1) + try: + var, val = var.split(None, 1) + in_line = '#define %s %s' % (var, val) # val ends in \n. + except _: + var = var.rstrip() + in_line = '#define %s\n' % var + if not values[var]: + in_line = '/* #undef %s */\n' % var + unused_values.discard(var) + out_lines.append(in_line) + + if unused_values: + print('unused values args:', file=sys.stderr) + print(' ' + '\n '.join(unused_values), file=sys.stderr) + return 1 + + output = ''.join(out_lines) + + leftovers = var_re.findall(output) + if leftovers: + print( + 'unprocessed values:\n', + '\n'.join([x[0] or x[1] for x in leftovers]), + file=sys.stderr) + return 1 + + def read(filename): + with open(filename) as f: + return f.read() + + if not os.path.exists(args.output) or read(args.output) != output: + with open(args.output, 'w') as f: + f.write(output) + os.chmod(args.output, os.stat(args.input).st_mode & 0o777) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/Meta/gn/secondary/AK/BUILD.gn b/Meta/gn/secondary/AK/BUILD.gn new file mode 100644 index 00000000000..8341dd1b1c3 --- /dev/null +++ b/Meta/gn/secondary/AK/BUILD.gn @@ -0,0 +1,371 @@ +import("//Meta/gn/build/write_cmake_config.gni") + +config("ak_headers") { + include_dirs = [ + "//", + "$root_gen_dir", + ] +} + +source_set("AK") { + public_configs = [ ":ak_headers" ] + public_deps = [ ":ak_debug_gen" ] + + # NOTE: Headers only! + sources = [ + "AllOf.h", + "AnyOf.h", + "ArbitrarySizedEnum.h", + "Array.h", + "Assertions.h", + "Atomic.h", + "AtomicRefCounted.h", + "Badge.h", + "Base64.h", + "BigIntBase.h", + "BinaryBufferWriter.h", + "BinaryHeap.h", + "BinarySearch.h", + "BitCast.h", + "BitStream.h", + "Bitmap.h", + "BitmapView.h", + "BufferedStream.h", + "BuiltinWrappers.h", + "BumpAllocator.h", + "ByteBuffer.h", + "ByteReader.h", + "CharacterTypes.h", + "Checked.h", + "CheckedFormatString.h", + "CircularBuffer.h", + "CircularDeque.h", + "CircularQueue.h", + "Complex.h", + "Concepts.h", + "ConstrainedStream.h", + "CountingStream.h", + "DOSPackedTime.h", + "DateConstants.h", + "DefaultDelete.h", + "Demangle.h", + "DeprecatedFlyString.h", + "DeprecatedString.h", + "Diagnostics.h", + "DisjointChunks.h", + "DistinctNumeric.h", + "DoublyLinkedList.h", + "Endian.h", + "EnumBits.h", + "Error.h", + "ExtraMathConstants.h", + "FPControl.h", + "Find.h", + "FixedArray.h", + "FixedPoint.h", + "FloatingPoint.h", + "FloatingPointStringConversions.h", + "FlyString.h", + "Format.h", + "Forward.h", + "Function.h", + "FuzzyMatch.h", + "GenericLexer.h", + "GenericShorthands.h", + "HashFunctions.h", + "HashMap.h", + "HashTable.h", + "Hex.h", + "IDAllocator.h", + "IPv4Address.h", + "IPv6Address.h", + "InsertionSort.h", + "IntegralMath.h", + "IntrusiveDetails.h", + "IntrusiveList.h", + "IntrusiveListRelaxedConst.h", + "IntrusiveRedBlackTree.h", + "IterationDecision.h", + "Iterator.h", + "JsonArray.h", + "JsonArraySerializer.h", + "JsonObject.h", + "JsonObjectSerializer.h", + "JsonParser.h", + "JsonPath.h", + "JsonValue.h", + "LEB128.h", + "LexicalPath.h", + "MACAddress.h", + "Math.h", + "MaybeOwned.h", + "MemMem.h", + "Memory.h", + "MemoryStream.h", + "NeverDestroyed.h", + "NoAllocationGuard.h", + "Noncopyable.h", + "NonnullOwnPtr.h", + "NonnullRefPtr.h", + "NumberFormat.h", + "NumericLimits.h", + "OptionParser.h", + "Optional.h", + "OwnPtr.h", + "Platform.h", + "PrintfImplementation.h", + "Ptr32.h", + "Queue.h", + "QuickSelect.h", + "QuickSort.h", + "Random.h", + "RecursionDecision.h", + "RedBlackTree.h", + "RefCountForwarder.h", + "RefCounted.h", + "RefPtr.h", + "Result.h", + "ReverseIterator.h", + "SIMD.h", + "SIMDExtras.h", + "SIMDMath.h", + "ScopeGuard.h", + "ScopeLogger.h", + "ScopedValueRollback.h", + "Singleton.h", + "SinglyLinkedList.h", + "SinglyLinkedListSizePolicy.h", + "SourceGenerator.h", + "SourceLocation.h", + "Span.h", + "Stack.h", + "StackInfo.h", + "Statistics.h", + "StdLibExtraDetails.h", + "StdLibExtras.h", + "Stream.h", + "String.h", + "StringBuilder.h", + "StringFloatingPointConversions.h", + "StringHash.h", + "StringImpl.h", + "StringUtils.h", + "StringView.h", + "TemporaryChange.h", + "Time.h", + "Traits.h", + "Trie.h", + "Try.h", + "Tuple.h", + "TypeCasts.h", + "TypeList.h", + "TypedTransfer.h", + "Types.h", + "UBSanitizer.h", + "UFixedBigInt.h", + "UFixedBigIntDivision.h", + "URL.h", + "URLParser.h", + "UUID.h", + "UnicodeUtils.h", + "Userspace.h", + "Utf16View.h", + "Utf32View.h", + "Utf8View.h", + "Variant.h", + "Vector.h", + "WeakPtr.h", + "Weakable.h", + "kmalloc.h", + "kstdio.h", + ] +} + +source_set("sources") { + deps = [ ":AK" ] + + # FIXME: Split out non-kernel sources to their own set + sources = [ + "Assertions.cpp", + "Base64.cpp", + "CircularBuffer.cpp", + "ConstrainedStream.cpp", + "CountingStream.cpp", + "DOSPackedTime.cpp", + "DeprecatedFlyString.cpp", + "DeprecatedString.cpp", + "Error.cpp", + "FloatingPointStringConversions.cpp", + "FlyString.cpp", + "Format.cpp", + "FuzzyMatch.cpp", + "GenericLexer.cpp", + "Hex.cpp", + "JsonObject.cpp", + "JsonParser.cpp", + "JsonPath.cpp", + "JsonValue.cpp", + "LexicalPath.cpp", + "MemoryStream.cpp", + "NumberFormat.cpp", + "OptionParser.cpp", + "Random.cpp", + "StackInfo.cpp", + "Stream.cpp", + "String.cpp", + "StringBuilder.cpp", + "StringFloatingPointConversions.cpp", + "StringImpl.cpp", + "StringUtils.cpp", + "StringView.cpp", + "Time.cpp", + "URL.cpp", + "URLParser.cpp", + "UUID.cpp", + "Utf16View.cpp", + "Utf32View.cpp", + "Utf8View.cpp", + "kmalloc.cpp", + ] +} + +write_cmake_config("ak_debug_gen") { + input = "Debug.h.in" + output = "$root_gen_dir/AK/Debug.h" + values = [ + "AFLACLOADER_DEBUG=", + "AUDIO_DEBUG=", + "AWAVLOADER_DEBUG=", + "BINDINGS_GENERATOR_DEBUG=", + "BMP_DEBUG=", + "CACHE_DEBUG=", + "CALLBACK_MACHINE_DEBUG=", + "CANVAS_RENDERING_CONTEXT_2D_DEBUG=", + "CMAKE_DEBUG=", + "COMPOSE_DEBUG=", + "COPY_DEBUG=", + "CPP_DEBUG=", + "CPP_LANGUAGE_SERVER_DEBUG=", + "CRYPTO_DEBUG=", + "CSS_LOADER_DEBUG=", + "CSS_PARSER_DEBUG=", + "CSS_TOKENIZER_DEBUG=", + "DDS_DEBUG=", + "DHCPV4CLIENT_DEBUG=", + "DHCPV4_DEBUG=", + "DIFF_DEBUG=", + "DISASM_DUMP_DEBUG=", + "DOUBLECLICK_DEBUG=", + "DRAG_DEBUG=", + "DWARF_DEBUG=", + "DYNAMIC_LOAD_DEBUG=", + "EDITOR_DEBUG=", + "ELF_IMAGE_DEBUG=", + "EMOJI_DEBUG=", + "ESCAPE_SEQUENCE_DEBUG=", + "EVENT_DEBUG=", + "FILE_CONTENT_DEBUG=", + "FILE_WATCHER_DEBUG=", + "FILL_PATH_DEBUG=", + "GEMINI_DEBUG=", + "GENERATE_DEBUG=", + "GHASH_PROCESS_DEBUG=", + "GIF_DEBUG=", + "GLOBAL_DTORS_DEBUG=", + "GL_DEBUG=", + "GPT_DEBUG=", + "HEAP_DEBUG=", + "HEARTS_DEBUG=", + "HEX_DEBUG=", + "HIGHLIGHT_FOCUSED_FRAME_DEBUG=", + "HTML_PARSER_DEBUG=", + "HTML_SCRIPT_DEBUG=", + "HTTPJOB_DEBUG=", + "HUNKS_DEBUG=", + "ICO_DEBUG=", + "IMAGE_DECODER_DEBUG=", + "IMAGE_LOADER_DEBUG=", + "ITEM_RECTS_DEBUG=", + "JOB_DEBUG=", + "JPEG_DEBUG=", + "JS_BYTECODE_DEBUG=", + "JS_MODULE_DEBUG=", + "KEYBOARD_SHORTCUTS_DEBUG=", + "LANGUAGE_SERVER_DEBUG=", + "LEXER_DEBUG=", + "LIBWEB_CSS_ANIMATION_DEBUG=", + "LIBWEB_CSS_DEBUG=", + "LINE_EDITOR_DEBUG=", + "LOG_DEBUG=", + "LOOKUPSERVER_DEBUG=", + "LZMA_DEBUG=", + "MALLOC_DEBUG=", + "MARKDOWN_DEBUG=", + "MATROSKA_DEBUG=", + "MATROSKA_TRACE_DEBUG=", + "MBR_DEBUG=", + "MEMORY_DEBUG=", + "MENU_DEBUG=", + "MOVE_DEBUG=", + "NETWORKJOB_DEBUG=", + "NT_DEBUG=", + "OCCLUSIONS_DEBUG=", + "OPENTYPE_GPOS_DEBUG=", + "PATH_DEBUG=", + "PDF_DEBUG=", + "PLAYBACK_MANAGER_DEBUG=", + "PNG_DEBUG=", + "PORTABLE_IMAGE_LOADER_DEBUG=", + "PROMISE_DEBUG=", + "PTHREAD_DEBUG=", + "REACHABLE_DEBUG=", + "REGEX_DEBUG=", + "REQUESTSERVER_DEBUG=", + "RESIZE_DEBUG=", + "RESOURCE_DEBUG=", + "RSA_PARSE_DEBUG=", + "SERVICE_DEBUG=", + "SHARED_QUEUE_DEBUG=", + "SHELL_JOB_DEBUG=", + "SHELL_POSIX_PARSER_DEBUG=", + "SH_DEBUG=", + "SH_LANGUAGE_SERVER_DEBUG=", + "SOLITAIRE_DEBUG=", + "SPAM_DEBUG=", + "SPICE_AGENT_DEBUG=", + "SQLSERVER_DEBUG=", + "SQL_DEBUG=", + "SYNTAX_HIGHLIGHTING_DEBUG=", + "SYSCALL_1_DEBUG=", + "SYSTEMSERVER_DEBUG=", + "SYSTEM_MENU_DEBUG=", + "TERMCAP_DEBUG=", + "TERMINAL_DEBUG=", + "TEXTEDITOR_DEBUG=", + "TIME_ZONE_DEBUG=", + "TLS_DEBUG=", + "TLS_SSL_KEYLOG_DEBUG=", + "TOKENIZER_TRACE_DEBUG=", + "UCI_DEBUG=", + "UPDATE_COALESCING_DEBUG=", + "URL_PARSER_DEBUG=", + "UTF8_DEBUG=", + "VPX_DEBUG=", + "WASI_DEBUG=", + "WASM_BINPARSER_DEBUG=", + "WASI_FINE_GRAINED_DEBUG=", + "WASM_TRACE_DEBUG=", + "WASM_VALIDATOR_DEBUG=", + "WEBDRIVER_DEBUG=", + "WEBGL_CONTEXT_DEBUG=", + "WEBP_DEBUG=", + "WEBSERVER_DEBUG=", + "WEB_FETCH_DEBUG=", + "WEB_WORKER_DEBUG=", + "WINDOWMANAGER_DEBUG=", + "WORKER_THREAD_DEBUG=", + "WSMESSAGELOOP_DEBUG=", + "WSSCREEN_DEBUG=", + "XML_PARSER_DEBUG=", + ] +} diff --git a/Meta/gn/secondary/BUILD.gn b/Meta/gn/secondary/BUILD.gn new file mode 100644 index 00000000000..c7b8e6283d8 --- /dev/null +++ b/Meta/gn/secondary/BUILD.gn @@ -0,0 +1,11 @@ +import("//Meta/gn/build/toolchain/compiler.gni") + +group("default") { + deps = [ "//Userland/Libraries/LibCore" ] +} + +# 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 +} diff --git a/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn new file mode 100644 index 00000000000..9ee63dd86cb --- /dev/null +++ b/Meta/gn/secondary/Userland/Libraries/LibCore/BUILD.gn @@ -0,0 +1,142 @@ +source_set("sources") { + include_dirs = [ "//Userland/Libraries" ] + deps = [ "//AK" ] + sources = [ + "AnonymousBuffer.cpp", + "AnonymousBuffer.h", + "ArgsParser.cpp", + "ArgsParser.h", + "Command.cpp", + "Command.h", + "ConfigFile.cpp", + "ConfigFile.h", + "DateTime.cpp", + "DateTime.h", + "Debounce.h", + "DeferredInvocationContext.h", + "DirIterator.cpp", + "DirIterator.h", + "Directory.cpp", + "Directory.h", + "DirectoryEntry.cpp", + "DirectoryEntry.h", + "ElapsedTimer.cpp", + "ElapsedTimer.h", + "Event.cpp", + "Event.h", + "EventLoop.cpp", + "EventLoop.h", + "EventLoopImplementation.cpp", + "EventLoopImplementation.h", + "EventLoopImplementationUnix.cpp", + "EventLoopImplementationUnix.h", + "File.cpp", + "File.h", + "Forward.h", + "LockFile.cpp", + "LockFile.h", + "MappedFile.cpp", + "MappedFile.h", + "MimeData.cpp", + "MimeData.h", + "NetworkJob.cpp", + "NetworkJob.h", + "NetworkResponse.h", + "Notifier.cpp", + "Notifier.h", + "Object.cpp", + "Object.h", + "Process.cpp", + "Process.h", + "ProcessStatisticsReader.cpp", + "ProcessStatisticsReader.h", + "Promise.h", + "Property.cpp", + "Property.h", + "Proxy.h", + "SOCKSProxyClient.cpp", + "SOCKSProxyClient.h", + "SecretString.cpp", + "SecretString.h", + "SessionManagement.cpp", + "SessionManagement.h", + "SharedCircularQueue.h", + "Socket.cpp", + "Socket.h", + "SocketAddress.h", + "StandardPaths.cpp", + "StandardPaths.h", + "System.cpp", + "System.h", + "SystemServerTakeover.cpp", + "SystemServerTakeover.h", + "TCPServer.cpp", + "TCPServer.h", + "ThreadEventQueue.cpp", + "ThreadEventQueue.h", + "Timer.cpp", + "Timer.h", + "UDPServer.cpp", + "UDPServer.h", + "UmaskScope.h", + "Version.cpp", + "Version.h", + ] + if (current_os != "android") { + sources += [ + "Account.cpp", + "Account.h", + "FilePermissionsMask.cpp", + "FilePermissionsMask.h", + "GetPassword.cpp", + "GetPassword.h", + "Group.cpp", + "Group.h", + "LocalServer.cpp", + "LocalServer.h", + ] + } +} + +source_set("filewatcher") { + include_dirs = [ "//Userland/Libraries" ] + sources = [ "FileWatcher.h" ] + deps = [ "//AK" ] + frameworks = [] + if (current_os == "linux") { + sources += [ "FileWatcherLinux.cpp" ] + } else if (current_os == "mac") { + sources += [ "FileWatcherMacOS.mm" ] + frameworks += [ + "CoreFoundation.framework", + "CoreServices.framework", + "Foundation.framework", + ] + } else if (current_os == "serenity") { + sources += [ "FileWatcherSerenity.cpp" ] + } else { + sources += [ "FileWatcherUnimplemented.cpp" ] + } +} + +shared_library("LibCore") { + libs = [] + + if (current_os == "linux" || current_os == "android") { + libs += [ "dl" ] + } + if (current_os == "linux") { + libs += [ "rt" ] + } + + output_name = "core" + + deps = [ + ":filewatcher", + ":sources", + "//AK:sources", + "//Meta/gn/build/libs/crypt", + "//Meta/gn/build/libs/pthread", + "//Userland/Libraries/LibSystem", + ] +} diff --git a/Meta/gn/secondary/Userland/Libraries/LibCrypt/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibCrypt/BUILD.gn new file mode 100644 index 00000000000..0a99970a3cd --- /dev/null +++ b/Meta/gn/secondary/Userland/Libraries/LibCrypt/BUILD.gn @@ -0,0 +1,36 @@ +group("LibCrypt") { + deps = [] + libs = [] + if (current_os == "serenity") { + deps += [ + ":crypt_shared", + ":crypt_static", + ] + } else if (current_os == "linux") { + libs += [ "crypt" ] + } +} + +if (current_os == "serenity") { + # FIXME: Special handling for LibCrypo/Hash/SHA2.cpp + shared_library("crypt_shared") { + output_name = "crypt" + cflags_cc = [ "-nostdlib" ] + ldflags = [ + "-nostdlib", + "-static-libstdc++", + ] + sources = [ + "crypt.cpp", + "crypt.h", + ] + } + + static_library("crypt_static") { + output_name = "crypt" + sources = [ + "crypt.cpp", + "crypt.h", + ] + } +} diff --git a/Meta/gn/secondary/Userland/Libraries/LibSystem/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibSystem/BUILD.gn new file mode 100644 index 00000000000..ed8d7f452fb --- /dev/null +++ b/Meta/gn/secondary/Userland/Libraries/LibSystem/BUILD.gn @@ -0,0 +1,32 @@ +group("LibSystem") { + deps = [] + if (current_os == "serenity") { + deps += [ + ":system_shared", + ":system_static", + ] + } +} + +if (current_os == "serenity") { + shared_library("system_shared") { + output_name = "system" + cflags_cc = [ "-nostdlib" ] + ldflags = [ + "-nostdlib", + "-static-libstdc++", + ] + sources = [ + "syscall.cpp", + "syscall.h", + ] + } + + static_library("system_static") { + output_name = "system" + sources = [ + "syscall.cpp", + "syscall.h", + ] + } +}