Add arflags to GN Allows the build to specify flags to the static library archiver tool. BUG=598599 Review URL: https://codereview.chromium.org/1904473002 Cr-Original-Commit-Position: refs/heads/master@{#388315} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 440b117bb10d5c7e195a26cf974ccbd5886948b0
diff --git a/tools/gn/config_values.h b/tools/gn/config_values.h index 823f1df..b6f153b 100644 --- a/tools/gn/config_values.h +++ b/tools/gn/config_values.h
@@ -30,6 +30,7 @@ const std::vector<SourceDir>& name() const { return name##_; } \ std::vector<SourceDir>& name() { return name##_; } + STRING_VALUES_ACCESSOR(arflags) STRING_VALUES_ACCESSOR(asmflags) STRING_VALUES_ACCESSOR(cflags) STRING_VALUES_ACCESSOR(cflags_c) @@ -65,6 +66,7 @@ } private: + std::vector<std::string> arflags_; std::vector<std::string> asmflags_; std::vector<std::string> cflags_; std::vector<std::string> cflags_c_;
diff --git a/tools/gn/config_values_generator.cc b/tools/gn/config_values_generator.cc index 3cc8235..e92f091 100644 --- a/tools/gn/config_values_generator.cc +++ b/tools/gn/config_values_generator.cc
@@ -67,6 +67,7 @@ GetDirList(scope_, #name, config_values_, input_dir_, \ &ConfigValues::name, err_); + FILL_STRING_CONFIG_VALUE(arflags) FILL_STRING_CONFIG_VALUE(asmflags) FILL_STRING_CONFIG_VALUE(cflags) FILL_STRING_CONFIG_VALUE(cflags_c)
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md index 38e8ce7..600daea 100644 --- a/tools/gn/docs/reference.md +++ b/tools/gn/docs/reference.md
@@ -3003,6 +3003,7 @@ Example: "gen/base/test" Linker tools have multiple inputs and (potentially) multiple outputs + The static library tool ("alink") is not considered a linker tool. The following expansions are available: {{inputs}} @@ -3062,6 +3063,9 @@ These should generally be treated the same as libs by your tool. Example: "libfoo.so libbar.so" + The static library ("alink") tool allows {{arflags}} plus the common + tool substitutions. + The copy tool allows the common compiler/linker substitutions, plus {{source}} which is the source of the copy. The stamp tool allows only the common tool substitutions. @@ -3725,6 +3729,42 @@ ``` +## **arflags**: Arguments passed to static_library archiver. + +``` + A list of flags passed to the archive/lib command that creates static + libraries. + + arflags are NOT pushed to dependents, so applying arflags to source + sets or any other target type will be a no-op. As with ldflags, + you could put the arflags in a config and set that as a public or + "all dependent" config, but that will likely not be what you want. + If you have a chain of static libraries dependent on each other, + this can cause the flags to propagate up to other static libraries. + Due to the nature of how arflags are typically used, you will normally + want to apply them directly on static_library targets themselves. + +``` + +### **Ordering of flags and values** + +``` + 1. Those set on the current target (not in a config). + 2. Those set on the "configs" on the target in order that the + configs appear in the list. + 3. Those set on the "all_dependent_configs" on the target in order + that the configs appear in the list. + 4. Those set on the "public_configs" on the target in order that + those configs appear in the list. + 5. all_dependent_configs pulled from dependencies, in the order of + the "deps" list. This is done recursively. If a config appears + more than once, only the first occurance will be used. + 6. public_configs pulled from dependencies, in the order of the + "deps" list. If a dependency is public, they will be applied + recursively. + + +``` ## **args**: Arguments passed to an action. ```
diff --git a/tools/gn/function_toolchain.cc b/tools/gn/function_toolchain.cc index bdf5385..aaa9b7e 100644 --- a/tools/gn/function_toolchain.cc +++ b/tools/gn/function_toolchain.cc
@@ -194,8 +194,8 @@ } bool IsLinkerTool(Toolchain::ToolType type) { - return type == Toolchain::TYPE_ALINK || - type == Toolchain::TYPE_SOLINK || + // "alink" is not counted as in the generic "linker" tool list. + return type == Toolchain::TYPE_SOLINK || type == Toolchain::TYPE_SOLINK_MODULE || type == Toolchain::TYPE_LINK; } @@ -690,6 +690,7 @@ " Example: \"gen/base/test\"\n" "\n" " Linker tools have multiple inputs and (potentially) multiple outputs\n" + " The static library tool (\"alink\") is not considered a linker tool.\n" " The following expansions are available:\n" "\n" " {{inputs}}\n" @@ -749,6 +750,9 @@ " These should generally be treated the same as libs by your tool.\n" " Example: \"libfoo.so libbar.so\"\n" "\n" + " The static library (\"alink\") tool allows {{arflags}} plus the common\n" + " tool substitutions.\n" + "\n" " The copy tool allows the common compiler/linker substitutions, plus\n" " {{source}} which is the source of the copy. The stamp tool allows\n" " only the common tool substitutions.\n" @@ -859,6 +863,10 @@ } else if (IsLinkerTool(tool_type)) { subst_validator = &IsValidLinkerSubstitution; subst_output_validator = &IsValidLinkerOutputsSubstitution; + } else if (tool_type == Toolchain::TYPE_ALINK) { + subst_validator = &IsValidALinkSubstitution; + // ALink uses the standard output file patterns as other linker tools. + subst_output_validator = &IsValidLinkerOutputsSubstitution; } else if (tool_type == Toolchain::TYPE_COPY || tool_type == Toolchain::TYPE_COPY_BUNDLE_DATA) { subst_validator = &IsValidCopySubstitution;
diff --git a/tools/gn/ninja_binary_target_writer.cc b/tools/gn/ninja_binary_target_writer.cc index 4a923c3..cb48688 100644 --- a/tools/gn/ninja_binary_target_writer.cc +++ b/tools/gn/ninja_binary_target_writer.cc
@@ -785,6 +785,11 @@ target_->output_type() == Target::LOADABLE_MODULE) { WriteLinkerFlags(optional_def_file); WriteLibs(); + } else if (target_->output_type() == Target::STATIC_LIBRARY) { + out_ << " arflags ="; + RecursiveTargetConfigStringsToStream(target_, &ConfigValues::arflags, + GetFlagOptions(), out_); + out_ << std::endl; } WriteOutputSubstitutions(); WriteSolibs(solibs); @@ -795,9 +800,8 @@ out_ << " ldflags ="; // First the ldflags from the target and its config. - EscapeOptions flag_options = GetFlagOptions(); RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, - flag_options, out_); + GetFlagOptions(), out_); // Followed by library search paths that have been recursively pushed // through the dependency tree.
diff --git a/tools/gn/ninja_binary_target_writer_unittest.cc b/tools/gn/ninja_binary_target_writer_unittest.cc index d620f94..ab8b641 100644 --- a/tools/gn/ninja_binary_target_writer_unittest.cc +++ b/tools/gn/ninja_binary_target_writer_unittest.cc
@@ -111,6 +111,7 @@ // There are no sources so there are no params to alink. (In practice // this will probably fail in the archive tool.) "build obj/foo/libstlib.a: alink || obj/foo/bar.stamp\n" + " arflags =\n" " output_extension = \n" " output_dir = \n"; std::string out_str = out.str(); @@ -138,6 +139,7 @@ "build obj/foo/libstlib.a: alink obj/foo/bar.input1.o " "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj " "|| obj/foo/bar.stamp\n" + " arflags =\n" " output_extension = \n" " output_dir = \n"; std::string out_str = out.str(); @@ -145,6 +147,38 @@ } } +TEST(NinjaBinaryTargetWriter, StaticLibrary) { + TestWithScope setup; + Err err; + + TestTarget target(setup, "//foo:bar", Target::STATIC_LIBRARY); + target.sources().push_back(SourceFile("//foo/input1.cc")); + target.config_values().arflags().push_back("--asdf"); + ASSERT_TRUE(target.OnResolved(&err)); + + std::ostringstream out; + NinjaBinaryTargetWriter writer(&target, out); + writer.Run(); + + const char expected[] = + "defines =\n" + "include_dirs =\n" + "cflags =\n" + "cflags_cc =\n" + "root_out_dir = .\n" + "target_out_dir = obj/foo\n" + "target_output_name = libbar\n" + "\n" + "build obj/foo/libbar.input1.o: cxx ../../foo/input1.cc\n" + "\n" + "build obj/foo/libbar.a: alink obj/foo/libbar.input1.o\n" + " arflags = --asdf\n" + " output_extension = \n" + " output_dir = \n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str); +} + // This tests that output extension and output dir overrides apply, and input // dependencies are applied. TEST(NinjaBinaryTargetWriter, OutputExtensionAndInputDeps) {
diff --git a/tools/gn/substitution_type.cc b/tools/gn/substitution_type.cc index 75d8b7a..fcca19d 100644 --- a/tools/gn/substitution_type.cc +++ b/tools/gn/substitution_type.cc
@@ -47,6 +47,8 @@ "{{output_extension}}", // SUBSTITUTION_OUTPUT_EXTENSION "{{solibs}}", // SUBSTITUTION_SOLIBS + "{{arflags}}", // SUBSTITUTION_ARFLAGS + "{{bundle_root_dir}}", // SUBSTITUTION_BUNDLE_ROOT_DIR "{{bundle_resources_dir}}", // SUBSTITUTION_BUNDLE_RESOURCES_DIR "{{bundle_executable_dir}}", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR @@ -96,6 +98,8 @@ "output_extension", // SUBSTITUTION_OUTPUT_EXTENSION "solibs", // SUBSTITUTION_SOLIBS + "arflags", // SUBSTITUTION_ARFLAGS + "bundle_root_dir", // SUBSTITUTION_BUNDLE_ROOT_DIR "bundle_resources_dir", // SUBSTITUTION_BUNDLE_RESOURCES_DIR "bundle_executable_dir", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR @@ -207,6 +211,15 @@ type == SUBSTITUTION_OUTPUT_EXTENSION; } +bool IsValidALinkSubstitution(SubstitutionType type) { + return IsValidToolSubstitution(type) || + type == SUBSTITUTION_LINKER_INPUTS || + type == SUBSTITUTION_LINKER_INPUTS_NEWLINE || + type == SUBSTITUTION_ARFLAGS || + type == SUBSTITUTION_OUTPUT_DIR || + type == SUBSTITUTION_OUTPUT_EXTENSION; +} + bool IsValidCopySubstitution(SubstitutionType type) { return IsValidToolSubstitution(type) || type == SUBSTITUTION_SOURCE;
diff --git a/tools/gn/substitution_type.h b/tools/gn/substitution_type.h index 2e63373..e82ecd6 100644 --- a/tools/gn/substitution_type.h +++ b/tools/gn/substitution_type.h
@@ -60,6 +60,9 @@ SUBSTITUTION_OUTPUT_EXTENSION, // {{output_extension}} SUBSTITUTION_SOLIBS, // {{solibs}} + // Valid for alink only. + SUBSTITUTION_ARFLAGS, // {{arflags}} + // Valid for bundle_data targets. SUBSTITUTION_BUNDLE_ROOT_DIR, // {{bundle_root_dir}} SUBSTITUTION_BUNDLE_RESOURCES_DIR, // {{bundle_resources_dir}} @@ -117,6 +120,7 @@ bool IsValidCompilerOutputsSubstitution(SubstitutionType type); bool IsValidLinkerSubstitution(SubstitutionType type); bool IsValidLinkerOutputsSubstitution(SubstitutionType type); +bool IsValidALinkSubstitution(SubstitutionType type); bool IsValidCopySubstitution(SubstitutionType type); bool IsValidCompileXCassetsSubstitution(SubstitutionType type);
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc index 46cd57e..dc0316b 100644 --- a/tools/gn/variables.cc +++ b/tools/gn/variables.cc
@@ -418,6 +418,25 @@ " public_deps = [ \":c\" ]\n" " }\n"; +const char kArflags[] = "arflags"; +const char kArflags_HelpShort[] = + "arflags: [string list] Arguments passed to static_library archiver."; +const char kArflags_Help[] = + "arflags: Arguments passed to static_library archiver.\n" + "\n" + " A list of flags passed to the archive/lib command that creates static\n" + " libraries.\n" + "\n" + " arflags are NOT pushed to dependents, so applying arflags to source\n" + " sets or any other target type will be a no-op. As with ldflags,\n" + " you could put the arflags in a config and set that as a public or\n" + " \"all dependent\" config, but that will likely not be what you want.\n" + " If you have a chain of static libraries dependent on each other,\n" + " this can cause the flags to propagate up to other static libraries.\n" + " Due to the nature of how arflags are typically used, you will normally\n" + " want to apply them directly on static_library targets themselves.\n" + COMMON_ORDERING_HELP; + const char kArgs[] = "args"; const char kArgs_HelpShort[] = "args: [string list] Arguments passed to an action."; @@ -1638,6 +1657,7 @@ if (info_map.empty()) { INSERT_VARIABLE(AllDependentConfigs) INSERT_VARIABLE(AllowCircularIncludesFrom) + INSERT_VARIABLE(Arflags) INSERT_VARIABLE(Args) INSERT_VARIABLE(Asmflags) INSERT_VARIABLE(AssertNoDeps)
diff --git a/tools/gn/variables.h b/tools/gn/variables.h index 2dafdee..2523c1f 100644 --- a/tools/gn/variables.h +++ b/tools/gn/variables.h
@@ -79,6 +79,10 @@ extern const char kAllowCircularIncludesFrom_HelpShort[]; extern const char kAllowCircularIncludesFrom_Help[]; +extern const char kArflags[]; +extern const char kArflags_HelpShort[]; +extern const char kArflags_Help[]; + extern const char kArgs[]; extern const char kArgs_HelpShort[]; extern const char kArgs_Help[];