Переглянути джерело

Generation of the `INDEX.lmi`, and simplify passing around build params.

default_compile_flags
vector-of-bool 5 роки тому
джерело
коміт
28f3fdc686
8 змінених файлів з 165 додано та 61 видалено
  1. +7
    -4
      src/dds/build.cpp
  2. +9
    -9
      src/dds/build/compile.cpp
  3. +9
    -6
      src/dds/build/compile.hpp
  4. +37
    -26
      src/dds/build/plan.cpp
  5. +13
    -7
      src/dds/build/plan.hpp
  6. +11
    -3
      src/dds/ddslim.main.cpp
  7. +77
    -6
      src/dds/deps.cpp
  8. +2
    -0
      src/dds/deps.hpp

+ 7
- 4
src/dds/build.cpp Переглянути файл

@@ -228,7 +228,7 @@ std::vector<compile_file_plan> file_compilations_of_lib(const build_params& para
sources //
| filter(should_compile_source) //
| transform([&](auto&& src) {
return compile_file_plan{rules, src, lib.name()};
return compile_file_plan{rules, "obj/" + lib.name(), src, lib.name()};
}) //
| to_vector;
}
@@ -395,7 +395,7 @@ std::vector<link_results> link_project(const build_params& par
ranges::views::all(compilations) //
| transform([&](const compile_file_plan& comp) -> std::pair<fs::path, fs::path> {
return std::pair(comp.source.path,
params.out_root / comp.get_object_file_path(params.toolchain));
comp.get_object_file_path(build_env{params.toolchain, params.out_root}));
}) //
| ranges::to<object_file_index>() //
;
@@ -408,7 +408,8 @@ std::vector<link_results> link_project(const build_params& par

} // namespace

void dds::build(const build_params& params, const package_manifest&) {
void dds::build(const build_params& params, const package_manifest& man) {
auto libs = collect_libraries(params.root, man.name);
// auto sroot = dds::sroot{params.root};
// auto comp_rules = sroot.base_compile_rules();

@@ -425,7 +426,9 @@ void dds::build(const build_params& params, const package_manifest&) {

auto compiles = collect_compiles(params, project);

dds::execute_all(compiles, params.toolchain, params.parallel_jobs, params.out_root);
dds::build_env env{params.toolchain, params.out_root};

dds::execute_all(compiles, params.parallel_jobs, env);

using namespace ranges::views;


+ 9
- 9
src/dds/build/compile.cpp Переглянути файл

@@ -13,8 +13,8 @@

using namespace dds;

void compile_file_plan::compile(const toolchain& tc, path_ref out_prefix) const {
const auto obj_path = out_prefix / get_object_file_path(tc);
void compile_file_plan::compile(const build_env& env) const {
const auto obj_path = get_object_file_path(env);
fs::create_directories(obj_path.parent_path());

spdlog::info("[{}] Compile: {}",
@@ -28,7 +28,7 @@ void compile_file_plan::compile(const toolchain& tc, path_ref out_prefix) const
extend(spec.include_dirs, rules.include_dirs());
extend(spec.definitions, rules.defs());

auto cmd = tc.create_compile_command(spec);
auto cmd = env.toolchain.create_compile_command(spec);
auto compile_res = run_proc(cmd);

auto end_time = std::chrono::steady_clock::now();
@@ -58,16 +58,16 @@ void compile_file_plan::compile(const toolchain& tc, path_ref out_prefix) const
}
}

fs::path compile_file_plan::get_object_file_path(const toolchain& tc) const noexcept {
fs::path compile_file_plan::get_object_file_path(const build_env& env) const noexcept {
auto relpath = fs::relative(source.path, source.basis_path);
relpath.replace_filename(relpath.filename().string() + tc.object_suffix());
return relpath;
auto ret = env.output_root / subdir / relpath;
ret.replace_filename(relpath.filename().string() + env.toolchain.object_suffix());
return ret;
}

void dds::execute_all(const std::vector<compile_file_plan>& compilations,
const toolchain& tc,
int n_jobs,
path_ref out_prefix) {
const build_env& env) {
// We don't bother with a nice thread pool, as the overhead of compiling
// source files dwarfs the cost of interlocking.
std::mutex mut;
@@ -89,7 +89,7 @@ void dds::execute_all(const std::vector<compile_file_plan>& compilations,
auto& compilation = *comp_iter++;
lk.unlock();
try {
compilation.compile(tc, out_prefix);
compilation.compile(env);
cancellation_point();
} catch (...) {
lk.lock();

+ 9
- 6
src/dds/build/compile.hpp Переглянути файл

@@ -10,6 +10,11 @@

namespace dds {

struct build_env {
dds::toolchain toolchain;
fs::path output_root;
};

struct compile_failure : std::runtime_error {
using runtime_error::runtime_error;
};
@@ -38,16 +43,14 @@ public:

struct compile_file_plan {
shared_compile_file_rules rules;
fs::path subdir;
dds::source_file source;
std::string qualifier;

fs::path get_object_file_path(const toolchain& tc) const noexcept;
void compile(const toolchain& tc, path_ref out_prefix) const;
fs::path get_object_file_path(const build_env& env) const noexcept;
void compile(const build_env&) const;
};

void execute_all(const std::vector<compile_file_plan>&,
const toolchain& tc,
int n_jobs,
path_ref out_prefix);
void execute_all(const std::vector<compile_file_plan>&, int n_jobs, const build_env& env);

} // namespace dds

+ 37
- 26
src/dds/build/plan.cpp Переглянути файл

@@ -41,6 +41,7 @@ library_plan library_plan::create(const library& lib, const library_build_params
cf_plan.source = sfile;
cf_plan.qualifier = lib.name();
cf_plan.rules = params.compile_rules;
cf_plan.subdir = fs::path("obj") / lib.name();
compile_files.push_back(std::move(cf_plan));
if (sfile.kind == source_kind::test) {
test_sources.push_back(sfile);
@@ -64,7 +65,12 @@ library_plan library_plan::create(const library& lib, const library_build_params
create_archive.emplace(std::move(ar_plan));
}

return library_plan{params.out_subdir, compile_files, create_archive, link_executables};
return library_plan{lib.name(),
lib.path(),
params.out_subdir,
compile_files,
create_archive,
link_executables};
}

namespace {
@@ -123,19 +129,17 @@ bool parallel_run(Range&& rng, int n_jobs, Fn&& fn) {

} // namespace

fs::path create_archive_plan::archive_file_path(const toolchain& tc) const noexcept {
fs::path fname = fmt::format("{}{}{}", "lib", name, tc.archive_suffix());
return fname;
fs::path create_archive_plan::archive_file_path(const build_env& env) const noexcept {
return env.output_root / fmt::format("{}{}{}", "lib", name, env.toolchain.archive_suffix());
}

void create_archive_plan::archive(const toolchain& tc,
path_ref out_prefix,
void create_archive_plan::archive(const build_env& env,
const std::vector<fs::path>& objects) const {
archive_spec ar;
ar.input_files = objects;
ar.out_path = out_prefix / archive_file_path(tc);
auto ar_cmd = tc.create_archive_command(ar);
auto out_relpath = fs::relative(ar.out_path, out_prefix).string();
ar.input_files = objects;
ar.out_path = archive_file_path(env);
auto ar_cmd = env.toolchain.create_archive_command(ar);
auto out_relpath = fs::relative(ar.out_path, env.output_root).string();

spdlog::info("[{}] Archive: {}", name, out_relpath);
auto start_time = std::chrono::steady_clock::now();
@@ -152,26 +156,33 @@ void create_archive_plan::archive(const toolchain& tc,
}
}

void build_plan::compile_all(const toolchain& tc, int njobs, path_ref out_prefix) const {
std::vector<std::pair<fs::path, std::reference_wrapper<const compile_file_plan>>> comps;
for (const auto& lib : create_libraries) {
const auto lib_out_prefix = out_prefix / lib.out_subdir;
for (auto&& cf_plan : lib.compile_files) {
comps.emplace_back(lib_out_prefix, cf_plan);
}
}
namespace {

auto okay = parallel_run(comps, njobs, [&](const auto& pair) {
const auto& [out_dir, cf_plan] = pair;
cf_plan.get().compile(tc, out_dir);
});
auto all_libraries(const build_plan& plan) {
return //
plan.build_packages //
| ranges::views::transform(&package_plan::create_libraries) //
| ranges::views::join //
;
}

} // namespace

void build_plan::compile_all(const build_env& env, int njobs) const {
auto all_compiles = //
all_libraries(*this) //
| ranges::views::transform(&library_plan::compile_files) //
| ranges::views::join //
;

auto okay = parallel_run(all_compiles, njobs, [&](const auto& cf) { cf.compile(env); });
if (!okay) {
throw std::runtime_error("Compilation failed.");
}
}

void build_plan::archive_all(const toolchain& tc, int njobs, path_ref out_prefix) const {
parallel_run(create_libraries, njobs, [&](const library_plan& lib) {
void build_plan::archive_all(const build_env& env, int njobs) const {
parallel_run(all_libraries(*this), njobs, [&](const library_plan& lib) {
if (!lib.create_archive) {
return;
}
@@ -180,10 +191,10 @@ void build_plan::archive_all(const toolchain& tc, int njobs, path_ref out_prefix
| ranges::views::filter(
[](auto&& comp) { return comp.source.kind == source_kind::source; }) //
| ranges::views::transform([&](auto&& comp) {
return out_prefix / lib.out_subdir / comp.get_object_file_path(tc);
return comp.get_object_file_path(env);
}) //
| ranges::to_vector //
;
lib.create_archive->archive(tc, out_prefix, objects);
lib.create_archive->archive(env, objects);
});
}

+ 13
- 7
src/dds/build/plan.hpp Переглянути файл

@@ -13,10 +13,9 @@ struct create_archive_plan {
std::string name;
fs::path out_dir;

fs::path archive_file_path(const toolchain& tc) const noexcept;
fs::path archive_file_path(const build_env& env) const noexcept;

void
archive(const toolchain& tc, path_ref out_prefix, const std::vector<fs::path>& objects) const;
void archive(const build_env& env, const std::vector<fs::path>& objects) const;
};

struct create_exe_plan {
@@ -26,6 +25,8 @@ struct create_exe_plan {
};

struct library_plan {
std::string name;
fs::path source_root;
fs::path out_subdir;
std::vector<compile_file_plan> compile_files;
std::optional<create_archive_plan> create_archive;
@@ -34,16 +35,21 @@ struct library_plan {
static library_plan create(const library& lib, const library_build_params& params);
};

struct build_plan {
struct package_plan {
std::string name;
std::vector<std::string> pkg_requires;
std::vector<library_plan> create_libraries;

// static build_plan generate(const build_params& params);
void add_library(const library& lib, const library_build_params& params) {
create_libraries.push_back(library_plan::create(lib, params));
}
};

struct build_plan {
std::vector<package_plan> build_packages;

void compile_all(const toolchain& tc, int njobs, path_ref out_prefix) const;
void archive_all(const toolchain& tc, int njobs, path_ref out_prefix) const;
void compile_all(const build_env& env, int njobs) const;
void archive_all(const build_env& env, int njobs) const;
};

} // namespace dds

+ 11
- 3
src/dds/ddslim.main.cpp Переглянути файл

@@ -350,7 +350,11 @@ struct cli_deps {
"Directory where build results will be stored",
{"deps-build-dir"},
dds::fs::current_path() / "_build/deps"};
path_flag lmi_path{cmd, "lmi_path", "Destination for the INDEX.lmi file", {"lmi-path"}};
path_flag lmi_path{cmd,
"lmi_path",
"Destination for the INDEX.lmi file",
{"lmi-path"},
dds::fs::current_path() / "_build/INDEX.lmi"};
args::Flag no_lmi{cmd,
"no_lmi",
"If specified, will not generate an INDEX.lmi",
@@ -374,8 +378,12 @@ struct cli_deps {
auto plan = dds::create_deps_build_plan(deps);
auto tc = tc_filepath.get_toolchain();
auto bdir = build_dir.Get();
plan.compile_all(tc, 6, bdir);
plan.archive_all(tc, 6, bdir);
dds::build_env env{std::move(tc), bdir};
plan.compile_all(env, 6);
plan.archive_all(env, 6);
if (!no_lmi.Get()) {
write_libman_index(lmi_path.Get(), plan, env);
}
return 0;
}
} build{*this};

+ 77
- 6
src/dds/deps.cpp Переглянути файл

@@ -3,6 +3,8 @@
#include <dds/repo/repo.hpp>
#include <dds/sdist.hpp>
#include <dds/util/string.hpp>
#include <libman/index.hpp>
#include <libman/parse.hpp>

#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
@@ -73,9 +75,9 @@ using sdist_index_type = std::map<std::string, std::reference_wrapper<const sdis

namespace {

void add_dep_includes(shared_compile_file_rules& rules,
const package_manifest& man,
const sdist_index_type& sd_idx) {
void linkup_dependencies(shared_compile_file_rules& rules,
const package_manifest& man,
const sdist_index_type& sd_idx) {
for (const dependency& dep : man.dependencies) {
auto found = sd_idx.find(dep.name);
if (found == sd_idx.end()) {
@@ -84,7 +86,7 @@ void add_dep_includes(shared_compile_file_rules& rules,
dep.name,
man.name));
}
add_dep_includes(rules, found->second.get().manifest, sd_idx);
linkup_dependencies(rules, found->second.get().manifest, sd_idx);
auto lib_src = found->second.get().path / "src";
auto lib_include = found->second.get().path / "include";
if (fs::exists(lib_include)) {
@@ -96,13 +98,15 @@ void add_dep_includes(shared_compile_file_rules& rules,
}

void add_sdist_to_dep_plan(build_plan& plan, const sdist& sd, const sdist_index_type& sd_idx) {
auto& pkg = plan.build_packages.emplace_back();
pkg.name = sd.manifest.name;
auto libs = collect_libraries(sd.path, sd.manifest.name);
for (const auto& lib : libs) {
shared_compile_file_rules comp_rules = lib.base_compile_rules();
add_dep_includes(comp_rules, sd.manifest, sd_idx);
linkup_dependencies(comp_rules, sd.manifest, sd_idx);
library_build_params params;
params.compile_rules = comp_rules;
plan.add_library(lib, params);
pkg.add_library(lib, params);
}
}

@@ -121,3 +125,70 @@ build_plan dds::create_deps_build_plan(const std::vector<sdist>& deps) {
}
return plan;
}

namespace {

fs::path generate_lml(const library_plan& lib, path_ref libdir, const build_env& env) {
auto fname = lib.name + ".lml";
auto lml_path = libdir / fname;

std::vector<lm::pair> kvs;
kvs.emplace_back("Type", "Library");
kvs.emplace_back("Name", lib.name);
if (lib.create_archive) {
kvs.emplace_back("Path",
fs::relative(lib.create_archive->archive_file_path(env),
lml_path.parent_path()).string());
}
auto pub_inc_dir = lib.source_root / "include";
auto src_dir = lib.source_root / "src";
if (fs::exists(src_dir)) {
pub_inc_dir = src_dir;
}
kvs.emplace_back("Include-Path", pub_inc_dir.string());

// TODO: Uses, Preprocessor-Define, and Special-Uses

fs::create_directories(lml_path.parent_path());
lm::write_pairs(lml_path, kvs);
return lml_path;
}

fs::path generate_lmp(const package_plan& pkg, path_ref basedir, const build_env& env) {
auto fname = pkg.name + ".lmp";
auto lmp_path = basedir / fname;

std::vector<lm::pair> kvs;
kvs.emplace_back("Type", "Package");
kvs.emplace_back("Name", pkg.name);
kvs.emplace_back("Namespace", pkg.name);

for (auto&& lib : pkg.create_libraries) {
auto lml = generate_lml(lib, basedir / pkg.name, env);
kvs.emplace_back("Library", fs::relative(lml, lmp_path.parent_path()).string());
}

// TODO: `Requires` for transitive package imports

fs::create_directories(lmp_path.parent_path());
lm::write_pairs(lmp_path, kvs);
return lmp_path;
}

} // namespace

void dds::write_libman_index(path_ref out_filepath, const build_plan& plan, const build_env& env) {
fs::create_directories(out_filepath.parent_path());
auto lm_items_dir = out_filepath.parent_path() / "_libman";
std::vector<lm::pair> kvs;
kvs.emplace_back("Type", "Index");
for (const package_plan& pkg : plan.build_packages) {
auto pkg_lmp = generate_lmp(pkg, lm_items_dir, env);
kvs.emplace_back("Package", fmt::format(
"{}; {}",
pkg.name,
fs::relative(pkg_lmp, out_filepath.parent_path()).string()
));
}
lm::write_pairs(out_filepath, kvs);
}

+ 2
- 0
src/dds/deps.hpp Переглянути файл

@@ -44,4 +44,6 @@ inline std::vector<sdist> find_dependencies(const repository& repo, Iter it, Snt

build_plan create_deps_build_plan(const std::vector<sdist>& deps);

void write_libman_index(path_ref where, const build_plan& plan, const build_env& env);

} // namespace dds

Завантаження…
Відмінити
Зберегти