| Index: tools/gn/target.cc
|
| diff --git a/tools/gn/target.cc b/tools/gn/target.cc
|
| index 0b189e63b4850690187cab57ce3458a5e34e7537..a7a3d07d2063e1b49aca0505d4a419c911889fb9 100644
|
| --- a/tools/gn/target.cc
|
| +++ b/tools/gn/target.cc
|
| @@ -170,6 +170,8 @@ bool Target::OnResolved(Err* err) {
|
| PullDependentTargets();
|
| PullForwardedDependentConfigs();
|
| PullRecursiveHardDeps();
|
| + if (!ResolvePrecompiledHeaders(err))
|
| + return false;
|
|
|
| FillOutputFiles();
|
|
|
| @@ -215,12 +217,12 @@ std::string Target::GetComputedOutputName(bool include_prefix) const {
|
| std::string result;
|
| if (include_prefix) {
|
| const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
|
| - const std::string& prefix = tool->output_prefix();
|
| - // Only add the prefix if the name doesn't already have it.
|
| - if (!base::StartsWithASCII(name, prefix, true))
|
| - result = prefix;
|
| + if (tool) {
|
| + // Only add the prefix if the name doesn't already have it.
|
| + if (!base::StartsWithASCII(name, tool->output_prefix(), true))
|
| + result = tool->output_prefix();
|
| + }
|
| }
|
| -
|
| result.append(name);
|
| return result;
|
| }
|
| @@ -429,6 +431,60 @@ void Target::FillOutputFiles() {
|
| computed_outputs_.push_back(OutputFile(settings()->build_settings(), out));
|
| }
|
|
|
| +bool Target::ResolvePrecompiledHeaders(Err* err) {
|
| + // Precompiled headers are stored on a ConfigValues struct. This way, the
|
| + // build can set all the precompiled header settings in a config and apply
|
| + // it to many targets. Likewise, the precompiled header values may be
|
| + // specified directly on a target.
|
| + //
|
| + // Unlike other values on configs which are lists that just get concatenated,
|
| + // the precompiled header settings are unique values. We allow them to be
|
| + // specified anywhere, but if they are specified in more than one place all
|
| + // places must match.
|
| +
|
| + // Track where the current settings came from for issuing errors.
|
| + const Label* pch_header_settings_from = NULL;
|
| + if (config_values_.has_precompiled_headers())
|
| + pch_header_settings_from = &label();
|
| +
|
| + for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
|
| + if (!iter.GetCurrentConfig())
|
| + continue; // Skip the one on the target itself.
|
| +
|
| + const Config* config = iter.GetCurrentConfig();
|
| + const ConfigValues& cur = config->config_values();
|
| + if (!cur.has_precompiled_headers())
|
| + continue; // This one has no precompiled header info, skip.
|
| +
|
| + if (config_values_.has_precompiled_headers()) {
|
| + // Already have a precompiled header values, the settings must match.
|
| + if (config_values_.precompiled_header() != cur.precompiled_header() ||
|
| + config_values_.precompiled_source() != cur.precompiled_source()) {
|
| + *err = Err(defined_from(),
|
| + "Precompiled header setting conflict.",
|
| + "The target " + label().GetUserVisibleName(false) + "\n"
|
| + "has conflicting precompiled header settings.\n"
|
| + "\n"
|
| + "From " + pch_header_settings_from->GetUserVisibleName(false) +
|
| + "\n header: " + config_values_.precompiled_header() +
|
| + "\n source: " + config_values_.precompiled_source().value() +
|
| + "\n\n"
|
| + "From " + config->label().GetUserVisibleName(false) +
|
| + "\n header: " + cur.precompiled_header() +
|
| + "\n source: " + cur.precompiled_source().value());
|
| + return false;
|
| + }
|
| + } else {
|
| + // Have settings from a config, apply them to ourselves.
|
| + pch_header_settings_from = &config->label();
|
| + config_values_.set_precompiled_header(cur.precompiled_header());
|
| + config_values_.set_precompiled_source(cur.precompiled_source());
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| bool Target::CheckVisibility(Err* err) const {
|
| for (const auto& pair : GetDeps(DEPS_ALL)) {
|
| if (!Visibility::CheckItemVisibility(this, pair.ptr, err))
|
|
|