|  | // Copyright (c) 2013 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 "tools/gn/binary_target_generator.h" | 
|  |  | 
|  | #include "tools/gn/config_values_generator.h" | 
|  | #include "tools/gn/deps_iterator.h" | 
|  | #include "tools/gn/err.h" | 
|  | #include "tools/gn/filesystem_utils.h" | 
|  | #include "tools/gn/functions.h" | 
|  | #include "tools/gn/scope.h" | 
|  | #include "tools/gn/settings.h" | 
|  | #include "tools/gn/value_extractors.h" | 
|  | #include "tools/gn/variables.h" | 
|  |  | 
|  | BinaryTargetGenerator::BinaryTargetGenerator( | 
|  | Target* target, | 
|  | Scope* scope, | 
|  | const FunctionCallNode* function_call, | 
|  | Target::OutputType type, | 
|  | Err* err) | 
|  | : TargetGenerator(target, scope, function_call, err), | 
|  | output_type_(type) { | 
|  | } | 
|  |  | 
|  | BinaryTargetGenerator::~BinaryTargetGenerator() = default; | 
|  |  | 
|  | void BinaryTargetGenerator::DoRun() { | 
|  | target_->set_output_type(output_type_); | 
|  |  | 
|  | if (!FillOutputName()) | 
|  | return; | 
|  |  | 
|  | if (!FillOutputPrefixOverride()) | 
|  | return; | 
|  |  | 
|  | if (!FillOutputDir()) | 
|  | return; | 
|  |  | 
|  | if (!FillOutputExtension()) | 
|  | return; | 
|  |  | 
|  | if (!FillSources()) | 
|  | return; | 
|  |  | 
|  | if (!FillPublic()) | 
|  | return; | 
|  |  | 
|  | if (!FillFriends()) | 
|  | return; | 
|  |  | 
|  | if (!FillCheckIncludes()) | 
|  | return; | 
|  |  | 
|  | if (!FillConfigs()) | 
|  | return; | 
|  |  | 
|  | if (!FillAllowCircularIncludesFrom()) | 
|  | return; | 
|  |  | 
|  | if (!FillCompleteStaticLib()) | 
|  | return; | 
|  |  | 
|  | // Config values (compiler flags, etc.) set directly on this target. | 
|  | ConfigValuesGenerator gen(&target_->config_values(), scope_, | 
|  | scope_->GetSourceDir(), err_); | 
|  | gen.Run(); | 
|  | if (err_->has_error()) | 
|  | return; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillCompleteStaticLib() { | 
|  | if (target_->output_type() == Target::STATIC_LIBRARY) { | 
|  | const Value* value = scope_->GetValue(variables::kCompleteStaticLib, true); | 
|  | if (!value) | 
|  | return true; | 
|  | if (!value->VerifyTypeIs(Value::BOOLEAN, err_)) | 
|  | return false; | 
|  | target_->set_complete_static_lib(value->boolean_value()); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillFriends() { | 
|  | const Value* value = scope_->GetValue(variables::kFriend, true); | 
|  | if (value) { | 
|  | return ExtractListOfLabelPatterns(*value, scope_->GetSourceDir(), | 
|  | &target_->friends(), err_); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillOutputName() { | 
|  | const Value* value = scope_->GetValue(variables::kOutputName, true); | 
|  | if (!value) | 
|  | return true; | 
|  | if (!value->VerifyTypeIs(Value::STRING, err_)) | 
|  | return false; | 
|  | target_->set_output_name(value->string_value()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillOutputPrefixOverride() { | 
|  | const Value* value = scope_->GetValue(variables::kOutputPrefixOverride, true); | 
|  | if (!value) | 
|  | return true; | 
|  | if (!value->VerifyTypeIs(Value::BOOLEAN, err_)) | 
|  | return false; | 
|  | target_->set_output_prefix_override(value->boolean_value()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillOutputDir() { | 
|  | const Value* value = scope_->GetValue(variables::kOutputDir, true); | 
|  | if (!value) | 
|  | return true; | 
|  | if (!value->VerifyTypeIs(Value::STRING, err_)) | 
|  | return false; | 
|  |  | 
|  | if (value->string_value().empty()) | 
|  | return true;  // Treat empty string as the default and do nothing. | 
|  |  | 
|  | const BuildSettings* build_settings = scope_->settings()->build_settings(); | 
|  | SourceDir dir = scope_->GetSourceDir().ResolveRelativeDir( | 
|  | *value, err_, build_settings->root_path_utf8()); | 
|  | if (err_->has_error()) | 
|  | return false; | 
|  |  | 
|  | if (!EnsureStringIsInOutputDir(build_settings->build_dir(), | 
|  | dir.value(), value->origin(), err_)) | 
|  | return false; | 
|  | target_->set_output_dir(dir); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillOutputExtension() { | 
|  | const Value* value = scope_->GetValue(variables::kOutputExtension, true); | 
|  | if (!value) | 
|  | return true; | 
|  | if (!value->VerifyTypeIs(Value::STRING, err_)) | 
|  | return false; | 
|  | target_->set_output_extension(value->string_value()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool BinaryTargetGenerator::FillAllowCircularIncludesFrom() { | 
|  | const Value* value = scope_->GetValue( | 
|  | variables::kAllowCircularIncludesFrom, true); | 
|  | if (!value) | 
|  | return true; | 
|  |  | 
|  | UniqueVector<Label> circular; | 
|  | ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(), | 
|  | ToolchainLabelForScope(scope_), &circular, err_); | 
|  | if (err_->has_error()) | 
|  | return false; | 
|  |  | 
|  | // Validate that all circular includes entries are in the deps. | 
|  | for (const auto& cur : circular) { | 
|  | bool found_dep = false; | 
|  | for (const auto& dep_pair : target_->GetDeps(Target::DEPS_LINKED)) { | 
|  | if (dep_pair.label == cur) { | 
|  | found_dep = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!found_dep) { | 
|  | *err_ = Err(*value, "Label not in deps.", | 
|  | "The label \"" + cur.GetUserVisibleName(false) + | 
|  | "\"\nwas not in the deps of this target. " | 
|  | "allow_circular_includes_from only allows\ntargets present in the " | 
|  | "deps."); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Add to the set. | 
|  | for (const auto& cur : circular) | 
|  | target_->allow_circular_includes_from().insert(cur); | 
|  | return true; | 
|  | } |