| Index: tools/gn/gyp_binary_target_writer.cc
|
| diff --git a/tools/gn/gyp_binary_target_writer.cc b/tools/gn/gyp_binary_target_writer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8cc0e6c571b0a64275660471c85e5cafe14db05d
|
| --- /dev/null
|
| +++ b/tools/gn/gyp_binary_target_writer.cc
|
| @@ -0,0 +1,291 @@
|
| +// 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/gyp_binary_target_writer.h"
|
| +
|
| +#include <set>
|
| +
|
| +#include "tools/gn/config_values_extractors.h"
|
| +#include "tools/gn/err.h"
|
| +#include "tools/gn/escape.h"
|
| +#include "tools/gn/settings.h"
|
| +#include "tools/gn/target.h"
|
| +
|
| +namespace {
|
| +
|
| +// This functor is used to capture the output of RecursiveTargetConfigToStream
|
| +// in an vector.
|
| +struct StringAccumulator {
|
| + StringAccumulator(std::vector<std::string>* result_in) : result(result_in) {}
|
| +
|
| + void operator()(const std::string& s, std::ostream&) const {
|
| + result->push_back(s);
|
| + }
|
| +
|
| + std::vector<std::string>* result;
|
| +};
|
| +
|
| +// Writes the given array with the given name. The indent should be the
|
| +// indenting for the name, the values will be indented 2 spaces from there.
|
| +// Writes nothing if there is nothing in the array.
|
| +void WriteArray(std::ostream& out,
|
| + const char* name,
|
| + const std::vector<std::string>& values,
|
| + int indent) {
|
| + if (values.empty())
|
| + return;
|
| +
|
| + EscapeOptions options;
|
| + options.mode = ESCAPE_JSON;
|
| +
|
| + std::string indent_str(indent, ' ');
|
| + out << indent_str << "'" << name << "': [";
|
| + for (size_t i = 0; i < values.size(); i++) {
|
| + out << " '";
|
| + EscapeStringToStream(out, values[i], options);
|
| + out << "',";
|
| + }
|
| + out << " ],\n";
|
| +}
|
| +
|
| +struct StringWriter {
|
| + StringWriter() {
|
| + options.mode = ESCAPE_JSON;
|
| + }
|
| +
|
| + void operator()(const std::string& s, std::ostream& out) const {
|
| + out << " '";
|
| + EscapeStringToStream(out, s, options);
|
| + out << "',";
|
| + }
|
| +
|
| + EscapeOptions options;
|
| +};
|
| +
|
| +struct IncludeWriter {
|
| + IncludeWriter(const GypHelper& h) : helper(h) {
|
| + options.mode = ESCAPE_JSON;
|
| + }
|
| +
|
| + void operator()(const SourceDir& d, std::ostream& out) const {
|
| + out << " '";
|
| + EscapeStringToStream(out, helper.GetDirReference(d, false), options);
|
| + out << "',";
|
| + }
|
| +
|
| + const GypHelper& helper;
|
| + EscapeOptions options;
|
| +};
|
| +
|
| +// Returns the value from the already-filled in cflags_* for the optimization
|
| +// level to set in the GYP file. Additionally, this removes the flag from the
|
| +// given vector so we don't get duplicates.
|
| +std::string GetVCOptimization(std::vector<std::string>* cflags) {
|
| + // Searches for the "/O?" option and returns the corresponding GYP value.
|
| + for (size_t i = 0; i < cflags->size(); i++) {
|
| + const std::string& cur = (*cflags)[i];
|
| + if (cur.size() == 3 && cur[0] == '/' && cur[1] == 'O') {
|
| + char level = cur[2];
|
| + cflags->erase(cflags->begin() + i); // Invalidates |cur|!
|
| + switch (level) {
|
| + case 'd': return "'0'";
|
| + case '1': return "'1'";
|
| + case '2': return "'2'";
|
| + case 'x': return "'3'";
|
| + default: return "'2'";
|
| + }
|
| + }
|
| + }
|
| + return "'2'"; // Default value.
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +GypBinaryTargetWriter::GypBinaryTargetWriter(const Target* debug_target,
|
| + const Target* release_target,
|
| + std::ostream& out)
|
| + : GypTargetWriter(debug_target, out),
|
| + release_target_(release_target) {
|
| +}
|
| +
|
| +GypBinaryTargetWriter::~GypBinaryTargetWriter() {
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::Run() {
|
| + out_ << " {\n";
|
| +
|
| + WriteName();
|
| + WriteType();
|
| +
|
| + out_ << " 'configurations': {\n";
|
| + out_ << " 'Debug': {\n";
|
| + WriteFlags(target_);
|
| + out_ << " },\n";
|
| + out_ << " 'Release': {\n";
|
| + WriteFlags(release_target_);
|
| + out_ << " },\n";
|
| + out_ << " 'Debug_x64': {},\n";
|
| + out_ << " 'Release_x64': {},\n";
|
| + out_ << " },\n";
|
| +
|
| + WriteSources();
|
| + WriteDeps();
|
| +
|
| + out_ << " },\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteName() {
|
| + std::string name = helper_.GetNameForTarget(target_);
|
| + out_ << " 'target_name': '";
|
| + out_ << name;
|
| + out_ << "',\n";
|
| +
|
| + std::string product_name;
|
| + if (target_->output_name().empty())
|
| + product_name = target_->label().name();
|
| + else
|
| + product_name = name;
|
| +
|
| + // TODO(brettw) GN knows not to prefix targets starting with "lib" with
|
| + // another "lib" on Linux, but GYP doesn't. We need to rename applicable
|
| + // targets here.
|
| +
|
| + out_ << " 'product_name': '" << product_name << "',\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteType() {
|
| + out_ << " 'type': ";
|
| + switch (target_->output_type()) {
|
| + case Target::EXECUTABLE:
|
| + out_ << "'executable',\n";
|
| + break;
|
| + case Target::STATIC_LIBRARY:
|
| + out_ << "'static_library',\n";
|
| + break;
|
| + case Target::SHARED_LIBRARY:
|
| + out_ << "'shared_library',\n";
|
| + break;
|
| + case Target::SOURCE_SET:
|
| + out_ << "'static_library',\n"; // TODO(brettw) fixme.
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +
|
| + if (target_->hard_dep())
|
| + out_ << " 'hard_dependency': 1,\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteFlags(const Target* target) {
|
| + WriteDefines(target);
|
| + WriteIncludes(target);
|
| + if (target->settings()->IsWin())
|
| + WriteVCFlags(target);
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteDefines(const Target* target) {
|
| + out_ << " 'defines': [";
|
| + RecursiveTargetConfigToStream<std::string>(target, &ConfigValues::defines,
|
| + StringWriter(), out_);
|
| + out_ << " ],\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteIncludes(const Target* target) {
|
| + out_ << " 'include_dirs': [";
|
| + RecursiveTargetConfigToStream<SourceDir>(target, &ConfigValues::include_dirs,
|
| + IncludeWriter(helper_), out_);
|
| + out_ << " ],\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteVCFlags(const Target* target) {
|
| + // C flags.
|
| + out_ << " 'msvs_settings': {\n";
|
| + out_ << " 'VCCLCompilerTool': {\n";
|
| +
|
| + std::vector<std::string> cflags;
|
| + StringAccumulator acc(&cflags);
|
| + RecursiveTargetConfigToStream<std::string>(target, &ConfigValues::cflags,
|
| + acc, out_);
|
| + // GYP always uses the VC optimization flag to add a /O? on Visual Studio.
|
| + // This can produce duplicate values. So look up the GYP value corresponding
|
| + // to the flags used, and set the same one.
|
| + std::string optimization = GetVCOptimization(&cflags);
|
| + WriteArray(out_, "AdditionalOptions", cflags, 14);
|
| + // TODO(brettw) cflags_c and cflags_cc!
|
| + out_ << " 'Optimization': " << optimization << ",\n";
|
| + out_ << " },\n";
|
| +
|
| + // Linker tool stuff.
|
| + out_ << " 'VCLinkerTool': {\n";
|
| +
|
| + // ...Library dirs.
|
| + EscapeOptions escape_options;
|
| + escape_options.mode = ESCAPE_JSON;
|
| + const OrderedSet<SourceDir> all_lib_dirs = target->all_lib_dirs();
|
| + if (!all_lib_dirs.empty()) {
|
| + out_ << " 'AdditionalLibraryDirectories': [";
|
| + for (size_t i = 0; i < all_lib_dirs.size(); i++) {
|
| + out_ << " '";
|
| + EscapeStringToStream(out_,
|
| + helper_.GetDirReference(all_lib_dirs[i], false),
|
| + escape_options);
|
| + out_ << "',";
|
| + }
|
| + out_ << " ],\n";
|
| + }
|
| +
|
| + // ...Libraries.
|
| + const OrderedSet<std::string> all_libs = target->all_libs();
|
| + if (!all_libs.empty()) {
|
| + out_ << " 'AdditionalDependencies': [";
|
| + for (size_t i = 0; i < all_libs.size(); i++) {
|
| + out_ << " '";
|
| + EscapeStringToStream(out_, all_libs[i], escape_options);
|
| + out_ << "',";
|
| + }
|
| + out_ << " ],\n";
|
| + }
|
| +
|
| + // ...LD flags.
|
| + // TODO(brettw) EnableUAC defaults to on and needs to be set. Also
|
| + // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false.
|
| + std::vector<std::string> ldflags;
|
| + acc.result = &ldflags;
|
| + RecursiveTargetConfigToStream<std::string>(target, &ConfigValues::ldflags,
|
| + acc, out_);
|
| + WriteArray(out_, "AdditionalOptions", ldflags, 14);
|
| + out_ << " },\n";
|
| +
|
| + out_ << " },\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteSources() {
|
| + out_ << " 'sources': [\n";
|
| +
|
| + const Target::FileList& sources = target_->sources();
|
| + for (size_t i = 0; i < sources.size(); i++) {
|
| + const SourceFile& input_file = sources[i];
|
| + out_ << " '" << helper_.GetFileReference(input_file) << "',\n";
|
| + }
|
| +
|
| + out_ << " ],\n";
|
| +}
|
| +
|
| +void GypBinaryTargetWriter::WriteDeps() {
|
| + const std::vector<const Target*>& deps = target_->deps();
|
| + if (deps.empty())
|
| + return;
|
| +
|
| + EscapeOptions escape_options;
|
| + escape_options.mode = ESCAPE_JSON;
|
| +
|
| + out_ << " 'dependencies': [\n";
|
| + for (size_t i = 0; i < deps.size(); i++) {
|
| + out_ << " '";
|
| + EscapeStringToStream(out_, helper_.GetFullRefForTarget(deps[i]),
|
| + escape_options);
|
| + out_ << "',\n";
|
| + }
|
| + out_ << " ],\n";
|
| +}
|
|
|