| namespace { | namespace { | ||||
| /// XXX: Duplicated in compile_exec.cpp !! | |||||
| template <typename Range, typename Fn> | template <typename Range, typename Fn> | ||||
| bool parallel_run(Range&& rng, int n_jobs, Fn&& fn) { | bool parallel_run(Range&& rng, int n_jobs, Fn&& fn) { | ||||
| // We don't bother with a nice thread pool, as the overhead of most build | // We don't bother with a nice thread pool, as the overhead of most build | ||||
| } | } | ||||
| void build_plan::link_all(const build_env& env, int njobs) const { | void build_plan::link_all(const build_env& env, int njobs) const { | ||||
| // Generate a pairing between executables and the libraries that own them | |||||
| std::vector<std::pair<std::reference_wrapper<const library_plan>, | std::vector<std::pair<std::reference_wrapper<const library_plan>, | ||||
| std::reference_wrapper<const link_executable_plan>>> | std::reference_wrapper<const link_executable_plan>>> | ||||
| executables; | executables; | ||||
| for (auto&& lib : iter_libraries(*this)) { | for (auto&& lib : iter_libraries(*this)) { | ||||
| for (auto&& exe : lib.executables()) { | for (auto&& exe : lib.executables()) { | ||||
| executables.emplace_back(lib, exe); | executables.emplace_back(lib, exe); | ||||
| std::vector<test_failure> build_plan::run_all_tests(build_env_ref env, int njobs) const { | std::vector<test_failure> build_plan::run_all_tests(build_env_ref env, int njobs) const { | ||||
| using namespace ranges::views; | using namespace ranges::views; | ||||
| // Collect executables that are tests | |||||
| auto test_executables = // | auto test_executables = // | ||||
| iter_libraries(*this) // | iter_libraries(*this) // | ||||
| | transform(&library_plan::executables) // | | transform(&library_plan::executables) // |
| namespace dds { | namespace dds { | ||||
| /** | |||||
| * Encompases an entire build plan. | |||||
| * | |||||
| * A build plan consists of some number of packages, defined as `package_plan` | |||||
| * objects. | |||||
| */ | |||||
| class build_plan { | class build_plan { | ||||
| /// The packages that are part of this plan. | |||||
| std::vector<package_plan> _packages; | std::vector<package_plan> _packages; | ||||
| public: | public: | ||||
| /** | |||||
| * Append a new package plan. Returns a reference to the package plan so that it can be further | |||||
| * tweaked. Note that the reference is not stable. | |||||
| */ | |||||
| package_plan& add_package(package_plan p) noexcept { | package_plan& add_package(package_plan p) noexcept { | ||||
| return _packages.emplace_back(std::move(p)); | return _packages.emplace_back(std::move(p)); | ||||
| } | } | ||||
| /** | |||||
| * All of the packages in this plan | |||||
| */ | |||||
| auto& packages() const noexcept { return _packages; } | auto& packages() const noexcept { return _packages; } | ||||
| void compile_all(const build_env& env, int njobs) const; | |||||
| void archive_all(const build_env& env, int njobs) const; | |||||
| void link_all(const build_env& env, int njobs) const; | |||||
| /** | |||||
| * Compile all files in the plan. | |||||
| */ | |||||
| void compile_all(const build_env& env, int njobs) const; | |||||
| /** | |||||
| * Generate all static library archive in the plan | |||||
| */ | |||||
| void archive_all(const build_env& env, int njobs) const; | |||||
| /** | |||||
| * Link all runtime binaries (executables) in the plan | |||||
| */ | |||||
| void link_all(const build_env& env, int njobs) const; | |||||
| /** | |||||
| * Execute all tests defined in the plan. Returns information for every failed test. | |||||
| */ | |||||
| std::vector<test_failure> run_all_tests(build_env_ref env, int njobs) const; | std::vector<test_failure> run_all_tests(build_env_ref env, int njobs) const; | ||||
| }; | }; | ||||
| namespace dds { | namespace dds { | ||||
| /** | |||||
| * A package is a top-level component with a name, namespace, and some number of associated | |||||
| * libraries. A package plan will roughly correspond to either a source distribution or a project | |||||
| * directory | |||||
| */ | |||||
| class package_plan { | class package_plan { | ||||
| std::string _name; | |||||
| std::string _namespace; | |||||
| /// Package name | |||||
| std::string _name; | |||||
| /// The package namespace. Used to specify interdependencies | |||||
| std::string _namespace; | |||||
| /// The libraries in this package | |||||
| std::vector<library_plan> _libraries; | std::vector<library_plan> _libraries; | ||||
| public: | public: | ||||
| /** | |||||
| * Create a new package plan. | |||||
| * @param name The name of the package | |||||
| * @param namespace_ The namespace of the package. Used when specifying linker dependencies. | |||||
| */ | |||||
| package_plan(std::string_view name, std::string_view namespace_) | package_plan(std::string_view name, std::string_view namespace_) | ||||
| : _name(name) | : _name(name) | ||||
| , _namespace(namespace_) {} | , _namespace(namespace_) {} | ||||
| /** | |||||
| * Add a library plan to this package plan | |||||
| * @param lp The `library_plan` to add to the package. Once added, the | |||||
| * library plan cannot be changed directly. | |||||
| */ | |||||
| void add_library(library_plan lp) { _libraries.emplace_back(std::move(lp)); } | void add_library(library_plan lp) { _libraries.emplace_back(std::move(lp)); } | ||||
| /** | |||||
| * Get the package name | |||||
| */ | |||||
| auto& name() const noexcept { return _name; } | auto& name() const noexcept { return _name; } | ||||
| /** | |||||
| * The package namespace | |||||
| */ | |||||
| auto& namespace_() const noexcept { return _namespace; } | auto& namespace_() const noexcept { return _namespace; } | ||||
| /** | |||||
| * The libraries in the package | |||||
| */ | |||||
| auto& libraries() const noexcept { return _libraries; } | auto& libraries() const noexcept { return _libraries; } | ||||
| }; | }; | ||||