Skip to content

Commit

Permalink
Merge pull request #731 from bnbarham/add-ninja-c-api
Browse files Browse the repository at this point in the history
Add a C API and corresponding Swift interface for the Ninja component
  • Loading branch information
dmbryson authored Jul 19, 2021
2 parents 9f581f6 + 92d9fd7 commit 5cd4df5
Show file tree
Hide file tree
Showing 25 changed files with 940 additions and 789 deletions.
19 changes: 2 additions & 17 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ let package = Package(
.library(
name: "llbuildAnalysis",
targets: ["llbuildAnalysis"]),

// Swift library for accessing [Ninja](ninjabuild.org) files.
.library(
name: "Ninja",
targets: ["Ninja"])
],
targets: [
// MARK: Products
Expand Down Expand Up @@ -64,7 +59,7 @@ let package = Package(
/// The public llbuild C API.
.target(
name: "libllbuild",
dependencies: ["llbuildCore", "llbuildBuildSystem"],
dependencies: ["llbuildCore", "llbuildBuildSystem", "llbuildNinja"],
path: "products/libllbuild"
),

Expand All @@ -76,16 +71,6 @@ let package = Package(
exclude: []
),

/// The public Swift Ninja API.
.target(
name: "Ninja",
dependencies: ["llbuild"],
path: "products/swift-Ninja"),
.testTarget(
name: "SwiftNinjaTests",
dependencies: ["llbuildTestSupport", "Ninja"],
path: "unittests/swift-Ninja"),

// MARK: Components

.target(
Expand Down Expand Up @@ -173,7 +158,7 @@ let package = Package(
.linkedLibrary("dl", .when(platforms: [.linux])),
.linkedLibrary("pthread", .when(platforms: [.linux]))]),

.testTarget(
.target(
name: "llbuildTestSupport",
path: "unittests/TestSupport"),

Expand Down
29 changes: 10 additions & 19 deletions include/llbuild/Core/MakefileDepsParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,40 @@ class MakefileDepsParser {

/// Called if an error is encountered in parsing the input.
///
/// \param message A C-string text message including information on the
/// error.
/// \param message A message including information on the error.
///
/// \param position The approximate position of the error in the input
/// buffer.
virtual void error(const char* message, uint64_t position) = 0;
virtual void error(StringRef message, uint64_t position) = 0;

/// Called when a new rule is encountered.
///
/// \param name - A pointer to the rule name string start.
///
/// \param length - The raw length of the rule name string, including escape
/// sequences.
/// \param name - The rule name.
///
/// \param unescapedWord - An unescaped version of the name.
virtual void actOnRuleStart(const char* name, uint64_t length,
const StringRef unescapedWord) = 0;
virtual void actOnRuleStart(StringRef name, StringRef unescapedWord) = 0;

/// Called when a new dependency is found for the current rule.
///
/// This is only called between paired calls to \see actOnRuleStart() and
/// \see actOnRuleEnd().
///
/// \param dependency - A pointer to the dependency string start.
///
/// \param length - The raw length of the dependency string, including
/// escape sequences.
/// \param dependency - The dependency string start.
///
/// \param unescapedWord - An unescaped version of the dependency.
virtual void actOnRuleDependency(const char* dependency, uint64_t length,
const StringRef unescapedWord) = 0;
virtual void actOnRuleDependency(StringRef dependency,
StringRef unescapedWord) = 0;

/// Called when a rule is complete.
virtual void actOnRuleEnd() = 0;
};

const char* data;
uint64_t length;
StringRef data;
ParseActions& actions;

public:
MakefileDepsParser(const char* data, uint64_t length, ParseActions& actions)
: data(data), length(length), actions(actions) {}
MakefileDepsParser(StringRef data, ParseActions& actions)
: data(data), actions(actions) {}

void parse();
};
Expand Down
41 changes: 22 additions & 19 deletions include/llbuild/Ninja/ManifestLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
#ifndef LLBUILD_NINJA_MANIFESTLOADER_H
#define LLBUILD_NINJA_MANIFESTLOADER_H

#include "llbuild/Basic/LLVM.h"
#include "llbuild/Ninja/Manifest.h"

#include <string>
#include <utility>
#include "llvm/ADT/StringRef.h"

#include <memory>

namespace llvm {
class MemoryBuffer;
}

namespace llbuild {
namespace ninja {
Expand All @@ -34,35 +40,32 @@ class ManifestLoaderActions {
/// Called at the beginning of loading, to register the manifest loader.
virtual void initialize(ManifestLoader* loader) = 0;

virtual void error(std::string filename, std::string message,
const Token& at) = 0;
virtual void error(StringRef filename, StringRef message, const Token& at) = 0;

/// Called by the loader to request the contents of a manifest file be loaded.
///
/// \param filename The name of the file to load.
///
/// \param forToken If non-null, the token triggering the file load, for use
/// in diagnostics.
/// \param path Absolute path of the file to load.
///
/// \param data_out On success, the contents of the file.
/// \param forFilename If non-empty, the name of the file triggering the file
/// load (for use in diagnostics).
///
/// \param length_out On success, the length of the data in the file.
/// \param forToken If non-null, the token triggering the file load (for use
/// in diagnostics).
///
/// \returns True on success. On failure, the action is assumed to have
/// produced an appropriate error.
virtual bool readFileContents(const std::string& fromFilename,
const std::string& filename,
const Token* forToken,
std::unique_ptr<char[]> *data_out,
uint64_t *length_out) = 0;
/// \returns The loaded file on success, or a nullptr. On failure, the action
/// is assumed to have produced an appropriate error.
virtual std::unique_ptr<llvm::MemoryBuffer> readFile(
StringRef path, StringRef forFilename, const Token* forToken) = 0;
};

/// Interface for loading Ninja build manifests.
class ManifestLoader {
void *impl;
class ManifestLoaderImpl;
std::unique_ptr<ManifestLoaderImpl> impl;

public:
ManifestLoader(StringRef workingDirectory, StringRef mainFilename, ManifestLoaderActions& actions);
ManifestLoader(StringRef workingDirectory, StringRef mainFilename,
ManifestLoaderActions& actions);
~ManifestLoader();

/// Load the manifest.
Expand Down
16 changes: 9 additions & 7 deletions include/llbuild/Ninja/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
#ifndef LLBUILD_NINJA_PARSER_H
#define LLBUILD_NINJA_PARSER_H

#include "llvm/ADT/ArrayRef.h"

#include "llbuild/Basic/LLVM.h"
#include "llbuild/Ninja/Lexer.h"

#include <string>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"

#include <memory>

namespace llbuild {
namespace ninja {
Expand All @@ -35,13 +36,13 @@ class ParseActions {

virtual ~ParseActions();

virtual void error(std::string message, const Token& at) = 0;
virtual void error(StringRef message, const Token& at) = 0;

/// Called at the beginning of parsing, to register the parser.
virtual void initialize(Parser* parser) = 0;

/// Called at the beginning of parsing a particular manifest.
virtual void actOnBeginManifest(std::string name) = 0;
virtual void actOnBeginManifest(StringRef name) = 0;
/// Called at the end of parsing the current manifest.
virtual void actOnEndManifest() = 0;

Expand Down Expand Up @@ -164,10 +165,11 @@ class ParseActions {

/// Interface for parsing a Ninja build manifest.
class Parser {
void *impl;
class ParserImpl;
std::unique_ptr<ParserImpl> impl;

public:
Parser(const char* data, uint64_t length, ParseActions& actions);
Parser(StringRef data, ParseActions &actions);
~Parser();

void parse();
Expand Down
32 changes: 14 additions & 18 deletions lib/BuildSystem/BuildSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2038,30 +2038,28 @@ class ClangShellCommand : public ExternalCommand {
ClangShellCommand* command)
: ti(ti), command(command) {}

virtual void error(const char* message, uint64_t position) override {
virtual void error(StringRef message, uint64_t position) override {
getBuildSystem(ti).getDelegate().commandHadError(command,
"error reading dependency file '" + command->depsPath +
"': " + std::string(message));
"': " + message.str());
++numErrors;
}

virtual void actOnRuleDependency(const char* dependency,
uint64_t length,
const StringRef unescapedWord) override {
virtual void actOnRuleDependency(StringRef dependency,
StringRef unescapedWord) override {
ti.discoveredDependency(BuildKey::makeNode(unescapedWord).toData());
getBuildSystem(ti).getDelegate().commandFoundDiscoveredDependency(command, unescapedWord,
DiscoveredDependencyKind::Input);
}

virtual void actOnRuleStart(const char* name, uint64_t length,
const StringRef unescapedWord) override {}
virtual void actOnRuleStart(StringRef name,
StringRef unescapedWord) override {}

virtual void actOnRuleEnd() override {}
};

DepsActions actions(ti, this);
core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(),
actions).parse();
core::MakefileDepsParser(input->getBuffer(), actions).parse();
return actions.numErrors == 0;
}

Expand Down Expand Up @@ -2604,16 +2602,15 @@ class SwiftCompilerShellCommand : public ExternalCommand {
StringRef depsPath, Command* command)
: ti(ti), depsPath(depsPath) {}

virtual void error(const char* message, uint64_t position) override {
virtual void error(StringRef message, uint64_t position) override {
getBuildSystem(ti).getDelegate().commandHadError(command,
"error reading dependency file '" + depsPath.str() +
"': " + std::string(message));
"': " + message.str());
++numErrors;
}

virtual void actOnRuleDependency(const char* dependency,
uint64_t length,
const StringRef unescapedWord) override {
virtual void actOnRuleDependency(StringRef dependency,
StringRef unescapedWord) override {
// Only process dependencies for the first rule (the output file), the
// rest are identical.
if (ruleNumber == 0) {
Expand All @@ -2623,17 +2620,16 @@ class SwiftCompilerShellCommand : public ExternalCommand {
}
}

virtual void actOnRuleStart(const char* name, uint64_t length,
const StringRef unescapedWord) override {}
virtual void actOnRuleStart(StringRef name,
StringRef unescapedWord) override {}

virtual void actOnRuleEnd() override {
++ruleNumber;
}
};

DepsActions actions(ti, depsPath, this);
core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(),
actions).parse();
core::MakefileDepsParser(input->getBuffer(), actions).parse();
return actions.numErrors == 0;
}

Expand Down
14 changes: 6 additions & 8 deletions lib/BuildSystem/ShellCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,17 @@ bool ShellCommand::processMakefileDiscoveredDependencies(BuildSystem& system,
ShellCommand* command, StringRef depsPath)
: system(system), ti(ti), command(command), depsPath(depsPath) {}

virtual void error(const char* message, uint64_t position) override {
virtual void error(StringRef message, uint64_t position) override {
std::string msg;
raw_string_ostream msgStream(msg);
msgStream << "error reading dependency file '" << depsPath.str() << "': "
msgStream << "error reading dependency file '" << depsPath << "': "
<< message << " at position " << position;
system.getDelegate().commandHadError(command, msgStream.str());
++numErrors;
}

virtual void actOnRuleDependency(const char* dependency,
uint64_t length,
const StringRef unescapedWord) override {
virtual void actOnRuleDependency(StringRef dependency,
StringRef unescapedWord) override {
if (llvm::sys::path::is_absolute(unescapedWord)) {
ti.discoveredDependency(BuildKey::makeNode(unescapedWord).toData());
system.getDelegate().commandFoundDiscoveredDependency(command, unescapedWord, DiscoveredDependencyKind::Input);
Expand All @@ -166,15 +165,14 @@ bool ShellCommand::processMakefileDiscoveredDependencies(BuildSystem& system,
system.getDelegate().commandFoundDiscoveredDependency(command, absPath, DiscoveredDependencyKind::Input);
}

virtual void actOnRuleStart(const char* name, uint64_t length,
virtual void actOnRuleStart(StringRef name,
const StringRef unescapedWord) override {}

virtual void actOnRuleEnd() override {}
};

DepsActions actions(system, ti, this, depsPath);
core::MakefileDepsParser(input->getBufferStart(), input->getBufferSize(),
actions).parse();
core::MakefileDepsParser(input->getBuffer(), actions).parse();
return actions.numErrors == 0;
}

Expand Down
Loading

0 comments on commit 5cd4df5

Please sign in to comment.