Browse Source

`dds compile-file` to compile individual files

default_compile_flags
vector-of-bool 4 years ago
parent
commit
707de851ad
5 changed files with 234 additions and 70 deletions
  1. +136
    -45
      src/dds.main.cpp
  2. +40
    -25
      src/dds/build/builder.cpp
  3. +5
    -0
      src/dds/build/builder.hpp
  4. +48
    -0
      src/dds/build/plan/full.cpp
  5. +5
    -0
      src/dds/build/plan/full.hpp

+ 136
- 45
src/dds.main.cpp View File

@@ -573,6 +573,113 @@ struct cli_sdist {
}
};

void load_project_deps(dds::builder& bd,
const dds::package_manifest& man,
dds::path_ref cat_path,
dds::path_ref repo_path) {
auto cat = dds::catalog::open(cat_path);
// Build the dependencies
dds::repository::with_repository( //
repo_path,
dds::repo_flags::write_lock | dds::repo_flags::create_if_absent,
[&](dds::repository repo) {
// Download dependencies
auto deps = repo.solve(man.dependencies, cat);
dds::get_all(deps, repo, cat);
for (const dds::package_id& pk : deps) {
auto sdist_ptr = repo.find(pk);
assert(sdist_ptr);
dds::sdist_build_params deps_params;
deps_params.subdir
= dds::fs::path("_deps") / sdist_ptr->manifest.pkg_id.to_string();
bd.add(*sdist_ptr, deps_params);
}
});
}

dds::builder create_project_builder(dds::path_ref pr_dir,
dds::path_ref cat_path,
dds::path_ref repo_path,
bool load_deps,
const dds::sdist_build_params& project_params) {
auto man = dds::package_manifest::load_from_directory(pr_dir).value_or(dds::package_manifest{});

dds::builder builder;
if (load_deps) {
load_project_deps(builder, man, cat_path, repo_path);
}
builder.add(dds::sdist{std::move(man), pr_dir}, project_params);
return builder;
}

/*
###### ####### ## ## ######## #### ## ########
## ## ## ## ### ### ## ## ## ## ##
## ## ## #### #### ## ## ## ## ##
## ## ## ## ### ## ######## ## ## ######
## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
###### ####### ## ## ## #### ######## ########
*/

struct cli_compile_file {
cli_base& base;
args::Command cmd{base.cmd_group, "compile-file", "Compile a single file"};

common_flags _flags{cmd};

common_project_flags project{cmd};

catalog_path_flag cat_path{cmd};
repo_path_flag repo_path{cmd};

args::Flag no_warnings{cmd, "no-warnings", "Disable compiler warnings", {"no-warnings"}};
toolchain_flag tc_filepath{cmd};

path_flag
lm_index{cmd,
"lm_index",
"Path to an existing libman index from which to load deps (usually INDEX.lmi)",
{"lm-index", 'I'}};

num_jobs_flag n_jobs{cmd};

path_flag out{cmd,
"out",
"The root build directory",
{"out"},
dds::fs::current_path() / "_build"};

args::PositionalList<dds::fs::path> source_files{cmd,
"source-files",
"One or more source files to compile"};

int run() {
dds::sdist_build_params main_params = {
.subdir = "",
.build_tests = true,
.build_apps = true,
.enable_warnings = !no_warnings.Get(),
};
auto bd = create_project_builder(project.root.Get(),
cat_path.Get(),
repo_path.Get(),
/* load_deps = */ !lm_index,
main_params);

bd.compile_files(source_files.Get(),
{
.out_root = out.Get(),
.existing_lm_index
= lm_index ? std::make_optional(lm_index.Get()) : std::nullopt,
.emit_lmi = {},
.toolchain = tc_filepath.get_toolchain(),
.parallel_jobs = n_jobs.Get(),
});
return 0;
}
};

/*
######## ## ## #### ## ########
## ## ## ## ## ## ## ##
@@ -614,45 +721,26 @@ struct cli_build {
dds::fs::current_path() / "_build"};

int run() {
dds::build_params params;
params.out_root = out.Get();
params.toolchain = tc_filepath.get_toolchain();
params.parallel_jobs = n_jobs.Get();

auto man = dds::package_manifest::load_from_directory(project.root.Get())
.value_or(dds::package_manifest{});

dds::builder bd;
dds::sdist_build_params main_params;
main_params.build_apps = !no_apps.Get();
main_params.enable_warnings = !no_warnings.Get();
main_params.run_tests = main_params.build_tests = !no_tests.Get();

bd.add(dds::sdist{man, project.root.Get()}, main_params);
if (lm_index) {
params.existing_lm_index = lm_index.Get();
} else {
// Download and build dependencies
// Build the dependencies
auto cat = cat_path.open();
dds::repository::with_repository( //
this->repo_path.Get(),
dds::repo_flags::write_lock | dds::repo_flags::create_if_absent,
[&](dds::repository repo) {
// Download dependencies
auto deps = repo.solve(man.dependencies, cat);
dds::get_all(deps, repo, cat);
for (const dds::package_id& pk : deps) {
auto sdist_ptr = repo.find(pk);
assert(sdist_ptr);
dds::sdist_build_params deps_params;
deps_params.subdir
= dds::fs::path("_deps") / sdist_ptr->manifest.pkg_id.to_string();
bd.add(*sdist_ptr, deps_params);
}
});
}
bd.build(params);
dds::sdist_build_params main_params = {
.subdir = "",
.build_tests = !no_tests.Get(),
.run_tests = !no_tests.Get(),
.build_apps = !no_apps.Get(),
.enable_warnings = !no_warnings.Get(),
};
auto bd = create_project_builder(project.root.Get(),
cat_path.Get(),
repo_path.Get(),
/* load_deps = */ !lm_index,
main_params);

bd.build({
.out_root = out.Get(),
.existing_lm_index = lm_index ? std::make_optional(lm_index.Get()) : std::nullopt,
.emit_lmi = {},
.toolchain = tc_filepath.get_toolchain(),
.parallel_jobs = n_jobs.Get(),
});
return 0;
}
};
@@ -760,12 +848,13 @@ int main(int argc, char** argv) {
spdlog::set_pattern("[%H:%M:%S] [%^%-5l%$] %v");
args::ArgumentParser parser("DDS - The drop-dead-simple library manager");

cli_base cli{parser};
cli_build build{cli};
cli_sdist sdist{cli};
cli_repo repo{cli};
cli_catalog catalog{cli};
cli_build_deps build_deps{cli};
cli_base cli{parser};
cli_compile_file compile_file{cli};
cli_build build{cli};
cli_sdist sdist{cli};
cli_repo repo{cli};
cli_catalog catalog{cli};
cli_build_deps build_deps{cli};

try {
parser.ParseCLI(argc, argv);
@@ -785,6 +874,8 @@ int main(int argc, char** argv) {
if (cli._verify_ident) {
std::cout << "yes\n";
return 0;
} else if (compile_file.cmd) {
return compile_file.run();
} else if (build.cmd) {
return build.run();
} else if (sdist.cmd) {

+ 40
- 25
src/dds/build/builder.cpp View File

@@ -205,14 +205,15 @@ void write_lmi(build_env_ref env, const build_plan& plan, path_ref base_dir, pat
}
}

} // namespace

void builder::build(const build_params& params) const {
template <typename Func>
void with_build_plan(const build_params& params,
const std::vector<sdist_target>& sdists,
Func&& fn) {
fs::create_directories(params.out_root);
auto db = database::open(params.out_root / ".dds.db");

state st;
auto plan = prepare_build_plan(st, _sdists);
auto plan = prepare_build_plan(st, sdists);
auto ureqs = prepare_ureqs(plan, params.toolchain, params.out_root);
build_env env{
params.toolchain,
@@ -239,30 +240,44 @@ void builder::build(const build_params& params) const {

plan.render_all(env);

dds::stopwatch sw;
plan.compile_all(env, params.parallel_jobs);
dds_log(info, "Compilation completed in {:L}ms", sw.elapsed_ms().count());
fn(std::move(env), std::move(plan));
}

sw.reset();
plan.archive_all(env, params.parallel_jobs);
dds_log(info, "Archiving completed in {:L}ms", sw.elapsed_ms().count());
} // namespace

sw.reset();
plan.link_all(env, params.parallel_jobs);
dds_log(info, "Runtime binary linking completed in {:L}ms", sw.elapsed_ms().count());
void builder::compile_files(const std::vector<fs::path>& files, const build_params& params) const {
with_build_plan(params, _sdists, [&](build_env_ref env, build_plan plan) {
plan.compile_files(env, params.parallel_jobs, files);
});
}

sw.reset();
auto test_failures = plan.run_all_tests(env, params.parallel_jobs);
dds_log(info, "Test execution finished in {:L}ms", sw.elapsed_ms().count());
void builder::build(const build_params& params) const {
with_build_plan(params, _sdists, [&](build_env_ref env, const build_plan& plan) {
dds::stopwatch sw;
plan.compile_all(env, params.parallel_jobs);
dds_log(info, "Compilation completed in {:L}ms", sw.elapsed_ms().count());

for (auto& fail : test_failures) {
log_failure(fail);
}
if (!test_failures.empty()) {
throw_user_error<errc::test_failure>();
}
sw.reset();
plan.archive_all(env, params.parallel_jobs);
dds_log(info, "Archiving completed in {:L}ms", sw.elapsed_ms().count());

if (params.emit_lmi) {
write_lmi(env, plan, params.out_root, *params.emit_lmi);
}
sw.reset();
plan.link_all(env, params.parallel_jobs);
dds_log(info, "Runtime binary linking completed in {:L}ms", sw.elapsed_ms().count());

sw.reset();
auto test_failures = plan.run_all_tests(env, params.parallel_jobs);
dds_log(info, "Test execution finished in {:L}ms", sw.elapsed_ms().count());

for (auto& fail : test_failures) {
log_failure(fail);
}
if (!test_failures.empty()) {
throw_user_error<errc::test_failure>();
}

if (params.emit_lmi) {
write_lmi(env, plan, params.out_root, *params.emit_lmi);
}
});
}

+ 5
- 0
src/dds/build/builder.hpp View File

@@ -53,6 +53,11 @@ public:
* Execute the build
*/
void build(const build_params& params) const;

/**
* Compile one or more source files
*/
void compile_files(const std::vector<fs::path>& files, const build_params& params) const;
};

} // namespace dds

+ 48
- 0
src/dds/build/plan/full.cpp View File

@@ -3,8 +3,10 @@
#include <dds/build/iter_compilations.hpp>
#include <dds/build/plan/compile_exec.hpp>
#include <dds/error/errors.hpp>
#include <dds/util/log.hpp>
#include <dds/util/parallel.hpp>

#include <range/v3/algorithm/any_of.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/filter.hpp>
@@ -46,6 +48,52 @@ void build_plan::compile_all(const build_env& env, int njobs) const {
}
}

void build_plan::compile_files(const build_env& env,
int njobs,
const std::vector<fs::path>& filepaths) const {
struct pending_file {
bool marked = false;
fs::path filepath;
};

auto as_pending = //
ranges::view::all(filepaths) //
| ranges::view::transform([](auto&& path) {
return pending_file{false, fs::weakly_canonical(path)};
})
| ranges::to_vector;

auto check_compilation = [&](const compile_file_plan& comp) {
return ranges::any_of(as_pending, [&](pending_file& f) {
bool same_file = f.filepath == fs::weakly_canonical(comp.source_path());
if (same_file) {
f.marked = true;
}
return same_file;
});
};

auto comps
= iter_compilations(*this) | ranges::view::filter(check_compilation) | ranges::to_vector;

bool any_unmarked = false;
auto unmarked = ranges::view::filter(as_pending, ranges::not_fn(&pending_file::marked));
for (auto&& um : unmarked) {
dds_log(error, "Source file [{}] is not compiled by this project", um.filepath.string());
any_unmarked = true;
}

if (any_unmarked) {
throw_user_error<errc::compile_failure>(
"One or more requested files is not part of this project (See above)");
}

auto okay = dds::compile_all(comps, env, njobs);
if (!okay) {
throw_user_error<errc::compile_failure>();
}
}

void build_plan::archive_all(const build_env& env, int njobs) const {
auto okay = parallel_run(iter_libraries(*this), njobs, [&](const library_plan& lib) {
if (lib.archive_plan()) {

+ 5
- 0
src/dds/build/plan/full.hpp View File

@@ -45,6 +45,11 @@ public:
*/
void link_all(const build_env& env, int njobs) const;

/**
* Compile the files given in the vector of file paths.
*/
void compile_files(const build_env& env, int njobs, const std::vector<fs::path>& paths) const;

/**
* Execute all tests defined in the plan. Returns information for every failed test.
*/

Loading…
Cancel
Save