namespace dds { | namespace dds { | ||||
/** | |||||
* Iterate over every library defined as part of the build plan | |||||
*/ | |||||
inline auto iter_libraries(const build_plan& plan) { | inline auto iter_libraries(const build_plan& plan) { | ||||
return // | return // | ||||
plan.packages() // | plan.packages() // | ||||
; | ; | ||||
} | } | ||||
/** | |||||
* Return a range iterating over ever file compilation defined in the given build plan | |||||
*/ | |||||
inline auto iter_compilations(const build_plan& plan) { | inline auto iter_compilations(const build_plan& plan) { | ||||
auto lib_compiles = // | auto lib_compiles = // | ||||
iter_libraries(plan) // | iter_libraries(plan) // |
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. | ||||
auto all_sources = src_dir.sources(); | |||||
auto all_sources = src_dir.collect_sources(); | |||||
for (const auto& sfile : all_sources) { | for (const auto& sfile : all_sources) { | ||||
if (sfile.kind == source_kind::test) { | if (sfile.kind == source_kind::test) { | ||||
test_sources.push_back(sfile); | test_sources.push_back(sfile); |
using namespace dds; | using namespace dds; | ||||
std::vector<source_file> source_directory::sources() const { | |||||
std::vector<source_file> source_directory::collect_sources() const { | |||||
using namespace ranges::views; | using namespace ranges::views; | ||||
// Strips nullopt elements and lifts the value from the results | |||||
auto drop_nulls = // | |||||
filter([](auto&& opt) { return opt.has_value(); }) // | |||||
| transform([](auto&& opt) { return *opt; }); // | |||||
// Collect all source files from the directory | // Collect all source files from the directory | ||||
return // | return // | ||||
fs::recursive_directory_iterator(path) // | fs::recursive_directory_iterator(path) // | ||||
| filter([](auto&& entry) { return entry.is_regular_file(); }) // | | filter([](auto&& entry) { return entry.is_regular_file(); }) // | ||||
| transform([&](auto&& entry) { return source_file::from_path(entry, path); }) // | | transform([&](auto&& entry) { return source_file::from_path(entry, path); }) // | ||||
// source_file::from_path returns an optional. Drop nulls | // source_file::from_path returns an optional. Drop nulls | ||||
| drop_nulls // | |||||
| filter([](auto&& opt) { return opt.has_value(); }) // | |||||
| transform([](auto&& opt) { return *opt; }) // | |||||
| ranges::to_vector; | | ranges::to_vector; | ||||
} | } |
namespace dds { | namespace dds { | ||||
/** | |||||
* A `source_directory` is a simple wrapper type that provides type safety and utilities to | |||||
* represent a source directory. | |||||
*/ | |||||
struct source_directory { | struct source_directory { | ||||
/// The actual path to the directory | |||||
fs::path path; | fs::path path; | ||||
std::vector<source_file> sources() const; | |||||
/** | |||||
* Generate a vector of every source file contained in this directory (including subdirectories) | |||||
*/ | |||||
std::vector<source_file> collect_sources() const; | |||||
/** | |||||
* Check if the directory exists | |||||
*/ | |||||
bool exists() const noexcept { return fs::exists(path); } | bool exists() const noexcept { return fs::exists(path); } | ||||
}; | }; | ||||
if (!fs::is_directory(include_dir.path)) { | if (!fs::is_directory(include_dir.path)) { | ||||
throw std::runtime_error("The `include` at the root of the project is not a directory"); | throw std::runtime_error("The `include` at the root of the project is not a directory"); | ||||
} | } | ||||
auto inc_sources = include_dir.sources(); | |||||
auto inc_sources = include_dir.collect_sources(); | |||||
// Drop any source files we found within `include/` | // Drop any source files we found within `include/` | ||||
erase_if(sources, [&](auto& info) { | erase_if(sources, [&](auto& info) { | ||||
if (info.kind != source_kind::header) { | if (info.kind != source_kind::header) { | ||||
if (!fs::is_directory(src_dir.path)) { | if (!fs::is_directory(src_dir.path)) { | ||||
throw std::runtime_error("The `src` at the root of the project is not a directory"); | throw std::runtime_error("The `src` at the root of the project is not a directory"); | ||||
} | } | ||||
auto src_sources = src_dir.sources(); | |||||
auto src_sources = src_dir.collect_sources(); | |||||
extend(sources, src_sources); | extend(sources, src_sources); | ||||
} | } | ||||