library_plan prepare_library(state& st, | library_plan prepare_library(state& st, | ||||
const sdist_target& sdt, | const sdist_target& sdt, | ||||
const library& lib, | |||||
const library_root& lib, | |||||
const package_manifest& pkg_man) { | const package_manifest& pkg_man) { | ||||
library_build_params lp; | library_build_params lp; | ||||
lp.out_subdir = sdt.params.subdir; | lp.out_subdir = sdt.params.subdir; |
* form the static library. | * form the static library. | ||||
*/ | */ | ||||
create_archive_plan(std::string_view name, | create_archive_plan(std::string_view name, | ||||
std::string_view full_name, | |||||
std::string_view qual_name, | |||||
path_ref subdir, | path_ref subdir, | ||||
std::vector<compile_file_plan> cfs) | std::vector<compile_file_plan> cfs) | ||||
: _name(name) | : _name(name) | ||||
, _qual_name(full_name) | |||||
, _qual_name(qual_name) | |||||
, _subdir(subdir) | , _subdir(subdir) | ||||
, _compile_files(std::move(cfs)) {} | , _compile_files(std::move(cfs)) {} | ||||
using namespace dds; | using namespace dds; | ||||
library_plan library_plan::create(const library& lib, | |||||
library_plan library_plan::create(const library_root& lib, | |||||
const library_build_params& params, | const library_build_params& params, | ||||
std::optional<std::string_view> full_name) { | |||||
std::optional<std::string_view> qual_name_) { | |||||
// Source files are kept in three groups: | // Source files are kept in three groups: | ||||
std::vector<source_file> app_sources; | std::vector<source_file> app_sources; | ||||
std::vector<source_file> test_sources; | std::vector<source_file> test_sources; | ||||
std::vector<source_file> lib_sources; | std::vector<source_file> lib_sources; | ||||
auto qual_name = std::string(full_name.value_or(lib.manifest().name)); | |||||
auto qual_name = std::string(qual_name_.value_or(lib.manifest().name)); | |||||
// Collect the source for this library. This will look for any compilable sources in the | // Collect the source for this library. This will look for any compilable sources in the | ||||
// `src/` subdirectory of the library. | // `src/` subdirectory of the library. | ||||
auto src_dir = lib.src_dir(); | |||||
auto src_dir = lib.src_source_root(); | |||||
if (src_dir.exists()) { | if (src_dir.exists()) { | ||||
// Sort each source file between the three source arrays, depending on | // Sort each source file between the three source arrays, depending on | ||||
// the kind of source that we are looking at. | // the kind of source that we are looking at. | ||||
const auto subdir_base = is_test ? params.out_subdir / "test" : params.out_subdir; | const auto subdir_base = is_test ? params.out_subdir / "test" : params.out_subdir; | ||||
// Put test/app executables in a further subdirectory based on the source file path | // Put test/app executables in a further subdirectory based on the source file path | ||||
const auto subdir | const auto subdir | ||||
= subdir_base / fs::relative(source.path.parent_path(), lib.src_dir().path); | |||||
= subdir_base / fs::relative(source.path.parent_path(), lib.src_source_root().path); | |||||
// Pick compile rules based on app/test | // Pick compile rules based on app/test | ||||
auto rules = is_test ? test_rules : compile_rules; | auto rules = is_test ? test_rules : compile_rules; | ||||
// Pick input libs based on app/test | // Pick input libs based on app/test |
#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/library.hpp> | |||||
#include <dds/library/root.hpp> | |||||
#include <dds/usage_reqs.hpp> | #include <dds/usage_reqs.hpp> | ||||
#include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
* initialize all of the constructor parameters correctly. | * initialize all of the constructor parameters correctly. | ||||
*/ | */ | ||||
class library_plan { | class library_plan { | ||||
/// The underlying library object | |||||
library _lib; | |||||
/// The underlying library root | |||||
library_root _lib; | |||||
/// The qualified name of the library | /// The qualified name of the library | ||||
std::string _qual_name; | std::string _qual_name; | ||||
/// The `create_archive_plan` for this library, if applicable | /// The `create_archive_plan` for this library, if applicable | ||||
public: | public: | ||||
/** | /** | ||||
* Construct a new `library_plan` | * Construct a new `library_plan` | ||||
* @param lib The `library` object underlying this plan. | |||||
* @param lib The `library_root` object underlying this plan. | |||||
* @param ar The `create_archive_plan`, or `nullopt` for this library. | * @param ar The `create_archive_plan`, or `nullopt` for this library. | ||||
* @param exes The `link_executable_plan` objects for this library. | * @param exes The `link_executable_plan` objects for this library. | ||||
*/ | */ | ||||
library_plan(library lib, | |||||
std::string_view full_name, | |||||
library_plan(library_root lib, | |||||
std::string_view qual_name, | |||||
std::optional<create_archive_plan> ar, | std::optional<create_archive_plan> ar, | ||||
std::vector<link_executable_plan> exes) | std::vector<link_executable_plan> exes) | ||||
: _lib(std::move(lib)) | : _lib(std::move(lib)) | ||||
, _qual_name(full_name) | |||||
, _qual_name(qual_name) | |||||
, _create_archive(std::move(ar)) | , _create_archive(std::move(ar)) | ||||
, _link_exes(std::move(exes)) {} | , _link_exes(std::move(exes)) {} | ||||
/** | /** | ||||
* Named constructor: Create a new `library_plan` automatically from some build-time parameters. | * Named constructor: Create a new `library_plan` automatically from some build-time parameters. | ||||
* | * | ||||
* @param lib The `library` object from which we will inherit several properties. | |||||
* @param lib The `library_root` from which we will inherit several properties and the build | |||||
* will be inferred | |||||
* @param params Parameters controlling the build of the library. i.e. if we create tests, | * @param params Parameters controlling the build of the library. i.e. if we create tests, | ||||
* enable warnings, etc. | * enable warnings, etc. | ||||
* @param full_name Optionally, provide the fully-qualified name of the library that is being | |||||
* @param qual_name Optionally, provide the fully-qualified name of the library that is being | |||||
* built | * built | ||||
* | * | ||||
* The `lib` parameter defines the usage requirements of this library, and they are looked up in | * The `lib` parameter defines the usage requirements of this library, and they are looked up in | ||||
* the `ureqs` map. If there are any missing requirements, an exception will be thrown. | * the `ureqs` map. If there are any missing requirements, an exception will be thrown. | ||||
*/ | */ | ||||
static library_plan create(const library& lib, | |||||
static library_plan create(const library_root& lib, | |||||
const library_build_params& params, | const library_build_params& params, | ||||
std::optional<std::string_view> full_name); | |||||
std::optional<std::string_view> qual_name); | |||||
}; | }; | ||||
} // namespace dds | } // namespace dds |
#include <dds/library/library.hpp> | |||||
#include <dds/library/root.hpp> | |||||
#include <dds/build/plan/compile_file.hpp> | #include <dds/build/plan/compile_file.hpp> | ||||
#include <dds/error/errors.hpp> | #include <dds/error/errors.hpp> | ||||
#include <dds/source/dir.hpp> | |||||
#include <dds/source/root.hpp> | |||||
#include <dds/util/algo.hpp> | #include <dds/util/algo.hpp> | ||||
#include <range/v3/view/filter.hpp> | #include <range/v3/view/filter.hpp> | ||||
namespace { | namespace { | ||||
auto collect_pf_sources(path_ref path) { | auto collect_pf_sources(path_ref path) { | ||||
auto include_dir = source_directory{path / "include"}; | |||||
auto src_dir = source_directory{path / "src"}; | |||||
auto include_dir = source_root{path / "include"}; | |||||
auto src_dir = source_root{path / "src"}; | |||||
source_list sources; | source_list sources; | ||||
} // namespace | } // namespace | ||||
library library::from_directory(path_ref lib_dir) { | |||||
library_root library_root::from_directory(path_ref lib_dir) { | |||||
auto sources = collect_pf_sources(lib_dir); | auto sources = collect_pf_sources(lib_dir); | ||||
library_manifest man; | library_manifest man; | ||||
man = library_manifest::load_from_file(man_path); | man = library_manifest::load_from_file(man_path); | ||||
} | } | ||||
auto lib = library(lib_dir, std::move(sources), std::move(man)); | |||||
auto lib = library_root(lib_dir, std::move(sources), std::move(man)); | |||||
return lib; | return lib; | ||||
} | } | ||||
fs::path library::public_include_dir() const noexcept { | |||||
auto inc_dir = include_dir(); | |||||
fs::path library_root::public_include_dir() const noexcept { | |||||
auto inc_dir = include_source_root(); | |||||
if (inc_dir.exists()) { | if (inc_dir.exists()) { | ||||
return inc_dir.path; | return inc_dir.path; | ||||
} | } | ||||
return src_dir().path; | |||||
return src_source_root().path; | |||||
} | } | ||||
fs::path library::private_include_dir() const noexcept { return src_dir().path; } | |||||
fs::path library_root::private_include_dir() const noexcept { return src_source_root().path; } | |||||
shared_compile_file_rules library::base_compile_rules() const noexcept { | |||||
auto inc_dir = include_dir(); | |||||
auto src_dir = this->src_dir(); | |||||
shared_compile_file_rules library_root::base_compile_rules() const noexcept { | |||||
auto inc_dir = include_source_root(); | |||||
auto src_dir = this->src_source_root(); | |||||
shared_compile_file_rules ret; | shared_compile_file_rules ret; | ||||
if (inc_dir.exists()) { | if (inc_dir.exists()) { | ||||
ret.include_dirs().push_back(inc_dir.path); | ret.include_dirs().push_back(inc_dir.path); | ||||
auto has_library_dirs | auto has_library_dirs | ||||
= [](path_ref dir) { return fs::exists(dir / "src") || fs::exists(dir / "include"); }; | = [](path_ref dir) { return fs::exists(dir / "src") || fs::exists(dir / "include"); }; | ||||
std::vector<library> dds::collect_libraries(path_ref root) { | |||||
std::vector<library> ret; | |||||
std::vector<library_root> dds::collect_libraries(path_ref root) { | |||||
std::vector<library_root> ret; | |||||
if (has_library_dirs(root)) { | if (has_library_dirs(root)) { | ||||
ret.emplace_back(library::from_directory(root)); | |||||
ret.emplace_back(library_root::from_directory(root)); | |||||
} | } | ||||
auto pf_libs_dir = root / "libs"; | auto pf_libs_dir = root / "libs"; | ||||
extend(ret, | extend(ret, | ||||
fs::directory_iterator(pf_libs_dir) // | fs::directory_iterator(pf_libs_dir) // | ||||
| ranges::views::filter(has_library_dirs) // | | ranges::views::filter(has_library_dirs) // | ||||
| ranges::views::transform([&](auto p) { return library::from_directory(p); })); | |||||
| ranges::views::transform( | |||||
[&](auto p) { return library_root::from_directory(p); })); | |||||
} | } | ||||
return ret; | return ret; | ||||
} | } |
#include <dds/build/plan/compile_file.hpp> | #include <dds/build/plan/compile_file.hpp> | ||||
#include <dds/library/manifest.hpp> | #include <dds/library/manifest.hpp> | ||||
#include <dds/source/dir.hpp> | |||||
#include <dds/source/file.hpp> | #include <dds/source/file.hpp> | ||||
#include <dds/source/root.hpp> | |||||
#include <string> | #include <string> | ||||
/** | /** | ||||
* Represents a library that exists on the filesystem | * Represents a library that exists on the filesystem | ||||
*/ | */ | ||||
class library { | |||||
class library_root { | |||||
// The path containing the source directories for this library | // The path containing the source directories for this library | ||||
fs::path _path; | fs::path _path; | ||||
// The sources that are part of this library | // The sources that are part of this library | ||||
// Private constructor. Use named constructor `from_directory`, which will build | // Private constructor. Use named constructor `from_directory`, which will build | ||||
// the construct arguments approperiately | // the construct arguments approperiately | ||||
library(path_ref dir, source_list&& src, library_manifest&& man) | |||||
library_root(path_ref dir, source_list&& src, library_manifest&& man) | |||||
: _path(dir) | : _path(dir) | ||||
, _sources(std::move(src)) | , _sources(std::move(src)) | ||||
, _man(std::move(man)) {} | , _man(std::move(man)) {} | ||||
* directory path. This will load the sources and manifest properly and | * directory path. This will load the sources and manifest properly and | ||||
* return the resulting library object. | * return the resulting library object. | ||||
*/ | */ | ||||
static library from_directory(path_ref); | |||||
static library_root from_directory(path_ref); | |||||
/** | /** | ||||
* Obtain the manifest for this library | * Obtain the manifest for this library | ||||
/** | /** | ||||
* The `src/` directory for this library. | * The `src/` directory for this library. | ||||
*/ | */ | ||||
source_directory src_dir() const noexcept { return source_directory{path() / "src"}; } | |||||
source_root src_source_root() const noexcept { return source_root{path() / "src"}; } | |||||
/** | /** | ||||
* The `include/` directory for this library | * The `include/` directory for this library | ||||
*/ | */ | ||||
source_directory include_dir() const noexcept { return source_directory{path() / "include"}; } | |||||
source_root include_source_root() const noexcept { return source_root{path() / "include"}; } | |||||
/** | /** | ||||
* The root path for this library (parent of `src/` and `include/`, if present) | * The root path for this library (parent of `src/` and `include/`, if present) | ||||
* but there might also be libraries in `where/libs`. This function will find | * but there might also be libraries in `where/libs`. This function will find | ||||
* them all. | * them all. | ||||
*/ | */ | ||||
std::vector<library> collect_libraries(path_ref where); | |||||
std::vector<library_root> collect_libraries(path_ref where); | |||||
} // namespace dds | } // namespace dds |
#include "./dist.hpp" | #include "./dist.hpp" | ||||
#include <dds/error/errors.hpp> | #include <dds/error/errors.hpp> | ||||
#include <dds/library/library.hpp> | |||||
#include <dds/library/root.hpp> | |||||
#include <dds/temp.hpp> | #include <dds/temp.hpp> | ||||
#include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
fs::copy(filepath, dest); | fs::copy(filepath, dest); | ||||
} | } | ||||
void sdist_copy_library(path_ref out_root, const library& lib, const sdist_params& params) { | |||||
void sdist_copy_library(path_ref out_root, const library_root& lib, const sdist_params& params) { | |||||
auto sources_to_keep = // | auto sources_to_keep = // | ||||
lib.all_sources() // | lib.all_sources() // | ||||
| ranges::views::filter([&](const source_file& sf) { | | ranges::views::filter([&](const source_file& sf) { | ||||
sdist dds::create_sdist_in_dir(path_ref out, const sdist_params& params) { | sdist dds::create_sdist_in_dir(path_ref out, const sdist_params& params) { | ||||
auto libs = collect_libraries(params.project_dir); | auto libs = collect_libraries(params.project_dir); | ||||
for (const library& lib : libs) { | |||||
for (const library_root& lib : libs) { | |||||
sdist_copy_library(out, lib, params); | sdist_copy_library(out, lib, params); | ||||
} | } | ||||
#include "./dir.hpp" | |||||
#include "./root.hpp" | |||||
#include <range/v3/range/conversion.hpp> | #include <range/v3/range/conversion.hpp> | ||||
#include <range/v3/view/filter.hpp> | #include <range/v3/view/filter.hpp> | ||||
using namespace dds; | using namespace dds; | ||||
std::vector<source_file> source_directory::collect_sources() const { | |||||
std::vector<source_file> source_root::collect_sources() const { | |||||
using namespace ranges::views; | using namespace ranges::views; | ||||
// Collect all source files from the directory | // Collect all source files from the directory | ||||
return // | return // |
namespace dds { | namespace dds { | ||||
/** | /** | ||||
* A `source_directory` is a simple wrapper type that provides type safety and utilities to | |||||
* represent a source directory. | |||||
* A `source_root` is a simple wrapper type that provides type safety and utilities to | |||||
* represent a source root. | |||||
*/ | */ | ||||
struct source_directory { | |||||
struct source_root { | |||||
/// The actual path to the directory | /// The actual path to the directory | ||||
fs::path path; | fs::path path; | ||||