Kaynağa Gözat

Merge branch 'feature/integrate-deps-build' into develop

default_compile_flags
vector-of-bool 5 yıl önce
ebeveyn
işleme
26aeaa8ba9
37 değiştirilmiş dosya ile 538 ekleme ve 622 silme
  1. +79
    -0
      catalog.json
  2. +0
    -1
      remote.dds
  3. +94
    -8
      src/dds/build.cpp
  4. +1
    -1
      src/dds/build.hpp
  5. +14
    -11
      src/dds/build/params.hpp
  6. +3
    -1
      src/dds/build/plan/archive.cpp
  7. +8
    -3
      src/dds/build/plan/compile_exec.cpp
  8. +12
    -1
      src/dds/build/plan/library.hpp
  9. +6
    -8
      src/dds/catalog/catalog.cpp
  10. +1
    -3
      src/dds/catalog/catalog.hpp
  11. +0
    -36
      src/dds/catalog/catalog.test.cpp
  12. +2
    -2
      src/dds/catalog/get.cpp
  13. +45
    -157
      src/dds/dds.main.cpp
  14. +0
    -168
      src/dds/deps.cpp
  15. +0
    -14
      src/dds/deps.hpp
  16. +0
    -56
      src/dds/library.hpp
  17. +1
    -1
      src/dds/library/library.cpp
  18. +92
    -0
      src/dds/library/library.hpp
  19. +1
    -1
      src/dds/library/manifest.cpp
  20. +30
    -0
      src/dds/library/manifest.hpp
  21. +0
    -19
      src/dds/library_manifest.hpp
  22. +1
    -1
      src/dds/package/id.cpp
  23. +48
    -0
      src/dds/package/id.hpp
  24. +1
    -1
      src/dds/package/id.test.cpp
  25. +5
    -5
      src/dds/package/manifest.cpp
  26. +40
    -0
      src/dds/package/manifest.hpp
  27. +0
    -31
      src/dds/package_id.hpp
  28. +0
    -27
      src/dds/package_manifest.hpp
  29. +28
    -26
      src/dds/repo/repo.cpp
  30. +2
    -1
      src/dds/repo/repo.hpp
  31. +1
    -1
      src/dds/sdist.cpp
  32. +4
    -4
      src/dds/sdist.hpp
  33. +1
    -1
      src/dds/solve/solve.hpp
  34. +6
    -16
      tests/dds.py
  35. +2
    -13
      tests/deps/do_test.py
  36. +0
    -2
      tests/deps/use-spdlog/use_spdlog_test.py
  37. +10
    -2
      tools/ci.py

+ 79
- 0
catalog.json Dosyayı Görüntüle

{
"version": 1,
"packages": {
"range-v3": {
"0.10.0": {
"git": {
"url": "https://github.com/ericniebler/range-v3.git",
"ref": "0.10.0",
"auto-lib": "Niebler/range-v3"
},
"depends": {}
}
},
"spdlog": {
"1.4.2": {
"git": {
"url": "https://github.com/gabime/spdlog.git",
"ref": "v1.4.2",
"auto-lib": "spdlog/spdlog"
},
"depends": {}
}
},
"nlohmann-json": {
"3.7.1": {
"git": {
"url": "https://github.com/vector-of-bool/json.git",
"ref": "dds/3.7.1"
},
"depends": {}
}
},
"ms-wil": {
"2019.11.10": {
"git": {
"url": "https://github.com/vector-of-bool/wil.git",
"ref": "dds/2019.11.10"
},
"depends": {}
}
},
"neo-buffer": {
"0.1.0": {
"git": {
"url": "https://github.com/vector-of-bool/neo-buffer.git",
"ref": "develop"
},
"depends": {}
}
},
"neo-sqlite3": {
"0.2.2": {
"git": {
"url": "https://github.com/vector-of-bool/neo-sqlite3.git",
"ref": "0.2.2"
},
"depends": {}
}
},
"semver": {
"0.2.1": {
"git": {
"url": "https://github.com/vector-of-bool/semver.git",
"ref": "0.2.1"
},
"depends": {}
}
},
"pubgrub": {
"0.1.2": {
"git": {
"url": "https://github.com/vector-of-bool/pubgrub.git",
"ref": "0.1.2"
},
"depends": {}
}
}
}
}

+ 0
- 1
remote.dds Dosyayı Görüntüle

Remote-Package: range-v3 0.9.1; git url=https://github.com/ericniebler/range-v3.git ref=0.9.1 auto=Niebler/range-v3
Remote-Package: range-v3 0.10.0; git url=https://github.com/ericniebler/range-v3.git ref=0.10.0 auto=Niebler/range-v3 Remote-Package: range-v3 0.10.0; git url=https://github.com/ericniebler/range-v3.git ref=0.10.0 auto=Niebler/range-v3
Remote-Package: spdlog 1.4.2; git url=https://github.com/gabime/spdlog.git ref=v1.4.2 auto=spdlog/spdlog Remote-Package: spdlog 1.4.2; git url=https://github.com/gabime/spdlog.git ref=v1.4.2 auto=spdlog/spdlog



+ 94
- 8
src/dds/build.cpp Dosyayı Görüntüle

#include <libman/index.hpp> #include <libman/index.hpp>
#include <libman/parse.hpp> #include <libman/parse.hpp>


#include <range/v3/algorithm/transform.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>


#include <array> #include <array>
#include <map>
#include <set>
#include <stdexcept> #include <stdexcept>


using namespace dds; using namespace dds;
} }
} }


void add_ureqs(usage_requirement_map& ureqs,
const sdist& sd,
const library& lib,
const library_plan& lib_plan,
build_env_ref env) {
lm::library& reqs = ureqs.add(sd.manifest.namespace_, lib.manifest().name);
reqs.include_paths.push_back(lib.public_include_dir());
reqs.name = lib.manifest().name;
reqs.uses = lib.manifest().uses;
reqs.links = lib.manifest().links;
if (lib_plan.create_archive()) {
reqs.linkable_path = lib_plan.create_archive()->calc_archive_file_path(env);
}
// TODO: preprocessor definitions
}

using sdist_index_type = std::map<std::string, std::reference_wrapper<const sdist>>;
using sdist_names = std::set<std::string>;

void add_sdist_to_build(build_plan& plan,
const sdist& sd,
const sdist_index_type& sd_idx,
build_env_ref env,
usage_requirement_map& ureqs,
sdist_names& already_added) {
if (already_added.find(sd.manifest.pkg_id.name) != already_added.end()) {
// This one has already been added
return;
}
spdlog::debug("Adding dependent build: {}", sd.manifest.pkg_id.name);
// Ensure that ever dependency is loaded up first)
for (const auto& dep : sd.manifest.dependencies) {
auto other = sd_idx.find(dep.name);
assert(other != sd_idx.end()
&& "Failed to load a transitive dependency shortly after initializing them. What?");
add_sdist_to_build(plan, other->second, sd_idx, env, ureqs, already_added);
}
// Record that we have been processed
already_added.insert(sd.manifest.pkg_id.name);
// Finally, actually add the package:
auto& pkg = plan.add_package(package_plan(sd.manifest.pkg_id.name, sd.manifest.namespace_));
auto libs = collect_libraries(sd.path);
for (const auto& lib : libs) {
shared_compile_file_rules comp_rules = lib.base_compile_rules();
library_build_params lib_params;
lib_params.out_subdir = fs::path("deps") / sd.manifest.pkg_id.name;
auto lib_plan = library_plan::create(lib, lib_params, ureqs);
// Create usage requirements for this libary.
add_ureqs(ureqs, sd, lib, lib_plan, env);
// Add it to the plan:
pkg.add_library(std::move(lib_plan));
}
}

void add_deps_to_build(build_plan& plan,
usage_requirement_map& ureqs,
const build_params& params,
build_env_ref env) {
auto sd_idx = params.dep_sdists //
| ranges::views::transform([](const auto& sd) {
return std::pair(sd.manifest.pkg_id.name, std::cref(sd));
}) //
| ranges::to<sdist_index_type>();

sdist_names already_added;
for (const sdist& sd : params.dep_sdists) {
add_sdist_to_build(plan, sd, sd_idx, env, ureqs, already_added);
}
}

} // namespace } // namespace


void dds::build(const build_params& params, const package_manifest& man) { void dds::build(const build_params& params, const package_manifest& man) {
fs::create_directories(params.out_root);
auto db = database::open(params.out_root / ".dds.db");
dds::build_env env{params.toolchain, params.out_root, db};

// The build plan we will fill out:
build_plan plan;

// Collect libraries for the current project
auto libs = collect_libraries(params.root); auto libs = collect_libraries(params.root);
if (!libs.size()) { if (!libs.size()) {
spdlog::warn("Nothing found to build!"); spdlog::warn("Nothing found to build!");
return; return;
} }


build_plan plan;
auto& pkg = plan.add_package(package_plan(man.pk_id.name, man.namespace_));
usage_requirement_map ureqs;


usage_requirement_map ureqs
= load_usage_requirements(params.root, params.out_root, params.lm_index);
if (params.existing_lm_index) {
ureqs = load_usage_requirements(params.root, params.out_root, *params.existing_lm_index);
} else {
add_deps_to_build(plan, ureqs, params, env);
}

// Initialize the build plan for this project.
auto& pkg = plan.add_package(package_plan(man.pkg_id.name, man.namespace_));

// assert(false && "Not ready yet!");


library_build_params lib_params; library_build_params lib_params;
lib_params.build_tests = params.build_tests; lib_params.build_tests = params.build_tests;
lib_params.build_apps = params.build_apps; lib_params.build_apps = params.build_apps;
lib_params.enable_warnings = params.enable_warnings; lib_params.enable_warnings = params.enable_warnings;


fs::create_directories(params.out_root);
auto db = database::open(params.out_root / ".dds.db");
dds::build_env env{params.toolchain, params.out_root, db};

if (man.test_driver) { if (man.test_driver) {
prepare_test_driver(lib_params, params, man, env); prepare_test_driver(lib_params, params, man, env);
} }

+ 1
- 1
src/dds/build.hpp Dosyayı Görüntüle

#pragma once #pragma once


#include <dds/build/params.hpp> #include <dds/build/params.hpp>
#include <dds/package_manifest.hpp>
#include <dds/package/manifest.hpp>


namespace dds { namespace dds {



+ 14
- 11
src/dds/build/params.hpp Dosyayı Görüntüle



#include <dds/toolchain/toolchain.hpp> #include <dds/toolchain/toolchain.hpp>
#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>
#include <dds/sdist.hpp>

#include <optional>


namespace dds { namespace dds {


struct build_params { struct build_params {
fs::path root;
fs::path out_root;
fs::path lm_index;
dds::toolchain toolchain;
bool do_export = false;
bool build_tests = false;
bool enable_warnings = false;
bool build_apps = false;
bool build_deps = false;
bool generate_compdb = true;
int parallel_jobs = 0;
fs::path root;
fs::path out_root;
std::optional<fs::path> existing_lm_index;
dds::toolchain toolchain;
std::vector<sdist> dep_sdists;
bool do_export = false;
bool build_tests = false;
bool enable_warnings = false;
bool build_apps = false;
bool generate_compdb = true;
int parallel_jobs = 0;
}; };


} // namespace dds } // namespace dds

+ 3
- 1
src/dds/build/plan/archive.cpp Dosyayı Görüntüle

using namespace dds; using namespace dds;


fs::path create_archive_plan::calc_archive_file_path(const build_env& env) const noexcept { fs::path create_archive_plan::calc_archive_file_path(const build_env& env) const noexcept {
return env.output_root / fmt::format("{}{}{}", "lib", _name, env.toolchain.archive_suffix());
return env.output_root / _subdir
/ fmt::format("{}{}{}", "lib", _name, env.toolchain.archive_suffix());
} }


void create_archive_plan::archive(const build_env& env) const { void create_archive_plan::archive(const build_env& env) const {
} }


spdlog::info("[{}] Archive: {}", _name, out_relpath); spdlog::info("[{}] Archive: {}", _name, out_relpath);
fs::create_directories(ar.out_path.parent_path());
auto&& [dur_ms, ar_res] = timed<std::chrono::milliseconds>([&] { return run_proc(ar_cmd); }); auto&& [dur_ms, ar_res] = timed<std::chrono::milliseconds>([&] { return run_proc(ar_cmd); });
spdlog::info("[{}] Archive: {} - {:n}ms", _name, out_relpath, dur_ms.count()); spdlog::info("[{}] Archive: {} - {:n}ms", _name, out_relpath, dur_ms.count());



+ 8
- 3
src/dds/build/plan/compile_exec.cpp Dosyayı Görüntüle

} }


bool should_compile(const compile_file_full& comp, build_env_ref env) { bool should_compile(const compile_file_full& comp, build_env_ref env) {
if (!fs::exists(comp.object_file_path)) {
// The output file simply doesn't exist. We have to recompile, of course.
return true;
}
database& db = env.db; database& db = env.db;
auto rb_info = get_rebuild_info(db, comp.object_file_path); auto rb_info = get_rebuild_info(db, comp.object_file_path);
if (rb_info.previous_command.empty()) { if (rb_info.previous_command.empty()) {
auto each_realized = // auto each_realized = //
compiles // compiles //
| views::transform([&](auto&& plan) { return realize_plan(plan, env); }) // | views::transform([&](auto&& plan) { return realize_plan(plan, env); }) //
| views::filter([&](auto&& real) { return should_compile(real, env); });
| views::filter([&](auto&& real) { return should_compile(real, env); }) //
| ranges::to_vector;


const auto total = compiles.size();
const auto total = each_realized.size();
const auto max_digits = fmt::format("{}", total).size(); const auto max_digits = fmt::format("{}", total).size();
compile_counter counter{{0}, total, max_digits};
compile_counter counter{{1}, total, max_digits};


std::vector<deps_info> all_new_deps; std::vector<deps_info> all_new_deps;
std::mutex mut; std::mutex mut;

+ 12
- 1
src/dds/build/plan/library.hpp Dosyayı Görüntüle



#include <dds/build/plan/archive.hpp> #include <dds/build/plan/archive.hpp>
#include <dds/build/plan/exe.hpp> #include <dds/build/plan/exe.hpp>
#include <dds/library.hpp>
#include <dds/library/library.hpp>
#include <dds/usage_reqs.hpp> #include <dds/usage_reqs.hpp>
#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>




namespace dds { namespace dds {


struct library_build_params {
fs::path out_subdir;
bool build_tests = false;
bool build_apps = false;
bool enable_warnings = false;

// Extras for compiling tests:
std::vector<fs::path> test_include_dirs;
std::vector<fs::path> test_link_files;
};

class library_plan { class library_plan {
std::string _name; std::string _name;
fs::path _source_root; fs::path _source_root;

+ 6
- 8
src/dds/catalog/catalog.cpp Dosyayı Görüntüle

lm_name TEXT, lm_name TEXT,
lm_namespace TEXT, lm_namespace TEXT,
UNIQUE(name, version), UNIQUE(name, version),
CONSTRAINT has_remote_info CHECK(
CONSTRAINT has_source_info CHECK(
( (
git_url NOT NULL git_url NOT NULL
AND git_ref NOT NULL AND git_ref NOT NULL
) )
= 1
), ),
CONSTRAINT valid_lm_info CHECK( CONSTRAINT valid_lm_info CHECK(
( (
} // namespace } // namespace


catalog catalog::open(const std::string& db_path) { catalog catalog::open(const std::string& db_path) {
if (db_path != ":memory:") {
fs::create_directories(fs::weakly_canonical(db_path).parent_path());
}
auto db = sqlite3::database::open(db_path); auto db = sqlite3::database::open(db_path);
try { try {
ensure_migrated(db); ensure_migrated(db);
git_remote_listing{ git_remote_listing{
*git_url, *git_url,
*git_ref, *git_ref,
lm_name ? std::make_optional(lm::usage{*lm_name, *lm_namespace}) : std::nullopt,
lm_name ? std::make_optional(lm::usage{*lm_namespace, *lm_name}) : std::nullopt,
}, },
}; };
} }
} }
} }
} }

std::vector<package_id> catalog::solve_requirements(const std::vector<dependency>& deps) const {
return dds::solve(deps,
[&](std::string_view pkg_name) { return this->by_name(pkg_name); },
[&](const package_id& pkg) { return this->dependencies_of(pkg); });
}

+ 1
- 3
src/dds/catalog/catalog.hpp Dosyayı Görüntüle



#include <dds/catalog/git.hpp> #include <dds/catalog/git.hpp>
#include <dds/deps.hpp> #include <dds/deps.hpp>
#include <dds/package_id.hpp>
#include <dds/package/id.hpp>
#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>


#include <neo/sqlite3/database.hpp> #include <neo/sqlite3/database.hpp>
auto content = dds::slurp_file(json_path); auto content = dds::slurp_file(json_path);
import_json_str(content); import_json_str(content);
} }

std::vector<package_id> solve_requirements(const std::vector<dependency>& deps) const;
}; };


} // namespace dds } // namespace dds

+ 0
- 36
src/dds/catalog/catalog.test.cpp Dosyayı Görüntüle

== dds::version_range_set{semver::version::parse("4.2.1"), == dds::version_range_set{semver::version::parse("4.2.1"),
semver::version::parse("4.3.0")}); semver::version::parse("4.3.0")});
} }

TEST_CASE_METHOD(catalog_test_case, "Simple solve") {
db.import_json_str(R"({
"version": 1,
"packages": {
"foo": {
"1.2.3": {
"depends": {
"bar": "~4.2.1"
},
"git": {
"url": "http://example.com",
"ref": "master"
}
}
},
"bar": {
"4.2.3": {
"depends": {},
"git": {
"url": "http://example.com",
"ref": "master"
}
}
}
}
})");
auto sln = db.solve_requirements({{"foo",
dds::version_range_set{semver::version::parse("1.0.0"),
semver::version::parse("2.0.0")}}});
REQUIRE(sln.size() == 2);
CHECK(sln[0].name == "foo");
CHECK(sln[0].version == semver::version::parse("1.2.3"));
CHECK(sln[1].name == "bar");
CHECK(sln[1].version == semver::version::parse("4.2.3"));
}

+ 2
- 2
src/dds/catalog/get.cpp Dosyayı Görüntüle



temporary_sdist dds::get_package_sdist(const package_info& pkg) { temporary_sdist dds::get_package_sdist(const package_info& pkg) {
auto tsd = std::visit([&](auto&& remote) { return do_pull_sdist(pkg, remote); }, pkg.remote); auto tsd = std::visit([&](auto&& remote) { return do_pull_sdist(pkg, remote); }, pkg.remote);
if (!(tsd.sdist.manifest.pk_id == pkg.ident)) {
if (!(tsd.sdist.manifest.pkg_id == pkg.ident)) {
throw std::runtime_error(fmt::format( throw std::runtime_error(fmt::format(
"The package name@version in the generated sdist does not match the name listed in " "The package name@version in the generated sdist does not match the name listed in "
"the remote listing file (expected '{}', but got '{}')", "the remote listing file (expected '{}', but got '{}')",
pkg.ident.to_string(), pkg.ident.to_string(),
tsd.sdist.manifest.pk_id.to_string()));
tsd.sdist.manifest.pkg_id.to_string()));
} }
return tsd; return tsd;
} }

+ 45
- 157
src/dds/dds.main.cpp Dosyayı Görüntüle

return get.run(); return get.run();
} else if (add.cmd) { } else if (add.cmd) {
return add.run(); return add.run();
} else if (list.cmd) {
return list.run();
} else { } else {
assert(false); assert(false);
std::terminate(); std::terminate();
int run() { int run() {
auto list_contents = [&](dds::repository repo) { auto list_contents = [&](dds::repository repo) {
auto same_name = [](auto&& a, auto&& b) { auto same_name = [](auto&& a, auto&& b) {
return a.manifest.pk_id.name == b.manifest.pk_id.name;
return a.manifest.pkg_id.name == b.manifest.pkg_id.name;
}; };


auto all = repo.iter_sdists(); auto all = repo.iter_sdists();
| ranges::views::transform(ranges::to_vector) // | ranges::views::transform(ranges::to_vector) //
| ranges::views::transform([](auto&& grp) { | ranges::views::transform([](auto&& grp) {
assert(grp.size() > 0); assert(grp.size() > 0);
return std::pair(grp[0].manifest.pk_id.name, grp);
return std::pair(grp[0].manifest.pkg_id.name, grp);
}); });


for (const auto& [name, grp] : grp_by_name) { for (const auto& [name, grp] : grp_by_name) {
spdlog::info("{}:", name); spdlog::info("{}:", name);
for (const dds::sdist& sd : grp) { for (const dds::sdist& sd : grp) {
spdlog::info(" - {}", sd.manifest.pk_id.version.to_string());
spdlog::info(" - {}", sd.manifest.pkg_id.version.to_string());
} }
} }




common_project_flags project{cmd}; common_project_flags project{cmd};


args::Flag build_tests{cmd, "build_tests", "Build and run the tests", {"tests", 'T'}};
args::Flag build_apps{cmd, "build_apps", "Build applications", {"apps", 'A'}};
args::Flag export_{cmd, "export", "Generate a library export", {"export", 'E'}};
catalog_path_flag cat_path{cmd};
repo_path_flag repo_path{cmd};

args::Flag no_tests{cmd, "no-tests", "Do not build and run tests", {"no-tests"}};
args::Flag no_apps{cmd, "no-apps", "Do not compile and link applications", {"no-apps"}};
args::Flag no_warnings{cmd, "no-warings", "Disable build warnings", {"no-warnings"}};
toolchain_flag tc_filepath{cmd}; toolchain_flag tc_filepath{cmd};


args::Flag enable_warnings{cmd,
"enable_warnings",
"Enable compiler warnings",
{"warnings", 'W'}};
args::Flag export_{cmd, "export", "Generate a library export", {"export", 'E'}};


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


args::ValueFlag<int> num_jobs{cmd, args::ValueFlag<int> num_jobs{cmd,
"jobs", "jobs",
params.out_root = out.Get(); params.out_root = out.Get();
params.toolchain = tc_filepath.get_toolchain(); params.toolchain = tc_filepath.get_toolchain();
params.do_export = export_.Get(); params.do_export = export_.Get();
params.build_tests = build_tests.Get();
params.build_apps = build_apps.Get();
params.enable_warnings = enable_warnings.Get();
params.build_tests = !no_tests.Get();
params.build_apps = !no_apps.Get();
params.enable_warnings = !no_warnings.Get();
params.parallel_jobs = num_jobs.Get(); params.parallel_jobs = num_jobs.Get();
params.lm_index = lm_index.Get();
dds::package_manifest man; dds::package_manifest man;
const auto man_filepath = params.root / "package.dds"; const auto man_filepath = params.root / "package.dds";
if (exists(man_filepath)) { if (exists(man_filepath)) {
man = dds::package_manifest::load_from_file(man_filepath); man = dds::package_manifest::load_from_file(man_filepath);
} }
dds::build(params, man);
return 0;
}
};

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

struct cli_deps {
cli_base& base;
args::Command cmd{base.cmd_group, "deps", "Obtain/inspect/build deps for the project"};

common_flags _flags{cmd};
common_project_flags project{cmd};

args::Group deps_group{cmd, "Subcommands"};

dds::package_manifest load_package_manifest() {
return dds::package_manifest::load_from_file(project.root.Get() / "package.dds");
}

struct {
cli_deps& parent;
args::Command cmd{parent.deps_group, "ls", "List project dependencies"};
common_flags _common{cmd};

int run() {
const auto man = parent.load_package_manifest();
for (const auto& dep : man.dependencies) {
std::cout << dep.name << " " << dep.versions << '\n';
}
return 0;
}
} ls{*this};

struct {
cli_deps& parent;
args::Command cmd{parent.deps_group,
"get",
"Ensure we have local copies of the project dependencies"};
common_flags _common{cmd};

repo_path_flag repo_where{cmd};
catalog_path_flag catalog_path{cmd};

int run() {
auto man = parent.load_package_manifest();
auto catalog = catalog_path.open();
bool failed = false;
auto solved_deps = catalog.solve_requirements(man.dependencies);
dds::repository::with_repository( //
repo_where.Get(),
if (lm_index) {
params.existing_lm_index = lm_index.Get();
} else {
// Download and build dependencies
// Build the dependencies
auto cat = cat_path.open();
params.dep_sdists = dds::repository::with_repository( //
this->repo_path.Get(),
dds::repo_flags::write_lock | dds::repo_flags::create_if_absent, dds::repo_flags::write_lock | dds::repo_flags::create_if_absent,
[&](dds::repository repo) { [&](dds::repository repo) {
for (const dds::package_id& pk : solved_deps) {
// Download dependencies
auto deps = repo.solve(man.dependencies, cat);
for (const dds::package_id& pk : deps) {
auto exists = !!repo.find(pk); auto exists = !!repo.find(pk);
if (!exists) { if (!exists) {
spdlog::info("Pull remote: {}", pk.to_string());
auto opt_pkg = catalog.get(pk);
if (opt_pkg) {
auto tsd = dds::get_package_sdist(*opt_pkg);
repo.add_sdist(tsd.sdist, dds::if_exists::ignore);
} else {
spdlog::error("No remote listing for {}", pk.to_string());
failed = true;
}
} else {
spdlog::info("Okay: {}", pk.to_string());
spdlog::info("Download dependency: {}", pk.to_string());
auto opt_pkg = cat.get(pk);
assert(opt_pkg);
auto tsd = dds::get_package_sdist(*opt_pkg);
repo.add_sdist(tsd.sdist, dds::if_exists::throw_exc);
} }
} }
return deps //
| ranges::views::transform([&](auto& id) {
auto ptr = repo.find(id);
assert(ptr);
return *ptr;
})
| ranges::to_vector;
}); });
if (failed) {
return 1;
}
return 0;
}
} get{*this};

struct {
cli_deps& parent;
args::Command cmd{parent.deps_group, "build", "Build project dependencies"};
common_flags _common{cmd};

path_flag build_dir{cmd,
"build_dir",
"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"},
dds::fs::current_path() / "_build/INDEX.lmi"};
args::Flag no_lmi{cmd,
"no_lmi",
"If specified, will not generate an INDEX.lmi",
{"skip-lmi"}};

repo_path_flag repo_where{cmd};

toolchain_flag tc_filepath{cmd};

int run() {
auto man = parent.load_package_manifest();
auto deps = dds::repository::with_repository( //
repo_where.Get(),
dds::repo_flags::read,
[&](dds::repository repo) {
return repo.solve(man.dependencies);
});

auto tc = tc_filepath.get_toolchain();
auto bdir = build_dir.Get();
dds::fs::create_directories(bdir);
auto db = dds::database::open(bdir / ".dds.db");
dds::build_env env{std::move(tc), bdir, db};

auto plan = dds::create_deps_build_plan(deps, env);
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};

int run() {
if (ls.cmd) {
return ls.run();
} else if (build.cmd) {
return build.run();
} else if (get.cmd) {
return get.run();
}
std::terminate();
dds::build(params, man);
return 0;
} }
}; };


cli_build build{cli}; cli_build build{cli};
cli_sdist sdist{cli}; cli_sdist sdist{cli};
cli_repo repo{cli}; cli_repo repo{cli};
cli_deps deps{cli};
cli_catalog catalog{cli}; cli_catalog catalog{cli};
try { try {
parser.ParseCLI(argc, argv); parser.ParseCLI(argc, argv);
return sdist.run(); return sdist.run();
} else if (repo.cmd) { } else if (repo.cmd) {
return repo.run(); return repo.run();
} else if (deps.cmd) {
return deps.run();
} else if (catalog.cmd) { } else if (catalog.cmd) {
return catalog.run(); return catalog.run();
} else { } else {

+ 0
- 168
src/dds/deps.cpp Dosyayı Görüntüle

str)); str));
} }
} }

using sdist_index_type = std::map<std::string, std::reference_wrapper<const sdist>>;
using sdist_names = std::set<std::string>;

namespace {

void resolve_ureqs_(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()) {
throw std::runtime_error(
fmt::format("Unable to resolve dependency '{}' (required by '{}')",
dep.name,
man.pk_id.to_string()));
}
resolve_ureqs_(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)) {
rules.include_dirs().push_back(lib_include);
} else {
rules.include_dirs().push_back(lib_src);
}
}
}

void resolve_ureqs(shared_compile_file_rules rules,
const sdist& sd,
const library& lib,
const library_plan& lib_plan,
build_env_ref env,
usage_requirement_map& ureqs) {
// Add the transitive requirements for this library to our compile rules.
for (auto&& use : lib.manifest().uses) {
ureqs.apply(rules, use.namespace_, use.name);
}

// Create usage requirements for this libary.
lm::library& reqs = ureqs.add(sd.manifest.namespace_, lib.manifest().name);
reqs.include_paths.push_back(lib.public_include_dir());
reqs.name = lib.manifest().name;
reqs.uses = lib.manifest().uses;
reqs.links = lib.manifest().links;
if (lib_plan.create_archive()) {
reqs.linkable_path = lib_plan.create_archive()->calc_archive_file_path(env);
}
// TODO: preprocessor definitions
}

void add_sdist_to_dep_plan(build_plan& plan,
const sdist& sd,
build_env_ref env,
const sdist_index_type& sd_idx,
usage_requirement_map& ureqs,
sdist_names& already_added) {
if (already_added.find(sd.manifest.pk_id.name) != already_added.end()) {
// We've already loaded this package into the plan.
return;
}
spdlog::debug("Add to plan: {}", sd.manifest.pk_id.name);
// First, load every dependency
for (const auto& dep : sd.manifest.dependencies) {
auto other = sd_idx.find(dep.name);
assert(other != sd_idx.end()
&& "Failed to load a transitive dependency shortly after initializing them. What?");
add_sdist_to_dep_plan(plan, other->second, env, sd_idx, ureqs, already_added);
}
// Record that we have been processed:
already_added.insert(sd.manifest.pk_id.name);
// Add the package:
auto& pkg = plan.add_package(package_plan(sd.manifest.pk_id.name, sd.manifest.namespace_));
auto libs = collect_libraries(sd.path);
for (const auto& lib : libs) {
shared_compile_file_rules comp_rules = lib.base_compile_rules();
library_build_params params;
auto lib_plan = library_plan::create(lib, params, ureqs);
resolve_ureqs(comp_rules, sd, lib, lib_plan, env, ureqs);
pkg.add_library(std::move(lib_plan));
}
}

} // namespace

build_plan dds::create_deps_build_plan(const std::vector<sdist>& deps, build_env_ref env) {
auto sd_idx = deps //
| ranges::views::transform([](const auto& sd) {
return std::pair(sd.manifest.pk_id.name, std::cref(sd));
}) //
| ranges::to<sdist_index_type>();

build_plan plan;
usage_requirement_map ureqs;
sdist_names already_added;
for (const sdist& sd : deps) {
spdlog::info("Recording dependency: {}", sd.manifest.pk_id.name);
add_sdist_to_dep_plan(plan, sd, env, sd_idx, ureqs, already_added);
}
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()->calc_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(pub_inc_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.namespace_());

for (auto&& lib : pkg.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.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);
}

+ 0
- 14
src/dds/deps.hpp Dosyayı Görüntüle



namespace dds { namespace dds {


struct sdist;
class repository;

enum class version_strength {
exact,
patch,
minor,
major,
};

using version_range_set = pubgrub::interval_set<semver::version>; using version_range_set = pubgrub::interval_set<semver::version>;


struct dependency { struct dependency {
static dependency parse_depends_string(std::string_view str); static dependency parse_depends_string(std::string_view str);
}; };


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

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

} // namespace dds } // namespace dds

+ 0
- 56
src/dds/library.hpp Dosyayı Görüntüle

#pragma once

#include <dds/build/plan/compile_file.hpp>
#include <dds/build/source_dir.hpp>
#include <dds/library_manifest.hpp>
#include <dds/source.hpp>

#include <string>

namespace dds {

struct library_ident {
std::string namespace_;
std::string name;
};

class library {
fs::path _path;
source_list _sources;
library_manifest _man;

library(path_ref dir, source_list&& src, library_manifest&& man)
: _path(dir)
, _sources(std::move(src))
, _man(std::move(man)) {}

public:
static library from_directory(path_ref);

auto& manifest() const noexcept { return _man; }

source_directory src_dir() const noexcept { return source_directory{path() / "src"}; }
source_directory include_dir() const noexcept { return source_directory{path() / "include"}; }

path_ref path() const noexcept { return _path; }
fs::path public_include_dir() const noexcept;
fs::path private_include_dir() const noexcept;

const source_list& all_sources() const noexcept { return _sources; }
shared_compile_file_rules base_compile_rules() const noexcept;
};

struct library_build_params {
fs::path out_subdir;
bool build_tests = false;
bool build_apps = false;
bool enable_warnings = false;

// Extras for compiling tests:
std::vector<fs::path> test_include_dirs;
std::vector<fs::path> test_link_files;
};

std::vector<library> collect_libraries(path_ref where);

} // namespace dds

src/dds/library.cpp → src/dds/library/library.cpp Dosyayı Görüntüle

#include <dds/library.hpp>
#include <dds/library/library.hpp>


#include <dds/build/plan/compile_file.hpp> #include <dds/build/plan/compile_file.hpp>
#include <dds/build/source_dir.hpp> #include <dds/build/source_dir.hpp>

+ 92
- 0
src/dds/library/library.hpp Dosyayı Görüntüle

#pragma once

#include <dds/build/plan/compile_file.hpp>
#include <dds/build/source_dir.hpp>
#include <dds/library/manifest.hpp>
#include <dds/source.hpp>

#include <string>

namespace dds {

/**
* Represents a library that exists on the filesystem
*/
class library {
// The path containing the source directories for this library
fs::path _path;
// The sources that are part of this library
source_list _sources;
// The library manifest associated with this library (may be generated)
library_manifest _man;

// Private constructor. Use named constructor `from_directory`, which will build
// the construct arguments approperiately
library(path_ref dir, source_list&& src, library_manifest&& man)
: _path(dir)
, _sources(std::move(src))
, _man(std::move(man)) {}

public:
/**
* Create a library object that refers to the library contained at the given
* directory path. This will load the sources and manifest properly and
* return the resulting library object.
*/
static library from_directory(path_ref);

/**
* Obtain the manifest for this library
*/
const library_manifest& manifest() const noexcept { return _man; }

/**
* The `src/` directory for this library.
*/
source_directory src_dir() const noexcept { return source_directory{path() / "src"}; }

/**
* The `include/` directory for this library
*/
source_directory include_dir() const noexcept { return source_directory{path() / "include"}; }

/**
* The root path for this library (parent of `src/` and `include/`, if present)
*/
path_ref path() const noexcept { return _path; }

/**
* The directory that should be considered the "public" include directory.
* Dependees that want to use this library should add this to their #include
* search path.
*/
fs::path public_include_dir() const noexcept;

/**
* The directory that contains the "private" heders for this libary. This
* directory should be added to the search path of the library when it is
* being built, but NOT to the search path of the dependees.
*/
fs::path private_include_dir() const noexcept;

/**
* Get the sources that this library contains
*/
const source_list& all_sources() const noexcept { return _sources; }

/**
* Generate a compile rules object that should be used when compiling
* this library.
*/
shared_compile_file_rules base_compile_rules() const noexcept;
};

/**
* Given the root source directory of a project/package/sdist, collect all of
* the libraries that it contains. There may be a library directly in `where`,
* but there might also be libraries in `where/libs`. This function will find
* them all.
*/
std::vector<library> collect_libraries(path_ref where);

} // namespace dds

src/dds/library_manifest.cpp → src/dds/library/manifest.cpp Dosyayı Görüntüle

#include "./library_manifest.hpp"
#include "./manifest.hpp"


#include <dds/util/algo.hpp> #include <dds/util/algo.hpp>
#include <range/v3/view/transform.hpp> #include <range/v3/view/transform.hpp>

+ 30
- 0
src/dds/library/manifest.hpp Dosyayı Görüntüle

#pragma once

#include <dds/util/fs.hpp>

#include <libman/library.hpp>

#include <vector>

namespace dds {

/**
* Represents the contents of a `library.dds`. This is somewhat a stripped-down
* version of lm::library, to only represent exactly the parts that we want to
* offer via `library.dds`.
*/
struct library_manifest {
/// The name of the library
std::string name;
/// The libraries that the owning library "uses"
std::vector<lm::usage> uses;
/// The libraries that the owning library must be linked with
std::vector<lm::usage> links;

/**
* Load the library manifest from an existing file
*/
static library_manifest load_from_file(const fs::path&);
};

} // namespace dds

+ 0
- 19
src/dds/library_manifest.hpp Dosyayı Görüntüle

#pragma once

#include <dds/util/fs.hpp>

#include <libman/library.hpp>

#include <vector>

namespace dds {

struct library_manifest {
std::string name;
std::vector<lm::usage> uses;
std::vector<lm::usage> links;

static library_manifest load_from_file(const fs::path&);
};

} // namespace dds

src/dds/package_id.cpp → src/dds/package/id.cpp Dosyayı Görüntüle

#include <dds/package_id.hpp>
#include <dds/package/id.hpp>


#include <spdlog/fmt/fmt.h> #include <spdlog/fmt/fmt.h>



+ 48
- 0
src/dds/package/id.hpp Dosyayı Görüntüle

#pragma once

#include <semver/version.hpp>

#include <string>
#include <string_view>
#include <tuple>

namespace dds {

/**
* Represents a unique package ID. We store this as a simple name-version pair.
*
* In text, this is represented with an `@` symbol in between. The `parse` and
* `to_string` method convert between this textual representation, and supports
* full round-trips.
*/
struct package_id {
/// The name of the package
std::string name;
/// The version of the package
semver::version version;

/// Default-initialize a package_id with a blank name and a default version
package_id() = default;
/// Construct a package ID from a name-version pair
package_id(std::string_view s, semver::version v);

/**
* Parse the given string into a package_id object.
*/
static package_id parse(std::string_view);

/**
* Convert this package_id into its corresponding textual representation.
* The returned string can be passed back to `parse()` for a round-trip
*/
std::string to_string() const noexcept;

friend bool operator<(const package_id& lhs, const package_id& rhs) noexcept {
return std::tie(lhs.name, lhs.version) < std::tie(rhs.name, rhs.version);
}
friend bool operator==(const package_id& lhs, const package_id& rhs) noexcept {
return std::tie(lhs.name, lhs.version) == std::tie(rhs.name, rhs.version);
}
};

} // namespace dds

src/dds/package_id.test.cpp → src/dds/package/id.test.cpp Dosyayı Görüntüle

#include <dds/package_id.hpp>
#include <dds/package/id.hpp>


#include <catch2/catch.hpp> #include <catch2/catch.hpp>



src/dds/package_manifest.cpp → src/dds/package/manifest.cpp Dosyayı Görüntüle

#include "./package_manifest.hpp"
#include "./manifest.hpp"


#include <dds/util/string.hpp> #include <dds/util/string.hpp>
#include <libman/parse.hpp> #include <libman/parse.hpp>
std::optional<std::string> opt_test_driver; std::optional<std::string> opt_test_driver;
lm::read(fmt::format("Reading package manifest '{}'", fpath.string()), lm::read(fmt::format("Reading package manifest '{}'", fpath.string()),
kvs, kvs,
lm::read_required("Name", ret.pk_id.name),
lm::read_required("Name", ret.pkg_id.name),
lm::read_opt("Namespace", ret.namespace_), lm::read_opt("Namespace", ret.namespace_),
lm::read_required("Version", version_str), lm::read_required("Version", version_str),
lm::read_accumulate("Depends", depends_strs), lm::read_accumulate("Depends", depends_strs),
lm::read_opt("Test-Driver", opt_test_driver), lm::read_opt("Test-Driver", opt_test_driver),
lm::reject_unknown()); lm::reject_unknown());


if (ret.pk_id.name.empty()) {
if (ret.pkg_id.name.empty()) {
throw std::runtime_error( throw std::runtime_error(
fmt::format("'Name' field in [{}] may not be an empty string", fpath.string())); fmt::format("'Name' field in [{}] may not be an empty string", fpath.string()));
} }
} }


if (ret.namespace_.empty()) { if (ret.namespace_.empty()) {
ret.namespace_ = ret.pk_id.name;
ret.namespace_ = ret.pkg_id.name;
} }


ret.pk_id.version = semver::version::parse(version_str);
ret.pkg_id.version = semver::version::parse(version_str);


ret.dependencies = depends_strs // ret.dependencies = depends_strs //
| ranges::views::transform(dependency::parse_depends_string) // | ranges::views::transform(dependency::parse_depends_string) //

+ 40
- 0
src/dds/package/manifest.hpp Dosyayı Görüntüle

#pragma once

#include <dds/deps.hpp>
#include <dds/package/id.hpp>
#include <dds/util/fs.hpp>

#include <optional>
#include <string>
#include <vector>

namespace dds {

/**
* Possible values for Test-Driver in a package.dds
*/
enum class test_lib {
catch_,
catch_main,
};

/**
* Struct representing the contents of a `packaeg.dds` file.
*/
struct package_manifest {
/// The package ID, as determined by `Name` and `Version` together
package_id pkg_id;
/// The declared `Namespace` of the package. This directly corresponds with the libman Namespace
std::string namespace_;
/// The `Test-Driver` that this package declares, or `nullopt` if absent.
std::optional<test_lib> test_driver;
/// The dependencies declared with the `Depends` fields, if any.
std::vector<dependency> dependencies;

/**
* Load a package manifest from a file on disk.
*/
static package_manifest load_from_file(path_ref);
};

} // namespace dds

+ 0
- 31
src/dds/package_id.hpp Dosyayı Görüntüle

#pragma once

#include <semver/version.hpp>

#include <string>
#include <string_view>
#include <tuple>

namespace dds {

struct package_id {
std::string name;
semver::version version;

package_id() = default;
package_id(std::string_view s, semver::version v);

static package_id parse(std::string_view);
std::string to_string() const noexcept;

auto tie() const noexcept { return std::tie(name, version); }

friend bool operator<(const package_id& lhs, const package_id& rhs) noexcept {
return lhs.tie() < rhs.tie();
}
friend bool operator==(const package_id& lhs, const package_id& rhs) noexcept {
return lhs.tie() == rhs.tie();
}
};

} // namespace dds

+ 0
- 27
src/dds/package_manifest.hpp Dosyayı Görüntüle

#pragma once

#include <dds/deps.hpp>
#include <dds/package_id.hpp>
#include <dds/util/fs.hpp>
#include <semver/version.hpp>

#include <optional>
#include <string>
#include <vector>

namespace dds {

enum class test_lib {
catch_,
catch_main,
};

struct package_manifest {
package_id pk_id;
std::string namespace_;
std::optional<test_lib> test_driver;
std::vector<dependency> dependencies;
static package_manifest load_from_file(path_ref);
};

} // namespace dds

+ 28
- 26
src/dds/repo/repo.cpp Dosyayı Görüntüle

#include "./repo.hpp" #include "./repo.hpp"


#include <dds/catalog/catalog.hpp>
#include <dds/sdist.hpp> #include <dds/sdist.hpp>
#include <dds/solve/solve.hpp> #include <dds/solve/solve.hpp>
#include <dds/util/paths.hpp> #include <dds/util/paths.hpp>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>


#include <range/v3/action/sort.hpp> #include <range/v3/action/sort.hpp>
#include <range/v3/action/unique.hpp>
#include <range/v3/range/conversion.hpp> #include <range/v3/range/conversion.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/filter.hpp> #include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp> #include <range/v3/view/transform.hpp>


"repository, we'll hard-exit immediately."); "repository, we'll hard-exit immediately.");
std::terminate(); std::terminate();
} }
auto sd_dest = _root / sd.manifest.pk_id.to_string();
auto sd_dest = _root / sd.manifest.pkg_id.to_string();
if (fs::exists(sd_dest)) { if (fs::exists(sd_dest)) {
auto msg = fmt::format("Source distribution '{}' is already available in the local repo", auto msg = fmt::format("Source distribution '{}' is already available in the local repo",
sd.path.string()); sd.path.string());
fs::remove_all(sd_dest); fs::remove_all(sd_dest);
} }
fs::rename(tmp_copy, sd_dest); fs::rename(tmp_copy, sd_dest);
spdlog::info("Source distribution '{}' successfully exported", sd.manifest.pk_id.to_string());
_sdists.insert(sdist::from_directory(sd_dest));
spdlog::info("Source distribution '{}' successfully exported", sd.manifest.pkg_id.to_string());
} }


const sdist* repository::find(const package_id& pkg) const noexcept { const sdist* repository::find(const package_id& pkg) const noexcept {
return &*found; return &*found;
} }


std::vector<sdist> repository::solve(const std::vector<dependency>& deps) const {
auto ids = dds::solve(deps,
[&](std::string_view name) -> std::vector<package_id> {
auto items = ranges::views::all(_sdists) //
| ranges::views::filter([&](const sdist& sd) {
return sd.manifest.pk_id.name == name;
})
| ranges::views::transform(
[](const sdist& sd) { return sd.manifest.pk_id; })
| ranges::to_vector;
ranges::sort(items, std::less<>{});
return items;
},
[&](const package_id& pkg_id) {
auto found = find(pkg_id);
assert(found);
std::vector<package_id> repository::solve(const std::vector<dependency>& deps,
const catalog& ctlg) const {
return dds::solve(deps,
[&](std::string_view name) -> std::vector<package_id> {
auto mine = ranges::views::all(_sdists) //
| ranges::views::filter([&](const sdist& sd) {
return sd.manifest.pkg_id.name == name;
})
| ranges::views::transform(
[](const sdist& sd) { return sd.manifest.pkg_id; });
auto avail = ctlg.by_name(name);
auto all = ranges::views::concat(mine, avail) | ranges::to_vector;
ranges::sort(all, std::less<>{});
ranges::unique(all, std::less<>{});
return all;
},
[&](const package_id& pkg_id) {
auto found = find(pkg_id);
if (found) {
return found->manifest.dependencies; return found->manifest.dependencies;
});
return ids //
| ranges::views::transform([&](const package_id& pk_id) {
auto found = find(pk_id);
assert(found);
return *found;
}) //
| ranges::to_vector;
}
return ctlg.dependencies_of(pkg_id);
});
} }

+ 2
- 1
src/dds/repo/repo.hpp Dosyayı Görüntüle



#include <dds/sdist.hpp> #include <dds/sdist.hpp>
#include <dds/util/flock.hpp> #include <dds/util/flock.hpp>
#include <dds/catalog/catalog.hpp>
#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>


#include <functional> #include <functional>
return r; return r;
} }


std::vector<sdist> solve(const std::vector<dependency>& deps) const;
std::vector<package_id> solve(const std::vector<dependency>& deps, const catalog&) const;
}; };


} // namespace dds } // namespace dds

+ 1
- 1
src/dds/sdist.cpp Dosyayı Görüntüle

sdist_export_file(out, params.project_dir, man_path); sdist_export_file(out, params.project_dir, man_path);
auto pkg_man = package_manifest::load_from_file(man_path); auto pkg_man = package_manifest::load_from_file(man_path);


spdlog::info("Generated export as {}", pkg_man.pk_id.to_string());
spdlog::info("Generated export as {}", pkg_man.pkg_id.to_string());


return sdist::from_directory(out); return sdist::from_directory(out);
} }

+ 4
- 4
src/dds/sdist.hpp Dosyayı Görüntüle



#include <tuple> #include <tuple>


#include <dds/package_manifest.hpp>
#include <dds/package/manifest.hpp>
#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>


namespace dds { namespace dds {


inline constexpr struct sdist_compare_t { inline constexpr struct sdist_compare_t {
bool operator()(const sdist& lhs, const sdist& rhs) const { bool operator()(const sdist& lhs, const sdist& rhs) const {
return lhs.manifest.pk_id < rhs.manifest.pk_id;
return lhs.manifest.pkg_id < rhs.manifest.pkg_id;
} }
bool operator()(const sdist& lhs, const package_id& rhs) const { bool operator()(const sdist& lhs, const package_id& rhs) const {
return lhs.manifest.pk_id < rhs;
return lhs.manifest.pkg_id < rhs;
} }
bool operator()(const package_id& lhs, const sdist& rhs) const { bool operator()(const package_id& lhs, const sdist& rhs) const {
return lhs < rhs.manifest.pk_id;
return lhs < rhs.manifest.pkg_id;
} }
using is_transparent = int; using is_transparent = int;
} sdist_compare; } sdist_compare;

+ 1
- 1
src/dds/solve/solve.hpp Dosyayı Görüntüle

#pragma once #pragma once


#include <dds/deps.hpp> #include <dds/deps.hpp>
#include <dds/package_id.hpp>
#include <dds/package/id.hpp>


#include <functional> #include <functional>



+ 6
- 16
tests/dds.py Dosyayı Görüntüle

def project_dir_arg(self) -> str: def project_dir_arg(self) -> str:
return f'--project-dir={self.source_root}' return f'--project-dir={self.source_root}'


def deps_ls(self) -> subprocess.CompletedProcess:
return self.run(['deps', 'ls'])

def deps_get(self) -> subprocess.CompletedProcess:
return self.run([
'deps',
'get',
f'--catalog={self.catalog_path}',
self.repo_dir_arg,
])

def deps_build(self, *, def deps_build(self, *,
toolchain: str = None) -> subprocess.CompletedProcess: toolchain: str = None) -> subprocess.CompletedProcess:
return self.run([ return self.run([
return self.run([ return self.run([
'build', 'build',
f'--out={self.build_dir}', f'--out={self.build_dir}',
['--tests'] if tests else [],
['--apps'] if apps else [],
['--warnings'] if warnings else [],
['--export'] if export else [],
f'--toolchain={toolchain or self.default_builtin_toolchain}', f'--toolchain={toolchain or self.default_builtin_toolchain}',
f'--lm-index={self.lmi_path}',
f'--catalog={self.catalog_path}',
f'--repo-dir={self.repo_dir}',
['--no-tests'] if not tests else [],
['--no-apps'] if not apps else [],
['--no-warnings'] if not warnings else [],
['--export'] if export else [],
self.project_dir_arg, self.project_dir_arg,
]) ])



+ 2
- 13
tests/deps/do_test.py Dosyayı Görüntüle

) )




@dds_conf
def test_ls(dds: DDS):
dds.run(['deps', 'ls'])


@dds_conf @dds_conf
def test_deps_build(dds: DDS): def test_deps_build(dds: DDS):
dds.catalog_import(dds.source_root / 'catalog.json') dds.catalog_import(dds.source_root / 'catalog.json')
assert not dds.repo_dir.exists() assert not dds.repo_dir.exists()
dds.deps_get()
assert dds.repo_dir.exists(), '`deps get` did not generate a repo directory'

assert not dds.lmi_path.exists()
dds.deps_build()
assert dds.lmi_path.exists(), '`deps build` did not generate the build dir'
dds.build()
assert dds.repo_dir.exists(), '`Building` did not generate a repo directory'




@dds_fixture_conf_1('use-remote') @dds_fixture_conf_1('use-remote')
def test_use_nlohmann_json_remote(dds: DDS): def test_use_nlohmann_json_remote(dds: DDS):
dds.catalog_import(dds.source_root / 'catalog.json') dds.catalog_import(dds.source_root / 'catalog.json')
dds.deps_get()
dds.deps_build()
dds.build(apps=True) dds.build(apps=True)


app_exe = dds.build_dir / f'app{dds.exe_suffix}' app_exe = dds.build_dir / f'app{dds.exe_suffix}'

+ 0
- 2
tests/deps/use-spdlog/use_spdlog_test.py Dosyayı Görüntüle



def test_get_build_use_spdlog(dds: DDS): def test_get_build_use_spdlog(dds: DDS):
dds.catalog_import(dds.source_root / 'catalog.json') dds.catalog_import(dds.source_root / 'catalog.json')
dds.deps_get()
tc_fname = 'gcc.tc.dds' if 'gcc' in dds.default_builtin_toolchain else 'msvc.tc.dds' tc_fname = 'gcc.tc.dds' if 'gcc' in dds.default_builtin_toolchain else 'msvc.tc.dds'
tc = str(dds.test_dir / tc_fname) tc = str(dds.test_dir / tc_fname)
dds.deps_build(toolchain=tc)
dds.build(toolchain=tc, apps=True) dds.build(toolchain=tc, apps=True)
proc.check_run((dds.build_dir / 'use-spdlog').with_suffix(dds.exe_suffix)) proc.check_run((dds.build_dir / 'use-spdlog').with_suffix(dds.exe_suffix))

+ 10
- 2
tools/ci.py Dosyayı Görüntüle

else: else:
assert False, 'impossible' assert False, 'impossible'


ci_repo_dir = paths.BUILD_DIR / '_ci-repo'
if not opts.skip_deps: if not opts.skip_deps:
ci_repo_dir = paths.BUILD_DIR / '_ci-repo'
if ci_repo_dir.exists(): if ci_repo_dir.exists():
shutil.rmtree(ci_repo_dir) shutil.rmtree(ci_repo_dir)
self_deps_get(paths.PREBUILT_DDS, ci_repo_dir) self_deps_get(paths.PREBUILT_DDS, ci_repo_dir)
dds_flags=['--warnings', '--tests', '--apps']) dds_flags=['--warnings', '--tests', '--apps'])
print('Main build PASSED!') print('Main build PASSED!')


cat_path = paths.BUILD_DIR / 'catalog.db'
proc.check_run([
paths.CUR_BUILT_DDS,
'catalog',
'import',
('--catalog', cat_path),
('--json', paths.PROJECT_ROOT / 'catalog.json'),
])
self_build( self_build(
paths.CUR_BUILT_DDS, paths.CUR_BUILT_DDS,
toolchain=opts.toolchain, toolchain=opts.toolchain,
dds_flags=['--warnings', '--tests', '--apps'])
dds_flags=[f'--repo-dir={ci_repo_dir}', f'--catalog={cat_path}'])
print('Bootstrap test PASSED!') print('Bootstrap test PASSED!')


return pytest.main([ return pytest.main([

Yükleniyor…
İptal
Kaydet