blob: c21769a572ce833f7113096b1e003a2c1cc81376 [file] [log] [blame]
// 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.
#ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_
#define TOOLS_GN_NINJA_BUILD_WRITER_H_
#include <iosfwd>
#include <map>
#include <string_view>
#include <unordered_map>
#include <vector>
#include "gn/path_output.h"
class Builder;
class BuildSettings;
class Err;
class Settings;
class Target;
class Toolchain;
namespace base {
class CommandLine;
} // namespace base
// Generates the toplevel "build.ninja" file. This references the individual
// toolchain files and lists all input .gn files as dependencies of the
// build itself.
class NinjaBuildWriter {
public:
NinjaBuildWriter(const BuildSettings* settings,
const std::unordered_map<const Settings*, const Toolchain*>&
used_toolchains,
const std::vector<const Target*>& all_targets,
const Toolchain* default_toolchain,
const std::vector<const Target*>& default_toolchain_targets,
std::ostream& out,
std::ostream& dep_out);
~NinjaBuildWriter();
// The design of this class is that this static factory function takes the
// Builder, extracts the relevant information, and passes it to the class
// constructor. The class itself doesn't depend on the Builder at all which
// makes testing much easier (tests integrating various functions along with
// the Builder get very complicated).
static bool RunAndWriteFile(const BuildSettings* settings,
const Builder& builder,
Err* err);
// Extracts from an existing build.ninja file's contents the commands
// necessary to run GN and regenerate build.ninja.
//
// The regeneration rules live at the top of the build.ninja file and their
// specific contents are an internal detail of NinjaBuildWriter. Used by
// commands::PrepareForRegeneration.
//
// On error, returns an empty string.
static std::string ExtractRegenerationCommands(std::istream& build_ninja_in);
bool Run(Err* err);
private:
// WriteNinjaRules writes the rules that ninja uses to regenerate its own
// build files, used whenever a build input file has changed.
//
// Ninja file regeneration is accomplished by two separate build statements.
// This is necessary to work around ninja's behavior of deleting all output
// files of a build edge if the edge uses a depfile and is interrupted before
// it can complete. Previously, interrupting regeneration would cause ninja to
// delete build.ninja, losing any flags/build settings passed to gen
// previously and requiring the user to manually 'gen' again.
//
// The workaround involves misleading ninja about when the build.ninja file is
// actually written. The first build statement runs the actual 'gen
// --regeneration' command, writing "build.ninja" (and .d and .stamp) and
// lists the "build.ninja.d" depfile to automatically trigger regeneration as
// needed, but does not list "build.ninja" as an output. The second
// statement's stated output is "build.ninja", but it simply uses the phony
// rule to refer to the first statement.
void WriteNinjaRules();
void WriteAllPools();
bool WriteSubninjas(Err* err);
bool WritePhonyAndAllRules(Err* err);
void WritePhonyRule(const Target* target, std::string_view phony_name);
const BuildSettings* build_settings_;
const std::unordered_map<const Settings*, const Toolchain*>& used_toolchains_;
const std::vector<const Target*>& all_targets_;
const Toolchain* default_toolchain_;
const std::vector<const Target*>& default_toolchain_targets_;
std::ostream& out_;
std::ostream& dep_out_;
PathOutput path_output_;
NinjaBuildWriter(const NinjaBuildWriter&) = delete;
NinjaBuildWriter& operator=(const NinjaBuildWriter&) = delete;
};
extern const char kNinjaRules_Help[];
// Exposed for testing.
base::CommandLine GetSelfInvocationCommandLine(
const BuildSettings* build_settings);
#endif // TOOLS_GN_NINJA_BUILD_WRITER_H_