Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gn for openSUSE:Factory checked in at 2025-06-27 23:01:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gn (Old) and /work/SRC/openSUSE:Factory/.gn.new.7067 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gn" Fri Jun 27 23:01:16 2025 rev:20 rq:1288703 version:0.20250520 Changes: -------- --- /work/SRC/openSUSE:Factory/gn/gn.changes 2025-03-13 22:05:23.944523901 +0100 +++ /work/SRC/openSUSE:Factory/.gn.new.7067/gn.changes 2025-06-27 23:02:40.008622607 +0200 @@ -1,0 +2,20 @@ +Tue May 20 16:30:31 UTC 2025 - Ruediger Oertel <r...@suse.com> + +- Update to version 0.20250520: + * Add `--filter-with-data` flag for `gn gen --ide=json` + * Handle --ide=vs2019 switch + * Handle hpp11 file extension. + * Fix `gn help --root-pattern` + * Build non-linkable deps async with Ninja's validaitons + * Generate compile_commands.json as part of build/gen.py + * apply the latest clang-format + * Add a test for source_set with modulemap + * Write .gitignore file to build directory + * Add more on how args are processed to "help execution". + * Make `gn_version` available in the dotfile. + * Tweak `help execution` wording after c0a46c5. + * Attempt to improve the documentation for "help execution". + * zos: build with -m64 and ignore unknown-pragmas + * Unit test parser/tokenizer against double minus + +------------------------------------------------------------------- Old: ---- gn-0.20250306.obscpio New: ---- _scmsync.obsinfo build.specials.obscpio gn-0.20250520.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gn.spec ++++++ --- /var/tmp/diff_new_pack.0znNpI/_old 2025-06-27 23:02:40.840656898 +0200 +++ /var/tmp/diff_new_pack.0znNpI/_new 2025-06-27 23:02:40.844657063 +0200 @@ -17,7 +17,7 @@ Name: gn -Version: 0.20250306 +Version: 0.20250520 Release: 0 Summary: A meta-build system that generates build files for Ninja License: BSD-3-Clause ++++++ _scmsync.obsinfo ++++++ mtime: 1747758745 commit: 9f8ced34396e82f73fc92bbb9e49c9117ac15cf6b3509d1325c37b7fbac65875 url: https://src.opensuse.org/chromium/gn.git revision: 9f8ced34396e82f73fc92bbb9e49c9117ac15cf6b3509d1325c37b7fbac65875 projectscmsync: https://src.opensuse.org/chromium/_ObsPrj.git ++++++ _service ++++++ --- /var/tmp/diff_new_pack.0znNpI/_old 2025-06-27 23:02:40.888658876 +0200 +++ /var/tmp/diff_new_pack.0znNpI/_new 2025-06-27 23:02:40.892659041 +0200 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gn.googlesource.com/gn.git</param> - <param name="revision">7a8aa3a08a13521336853a28c46537ec04338a2d</param> + <param name="revision">cad8f67e2dd0cea00bbe4566efe2fdf4c1821563</param> <param name="versionformat">0.%cd</param> <param name="changesgenerate">enable</param> </service> ++++++ gn-0.20250306.obscpio -> gn-0.20250520.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/build/gen.py new/gn-0.20250520/build/gen.py --- old/gn-0.20250306/build/gen.py 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/build/gen.py 2025-05-20 17:50:44.000000000 +0200 @@ -206,9 +206,13 @@ default='../third_party/zoslib', dest='zoslib_dir', help=('Specify the path of ZOSLIB directory, to link ' + - 'with <ZOSLIB_DIR>/install/lib/libzoslib.a, and ' + - 'add -I<ZOSLIB_DIR>/install/include to the compile ' + + 'with <ZOSLIB_DIR>/lib/libzoslib.a, and ' + + 'add -I<ZOSLIB_DIR>/include to the compile ' + 'commands. See README.md for details.')) + args_list.add('--generate-compilation-database', + action='store_true', + help=('Generate compile_commands.json with ' + + '`ninja -t compdb`.')) args_list.add_to_parser(parser) options = parser.parse_args(argv) @@ -383,12 +387,17 @@ f.write(ninja_template) f.write('\n'.join(ninja_lines)) + build_dir = os.path.dirname(path) 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') + build_dir) + ' ' + + os.path.relpath(template_filename, build_dir) + '\n') + if options.generate_compilation_database: + with open(os.path.join(REPO_ROOT, 'compile_commands.json'), 'w') as f: + subprocess.run( + ['ninja', '-C', build_dir, '-t', 'compdb'], stdout=f, check=True) def WriteGNNinja(path, platform, host, options, args_list): if platform.is_msvc(): @@ -417,7 +426,7 @@ '.', ] if platform.is_zos(): - include_dirs += [ options.zoslib_dir + '/install/include' ] + include_dirs += [ options.zoslib_dir + '/include' ] libs = [] @@ -531,7 +540,10 @@ cflags.append('-fPIC') cflags.extend(['-D_BSD_SOURCE']) elif platform.is_zos(): + cflags.append('-m64') + ldflags.append('-m64') cflags.append('-fzos-le-char-mode=ascii') + cflags.append('-Wno-unknown-pragmas') cflags.append('-Wno-unused-function') cflags.append('-D_OPEN_SYS_FILE_EXT') cflags.append('-DPATH_MAX=1024') @@ -907,7 +919,7 @@ ]) if platform.is_zos(): - libs.extend([ options.zoslib_dir + '/install/lib/libzoslib.a' ]) + libs.extend([ options.zoslib_dir + '/lib/libzoslib.a' ]) if platform.is_windows(): static_libraries['base']['sources'].extend([ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/docs/reference.md new/gn-0.20250520/docs/reference.md --- old/gn-0.20250306/docs/reference.md 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/docs/reference.md 2025-05-20 17:50:44.000000000 +0200 @@ -919,6 +919,10 @@ --json-ide-script-args=<argument> Optional second argument that will be passed to executed script. + + --filter-with-data + Additionally follows data deps when filtering. Without this flag, only + public and private linked deps will be followed. Only used with --filters. ``` #### **Ninja Outputs** @@ -4557,7 +4561,10 @@ ### <a name="var_gn_version"></a>**gn_version**: [number] The version of gn. [Back to Top](#gn-reference) ``` - Corresponds to the number printed by `gn --version`. + Corresponds to the number printed by `gn --version`. This variable is + only variable available in the dotfile (all the rest are missing + because the dotfile has to be parsed before args.gn or anything else + is processed). ``` #### **Example** @@ -7103,6 +7110,7 @@ ``` First, system default arguments are set based on the current system. The built-in arguments are: + - gn_version - host_cpu - host_os - current_cpu @@ -7111,7 +7119,8 @@ - target_os Next, project-specific overrides are applied. These are specified inside - the default_args variable of //.gn. See "gn help dotfile" for more. + the default_args variable of //.gn. See "gn help dotfile" for more. Note + that during processing of the dotfile itself, only `gn_version` is defined. If specified, arguments from the --args command line flag are used. If that flag is not specified, args from previous builds in the build directory will @@ -7170,6 +7179,10 @@ --dotfile: gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn + + The system variable `gn_version` is available in the dotfile, but none of + the other variables are, because the dotfile is processed before args.gn + or anything else is processed. ``` #### **Variables** @@ -7362,18 +7375,52 @@ 2. Execute the build config file identified by .gn to set up the global variables and default toolchain name. Any arguments, variables, defaults, etc. set up in this file will be visible to all files in the build. + Any values set in the `default_args` scope will be merged into + subsequent `declare_args()` scopes and override the default values. - 3. Load the //BUILD.gn (in the source root directory). + 3. Process the --args command line option or load the arguments from + the args.gn file in the build directory. These values will be merged + into any subsequent declare_args() scope (after the `default_args` + are merged in) to override the default values. See `help buildargs` + for more on how args are handled. + + 4. Load the BUILDCONFIG.gn file and create a dedicated scope for it. + + 5. Load the //BUILD.gn (in the source root directory). The BUILD.gn + file is executed in a scope whose parent scope is the BUILDCONFIG.gn + file, i.e., only the definitions in the BUILDCONFIG.gn file exist. + + 5. If the BUILD.gn file imports other files, each of those other + files is executed in a separate scope whose parent is the BUILDCONFIG.gn + file, i.e., no definitions from the importing BUILD.gn file are + available. When the imported file has been fully processed, its scope + is merged into the BUILD.gn file's scope. If there is a conflict + (both the BUILD.gn file and the imported file define some variable + or rule with the same name but different values), a runtime error + will be thrown. See "gn help import" for more on this. - 4. Recursively evaluate rules and load BUILD.gn in other directories as + 6. Recursively evaluate rules and load BUILD.gn in other directories as necessary to resolve dependencies. If a BUILD file isn't found in the specified location, GN will look in the corresponding location inside the secondary_source defined in the dotfile (see "gn help dotfile"). + Each BUILD.gn file will again be executed in a new scope whose only + parent is BUILDCONFIG.gn's scope. + + 7. If a target is referenced using an alternate toolchain, then - 5. When a target's dependencies are resolved, write out the `.ninja` + 1. The toolchain file is loaded in a scope whose parent is the + BUILDCONFIG.gn file. + 2. The BUILDCONFIG.gn file is re-loaded and re-parsed into a new + scope, with any `toolchain_args` merged into the defaults. See + `help buildargs` for more on how args are handled. + 3. The BUILD.gn containing the target is then parsed as in step 5, + only we use the scope from step 7.2 instead of the default + BUILDCONFIG.gn scope. + + 8. When a target's dependencies are resolved, write out the `.ninja` file to disk. - 6. When all targets are resolved, write out the root build.ninja file. + 9. When all targets are resolved, write out the root build.ninja file. Note that the BUILD.gn file name may be modulated by .gn arguments such as build_file_extension. @@ -7395,9 +7442,14 @@ } There is also a generic "target" function for programmatically defined types - (see "gn help target"). You can define new types using templates (see "gn - help template"). A template defines some custom code that expands to one or - more other targets. + (see "gn help target"). + + You can define new types using templates (see "gn help template"). A template + defines some custom code that expands to one or more other targets. When a + template is invoked, it is executed in the scope of the file that defined the + template (as described above). To access values from the caller's scope, you + must use the `invoker` variable (see "gn help template" for more on the + invoker). Before executing the code inside the target's { }, the target defaults are applied (see "gn help set_defaults"). It will inject implicit variable @@ -8344,6 +8396,7 @@ * --nocolor: Force non-colored output. * -q: Quiet mode. Don't print output on success. * --root: Explicitly specify source root. + * --root-pattern: Add root pattern override. * --root-target: Override the root target. * --runtime-deps-list-file: Save runtime dependencies for targets in file. * --script-executable: Set the executable used to execute scripts. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/base/numerics/checked_math.h new/gn-0.20250520/src/base/numerics/checked_math.h --- old/gn-0.20250306/src/base/numerics/checked_math.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/base/numerics/checked_math.h 2025-05-20 17:50:44.000000000 +0200 @@ -66,8 +66,7 @@ #elif defined(_MSC_VER) _Check_return_ #endif - constexpr bool - AssignIfValid(Dst* result) const { + constexpr bool AssignIfValid(Dst* result) const { return BASE_NUMERICS_LIKELY(IsValid<Dst>()) ? ((*result = static_cast<Dst>(state_.value())), true) : false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/base/numerics/checked_math_impl.h new/gn-0.20250520/src/base/numerics/checked_math_impl.h --- old/gn-0.20250306/src/base/numerics/checked_math_impl.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/base/numerics/checked_math_impl.h 2025-05-20 17:50:44.000000000 +0200 @@ -417,20 +417,20 @@ // This is just boilerplate that wraps the standard floating point arithmetic. // A macro isn't the nicest solution, but it beats rewriting these repeatedly. -#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ - template <typename T, typename U> \ - struct Checked##NAME##Op< \ - T, U, \ - typename std::enable_if<std::is_floating_point<T>::value || \ - std::is_floating_point<U>::value>::type> { \ - using result_type = typename MaxExponentPromotion<T, U>::type; \ - template <typename V> \ - static constexpr bool Do(T x, U y, V* result) { \ - using Promotion = typename MaxExponentPromotion<T, U>::type; \ - Promotion presult = x OP y; \ - *result = static_cast<V>(presult); \ - return IsValueInRangeForNumericType<V>(presult); \ - } \ +#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ + template <typename T, typename U> \ + struct Checked##NAME## \ + Op<T, U, \ + typename std::enable_if<std::is_floating_point<T>::value || \ + std::is_floating_point<U>::value>::type> { \ + using result_type = typename MaxExponentPromotion<T, U>::type; \ + template <typename V> \ + static constexpr bool Do(T x, U y, V* result) { \ + using Promotion = typename MaxExponentPromotion<T, U>::type; \ + Promotion presult = x OP y; \ + *result = static_cast<V>(presult); \ + return IsValueInRangeForNumericType<V>(presult); \ + } \ }; BASE_FLOAT_ARITHMETIC_OPS(Add, +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/base/numerics/clamped_math_impl.h new/gn-0.20250520/src/base/numerics/clamped_math_impl.h --- old/gn-0.20250306/src/base/numerics/clamped_math_impl.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/base/numerics/clamped_math_impl.h 2025-05-20 17:50:44.000000000 +0200 @@ -315,17 +315,17 @@ // This is just boilerplate that wraps the standard floating point arithmetic. // A macro isn't the nicest solution, but it beats rewriting these repeatedly. -#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ - template <typename T, typename U> \ - struct Clamped##NAME##Op< \ - T, U, \ - typename std::enable_if<std::is_floating_point<T>::value || \ - std::is_floating_point<U>::value>::type> { \ - using result_type = typename MaxExponentPromotion<T, U>::type; \ - template <typename V = result_type> \ - static constexpr V Do(T x, U y) { \ - return saturated_cast<V>(x OP y); \ - } \ +#define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ + template <typename T, typename U> \ + struct Clamped##NAME## \ + Op<T, U, \ + typename std::enable_if<std::is_floating_point<T>::value || \ + std::is_floating_point<U>::value>::type> { \ + using result_type = typename MaxExponentPromotion<T, U>::type; \ + template <typename V = result_type> \ + static constexpr V Do(T x, U y) { \ + return saturated_cast<V>(x OP y); \ + } \ }; BASE_FLOAT_ARITHMETIC_OPS(Add, +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/args.cc new/gn-0.20250520/src/gn/args.cc --- old/gn-0.20250306/src/gn/args.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/args.cc 2025-05-20 17:50:44.000000000 +0200 @@ -21,6 +21,7 @@ First, system default arguments are set based on the current system. The built-in arguments are: + - gn_version - host_cpu - host_os - current_cpu @@ -29,7 +30,8 @@ - target_os Next, project-specific overrides are applied. These are specified inside - the default_args variable of //.gn. See "gn help dotfile" for more. + the default_args variable of //.gn. See "gn help dotfile" for more. Note + that during processing of the dotfile itself, only `gn_version` is defined. If specified, arguments from the --args command line flag are used. If that flag is not specified, args from previous builds in the build directory will diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/build_settings.h new/gn-0.20250520/src/gn/build_settings.h --- old/gn-0.20250306/src/gn/build_settings.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/build_settings.h 2025-05-20 17:50:44.000000000 +0200 @@ -77,6 +77,16 @@ no_stamp_files_ = no_stamp_files; } + // The 'async_non_linkable_deps' boolean flag can be set to generate Ninja + // files that build non-linkable deps asynchronously using Ninja validations + // instead of order-only dependencies. + // This speeds up build by increasing the parallerism of the build graph. + // This requires Ninja 1.11 for the `validations` feature. + bool async_non_linkable_deps() const { return async_non_linkable_deps_; } + void set_async_non_linkable_deps(bool async_non_linkable_deps) { + async_non_linkable_deps_ = async_non_linkable_deps; + } + const SourceFile& build_config_file() const { return build_config_file_; } void set_build_config_file(const SourceFile& f) { build_config_file_ = f; } @@ -153,6 +163,7 @@ // See 40045b9 for the reason behind using 1.7.2 as the default version. Version ninja_required_version_{1, 7, 2}; bool no_stamp_files_ = true; + bool async_non_linkable_deps_ = false; SourceFile build_config_file_; SourceFile arg_file_template_path_; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/command_gen.cc new/gn-0.20250520/src/gn/command_gen.cc --- old/gn-0.20250306/src/gn/command_gen.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/command_gen.cc 2025-05-20 17:50:44.000000000 +0200 @@ -9,6 +9,7 @@ #include <unordered_map> #include "base/command_line.h" +#include "base/files/file_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/timer/elapsed_timer.h" @@ -75,6 +76,7 @@ const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args"; const char kSwitchExportCompileCommands[] = "export-compile-commands"; const char kSwitchExportRustProject[] = "export-rust-project"; +const char kSwitchFilterWithData[] = "filter-with-data"; // A map type used to implement --ide=ninja_outputs using NinjaOutputsMap = NinjaOutputsWriter::MapType; @@ -264,6 +266,8 @@ version = VisualStudioWriter::Version::Vs2015; else if (ide == kSwitchIdeValueVs2017) version = VisualStudioWriter::Version::Vs2017; + else if (ide == kSwitchIdeValueVs2019) + version = VisualStudioWriter::Version::Vs2019; else if (ide == kSwitchIdeValueVs2022) version = VisualStudioWriter::Version::Vs2022; @@ -356,10 +360,11 @@ std::string exec_script_extra_args = command_line->GetSwitchValueString(kSwitchJsonIdeScriptArgs); std::string filters = command_line->GetSwitchValueString(kSwitchFilters); + bool filter_with_data = command_line->HasSwitch(kSwitchFilterWithData); bool res = JSONProjectWriter::RunAndWriteFiles( build_settings, builder, file_name, exec_script, exec_script_extra_args, - filters, quiet, err); + filters, filter_with_data, quiet, err); if (res && !quiet) { OutputString("Generating JSON projects took " + base::Int64ToString(timer.Elapsed().InMilliseconds()) + @@ -490,6 +495,19 @@ return true; } +bool WriteIgnoreFile(Setup& setup, Err* err) { + // Write a .gitignore file that causes the build directory to be ignored. + base::FilePath output_path = + setup.build_settings() + .GetFullPath(setup.build_settings().build_dir()) + .Append(FILE_PATH_LITERAL(".gitignore")); + + if (base::PathExists(output_path)) + return true; + + return WriteFile(output_path, "# Created by GN\n*\n", err); +} + } // namespace const char kGen[] = "gen"; @@ -661,6 +679,10 @@ --json-ide-script-args=<argument> Optional second argument that will be passed to executed script. + --filter-with-data + Additionally follows data deps when filtering. Without this flag, only + public and private linked deps will be followed. Only used with --filters. + Ninja Outputs The --ninja-outputs-file=<FILE> option dumps a JSON file that maps GN labels @@ -870,6 +892,11 @@ err.PrintToStdout(); return 1; } + + if (!WriteIgnoreFile(*setup, &err)) { + err.PrintToStdout(); + return 1; + } TickDelta elapsed_time = timer.Elapsed(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/json_project_writer.cc new/gn-0.20250520/src/gn/json_project_writer.cc --- old/gn-0.20250306/src/gn/json_project_writer.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/json_project_writer.cc 2025-05-20 17:50:44.000000000 +0200 @@ -40,21 +40,26 @@ namespace { -void AddTargetDependencies(const Target* target, TargetSet* deps) { - for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) { +void AddTargetDependencies(const Target* target, TargetSet* deps, + Target::DepsIterationType iteration_type) { + for (const auto& pair : target->GetDeps(iteration_type)) { if (deps->add(pair.ptr)) { - AddTargetDependencies(pair.ptr, deps); + AddTargetDependencies(pair.ptr, deps, iteration_type); } } } +} // namespace + // Filters targets according to filter string; Will also recursively // add dependent targets. -bool FilterTargets(const BuildSettings* build_settings, - std::vector<const Target*>& all_targets, - std::vector<const Target*>* targets, - const std::string& dir_filter_string, - Err* err) { +bool JSONProjectWriter::FilterTargets( + const BuildSettings* build_settings, + std::vector<const Target*>& all_targets, + std::vector<const Target*>* targets, + const std::string& dir_filter_string, + bool filter_with_data_deps, + Err* err) { if (dir_filter_string.empty()) { *targets = all_targets; } else { @@ -67,8 +72,10 @@ commands::FilterTargetsByPatterns(all_targets, filters, targets); TargetSet target_set(targets->begin(), targets->end()); + Target::DepsIterationType iteration_type = + filter_with_data_deps ? Target::DEPS_ALL : Target::DEPS_LINKED; for (const auto* target : *targets) - AddTargetDependencies(target, &target_set); + AddTargetDependencies(target, &target_set, iteration_type); targets->assign(target_set.begin(), target_set.end()); } @@ -83,8 +90,6 @@ return true; } -} // namespace - bool JSONProjectWriter::RunAndWriteFiles( const BuildSettings* build_settings, const Builder& builder, @@ -92,6 +97,7 @@ const std::string& exec_script, const std::string& exec_script_extra_args, const std::string& dir_filter_string, + bool filter_with_data_deps, bool quiet, Err* err) { SourceFile output_file = build_settings->build_dir().ResolveRelativeFile( @@ -104,8 +110,8 @@ std::vector<const Target*> all_targets = builder.GetAllResolvedTargets(); std::vector<const Target*> targets; - if (!FilterTargets(build_settings, all_targets, &targets, dir_filter_string, - err)) { + if (!JSONProjectWriter::FilterTargets(build_settings, all_targets, &targets, dir_filter_string, + filter_with_data_deps, err)) { return false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/json_project_writer.h new/gn-0.20250520/src/gn/json_project_writer.h --- old/gn-0.20250306/src/gn/json_project_writer.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/json_project_writer.h 2025-05-20 17:50:44.000000000 +0200 @@ -20,6 +20,7 @@ const std::string& exec_script, const std::string& exec_script_extra_args, const std::string& dir_filter_string, + bool filter_with_data_deps, bool quiet, Err* err); @@ -27,6 +28,14 @@ FRIEND_TEST_ALL_PREFIXES(JSONWriter, ActionWithResponseFile); FRIEND_TEST_ALL_PREFIXES(JSONWriter, ForEachWithResponseFile); FRIEND_TEST_ALL_PREFIXES(JSONWriter, RustTarget); + FRIEND_TEST_ALL_PREFIXES(JSONWriter, FilterTargetsWithDataDeps); + + static bool FilterTargets(const BuildSettings* build_settings, + std::vector<const Target*>& all_targets, + std::vector<const Target*>* targets, + const std::string& dir_filter_string, + bool filter_with_data_deps, + Err* err); static StringOutputBuffer GenerateJSON( const BuildSettings* build_settings, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/json_project_writer_unittest.cc new/gn-0.20250520/src/gn/json_project_writer_unittest.cc --- old/gn-0.20250306/src/gn/json_project_writer_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/json_project_writer_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -780,3 +780,58 @@ )_"; EXPECT_EQ(expected_json, out) << out; } + +TEST_F(JSONWriter, FilterTargetsWithDataDeps) { + Err err; + TestWithScope setup; + + // Create targets :a, :b, :c + Target target_a(setup.settings(), Label(SourceDir("//foo/"), "a")); + target_a.set_output_type(Target::STATIC_LIBRARY); + target_a.visibility().SetPublic(); + + Target target_b(setup.settings(), Label(SourceDir("//foo/"), "b")); + target_b.set_output_type(Target::STATIC_LIBRARY); + target_b.visibility().SetPublic(); + + Target target_c(setup.settings(), Label(SourceDir("//foo/"), "c")); + target_c.set_output_type(Target::STATIC_LIBRARY); + target_c.visibility().SetPublic(); + + // :a depends on :b, and data_depends on :c + target_a.private_deps().push_back(LabelTargetPair(&target_b)); + target_a.data_deps().push_back(LabelTargetPair(&target_c)); + + target_a.SetToolchain(setup.toolchain()); + target_b.SetToolchain(setup.toolchain()); + target_c.SetToolchain(setup.toolchain()); + + ASSERT_TRUE(target_a.OnResolved(&err)); + ASSERT_TRUE(target_b.OnResolved(&err)); + ASSERT_TRUE(target_c.OnResolved(&err)); + + std::vector<const Target*> all_targets = {&target_a, &target_b, &target_c}; + std::vector<const Target*> filtered; + + // Only DEPS_LINKED (should include :a and :b, but not :c) + ASSERT_TRUE(JSONProjectWriter::FilterTargets( + setup.build_settings(), all_targets, &filtered, + "//foo:a", /*filter_with_data_deps=*/false, &err)); + std::set<Label> labels_linked; + for (const Target* t : filtered) + labels_linked.insert(t->label()); + EXPECT_GT(labels_linked.count(Label(SourceDir("//foo/"), "a")), 0u); + EXPECT_GT(labels_linked.count(Label(SourceDir("//foo/"), "b")), 0u); + EXPECT_EQ(labels_linked.count(Label(SourceDir("//foo/"), "c")), 0u); + + // DEPS_ALL (should include :a, :b, :c) + ASSERT_TRUE(JSONProjectWriter::FilterTargets( + setup.build_settings(), all_targets, &filtered, + "//foo:a", /*filter_with_data_deps=*/true, &err)); + std::set<Label> labels_all; + for (const Target* t : filtered) + labels_all.insert(t->label()); + EXPECT_GT(labels_all.count(Label(SourceDir("//foo/"), "a")), 0u); + EXPECT_GT(labels_all.count(Label(SourceDir("//foo/"), "b")), 0u); + EXPECT_GT(labels_all.count(Label(SourceDir("//foo/"), "c")), 0u); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/ninja_c_binary_target_writer.cc new/gn-0.20250520/src/gn/ninja_c_binary_target_writer.cc --- old/gn-0.20250306/src/gn/ninja_c_binary_target_writer.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/ninja_c_binary_target_writer.cc 2025-05-20 17:50:44.000000000 +0200 @@ -679,6 +679,8 @@ } // Append data dependencies as order-only dependencies. + // If `async_non_linkable_deps` flag is set, it uses + // validations instead. // // This will include data dependencies and input dependencies (like when // this target depends on an action). Having the data dependencies in this @@ -691,7 +693,11 @@ // on the sources, there is already an implicit order-only dependency. // However, it's extra work to separate these out and there's no disadvantage // to listing them again. - WriteOrderOnlyDependencies(classified_deps.non_linkable_deps); + if (settings_->build_settings()->async_non_linkable_deps()) { + WriteValidations(classified_deps.non_linkable_deps); + } else { + WriteOrderOnlyDependencies(classified_deps.non_linkable_deps); + } // End of the link "build" line. out_ << std::endl; @@ -760,15 +766,32 @@ void NinjaCBinaryTargetWriter::WriteOrderOnlyDependencies( const UniqueVector<const Target*>& non_linkable_deps) { - if (!non_linkable_deps.empty()) { - out_ << " ||"; + if (non_linkable_deps.empty()) + return; + + out_ << " ||"; + + // Non-linkable targets. + for (auto* non_linkable_dep : non_linkable_deps) { + if (non_linkable_dep->has_dependency_output()) { + out_ << " "; + path_output_.WriteFile(out_, non_linkable_dep->dependency_output()); + } + } +} + +void NinjaCBinaryTargetWriter::WriteValidations( + const UniqueVector<const Target*>& non_linkable_deps) { + if (non_linkable_deps.empty()) + return; + + out_ << " |@"; - // Non-linkable targets. - for (auto* non_linkable_dep : non_linkable_deps) { - if (non_linkable_dep->has_dependency_output()) { - out_ << " "; - path_output_.WriteFile(out_, non_linkable_dep->dependency_output()); - } + // Non-linkable targets. + for (auto* non_linkable_dep : non_linkable_deps) { + if (non_linkable_dep->has_dependency_output()) { + out_ << " "; + path_output_.WriteFile(out_, non_linkable_dep->dependency_output()); } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/ninja_c_binary_target_writer.h new/gn-0.20250520/src/gn/ninja_c_binary_target_writer.h --- old/gn-0.20250306/src/gn/ninja_c_binary_target_writer.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/ninja_c_binary_target_writer.h 2025-05-20 17:50:44.000000000 +0200 @@ -103,6 +103,14 @@ void WriteOrderOnlyDependencies( const UniqueVector<const Target*>& non_linkable_deps); + // Writes the validations for the link or stamp line. This is + // the "|@" and everything following it on the ninja line. + // + // The validations are the non-linkable deps passed in as an argument, plus + // the data file dependencies in the target. + void WriteValidations( + const UniqueVector<const Target*>& non_linkable_deps); + // Checks for duplicates in the given list of output files. If any duplicates // are found, throws an error and return false. bool CheckForDuplicateObjectFiles(const std::vector<OutputFile>& files) const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/ninja_c_binary_target_writer_unittest.cc new/gn-0.20250520/src/gn/ninja_c_binary_target_writer_unittest.cc --- old/gn-0.20250306/src/gn/ninja_c_binary_target_writer_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/ninja_c_binary_target_writer_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -2303,6 +2303,44 @@ EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; } +TEST_F(NinjaCBinaryTargetWriterTest, ModuleMapInSourceSet) { + TestWithScope setup; + Err err; + + TestTarget target(setup, "//foo:bar", Target::SOURCE_SET); + target.sources().push_back(SourceFile("//foo/bar.cc")); + target.sources().push_back(SourceFile("//foo/bar.modulemap")); + target.source_types_used().Set(SourceFile::SOURCE_CPP); + target.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); + ASSERT_TRUE(target.OnResolved(&err)); + + std::ostringstream out; + NinjaCBinaryTargetWriter writer(&target, out); + writer.Run(); + + const char expected[] = + "defines =\n" + "include_dirs =\n" + "cflags =\n" + "cflags_cc =\n" + "root_out_dir = .\n" + "target_gen_dir = gen/foo\n" + "target_out_dir = obj/foo\n" + "target_output_name = bar\n" + "\n" + "build obj/foo/bar.bar.o: cxx ../../foo/bar.cc | " + "obj/foo/bar.bar.pcm\n" + " source_file_part = bar.cc\n" + " source_name_part = bar\n" + "build obj/foo/bar.bar.pcm: cxx_module ../../foo/bar.modulemap\n" + " source_file_part = bar.modulemap\n" + " source_name_part = bar\n" + "\n" + "build phony/foo/bar: phony obj/foo/bar.bar.o\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; +} + // Test linking of targets containing Swift modules. TEST_F(NinjaCBinaryTargetWriterTest, SwiftModule) { Err err; @@ -2808,3 +2846,51 @@ std::string out_str = out.str(); EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; } + +TEST_F(NinjaCBinaryTargetWriterTest, AsyncNonLinkableDeps) { + Err err; + TestWithScope setup; + BuildSettings* settings = setup.build_settings(); + settings->set_async_non_linkable_deps(true); + + Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep")); + datadep.set_output_type(Target::ACTION); + datadep.visibility().SetPublic(); + datadep.SetToolchain(setup.toolchain()); + ASSERT_TRUE(datadep.OnResolved(&err)); + + Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); + target.sources().push_back(SourceFile("//foo/source.cc")); + target.set_output_type(Target::EXECUTABLE); + target.visibility().SetPublic(); + target.SetToolchain(setup.toolchain()); + target.data_deps().push_back(LabelTargetPair(&datadep)); + ASSERT_TRUE(target.OnResolved(&err)); + + std::ostringstream out; + NinjaBinaryTargetWriter writer(&target, out); + writer.Run(); + + const char expected[] = + "defines =\n" + "include_dirs =\n" + "root_out_dir = .\n" + "target_gen_dir = gen/foo\n" + "target_out_dir = obj/foo\n" + "target_output_name = bar\n" + "\n" + "build obj/foo/bar.source.o: cxx ../../foo/source.cc\n" + " source_file_part = source.cc\n" + " source_name_part = source\n" + "\n" + "build ./bar: link obj/foo/bar.source.o |@ phony/foo/datadep\n" + " ldflags =\n" + " libs =\n" + " frameworks =\n" + " swiftmodules =\n" + " output_extension =\n" + " output_dir =\n"; + + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/parser_unittest.cc new/gn-0.20250520/src/gn/parser_unittest.cc --- old/gn-0.20250306/src/gn/parser_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/parser_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -145,6 +145,18 @@ DoExpressionErrorTest("(a +", 1, 4); } +TEST(Parser, DoubleMinus) { + const char* input = "1--1\n"; + const char* expected = + "BINARY(-)\n" + " LITERAL(1)\n" + " LITERAL(-1)\n"; + DoExpressionPrintTest(input, expected); + DoExpressionErrorTest("1-- 1", 1, 3); + DoExpressionErrorTest("1 -- 1", 1, 4); + DoExpressionErrorTest("1 - - 1", 1, 5); +} + TEST(Parser, OrderOfOperationsLeftAssociative) { const char* input = "5 - 1 - 2\n"; const char* expected = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/scope_per_file_provider.cc new/gn-0.20250520/src/gn/scope_per_file_provider.cc --- old/gn-0.20250306/src/gn/scope_per_file_provider.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/scope_per_file_provider.cc 2025-05-20 17:50:44.000000000 +0200 @@ -14,19 +14,28 @@ #include "last_commit_position.h" -ScopePerFileProvider::ScopePerFileProvider(Scope* scope, bool allow_target_vars) - : ProgrammaticProvider(scope), allow_target_vars_(allow_target_vars) {} +ScopePerFileProvider::ScopePerFileProvider(Scope* scope, + bool allow_target_vars, + bool dotfile_scope) + : ProgrammaticProvider(scope), + allow_target_vars_(allow_target_vars), + dotfile_scope_(dotfile_scope) {} ScopePerFileProvider::~ScopePerFileProvider() = default; const Value* ScopePerFileProvider::GetProgrammaticValue( std::string_view ident) { + if (ident == variables::kGnVersion) + return GetGnVersion(); + + // In the dotfile scope, gn_version is the only thing defined. + if (dotfile_scope_) + return nullptr; + if (ident == variables::kCurrentToolchain) return GetCurrentToolchain(); if (ident == variables::kDefaultToolchain) return GetDefaultToolchain(); - if (ident == variables::kGnVersion) - return GetGnVersion(); if (ident == variables::kPythonPath) return GetPythonPath(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/scope_per_file_provider.h new/gn-0.20250520/src/gn/scope_per_file_provider.h --- old/gn-0.20250306/src/gn/scope_per_file_provider.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/scope_per_file_provider.h 2025-05-20 17:50:44.000000000 +0200 @@ -16,8 +16,12 @@ public: // allow_target_vars allows the target-related variables to get resolved. // When allow_target_vars is unset, the target-related values will be - // undefined to GN script. - ScopePerFileProvider(Scope* scope, bool allow_target_vars); + // undefined to GN script. When dotfile_scope is set, only the values + // safe to reference in a dotfile will be resolved. At the moment that + // is just gn_version. + ScopePerFileProvider(Scope* scope, + bool allow_target_vars, + bool dotfile_scope = false); ~ScopePerFileProvider() override; // ProgrammaticProvider implementation. @@ -35,6 +39,7 @@ const Value* GetTargetOutDir(); bool allow_target_vars_; + bool dotfile_scope_; // All values are lazily created. std::unique_ptr<Value> current_toolchain_; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/scope_per_file_provider_unittest.cc new/gn-0.20250520/src/gn/scope_per_file_provider_unittest.cc --- old/gn-0.20250306/src/gn/scope_per_file_provider_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/scope_per_file_provider_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -55,4 +55,13 @@ EXPECT_EQ("//out/Debug/tc/gen/source", GPV(variables::kTargetGenDir)); EXPECT_EQ("//out/Debug/tc/obj/source", GPV(variables::kTargetOutDir)); } + + // Test just the dotfile scope. + { + Scope scope(test.settings()); + ScopePerFileProvider provider(&scope, false, true); + EXPECT_GE(provider.GetProgrammaticValue(variables::kGnVersion)->int_value(), + 0); + EXPECT_EQ(nullptr, provider.GetProgrammaticValue(variables::kRootBuildDir)); + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/setup.cc new/gn-0.20250520/src/gn/setup.cc --- old/gn-0.20250306/src/gn/setup.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/setup.cc 2025-05-20 17:50:44.000000000 +0200 @@ -59,6 +59,10 @@ gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn + The system variable `gn_version` is available in the dotfile, but none of + the other variables are, because the dotfile is processed before args.gn + or anything else is processed. + Variables arg_file_template [optional] @@ -403,6 +407,9 @@ dotfile_scope_(&dotfile_settings_) { dotfile_settings_.set_toolchain_label(Label()); + dotfile_provider_ = + std::make_unique<ScopePerFileProvider>(&dotfile_scope_, false, true); + build_settings_.set_item_defined_callback( [task_runner = scheduler_.task_runner(), builder = &builder_](std::unique_ptr<Item> item) { @@ -1179,5 +1186,15 @@ export_compile_commands_.push_back(std::move(pat)); } + // Async non-linkable deps. + const Value* async_non_linkable_deps = + dotfile_scope_.GetValue("async_non_linkable_deps", true); + if (async_non_linkable_deps) { + if (!async_non_linkable_deps->VerifyTypeIs(Value::BOOLEAN, err)) { + return false; + } + build_settings_.set_async_non_linkable_deps(async_non_linkable_deps->boolean_value()); + } + return true; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/setup.h new/gn-0.20250520/src/gn/setup.h --- old/gn-0.20250306/src/gn/setup.h 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/setup.h 2025-05-20 17:50:44.000000000 +0200 @@ -15,6 +15,7 @@ #include "gn/loader.h" #include "gn/scheduler.h" #include "gn/scope.h" +#include "gn/scope_per_file_provider.h" #include "gn/settings.h" #include "gn/token.h" #include "gn/toolchain.h" @@ -188,6 +189,7 @@ // dot file. Settings dotfile_settings_; Scope dotfile_scope_; + std::unique_ptr<ScopePerFileProvider> dotfile_provider_; // State for invoking the dotfile. base::FilePath dotfile_name_; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/source_file.cc new/gn-0.20250520/src/gn/source_file.cc --- old/gn-0.20250306/src/gn/source_file.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/source_file.cc 2025-05-20 17:50:44.000000000 +0200 @@ -101,6 +101,9 @@ } // Other cases + if (EndsWithExtension(file, "hpp11")) + return SourceFile::SOURCE_H; + if (EndsWithExtension(file, "swift")) return SourceFile::SOURCE_SWIFT; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/source_file_unittest.cc new/gn-0.20250520/src/gn/source_file_unittest.cc --- old/gn-0.20250306/src/gn/source_file_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/source_file_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -33,6 +33,7 @@ {"foo.h", SourceFile::SOURCE_H}, {"foo.hh", SourceFile::SOURCE_H}, {"foo.hpp", SourceFile::SOURCE_H}, + {"foo.hpp11", SourceFile::SOURCE_H}, {"foo.inc", SourceFile::SOURCE_H}, {"foo.inl", SourceFile::SOURCE_H}, {"foo.ipp", SourceFile::SOURCE_H}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/switches.cc new/gn-0.20250520/src/gn/switches.cc --- old/gn-0.20250306/src/gn/switches.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/switches.cc 2025-05-20 17:50:44.000000000 +0200 @@ -338,6 +338,7 @@ INSERT_VARIABLE(NinjaExecutable) INSERT_VARIABLE(NoColor) INSERT_VARIABLE(Root) + INSERT_VARIABLE(RootPattern) INSERT_VARIABLE(RootTarget) INSERT_VARIABLE(Quiet) INSERT_VARIABLE(RuntimeDepsListFile) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/target.cc new/gn-0.20250520/src/gn/target.cc --- old/gn-0.20250306/src/gn/target.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/target.cc 2025-05-20 17:50:44.000000000 +0200 @@ -215,18 +215,52 @@ 2. Execute the build config file identified by .gn to set up the global variables and default toolchain name. Any arguments, variables, defaults, etc. set up in this file will be visible to all files in the build. + Any values set in the `default_args` scope will be merged into + subsequent `declare_args()` scopes and override the default values. - 3. Load the //BUILD.gn (in the source root directory). + 3. Process the --args command line option or load the arguments from + the args.gn file in the build directory. These values will be merged + into any subsequent declare_args() scope (after the `default_args` + are merged in) to override the default values. See `help buildargs` + for more on how args are handled. + + 4. Load the BUILDCONFIG.gn file and create a dedicated scope for it. + + 5. Load the //BUILD.gn (in the source root directory). The BUILD.gn + file is executed in a scope whose parent scope is the BUILDCONFIG.gn + file, i.e., only the definitions in the BUILDCONFIG.gn file exist. + + 5. If the BUILD.gn file imports other files, each of those other + files is executed in a separate scope whose parent is the BUILDCONFIG.gn + file, i.e., no definitions from the importing BUILD.gn file are + available. When the imported file has been fully processed, its scope + is merged into the BUILD.gn file's scope. If there is a conflict + (both the BUILD.gn file and the imported file define some variable + or rule with the same name but different values), a runtime error + will be thrown. See "gn help import" for more on this. - 4. Recursively evaluate rules and load BUILD.gn in other directories as + 6. Recursively evaluate rules and load BUILD.gn in other directories as necessary to resolve dependencies. If a BUILD file isn't found in the specified location, GN will look in the corresponding location inside the secondary_source defined in the dotfile (see "gn help dotfile"). + Each BUILD.gn file will again be executed in a new scope whose only + parent is BUILDCONFIG.gn's scope. - 5. When a target's dependencies are resolved, write out the `.ninja` + 7. If a target is referenced using an alternate toolchain, then + + 1. The toolchain file is loaded in a scope whose parent is the + BUILDCONFIG.gn file. + 2. The BUILDCONFIG.gn file is re-loaded and re-parsed into a new + scope, with any `toolchain_args` merged into the defaults. See + `help buildargs` for more on how args are handled. + 3. The BUILD.gn containing the target is then parsed as in step 5, + only we use the scope from step 7.2 instead of the default + BUILDCONFIG.gn scope. + + 8. When a target's dependencies are resolved, write out the `.ninja` file to disk. - 6. When all targets are resolved, write out the root build.ninja file. + 9. When all targets are resolved, write out the root build.ninja file. Note that the BUILD.gn file name may be modulated by .gn arguments such as build_file_extension. @@ -246,9 +280,14 @@ } There is also a generic "target" function for programmatically defined types - (see "gn help target"). You can define new types using templates (see "gn - help template"). A template defines some custom code that expands to one or - more other targets. + (see "gn help target"). + + You can define new types using templates (see "gn help template"). A template + defines some custom code that expands to one or more other targets. When a + template is invoked, it is executed in the scope of the file that defined the + template (as described above). To access values from the caller's scope, you + must use the `invoker` variable (see "gn help template" for more on the + invoker). Before executing the code inside the target's { }, the target defaults are applied (see "gn help set_defaults"). It will inject implicit variable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/tokenizer_unittest.cc new/gn-0.20250520/src/gn/tokenizer_unittest.cc --- old/gn-0.20250306/src/gn/tokenizer_unittest.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/tokenizer_unittest.cc 2025-05-20 17:50:44.000000000 +0200 @@ -100,6 +100,18 @@ CheckTokenizer("- + = += -= != == < > <= >= ! || && . ,", operators)); } +TEST(Tokenizer, DoubleMinus) { + TokenExpectation tokens[] = { + {Token::INTEGER, "1"}, {Token::MINUS, "-"}, {Token::INTEGER, "-1"}}; + EXPECT_TRUE(CheckTokenizer(" 1 - -1 ", tokens)); +} + +TEST(Tokenizer, DoubleMinusNoSpace) { + TokenExpectation tokens[] = { + {Token::INTEGER, "1"}, {Token::MINUS, "-"}, {Token::INTEGER, "-1"}}; + EXPECT_TRUE(CheckTokenizer(" 1--1 ", tokens)); +} + TEST(Tokenizer, Scoper) { TokenExpectation scopers[] = { {Token::LEFT_BRACE, "{"}, {Token::LEFT_BRACKET, "["}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gn-0.20250306/src/gn/variables.cc new/gn-0.20250520/src/gn/variables.cc --- old/gn-0.20250306/src/gn/variables.cc 2025-03-06 11:54:20.000000000 +0100 +++ new/gn-0.20250520/src/gn/variables.cc 2025-05-20 17:50:44.000000000 +0200 @@ -16,7 +16,10 @@ const char kGnVersion_Help[] = R"(gn_version: [number] The version of gn. - Corresponds to the number printed by `gn --version`. + Corresponds to the number printed by `gn --version`. This variable is + only variable available in the dotfile (all the rest are missing + because the dotfile has to be parsed before args.gn or anything else + is processed). Example ++++++ gn.obsinfo ++++++ --- /var/tmp/diff_new_pack.0znNpI/_old 2025-06-27 23:02:41.324676846 +0200 +++ /var/tmp/diff_new_pack.0znNpI/_new 2025-06-27 23:02:41.328677011 +0200 @@ -1,5 +1,5 @@ name: gn -version: 0.20250306 -mtime: 1741258460 -commit: 7a8aa3a08a13521336853a28c46537ec04338a2d +version: 0.20250520 +mtime: 1747756244 +commit: cad8f67e2dd0cea00bbe4566efe2fdf4c1821563