Commit 05316e06 authored by dpranke's avatar dpranke Committed by Commit bot

Re-land r406064 "[GN] Add JSON project writer".

This re-lands the CL with the fixes to the GYP build.

TBR=brettw@chromium.org
CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win8_chromium_gyp_rel,win8_chromium_gyp_dbg;tryserver.chromium.mac:mac_chromium_gyp_rel,mac_chromium_gyp_dbg

Review-Url: https://codereview.chromium.org/2156173003
Cr-Commit-Position: refs/heads/master@{#406165}
parent 1c26c544
...@@ -408,6 +408,7 @@ Martin Bednorz <m.s.bednorz@gmail.com> ...@@ -408,6 +408,7 @@ Martin Bednorz <m.s.bednorz@gmail.com>
Martina Kollarova <martina.kollarova@intel.com> Martina Kollarova <martina.kollarova@intel.com>
Masahiro Yado <yado.masa@gmail.com> Masahiro Yado <yado.masa@gmail.com>
Masaru Nishida <msr.i386@gmail.com> Masaru Nishida <msr.i386@gmail.com>
Matej Knopp <matej.knopp@gmail.com>
Matheus Bratfisch <matheusbrat@gmail.com> Matheus Bratfisch <matheusbrat@gmail.com>
Mathias Bynens <mathias@qiwi.be> Mathias Bynens <mathias@qiwi.be>
Mathieu Meisser <mmeisser@logitech.com> Mathieu Meisser <mmeisser@logitech.com>
......
...@@ -58,6 +58,8 @@ static_library("gn_lib") { ...@@ -58,6 +58,8 @@ static_library("gn_lib") {
"create_bundle_target_generator.h", "create_bundle_target_generator.h",
"deps_iterator.cc", "deps_iterator.cc",
"deps_iterator.h", "deps_iterator.h",
"desc_builder.cc",
"desc_builder.h",
"eclipse_writer.cc", "eclipse_writer.cc",
"eclipse_writer.h", "eclipse_writer.h",
"err.cc", "err.cc",
...@@ -101,6 +103,8 @@ static_library("gn_lib") { ...@@ -101,6 +103,8 @@ static_library("gn_lib") {
"input_file_manager.h", "input_file_manager.h",
"item.cc", "item.cc",
"item.h", "item.h",
"json_project_writer.cc",
"json_project_writer.h",
"label.cc", "label.cc",
"label.h", "label.h",
"label_pattern.cc", "label_pattern.cc",
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "tools/gn/build_settings.h" #include "tools/gn/build_settings.h"
#include "tools/gn/commands.h" #include "tools/gn/commands.h"
#include "tools/gn/eclipse_writer.h" #include "tools/gn/eclipse_writer.h"
#include "tools/gn/json_project_writer.h"
#include "tools/gn/ninja_target_writer.h" #include "tools/gn/ninja_target_writer.h"
#include "tools/gn/ninja_writer.h" #include "tools/gn/ninja_writer.h"
#include "tools/gn/qt_creator_writer.h" #include "tools/gn/qt_creator_writer.h"
...@@ -36,10 +37,14 @@ const char kSwitchIdeValueVs[] = "vs"; ...@@ -36,10 +37,14 @@ const char kSwitchIdeValueVs[] = "vs";
const char kSwitchIdeValueVs2013[] = "vs2013"; const char kSwitchIdeValueVs2013[] = "vs2013";
const char kSwitchIdeValueVs2015[] = "vs2015"; const char kSwitchIdeValueVs2015[] = "vs2015";
const char kSwitchIdeValueXcode[] = "xcode"; const char kSwitchIdeValueXcode[] = "xcode";
const char kSwitchIdeValueJson[] = "json";
const char kSwitchNinjaExtraArgs[] = "ninja-extra-args"; const char kSwitchNinjaExtraArgs[] = "ninja-extra-args";
const char kSwitchRootTarget[] = "root-target"; const char kSwitchRootTarget[] = "root-target";
const char kSwitchSln[] = "sln"; const char kSwitchSln[] = "sln";
const char kSwitchWorkspace[] = "workspace"; const char kSwitchWorkspace[] = "workspace";
const char kSwitchJsonFileName[] = "json-file-name";
const char kSwitchJsonIdeScript[] = "json-ide-script";
const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args";
// Called on worker thread to write the ninja file. // Called on worker thread to write the ninja file.
void BackgroundDoWrite(const Target* target) { void BackgroundDoWrite(const Target* target) {
...@@ -113,7 +118,7 @@ void PrintInvalidGeneratedInput(const Builder* builder, ...@@ -113,7 +118,7 @@ void PrintInvalidGeneratedInput(const Builder* builder,
if (generator) { if (generator) {
err += "but this file was not generated by any dependencies of the " + err += "but this file was not generated by any dependencies of the " +
target_str + ". The target\nthat generates the file is:\n "; target_str + ". The target\nthat generates the file is:\n ";
err += generator->label().GetUserVisibleName(show_toolchains); err += generator->label().GetUserVisibleName(show_toolchains);
} else { } else {
err += "but no targets in the build generate that file."; err += "but no targets in the build generate that file.";
...@@ -166,11 +171,12 @@ bool RunIdeWriter(const std::string& ide, ...@@ -166,11 +171,12 @@ bool RunIdeWriter(const std::string& ide,
Err* err) { Err* err) {
const base::CommandLine* command_line = const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess(); base::CommandLine::ForCurrentProcess();
bool quiet = command_line->HasSwitch(switches::kQuiet);
base::ElapsedTimer timer; base::ElapsedTimer timer;
if (ide == kSwitchIdeValueEclipse) { if (ide == kSwitchIdeValueEclipse) {
bool res = EclipseWriter::RunAndWriteFile(build_settings, builder, err); bool res = EclipseWriter::RunAndWriteFile(build_settings, builder, err);
if (res && !command_line->HasSwitch(switches::kQuiet)) { if (res && !quiet) {
OutputString("Generating Eclipse settings took " + OutputString("Generating Eclipse settings took " +
base::Int64ToString(timer.Elapsed().InMilliseconds()) + base::Int64ToString(timer.Elapsed().InMilliseconds()) +
"ms\n"); "ms\n");
...@@ -189,7 +195,7 @@ bool RunIdeWriter(const std::string& ide, ...@@ -189,7 +195,7 @@ bool RunIdeWriter(const std::string& ide,
filters = command_line->GetSwitchValueASCII(kSwitchFilters); filters = command_line->GetSwitchValueASCII(kSwitchFilters);
bool res = VisualStudioWriter::RunAndWriteFiles( bool res = VisualStudioWriter::RunAndWriteFiles(
build_settings, builder, version, sln_name, filters, err); build_settings, builder, version, sln_name, filters, err);
if (res && !command_line->HasSwitch(switches::kQuiet)) { if (res && !quiet) {
OutputString("Generating Visual Studio projects took " + OutputString("Generating Visual Studio projects took " +
base::Int64ToString(timer.Elapsed().InMilliseconds()) + base::Int64ToString(timer.Elapsed().InMilliseconds()) +
"ms\n"); "ms\n");
...@@ -202,7 +208,7 @@ bool RunIdeWriter(const std::string& ide, ...@@ -202,7 +208,7 @@ bool RunIdeWriter(const std::string& ide,
command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs), command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs),
command_line->GetSwitchValueASCII(kSwitchFilters), build_settings, command_line->GetSwitchValueASCII(kSwitchFilters), build_settings,
builder, err); builder, err);
if (res && !command_line->HasSwitch(switches::kQuiet)) { if (res && !quiet) {
OutputString("Generating Xcode projects took " + OutputString("Generating Xcode projects took " +
base::Int64ToString(timer.Elapsed().InMilliseconds()) + base::Int64ToString(timer.Elapsed().InMilliseconds()) +
"ms\n"); "ms\n");
...@@ -214,12 +220,32 @@ bool RunIdeWriter(const std::string& ide, ...@@ -214,12 +220,32 @@ bool RunIdeWriter(const std::string& ide,
root_target = command_line->GetSwitchValueASCII(kSwitchRootTarget); root_target = command_line->GetSwitchValueASCII(kSwitchRootTarget);
bool res = QtCreatorWriter::RunAndWriteFile(build_settings, builder, err, bool res = QtCreatorWriter::RunAndWriteFile(build_settings, builder, err,
root_target); root_target);
if (res && !command_line->HasSwitch(switches::kQuiet)) { if (res && !quiet) {
OutputString("Generating QtCreator projects took " + OutputString("Generating QtCreator projects took " +
base::Int64ToString(timer.Elapsed().InMilliseconds()) + base::Int64ToString(timer.Elapsed().InMilliseconds()) +
"ms\n"); "ms\n");
} }
return res; return res;
} else if (ide == kSwitchIdeValueJson) {
std::string file_name =
command_line->GetSwitchValueASCII(kSwitchJsonFileName);
if (file_name.empty())
file_name = "project.json";
std::string exec_script =
command_line->GetSwitchValueASCII(kSwitchJsonIdeScript);
std::string exec_script_extra_args =
command_line->GetSwitchValueASCII(kSwitchJsonIdeScriptArgs);
std::string filters = command_line->GetSwitchValueASCII(kSwitchFilters);
bool res = JSONProjectWriter::RunAndWriteFiles(
build_settings, builder, file_name, exec_script, exec_script_extra_args,
filters, quiet, err);
if (res && !quiet) {
OutputString("Generating JSON projects took " +
base::Int64ToString(timer.Elapsed().InMilliseconds()) +
"ms\n");
}
return res;
} }
*err = Err(Location(), "Unknown IDE: " + ide); *err = Err(Location(), "Unknown IDE: " + ide);
...@@ -229,8 +255,7 @@ bool RunIdeWriter(const std::string& ide, ...@@ -229,8 +255,7 @@ bool RunIdeWriter(const std::string& ide,
} // namespace } // namespace
const char kGen[] = "gen"; const char kGen[] = "gen";
const char kGen_HelpShort[] = const char kGen_HelpShort[] = "gen: Generate ninja files.";
"gen: Generate ninja files.";
const char kGen_Help[] = const char kGen_Help[] =
"gn gen: Generate ninja files.\n" "gn gen: Generate ninja files.\n"
"\n" "\n"
...@@ -259,12 +284,13 @@ const char kGen_Help[] = ...@@ -259,12 +284,13 @@ const char kGen_Help[] =
" \"vs2015\" - Visual Studio 2015 project/solution files.\n" " \"vs2015\" - Visual Studio 2015 project/solution files.\n"
" \"xcode\" - Xcode workspace/solution files.\n" " \"xcode\" - Xcode workspace/solution files.\n"
" \"qtcreator\" - QtCreator project files.\n" " \"qtcreator\" - QtCreator project files.\n"
" \"json\" - JSON file containing target information\n"
"\n" "\n"
" --filters=<path_prefixes>\n" " --filters=<path_prefixes>\n"
" Semicolon-separated list of label patterns used to limit the set\n" " Semicolon-separated list of label patterns used to limit the set\n"
" of generated projects (see \"gn help label_pattern\"). Only\n" " of generated projects (see \"gn help label_pattern\"). Only\n"
" matching targets and their dependencies will be included in the\n" " matching targets and their dependencies will be included in the\n"
" solution. Only used for Visual Studio and Xcode.\n" " solution. Only used for Visual Studio, Xcode and JSON.\n"
"\n" "\n"
"Visual Studio Flags\n" "Visual Studio Flags\n"
"\n" "\n"
...@@ -305,7 +331,27 @@ const char kGen_Help[] = ...@@ -305,7 +331,27 @@ const char kGen_Help[] =
" properly define includes/defines for each file individually.\n" " properly define includes/defines for each file individually.\n"
" Instead, one set of includes/defines is generated for the entire\n" " Instead, one set of includes/defines is generated for the entire\n"
" project. This works fairly well but may still result in a few indexer\n" " project. This works fairly well but may still result in a few indexer\n"
" issues here and there.\n"; " issues here and there.\n"
"\n"
"Generic JSON Output\n"
"\n"
" Dumps target information to JSON file and optionally invokes python\n"
" script on generated file. \n"
" See comments at the beginning of json_project_writer.cc and\n"
" desc_builder.cc for overview of JSON file format.\n"
"\n"
" --json-file-name=<json_file_name>\n"
" Overrides default file name (project.json) of generated JSON file.\n"
"\n"
" --json-ide-script=<path_to_python_script>\n"
" Executes python script after the JSON file is generated.\n"
" Path can be project absolute (//), system absolute (/) or\n"
" relative, in which case the output directory will be base.\n"
" Path to generated JSON file will be first argument when invoking\n"
" script.\n"
"\n"
" --json-ide-script-args=<argument>\n"
" Optional second argument that will passed to executed script.\n";
int RunGen(const std::vector<std::string>& args) { int RunGen(const std::vector<std::string>& args) {
base::ElapsedTimer timer; base::ElapsedTimer timer;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/values.h"
#include "tools/gn/builder.h" #include "tools/gn/builder.h"
#include "tools/gn/filesystem_utils.h" #include "tools/gn/filesystem_utils.h"
#include "tools/gn/item.h" #include "tools/gn/item.h"
...@@ -280,22 +281,20 @@ base::FilePath BuildFileForItem(const Item* item) { ...@@ -280,22 +281,20 @@ base::FilePath BuildFileForItem(const Item* item) {
return item->defined_from()->GetRange().begin().file()->physical_name(); return item->defined_from()->GetRange().begin().file()->physical_name();
} }
void PrintTargetsAsBuildfiles(bool indent, void PrintTargetsAsBuildfiles(const std::vector<const Target*>& targets,
const std::vector<const Target*>& targets) { base::ListValue* out) {
// Output the set of unique source files. // Output the set of unique source files.
std::set<std::string> unique_files; std::set<std::string> unique_files;
for (const Target* target : targets) for (const Target* target : targets)
unique_files.insert(FilePathToUTF8(BuildFileForItem(target))); unique_files.insert(FilePathToUTF8(BuildFileForItem(target)));
for (const std::string& file : unique_files) { for (const std::string& file : unique_files) {
if (indent) out->AppendString(file);
OutputString(" ");
OutputString(file + "\n");
} }
} }
void PrintTargetsAsLabels(bool indent, void PrintTargetsAsLabels(const std::vector<const Target*>& targets,
const std::vector<const Target*>& targets) { base::ListValue* out) {
// Putting the labels into a set automatically sorts them for us. // Putting the labels into a set automatically sorts them for us.
std::set<Label> unique_labels; std::set<Label> unique_labels;
for (auto* target : targets) for (auto* target : targets)
...@@ -307,16 +306,13 @@ void PrintTargetsAsLabels(bool indent, ...@@ -307,16 +306,13 @@ void PrintTargetsAsLabels(bool indent,
for (const Label& label : unique_labels) { for (const Label& label : unique_labels) {
// Print toolchain only for ones not in the default toolchain. // Print toolchain only for ones not in the default toolchain.
if (indent) out->AppendString(label.GetUserVisibleName(label.GetToolchainLabel() !=
OutputString(" "); default_tc_label));
OutputString(label.GetUserVisibleName(
label.GetToolchainLabel() != default_tc_label));
OutputString("\n");
} }
} }
void PrintTargetsAsOutputs(bool indent, void PrintTargetsAsOutputs(const std::vector<const Target*>& targets,
const std::vector<const Target*>& targets) { base::ListValue* out) {
if (targets.empty()) if (targets.empty())
return; return;
...@@ -336,10 +332,7 @@ void PrintTargetsAsOutputs(bool indent, ...@@ -336,10 +332,7 @@ void PrintTargetsAsOutputs(bool indent,
std::string result = RebasePath(output_as_source.value(), std::string result = RebasePath(output_as_source.value(),
build_settings->build_dir(), build_settings->build_dir(),
build_settings->root_path_utf8()); build_settings->root_path_utf8());
if (indent) out->AppendString(result);
OutputString(" ");
OutputString(result);
OutputString("\n");
} }
} }
...@@ -490,7 +483,8 @@ bool FilterPatternsFromString(const BuildSettings* build_settings, ...@@ -490,7 +483,8 @@ bool FilterPatternsFromString(const BuildSettings* build_settings,
return true; return true;
} }
void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) { void FilterAndPrintTargets(std::vector<const Target*>* targets,
base::ListValue* out) {
if (targets->empty()) if (targets->empty())
return; return;
...@@ -504,21 +498,40 @@ void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) { ...@@ -504,21 +498,40 @@ void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
return; return;
switch (printing_mode) { switch (printing_mode) {
case TARGET_PRINT_BUILDFILE: case TARGET_PRINT_BUILDFILE:
PrintTargetsAsBuildfiles(indent, *targets); PrintTargetsAsBuildfiles(*targets, out);
break; break;
case TARGET_PRINT_LABEL: case TARGET_PRINT_LABEL:
PrintTargetsAsLabels(indent, *targets); PrintTargetsAsLabels(*targets, out);
break; break;
case TARGET_PRINT_OUTPUT: case TARGET_PRINT_OUTPUT:
PrintTargetsAsOutputs(indent, *targets); PrintTargetsAsOutputs(*targets, out);
break; break;
} }
} }
void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
base::ListValue tmp;
FilterAndPrintTargets(targets, &tmp);
for (const auto& value : tmp) {
std::string string;
value->GetAsString(&string);
if (indent)
OutputString(" ");
OutputString(string);
OutputString("\n");
}
}
void FilterAndPrintTargetSet(bool indent, void FilterAndPrintTargetSet(bool indent,
const std::set<const Target*>& targets) { const std::set<const Target*>& targets) {
std::vector<const Target*> target_vector(targets.begin(), targets.end()); std::vector<const Target*> target_vector(targets.begin(), targets.end());
FilterAndPrintTargets(indent, &target_vector); FilterAndPrintTargets(indent, &target_vector);
} }
void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
base::ListValue* out) {
std::vector<const Target*> target_vector(targets.begin(), targets.end());
FilterAndPrintTargets(&target_vector, out);
}
} // namespace commands } // namespace commands
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/values.h"
#include "tools/gn/target.h" #include "tools/gn/target.h"
#include "tools/gn/unique_vector.h" #include "tools/gn/unique_vector.h"
...@@ -179,8 +180,13 @@ bool FilterPatternsFromString(const BuildSettings* build_settings, ...@@ -179,8 +180,13 @@ bool FilterPatternsFromString(const BuildSettings* build_settings,
// //
// The vector will be modified so that only the printed targets will remain. // The vector will be modified so that only the printed targets will remain.
void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets); void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets);
void FilterAndPrintTargets(std::vector<const Target*>* targets,
base::ListValue* out);
void FilterAndPrintTargetSet(bool indent, void FilterAndPrintTargetSet(bool indent,
const std::set<const Target*>& targets); const std::set<const Target*>& targets);
void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
base::ListValue* out);
// Extra help from command_check.cc // Extra help from command_check.cc
extern const char kNoGnCheck_Help[]; extern const char kNoGnCheck_Help[];
......
This diff is collapsed.
// Copyright (c) 2016 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.
#ifndef TOOLS_GN_DESC_BUILDER_H_
#define TOOLS_GN_DESC_BUILDER_H_
#include "base/values.h"
#include "tools/gn/target.h"
class DescBuilder {
public:
// Creates Dictionary representation for given target
static std::unique_ptr<base::DictionaryValue> DescriptionForTarget(
const Target* target,
const std::string& what,
bool all,
bool tree,
bool blame);
// Creates Dictionary representation for given config
static std::unique_ptr<base::DictionaryValue> DescriptionForConfig(
const Config* config,
const std::string& what);
};
#endif
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
'create_bundle_target_generator.h', 'create_bundle_target_generator.h',
'deps_iterator.cc', 'deps_iterator.cc',
'deps_iterator.h', 'deps_iterator.h',
'desc_builder.cc',
'desc_builder.h',
'eclipse_writer.cc', 'eclipse_writer.cc',
'eclipse_writer.h', 'eclipse_writer.h',
'err.cc', 'err.cc',
...@@ -101,6 +103,8 @@ ...@@ -101,6 +103,8 @@
'input_file_manager.h', 'input_file_manager.h',
'item.cc', 'item.cc',
'item.h', 'item.h',
'json_project_writer.cc',
'json_project_writer.h',
'label.cc', 'label.cc',
'label.h', 'label.h',
'label_pattern.cc', 'label_pattern.cc',
......
// Copyright (c) 2016 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/json_project_writer.h"
#include <iostream>
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "tools/gn/builder.h"
#include "tools/gn/commands.h"
#include "tools/gn/deps_iterator.h"
#include "tools/gn/desc_builder.h"
#include "tools/gn/exec_process.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/settings.h"
// Structure of JSON output file
// {
// "build_settings" = {
// "root_path" : "absolute path of project root",
// "build_dir" : "build directory (project relative)",
// "default_toolchain" : "name of default toolchain"
// }
// "targets" = {
// "target x name" : { target x properties },
// "target y name" : { target y properties },
// ...
// }
// }
// See desc_builder.cc for overview of target properties
namespace {
void AddTargetDependencies(const Target* target,
std::set<const Target*>* deps) {
for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) {
if (deps->find(pair.ptr) == deps->end()) {
deps->insert(pair.ptr);
AddTargetDependencies(pair.ptr, deps);
}
}
}
// Filters targets according to filter string; Will also recursively
// add dependent targets.
bool FilterTargets(const BuildSettings* build_settings,
std::vector<const Target*>& all_targets,
std::vector<const Target*>* targets,
const std::string& dir_filter_string,
Err* err) {
if (dir_filter_string.empty()) {
*targets = all_targets;
} else {
targets->reserve(all_targets.size());
std::vector<LabelPattern> filters;
if (!commands::FilterPatternsFromString(build_settings, dir_filter_string,
&filters, err)) {
return false;
}
commands::FilterTargetsByPatterns(all_targets, filters, targets);
std::set<const Target*> target_set(targets->begin(), targets->end());
for (const auto* target : *targets)
AddTargetDependencies(target, &target_set);
targets->clear();
targets->insert(targets->end(), target_set.begin(), target_set.end());
}
// Sort the list of targets per-label to get a consistent ordering of them
// in the generated project (and thus stability of the file generated).
std::sort(targets->begin(), targets->end(),
[](const Target* a, const Target* b) {
return a->label().name() < b->label().name();
});
return true;
}
std::string RenderJSON(const BuildSettings* build_settings,
const Builder* builder,
std::vector<const Target*>& all_targets) {
Label default_toolchain_label;
auto targets = base::WrapUnique(new base::DictionaryValue());
for (const auto* target : all_targets) {
if (default_toolchain_label.is_null())
default_toolchain_label = target->settings()->default_toolchain_label();
auto description =
DescBuilder::DescriptionForTarget(target, "", false, false, false);
// Outputs need to be asked for separately.
auto outputs = DescBuilder::DescriptionForTarget(target, "source_outputs",
false, false, false);
base::DictionaryValue* outputs_value = nullptr;
if (outputs->GetDictionary("source_outputs", &outputs_value) &&
!outputs_value->empty()) {
description->MergeDictionary(outputs.get());
}
targets->Set(target->label().GetUserVisibleName(default_toolchain_label),
std::move(description));
}
auto settings = base::WrapUnique(new base::DictionaryValue());
settings->SetString("root_path", build_settings->root_path_utf8());
settings->SetString("build_dir", build_settings->build_dir().value());
settings->SetString("default_toolchain",
default_toolchain_label.GetUserVisibleName(false));
auto output = base::WrapUnique(new base::DictionaryValue());
output->Set("targets", std::move(targets));
output->Set("build_settings", std::move(settings));
std::string s;
base::JSONWriter::WriteWithOptions(
*output.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
return s;
}
bool InvokePython(const BuildSettings* build_settings,
const base::FilePath& python_script_path,
const std::string& python_script_extra_args,
const base::FilePath& output_path,
bool quiet,
Err* err) {
const base::FilePath& python_path = build_settings->python_path();
base::CommandLine cmdline(python_path);
cmdline.AppendArg("--");
cmdline.AppendArgPath(python_script_path);
cmdline.AppendArgPath(output_path);
if (!python_script_extra_args.empty()) {
cmdline.AppendArg(python_script_extra_args);
}
base::FilePath startup_dir =
build_settings->GetFullPath(build_settings->build_dir());
std::string output;
std::string stderr_output;
int exit_code = 0;
if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
&exit_code)) {
*err =
Err(Location(), "Could not execute python.",
"I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
return false;
}
if (!quiet) {
std::cout << output;
std::cerr << stderr_output;
}
if (exit_code != 0) {
*err = Err(Location(), "Python has quit with exit code " +
base::IntToString(exit_code) + ".");
return false;
}
return true;
}
} // namespace
bool JSONProjectWriter::RunAndWriteFiles(
const BuildSettings* build_settings,
const Builder* builder,
const std::string& file_name,
const std::string& exec_script,
const std::string& exec_script_extra_args,
const std::string& dir_filter_string,
bool quiet,
Err* err) {
SourceFile output_file = build_settings->build_dir().ResolveRelativeFile(
Value(nullptr, file_name), err);
if (output_file.is_null()) {
return false;
}
base::FilePath output_path = build_settings->GetFullPath(output_file);
std::vector<const Target*> all_targets = builder->GetAllResolvedTargets();
std::vector<const Target*> targets;
if (!FilterTargets(build_settings, all_targets, &targets, dir_filter_string,
err)) {
return false;
}
std::string json = RenderJSON(build_settings, builder, targets);
if (!ContentsEqual(output_path, json)) {
if (!WriteFileIfChanged(output_path, json, err)) {
return false;
}
if (!exec_script.empty()) {
SourceFile script_file;
if (exec_script[0] != '/') {
// Relative path, assume the base is in build_dir.
script_file = build_settings->build_dir().ResolveRelativeFile(
Value(nullptr, exec_script), err);
if (script_file.is_null()) {
return false;
}
} else {
script_file = SourceFile(exec_script);
}
base::FilePath script_path = build_settings->GetFullPath(script_file);
return InvokePython(build_settings, script_path, exec_script_extra_args,
output_path, quiet, err);
}
}
return true;
}
// Copyright (c) 2016 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.
#ifndef TOOLS_GN_JSON_WRITER_H_
#define TOOLS_GN_JSON_WRITER_H_
#include "tools/gn/err.h"
#include "tools/gn/target.h"
class Builder;
class BuildSettings;
class JSONProjectWriter {
public:
static bool RunAndWriteFiles(const BuildSettings* build_setting,
const Builder* builder,
const std::string& file_name,
const std::string& exec_script,
const std::string& exec_script_extra_args,
const std::string& dir_filter_string,
bool quiet,
Err* err);
};
#endif
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "tools/gn/config_values_extractors.h" #include "tools/gn/config_values_extractors.h"
#include "tools/gn/deps_iterator.h" #include "tools/gn/deps_iterator.h"
#include "tools/gn/filesystem_utils.h" #include "tools/gn/filesystem_utils.h"
#include "tools/gn/functions.h"
#include "tools/gn/scheduler.h" #include "tools/gn/scheduler.h"
#include "tools/gn/source_file_type.h" #include "tools/gn/source_file_type.h"
#include "tools/gn/substitution_writer.h" #include "tools/gn/substitution_writer.h"
...@@ -215,29 +216,29 @@ Target::~Target() { ...@@ -215,29 +216,29 @@ Target::~Target() {
const char* Target::GetStringForOutputType(OutputType type) { const char* Target::GetStringForOutputType(OutputType type) {
switch (type) { switch (type) {
case UNKNOWN: case UNKNOWN:
return "Unknown"; return "unknown";
case GROUP: case GROUP:
return "Group"; return functions::kGroup;
case EXECUTABLE: case EXECUTABLE:
return "Executable"; return functions::kExecutable;
case LOADABLE_MODULE: case LOADABLE_MODULE:
return "Loadable module"; return functions::kLoadableModule;
case SHARED_LIBRARY: case SHARED_LIBRARY:
return "Shared library"; return functions::kSharedLibrary;
case STATIC_LIBRARY: case STATIC_LIBRARY:
return "Static library"; return functions::kStaticLibrary;
case SOURCE_SET: case SOURCE_SET:
return "Source set"; return functions::kSourceSet;
case COPY_FILES: case COPY_FILES:
return "Copy"; return functions::kCopy;
case ACTION: case ACTION:
return "Action"; return functions::kAction;
case ACTION_FOREACH: case ACTION_FOREACH:
return "ActionForEach"; return functions::kActionForEach;
case BUNDLE_DATA: case BUNDLE_DATA:
return "Bundle data"; return functions::kBundleData;
case CREATE_BUNDLE: case CREATE_BUNDLE:
return "Create bundle"; return functions::kCreateBundle;
default: default:
return ""; return "";
} }
......
...@@ -4,8 +4,10 @@ ...@@ -4,8 +4,10 @@
#include "tools/gn/visibility.h" #include "tools/gn/visibility.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/values.h"
#include "tools/gn/err.h" #include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h" #include "tools/gn/filesystem_utils.h"
#include "tools/gn/item.h" #include "tools/gn/item.h"
...@@ -83,6 +85,14 @@ std::string Visibility::Describe(int indent, bool include_brackets) const { ...@@ -83,6 +85,14 @@ std::string Visibility::Describe(int indent, bool include_brackets) const {
return result; return result;
} }
std::unique_ptr<base::Value> Visibility::AsValue() const {
auto* res = new base::ListValue();
for (const auto& pattern : patterns_)
res->AppendString(pattern.Describe());
return WrapUnique(res);
}
// static // static
bool Visibility::CheckItemVisibility(const Item* from, bool Visibility::CheckItemVisibility(const Item* from,
const Item* to, const Item* to,
...@@ -93,7 +103,7 @@ bool Visibility::CheckItemVisibility(const Item* from, ...@@ -93,7 +103,7 @@ bool Visibility::CheckItemVisibility(const Item* from,
"The item " + from->label().GetUserVisibleName(false) + "\n" "The item " + from->label().GetUserVisibleName(false) + "\n"
"can not depend on " + to_label + "\n" "can not depend on " + to_label + "\n"
"because it is not in " + to_label + "'s visibility list: " + "because it is not in " + to_label + "'s visibility list: " +
to->visibility().Describe(0, true)); to->visibility().Describe(0, true));
return false; return false;
} }
return true; return true;
......
...@@ -5,12 +5,17 @@ ...@@ -5,12 +5,17 @@
#ifndef TOOLS_GN_VISIBILITY_H_ #ifndef TOOLS_GN_VISIBILITY_H_
#define TOOLS_GN_VISIBILITY_H_ #define TOOLS_GN_VISIBILITY_H_
#include <memory>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "tools/gn/label_pattern.h" #include "tools/gn/label_pattern.h"
#include "tools/gn/source_dir.h" #include "tools/gn/source_dir.h"
namespace base {
class Value;
}
class Err; class Err;
class Item; class Item;
class Label; class Label;
...@@ -43,6 +48,9 @@ class Visibility { ...@@ -43,6 +48,9 @@ class Visibility {
// result will end in a newline. // result will end in a newline.
std::string Describe(int indent, bool include_brackets) const; std::string Describe(int indent, bool include_brackets) const;
// Returns value representation of this visibility
std::unique_ptr<base::Value> AsValue() const;
// Helper function to check visibility between the given two items. If // Helper function to check visibility between the given two items. If
// to is invisible to from, returns false and sets the error. // to is invisible to from, returns false and sets the error.
static bool CheckItemVisibility(const Item* from, const Item* to, Err* err); static bool CheckItemVisibility(const Item* from, const Item* to, Err* err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment