| Index: tools/gn/command_analyze.cc
|
| diff --git a/tools/gn/command_analyze.cc b/tools/gn/command_analyze.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..08740e0890c50359a3b14e53595abc40ce76328e
|
| --- /dev/null
|
| +++ b/tools/gn/command_analyze.cc
|
| @@ -0,0 +1,121 @@
|
| +// 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 <algorithm>
|
| +#include <iterator>
|
| +#include <set>
|
| +#include <vector>
|
| +
|
| +#include "base/files/file_path.h"
|
| +#include "base/files/file_util.h"
|
| +#include "tools/gn/commands.h"
|
| +#include "tools/gn/filesystem_utils.h"
|
| +#include "tools/gn/graph.h"
|
| +#include "tools/gn/location.h"
|
| +#include "tools/gn/setup.h"
|
| +
|
| +namespace commands {
|
| +
|
| +const char kAnalyze[] = "analyze";
|
| +const char kAnalyze_HelpShort[] =
|
| + "analyze: Analyze which targets are affected by a list of files.";
|
| +const char kAnalyze_Help[] =
|
| + "gn analyze <out_dir> <input_path> <output_path>\n"
|
| + "\n"
|
| + " Analyze which targets are affected by a list of files.\n"
|
| + "\n"
|
| + " This command takes two arguments, input_path and output_path\n"
|
| + "\n"
|
| + " input_path is a path to a JSON file containing a dict with three\n"
|
| + " keys:\n"
|
| + "\n"
|
| + " - \"files\": A list of the filenames to check.\n"
|
| + "\n"
|
| + " - \"test_targets\": An list of the labels for targets that\n"
|
| + " are needed to run the tests we wish to run.\n"
|
| + "\n"
|
| + " - \"compile_targets\": A list of the labels targets that we wish to\n"
|
| + " rebuild, but aren't necessarily needed for testing. The\n"
|
| + " important difference between this field and \"test_targets\"\n"
|
| + " is that if an item in the compile_targets list is a group, then\n"
|
| + " any dependencies of that group will be returned if they are out\n"
|
| + " of date, but the group itself does not need to be. If the\n"
|
| + " dependencies themselves are groups, the same filtering is\n"
|
| + " repeated. This filtering can be used to avoid rebuilding\n"
|
| + " dependencies of a group that are unaffected by the input files.\n"
|
| + " The list may contain the string \"all\" to refer to a\n"
|
| + " pseudo-group that contains every root target in the build graph.\n"
|
| + "\n"
|
| + " output_path is a path indicating where the results of the command\n"
|
| + " are to be written. The results will be a JSON file containing a dict\n"
|
| + " with one or more of following keys:\n"
|
| + "\n"
|
| + " - \"compile_targets\": A list of the labels derived from the input\n"
|
| + " compile_targets list that are affected by the input files.\n"
|
| + " Due to the way the filtering works for compile targets as\n"
|
| + " described above, this list may contain targets that do not appear\n"
|
| + " in the input list.\n"
|
| + "\n"
|
| + " - \"test_targets\": A list of the labels from the input\n"
|
| + " test_targets list that are affected by the input files. This list\n"
|
| + " will be a proper subset of the input list.\n"
|
| + "\n"
|
| + " - \"invalid_targets\": A list of any names from the input that\n"
|
| + " do not exist in the build graph.\n"
|
| + "\n"
|
| + " - \"status\": A string containing one of three values:\n"
|
| + " - \"Found dependency\"\n"
|
| + " - \"No dependency\"\n"
|
| + " - \"Found dependency (all)\"\n"
|
| + " In the first case, the lists returned in compile_targets and\n"
|
| + " test_targets should be passed to ninja to build. In the second\n"
|
| + " case, nothing was affected and no build is necessary. In the third\n"
|
| + " case, GN could not determine the correct answer and returned the\n"
|
| + " input as the output in order to be safe.\n"
|
| + "\n"
|
| + " - \"error\": This will only be present if an error occurred, and\n"
|
| + " will contain a string describing the error. In addition, in this\n"
|
| + " case the return code of the command will beĀ 1.\n";
|
| +
|
| +int RunAnalyze(const std::vector<std::string>& args) {
|
| + if (args.size() != 3) {
|
| + Err(Location(), "You're holding it wrong.",
|
| + "Usage: \"gn analyze <out_dir> <input_path> <output_path>")
|
| + .PrintToStdout();
|
| + return 1;
|
| + }
|
| +
|
| + std::string input;
|
| + bool ret = base::ReadFileToString(UTF8ToFilePath(args[1]), &input);
|
| + if (!ret) {
|
| + Err(Location(), "Input file " + args[1] + " not found.").PrintToStdout();
|
| + return 1;
|
| + }
|
| +
|
| + Setup* setup = new Setup;
|
| + setup->build_settings().set_check_for_bad_items(false);
|
| + if (!setup->DoSetup(args[0], false) || !setup->Run())
|
| + return 1;
|
| +
|
| + Graph graph(setup->builder().GetAllResolvedTargets(),
|
| + setup->loader()->default_toolchain_label());
|
| +
|
| + std::string output;
|
| + Err err = Analyze(graph, input, &output);
|
| + if (err.has_error()) {
|
| + err.PrintToStdout();
|
| + return 1;
|
| + }
|
| +
|
| + std::string output_path = args[2];
|
| + WriteFile(base::FilePath(output_path), output, &err);
|
| + if (err.has_error()) {
|
| + err.PrintToStdout();
|
| + return 1;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +} // namespace commands
|
|
|