Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/actions/build-and-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ description: Shared build/test steps for all runners
inputs:
build:
required: true
type: string
coverage:
required: true
type: boolean
runs:
using: "composite"
steps:
Expand Down
1 change: 0 additions & 1 deletion .github/actions/setup-llvm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ name: Setup LLVM
description: Install LLVM from apt.llvm.org
inputs:
version:
type: string
required: true
runs:
using: "composite"
Expand Down
140 changes: 63 additions & 77 deletions src/BuildConfig.hpp → include/Builder/BuildGraph.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
#pragma once

#include "Builder/BuildProfile.hpp"
#include "Builder/Compiler.hpp"
#include "Builder/NinjaPlan.hpp"
#include "Builder/Project.hpp"
#include "Builder/SourceLayout.hpp"
#include "Command.hpp"
#include "Manifest.hpp"
#include "Rustify/Result.hpp"

#include <cstdint>
#include <filesystem>
#include <optional>
#include <ostream>
#include <string>
#include <string_view>
#include <tbb/spin_mutex.h>
Expand All @@ -19,30 +22,42 @@

namespace cabin {

// clang-format off
inline const std::unordered_set<std::string> SOURCE_FILE_EXTS{
".c", ".c++", ".cc", ".cpp", ".cxx"
};
inline const std::unordered_set<std::string> HEADER_FILE_EXTS{
".h", ".h++", ".hh", ".hpp", ".hxx"
};
// clang-format on
namespace fs = std::filesystem;

class BuildConfig {
class BuildGraph {
public:
struct TestTarget;
// NOLINTNEXTLINE(*-non-private-member-variables-in-classes)
fs::path outBasePath;
enum class TestKind : std::uint8_t { Unit, Integration };

private:
Project project;
Compiler compiler;
BuildProfile buildProfile;
std::string libName;
struct TestTarget {
std::string ninjaTarget;
std::string sourcePath;
TestKind kind = TestKind::Unit;
};

static Result<BuildGraph> create(const Manifest& manifest,
const BuildProfile& buildProfile);

const fs::path& outBasePath() const { return outBasePath_; }
const Manifest& manifest() const { return project.manifest; }
const BuildProfile& buildProfile() const { return buildProfile_; }

bool hasBinaryTarget() const { return hasBinaryTarget_; }
bool hasLibraryTarget() const { return hasLibraryTarget_; }
const std::string& libraryName() const { return libName; }
const std::vector<TestTarget>& testTargets() const { return testTargets_; }

Result<void> installDeps(bool includeDevDeps);
void enableCoverage();
Result<void> plan();
Result<void> writeBuildFilesIfNeeded() const;
Result<void> generateCompdb() const;

bool hasBinaryTarget{ false };
bool hasLibraryTarget{ false };
Result<bool> needsBuild(const std::vector<std::string>& targets) const;
Command ninjaCommand(bool dryRun = false) const;
Result<ExitStatus> buildTargets(const std::vector<std::string>& targets,
std::string_view displayName) const;

private:
struct CompileUnit {
std::string source;
std::unordered_set<std::string> dependencies;
Expand All @@ -58,18 +73,8 @@ class BuildConfig {
objectSubdir(std::move(objectSubdir)) {}
};

std::unordered_map<std::string, CompileUnit> compileUnits;
std::vector<TestTarget> testTargets;
std::unordered_set<std::string> srcObjectTargets;
std::string archiver = "ar";

std::string cxxFlags;
std::string defines;
std::string includes;
std::string ldFlags;
std::string libs;

NinjaPlan ninjaPlan;
BuildGraph(BuildProfile buildProfile, std::string libName, Project project,
Compiler compiler);

bool isUpToDate(std::string_view fileName) const;
std::string mapHeaderToObj(const fs::path& headerPath) const;
Expand All @@ -79,36 +84,9 @@ class BuildConfig {
const std::unordered_set<std::string>& dependencies,
bool isTest);

explicit BuildConfig(BuildProfile buildProfile, std::string libName,
Project project, Compiler compiler)
: outBasePath(project.outBasePath), project(std::move(project)),
compiler(std::move(compiler)), buildProfile(std::move(buildProfile)),
libName(std::move(libName)), ninjaPlan(outBasePath) {}

public:
enum class TestKind : std::uint8_t { Unit, Integration };

struct TestTarget {
std::string ninjaTarget;
std::string sourcePath;
TestKind kind = TestKind::Unit;
};

static Result<BuildConfig>
init(const Manifest& manifest,
const BuildProfile& buildProfile = BuildProfile::Dev);

bool hasBinTarget() const { return hasBinaryTarget; }
bool hasLibTarget() const { return hasLibraryTarget; }
const std::string& getLibName() const { return libName; }

bool ninjaIsUpToDate() const { return isUpToDate("build.ninja"); }
bool compdbIsUpToDate() const { return isUpToDate("compile_commands.json"); }

const std::vector<TestTarget>& getTestTargets() const { return testTargets; }

Result<void> installDeps(bool includeDevDeps);
void enableCoverage();
Result<std::string> runMM(const std::string& sourceFile,
bool isTest = false) const;
Result<bool> containsTestCode(const std::string& sourceFile) const;

Result<void> processSrc(const fs::path& sourceFilePath,
const SourceRoot& root,
Expand All @@ -130,24 +108,32 @@ class BuildConfig {
const std::unordered_set<std::string>& objTargetDeps,
const std::unordered_set<std::string>& buildObjTargets) const;

Result<void> configureBuild();
Result<void> configure();
void writeBuildFiles() const;

void emitCompdb(std::ostream& os) const;
Result<std::string> runMM(const std::string& sourceFile,
bool isTest = false) const;
Result<bool> containsTestCode(const std::string& sourceFile) const;
fs::path outBasePath_;
Project project;
Compiler compiler;
BuildProfile buildProfile_;
std::string libName;

void writeBuildFiles() const;
bool hasBinaryTarget_{ false };
bool hasLibraryTarget_{ false };

std::unordered_map<std::string, CompileUnit> compileUnits;
std::vector<TestTarget> testTargets_;
std::unordered_set<std::string> srcObjectTargets;
std::string archiver = "ar";

std::string cxxFlags;
std::string defines;
std::string includes;
std::string ldFlags;
std::string libs;

NinjaPlan ninjaPlan;
};

Result<BuildConfig> emitNinja(const Manifest& manifest,
const BuildProfile& buildProfile,
bool includeDevDeps, bool enableCoverage = false);
Result<std::string> emitCompdb(const Manifest& manifest,
const BuildProfile& buildProfile,
bool includeDevDeps);
Command getNinjaCommand();
Result<bool> ninjaNeedsWork(const fs::path& outDir,
const std::vector<std::string>& targets);
std::vector<fs::path> listSourceFilePaths(const fs::path& dir);

} // namespace cabin
28 changes: 28 additions & 0 deletions include/Builder/DepGraph.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include "Builder/BuildGraph.hpp"
#include "Builder/BuildProfile.hpp"
#include "Manifest.hpp"
#include "Rustify/Result.hpp"

#include <filesystem>
#include <optional>
#include <utility>

namespace cabin {

namespace fs = std::filesystem;

class DepGraph {
public:
explicit DepGraph(fs::path rootPath) : rootPath(std::move(rootPath)) {}

Result<void> resolve();
Result<BuildGraph> computeBuildGraph(const BuildProfile& buildProfile) const;

private:
fs::path rootPath;
std::optional<Manifest> rootManifest;
};

} // namespace cabin
17 changes: 17 additions & 0 deletions include/Builder/SourceLayout.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <string>
#include <unordered_set>

namespace cabin {

// clang-format off
inline const std::unordered_set<std::string> SOURCE_FILE_EXTS{
".c", ".c++", ".cc", ".cpp", ".cxx"
};
inline const std::unordered_set<std::string> HEADER_FILE_EXTS{
".h", ".h++", ".hh", ".hpp", ".hxx"
};
// clang-format on

} // namespace cabin
Loading
Loading