Browse Source

`build-deps` command to build a set of dependencies

default_compile_flags
vector-of-bool 5 years ago
parent
commit
cef6707c36
4 changed files with 132 additions and 18 deletions
  1. +114
    -11
      src/dds.main.cpp
  2. +7
    -7
      tests/dds.py
  3. +4
    -0
      tests/deps/build-deps/project/deps.dds
  4. +7
    -0
      tests/deps/build-deps/test_build_deps.py

+ 114
- 11
src/dds.main.cpp View File

#include <dds/util/paths.hpp> #include <dds/util/paths.hpp>
#include <dds/util/signal.hpp> #include <dds/util/signal.hpp>


#include <range/v3/action/join.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/group_by.hpp> #include <range/v3/view/group_by.hpp>
#include <range/v3/view/transform.hpp> #include <range/v3/view/transform.hpp>


dds::catalog open() { return dds::catalog::open(Get()); } dds::catalog open() { return dds::catalog::open(Get()); }
}; };


struct num_jobs_flag : args::ValueFlag<int> {
num_jobs_flag(args::Group& cmd)
: ValueFlag(cmd,
"jobs",
"Set the number of parallel jobs when compiling files",
{"jobs", 'j'},
0) {}
};

/** /**
* Base class holds the actual argument parser * Base class holds the actual argument parser
*/ */
"Path to an existing libman index from which to load deps (usually INDEX.lmi)", "Path to an existing libman index from which to load deps (usually INDEX.lmi)",
{"lm-index", 'I'}}; {"lm-index", 'I'}};


args::ValueFlag<int> num_jobs{cmd,
"jobs",
"Set the number of parallel jobs when compiling files",
{"jobs", 'j'},
0};
num_jobs_flag n_jobs{cmd};


path_flag out{cmd, path_flag out{cmd,
"out", "out",
dds::build_params params; dds::build_params params;
params.out_root = out.Get(); params.out_root = out.Get();
params.toolchain = tc_filepath.get_toolchain(); params.toolchain = tc_filepath.get_toolchain();
params.parallel_jobs = num_jobs.Get();
params.parallel_jobs = n_jobs.Get();
dds::package_manifest man; dds::package_manifest man;
const auto man_filepath = project.root.Get() / "package.dds"; const auto man_filepath = project.root.Get() / "package.dds";
if (exists(man_filepath)) { if (exists(man_filepath)) {
} }
}; };


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

struct cli_build_deps {
cli_base& base;
args::Command cmd{base.cmd_group,
"build-deps",
"Build a set of dependencies and emit a libman index"};

toolchain_flag tc{cmd};
repo_path_flag repo_path{cmd};
catalog_path_flag cat_path{cmd};
num_jobs_flag n_jobs{cmd};

args::ValueFlagList<dds::fs::path> deps_files{cmd,
"deps-file",
"Install dependencies from the named files",
{"deps", 'd'}};

path_flag out_path{cmd,
"out-path",
"Directory where build results should be placed",
{"out", 'o'},
dds::fs::current_path() / "_deps"};

path_flag lmi_path{cmd,
"lmi-path",
"Path to the output libman index file (INDEX.lmi)",
{"lmi-path"},
dds::fs::current_path() / "INDEX.lmi"};

args::PositionalList<std::string> deps{cmd, "deps", "List of dependencies to install"};

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

dds::builder bd;
dds::sdist_build_params sdist_params;

auto all_file_deps
= deps_files.Get() //
| ranges::views::transform([&](auto dep_fpath) {
spdlog::info("Reading deps from {}", dep_fpath.string());
return dds::package_manifest::load_from_file(dep_fpath).dependencies;
})
| ranges::actions::join;

auto cmd_deps = ranges::views::transform(deps.Get(), [&](auto dep_str) {
return dds::dependency::parse_depends_string(dep_str);
});

auto all_deps = ranges::views::concat(all_file_deps, cmd_deps) | ranges::to_vector;

auto cat = cat_path.open();
dds::repository::with_repository( //
repo_path.Get(),
dds::repo_flags::write_lock | dds::repo_flags::create_if_absent,
[&](dds::repository repo) {
// Download dependencies
spdlog::info("Loading {} dependencies", all_deps.size());
auto deps = repo.solve(all_deps, cat);
for (const dds::package_id& pk : deps) {
auto exists = !!repo.find(pk);
if (!exists) {
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);
}
auto sdist_ptr = repo.find(pk);
assert(sdist_ptr);
dds::sdist_build_params deps_params;
deps_params.subdir = sdist_ptr->manifest.pkg_id.to_string();
bd.add(*sdist_ptr, deps_params);
}
});

bd.build(params);
return 0;
}
};

} // namespace } // namespace


/* /*
spdlog::set_pattern("[%H:%M:%S] [%^%-5l%$] %v"); spdlog::set_pattern("[%H:%M:%S] [%^%-5l%$] %v");
args::ArgumentParser parser("DDS - The drop-dead-simple library manager"); 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_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};
try { try {
parser.ParseCLI(argc, argv); parser.ParseCLI(argc, argv);
} catch (const args::Help&) { } catch (const args::Help&) {
return repo.run(); return repo.run();
} else if (catalog.cmd) { } else if (catalog.cmd) {
return catalog.run(); return catalog.run();
} else if (build_deps.cmd) {
return build_deps.run();
} else { } else {
assert(false); assert(false);
std::terminate(); std::terminate();

+ 7
- 7
tests/dds.py View File

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_build(self, *,
def build_deps(self, args: proc.CommandLine, *,
toolchain: str = None) -> subprocess.CompletedProcess: toolchain: str = None) -> subprocess.CompletedProcess:
return self.run([ return self.run([
'deps',
'build',
'build-deps',
f'--toolchain={toolchain or self.default_builtin_toolchain}', f'--toolchain={toolchain or self.default_builtin_toolchain}',
self.repo_dir_arg,
f'--deps-build-dir={self.deps_build_dir}',
f'--repo-dir={self.repo_dir}',
f'--out={self.deps_build_dir}',
f'--lmi-path={self.lmi_path}', f'--lmi-path={self.lmi_path}',
args,
]) ])


def build(self, def build(self,
@property @property
def default_builtin_toolchain(self) -> str: def default_builtin_toolchain(self) -> str:
if os.name == 'posix': if os.name == 'posix':
return ':gcc-9'
return ':c++17:gcc-9'
elif os.name == 'nt': elif os.name == 'nt':
return ':msvc'
return ':c++17:msvc'
else: else:
raise RuntimeError( raise RuntimeError(
f'No default builtin toolchain defined for tests on platform "{os.name}"' f'No default builtin toolchain defined for tests on platform "{os.name}"'

+ 4
- 0
tests/deps/build-deps/project/deps.dds View File

Name: dummy
Version: 0.0.0

Depends: neo-sqlite3 +0.0.0

+ 7
- 0
tests/deps/build-deps/test_build_deps.py View File

from tests import dds, DDS


def test_build_deps(dds: DDS):
assert not dds.deps_build_dir.is_dir()
dds.build_deps(['-d', 'deps.dds'])
assert dds.deps_build_dir.is_dir()

Loading…
Cancel
Save