// 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 "gn/binary_target_generator.h" #include "gn/config_values_generator.h" #include "gn/deps_iterator.h" #include "gn/err.h" #include "gn/filesystem_utils.h" #include "gn/functions.h" #include "gn/parse_tree.h" #include "gn/rust_values_generator.h" #include "gn/rust_variables.h" #include "gn/scope.h" #include "gn/settings.h" #include "gn/swift_values_generator.h" #include "gn/value_extractors.h" #include "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; if (!FillPool()) return; if (!ValidateSources()) return; if (target_->source_types_used().RustSourceUsed()) { RustValuesGenerator rustgen(target_, scope_, function_call_, err_); rustgen.Run(); if (err_->has_error()) return; } if (target_->source_types_used().SwiftSourceUsed()) { SwiftValuesGenerator swiftgen(target_, scope_, err_); swiftgen.Run(); if (err_->has_error()) 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::FillSources() { bool ret = TargetGenerator::FillSources(); for (std::size_t i = 0; i < target_->sources().size(); ++i) { const auto& source = target_->sources()[i]; const SourceFile::Type source_type = source.GetType(); switch (source_type) { case SourceFile::SOURCE_CPP: case SourceFile::SOURCE_MODULEMAP: case SourceFile::SOURCE_H: case SourceFile::SOURCE_C: case SourceFile::SOURCE_M: case SourceFile::SOURCE_MM: case SourceFile::SOURCE_S: case SourceFile::SOURCE_ASM: case SourceFile::SOURCE_O: case SourceFile::SOURCE_DEF: case SourceFile::SOURCE_GO: case SourceFile::SOURCE_RS: case SourceFile::SOURCE_RC: case SourceFile::SOURCE_SWIFT: // These are allowed. break; case SourceFile::SOURCE_UNKNOWN: case SourceFile::SOURCE_SWIFTMODULE: case SourceFile::SOURCE_NUMTYPES: *err_ = Err(scope_->GetValue(variables::kSources, true)->list_value()[i], std::string("Only source, header, and object files belong in " "the sources of a ") + Target::GetStringForOutputType(target_->output_type()) + ". " + source.value() + " is not one of the valid types."); } target_->source_types_used().Set(source_type); } return ret; } 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(scope_->settings()->build_settings(), *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::FillAllowCircularIncludesFrom() { const Value* value = scope_->GetValue(variables::kAllowCircularIncludesFrom, true); if (!value) return true; UniqueVector