summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/gn/BUILD.gn1
-rw-r--r--tools/gn/config_values_extractors_unittest.cc121
-rw-r--r--tools/gn/gn.gyp1
-rw-r--r--tools/gn/variables.cc46
4 files changed, 159 insertions, 10 deletions
diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn
index 20aea83..9712706 100644
--- a/tools/gn/BUILD.gn
+++ b/tools/gn/BUILD.gn
@@ -173,6 +173,7 @@ test("gn_unittests") {
sources = [
"builder_unittest.cc",
"c_include_iterator_unittest.cc",
+ "config_values_extractors_unittest.cc",
"escape_unittest.cc",
"filesystem_utils_unittest.cc",
"file_template_unittest.cc",
diff --git a/tools/gn/config_values_extractors_unittest.cc b/tools/gn/config_values_extractors_unittest.cc
new file mode 100644
index 0000000..0076b9e
--- /dev/null
+++ b/tools/gn/config_values_extractors_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sstream>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/config.h"
+#include "tools/gn/config_values_extractors.h"
+#include "tools/gn/target.h"
+#include "tools/gn/test_with_scope.h"
+
+namespace {
+
+struct FlagWriter {
+ void operator()(const std::string& dir, std::ostream& out) const {
+ out << dir << " ";
+ }
+};
+
+struct IncludeWriter {
+ void operator()(const SourceDir& dir, std::ostream& out) const {
+ out << dir.value() << " ";
+ }
+};
+
+} // namespace
+
+TEST(ConfigValuesExtractors, IncludeOrdering) {
+ TestWithScope setup;
+
+ // Construct a chain of dependencies: target -> dep1 -> dep2
+ // Add representative values: cflags (opaque, always copied) and include_dirs
+ // (uniquified) to each one so we can check what comes out the other end.
+
+ // Set up dep2, direct and all dependent configs.
+ Config dep2_all(setup.settings(), Label(SourceDir("//dep2/"), "all"));
+ dep2_all.config_values().cflags().push_back("--dep2-all");
+ dep2_all.config_values().include_dirs().push_back(SourceDir("//dep2/all/"));
+
+ Config dep2_direct(setup.settings(), Label(SourceDir("//dep2/"), "direct"));
+ dep2_direct.config_values().cflags().push_back("--dep2-direct");
+ dep2_direct.config_values().include_dirs().push_back(
+ SourceDir("//dep2/direct/"));
+
+ Target dep2(setup.settings(), Label(SourceDir("//dep2/"), "dep2"));
+ dep2.set_output_type(Target::SOURCE_SET);
+ dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all));
+ dep2.direct_dependent_configs().push_back(LabelConfigPair(&dep2_direct));
+
+ // Set up dep1, direct and all dependent configs.
+ Config dep1_all(setup.settings(), Label(SourceDir("//dep1/"), "all"));
+ dep1_all.config_values().cflags().push_back("--dep1-all");
+ dep1_all.config_values().include_dirs().push_back(SourceDir("//dep1/all/"));
+
+ Config dep1_direct(setup.settings(), Label(SourceDir("//dep1/"), "direct"));
+ dep1_direct.config_values().cflags().push_back("--dep1-direct");
+ dep1_direct.config_values().include_dirs().push_back(
+ SourceDir("//dep1/direct/"));
+
+ Target dep1(setup.settings(), Label(SourceDir("//dep1/"), "dep1"));
+ dep1.set_output_type(Target::SOURCE_SET);
+ dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all));
+ dep1.direct_dependent_configs().push_back(LabelConfigPair(&dep1_direct));
+ dep1.deps().push_back(LabelTargetPair(&dep2));
+
+ // Set up target, direct and all dependent configs.
+ Config target_all(setup.settings(), Label(SourceDir("//target/"), "all"));
+ target_all.config_values().cflags().push_back("--target-all");
+ target_all.config_values().include_dirs().push_back(
+ SourceDir("//target/all/"));
+
+ Config target_direct(setup.settings(),
+ Label(SourceDir("//target/"), "direct"));
+ target_direct.config_values().cflags().push_back("--target-direct");
+ target_direct.config_values().include_dirs().push_back(
+ SourceDir("//target/direct/"));
+
+ // This config is applied directly to target.
+ Config target_config(setup.settings(),
+ Label(SourceDir("//target/"), "config"));
+ target_config.config_values().cflags().push_back("--target-config");
+ target_config.config_values().include_dirs().push_back(
+ SourceDir("//target/config/"));
+
+ Target target(setup.settings(), Label(SourceDir("//target/"), "target"));
+ target.set_output_type(Target::SOURCE_SET);
+ target.all_dependent_configs().push_back(LabelConfigPair(&target_all));
+ target.direct_dependent_configs().push_back(LabelConfigPair(&target_direct));
+ target.configs().push_back(LabelConfigPair(&target_config));
+ target.deps().push_back(LabelTargetPair(&dep1));
+
+
+ // Additionally add some values directly on "target".
+ target.config_values().cflags().push_back("--target");
+ target.config_values().include_dirs().push_back(
+ SourceDir("//target/"));
+
+ // Mark targets resolved. This should push dependent configs.
+ dep2.OnResolved();
+ dep1.OnResolved();
+ target.OnResolved();
+
+ // Verify cflags by serializing.
+ std::ostringstream flag_out;
+ FlagWriter flag_writer;
+ RecursiveTargetConfigToStream<std::string, FlagWriter>(
+ &target, &ConfigValues::cflags, flag_writer, flag_out);
+ EXPECT_EQ(flag_out.str(),
+ "--target --target-config --target-all --target-direct "
+ "--dep1-all --dep2-all --dep1-direct ");
+
+ // Verify include dirs by serializing.
+ std::ostringstream include_out;
+ IncludeWriter include_writer;
+ RecursiveTargetConfigToStream<SourceDir, IncludeWriter>(
+ &target, &ConfigValues::include_dirs, include_writer, include_out);
+ EXPECT_EQ(include_out.str(),
+ "//target/ //target/config/ //target/all/ //target/direct/ "
+ "//dep1/all/ //dep2/all/ //dep1/direct/ ");
+}
diff --git a/tools/gn/gn.gyp b/tools/gn/gn.gyp
index 0ae37ca..75f72c46 100644
--- a/tools/gn/gn.gyp
+++ b/tools/gn/gn.gyp
@@ -174,6 +174,7 @@
'sources': [
'builder_unittest.cc',
'c_include_iterator_unittest.cc',
+ 'config_values_extractors_unittest.cc',
'escape_unittest.cc',
'filesystem_utils_unittest.cc',
'file_template_unittest.cc',
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index 4b49f60..344a9d9 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -240,6 +240,25 @@ const char kTargetOutDir_Help[] =
// Target variables ------------------------------------------------------------
+#define COMMON_ORDERING_HELP \
+ "\n" \
+ "Ordering of flags and values:\n" \
+ "\n" \
+ " 1. Those set on the current target (not in a config).\n" \
+ " 2. Those set on the \"configs\" on the target in order that the\n" \
+ " configs appear in the list.\n" \
+ " 3. Those set on the \"all_dependent_configs\" on the target in order\n" \
+ " that the configs appear in the list.\n" \
+ " 4. Those set on the \"direct_dependent_configs\" on the target in\n" \
+ " order that those configs appear in the list.\n" \
+ " 5. all_dependent_configs pulled from dependencies, in the order of\n" \
+ " the \"deps\" list. This is done recursively. If a config appears\n" \
+ " more than once, only the first occurance will be used.\n" \
+ " 6. direct_dependent_configs pulled from dependencies, in the order\n" \
+ " of the \"deps\" list. If a dependency has\n" \
+ " \"forward_dependent_configs_from\", they will be applied\n" \
+ " recursively.\n"
+
const char kAllDependentConfigs[] = "all_dependent_configs";
const char kAllDependentConfigs_HelpShort[] =
"all_dependent_configs: [label list] Configs to be forced on dependents.";
@@ -259,7 +278,8 @@ const char kAllDependentConfigs_Help[] =
" capability should generally only be used to add defines and include\n"
" directories necessary to compile a target's headers.\n"
"\n"
- " See also \"direct_dependent_configs\".\n";
+ " See also \"direct_dependent_configs\".\n"
+ COMMON_ORDERING_HELP;
const char kArgs[] = "args";
const char kArgs_HelpShort[] =
@@ -294,7 +314,8 @@ const char kCommonCflagsHelp[] =
" To target one of these variants individually, use \"cflags_c\",\n"
" \"cflags_cc\", \"cflags_objc\", and \"cflags_objcc\", respectively.\n"
" These variant-specific versions will be appended to the \"cflags\".\n"
- COMMON_FLAGS_HELP;
+ COMMON_FLAGS_HELP
+ COMMON_ORDERING_HELP;
const char* kCflags_Help = kCommonCflagsHelp;
const char kCflagsC[] = "cflags_c";
@@ -334,6 +355,7 @@ const char kConfigs_Help[] =
" configs applying to a given target type (see \"set_defaults\").\n"
" When a target is being defined, it can add to or remove from this\n"
" list.\n"
+ COMMON_ORDERING_HELP
"\n"
"Example:\n"
" static_library(\"foo\") {\n"
@@ -392,6 +414,7 @@ const char kDefines_Help[] =
"\n"
" These strings will be passed to the C/C++ compiler as #defines. The\n"
" strings may or may not include an \"=\" to assign a value.\n"
+ COMMON_ORDERING_HELP
"\n"
"Example:\n"
" defines = [ \"AWESOME_FEATURE\", \"LOG_LEVEL=3\" ]\n";
@@ -464,7 +487,8 @@ const char kDirectDependentConfigs_Help[] =
" capability should generally only be used to add defines and include\n"
" directories necessary to compile a target's headers.\n"
"\n"
- " See also \"all_dependent_configs\".\n";
+ " See also \"all_dependent_configs\".\n"
+ COMMON_ORDERING_HELP;
const char kForwardDependentConfigsFrom[] = "forward_dependent_configs_from";
const char kForwardDependentConfigsFrom_HelpShort[] =
@@ -551,6 +575,7 @@ const char kIncludeDirs_Help[] =
"\n"
" The directories in this list will be added to the include path for\n"
" the files in the affected target.\n"
+ COMMON_ORDERING_HELP
"\n"
"Example:\n"
" include_dirs = [ \"src/include\", \"//third_party/foo\" ]\n";
@@ -566,6 +591,11 @@ const char kLdflags_Help[] =
" These flags are passed on the command-line to the linker and generally\n"
" specify various linking options. Most targets will not need these and\n"
" will use \"libs\" and \"lib_dirs\" instead.\n"
+ "\n"
+ " ldflags are NOT pushed to dependents, so applying ldflags to source\n"
+ " sets or static libraries will be a no-op. If you want to apply ldflags\n"
+ " to dependent targets, put them in a config and set it in the\n"
+ " all_dependent_configs or direct_dependent_configs.\n"
COMMON_FLAGS_HELP;
#define COMMON_LIB_INHERITANCE_HELP \
@@ -574,13 +604,7 @@ const char kLdflags_Help[] =
" First, then are inherited across static library boundaries until a\n" \
" shared library or executable target is reached. Second, they are\n" \
" uniquified so each one is only passed once (the first instance of it\n" \
- " will be the one used).\n" \
- "\n" \
- " The order that libs/lib_dirs apply is:\n" \
- " 1. Ones set on the target itself.\n" \
- " 2. Ones from the configs applying to the target.\n" \
- " 3. Ones from deps of the target, in order (recursively following\n" \
- " these rules).\n"
+ " will be the one used).\n"
const char kLibDirs[] = "lib_dirs";
const char kLibDirs_HelpShort[] =
@@ -594,6 +618,7 @@ const char kLibDirs_Help[] =
" for the required libraries. If an item is not an absolute path, it\n"
" will be treated as being relative to the current build file.\n"
COMMON_LIB_INHERITANCE_HELP
+ COMMON_ORDERING_HELP
"\n"
"Example:\n"
" lib_dirs = [ \"/usr/lib/foo\", \"lib/doom_melon\" ]\n";
@@ -621,6 +646,7 @@ const char kLibs_Help[] =
" special-cased: the switch \"-framework\" will be prepended instead of\n"
" the lib_prefix, and the \".framework\" suffix will be trimmed.\n"
COMMON_LIB_INHERITANCE_HELP
+ COMMON_ORDERING_HELP
"\n"
"Examples:\n"
" On Windows:\n"