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[];