const library& lib, | const library& lib, | ||||
const project& project, | const project& project, | ||||
path_ref export_root) { | path_ref export_root) { | ||||
auto relpath = fs::relative(lib.base_dir(), project.root()); | |||||
auto relpath = fs::relative(lib.path(), project.root()); | |||||
auto lib_out_root = export_root / relpath; | auto lib_out_root = export_root / relpath; | ||||
auto header_root = lib.base_dir() / "include"; | |||||
auto header_root = lib.path() / "include"; | |||||
if (!fs::is_directory(header_root)) { | if (!fs::is_directory(header_root)) { | ||||
header_root = lib.base_dir() / "src"; | |||||
header_root = lib.path() / "src"; | |||||
} | } | ||||
auto lml_path = export_root / fmt::format("{}.lml", lib.name()); | auto lml_path = export_root / fmt::format("{}.lml", lib.name()); | ||||
if (fs::is_directory(header_root)) { | if (fs::is_directory(header_root)) { | ||||
auto header_dest = lib_out_root / "include"; | auto header_dest = lib_out_root / "include"; | ||||
copy_headers(header_root, header_dest, lib.sources()); | |||||
copy_headers(header_root, header_dest, lib.all_sources()); | |||||
pairs.emplace_back("Include-Path", fs::relative(header_dest, lml_parent_dir).string()); | pairs.emplace_back("Include-Path", fs::relative(header_dest, lml_parent_dir).string()); | ||||
} | } | ||||
std::vector<compile_file_plan> file_compilations_of_lib(const build_params& params, | std::vector<compile_file_plan> file_compilations_of_lib(const build_params& params, | ||||
const library& lib) { | const library& lib) { | ||||
const auto& sources = lib.sources(); | |||||
const auto& sources = lib.all_sources(); | |||||
std::vector<fs::path> dep_includes; | std::vector<fs::path> dep_includes; | ||||
std::vector<std::string> dep_defines; | std::vector<std::string> dep_defines; | ||||
extend(rules.defs(), dep_defines); | extend(rules.defs(), dep_defines); | ||||
extend(rules.include_dirs(), lib.manifest().private_includes); | extend(rules.include_dirs(), lib.manifest().private_includes); | ||||
extend(rules.include_dirs(), dep_includes); | extend(rules.include_dirs(), dep_includes); | ||||
rules.include_dirs().push_back(fs::absolute(lib.base_dir() / "src")); | |||||
rules.include_dirs().push_back(fs::absolute(lib.base_dir() / "include")); | |||||
rules.include_dirs().push_back(fs::absolute(lib.path() / "src")); | |||||
rules.include_dirs().push_back(fs::absolute(lib.path() / "include")); | |||||
rules.enable_warnings() = params.enable_warnings; | rules.enable_warnings() = params.enable_warnings; | ||||
return // | return // | ||||
// Collect object files that make up that library | // Collect object files that make up that library | ||||
arc.input_files = // | arc.input_files = // | ||||
lib.sources() // | |||||
lib.all_sources() // | |||||
| filter([](auto&& s) { return s.kind == source_kind::source; }) // | | filter([](auto&& s) { return s.kind == source_kind::source; }) // | ||||
| transform([&](auto&& s) { return obj_for_source(obj_idx, s.path); }) // | | transform([&](auto&& s) { return obj_for_source(obj_idx, s.path); }) // | ||||
| to_vector // | | to_vector // | ||||
const library& lib, | const library& lib, | ||||
const object_file_index& obj_idx) { | const object_file_index& obj_idx) { | ||||
return // | return // | ||||
lib.sources() // | |||||
lib.all_sources() // | |||||
| filter([&](auto&& s) { return s.kind == sk; }) // | | filter([&](auto&& s) { return s.kind == sk; }) // | ||||
| transform([&](auto&& s) { | | transform([&](auto&& s) { | ||||
return link_one_exe(get_exe_path(s), s.path, params, lib, obj_idx); | return link_one_exe(get_exe_path(s), s.path, params, lib, obj_idx); | ||||
} // namespace | } // namespace | ||||
void dds::build(const build_params& params, const package_manifest&) { | void dds::build(const build_params& params, const package_manifest&) { | ||||
// auto sroot = dds::sroot{params.root}; | |||||
// auto comp_rules = sroot.base_compile_rules(); | |||||
// sroot_build_params sr_params; | |||||
// sr_params.main_name = man.name; | |||||
// sr_params.build_tests = params.build_tests; | |||||
// sr_params.build_apps = params.build_apps; | |||||
// sr_params.compile_rules = comp_rules; | |||||
// build_plan plan; | |||||
// plan.add_sroot(sroot, sr_params); | |||||
// plan.compile_all(params.toolchain, params.parallel_jobs, params.out_root); | |||||
auto project = project::from_directory(params.root); | auto project = project::from_directory(params.root); | ||||
auto compiles = collect_compiles(params, project); | auto compiles = collect_compiles(params, project); |
using namespace dds; | using namespace dds; | ||||
void build_plan::add_sroot(const sroot& root, const sroot_build_params& params) { | |||||
create_libraries.push_back(library_plan::create(root, params)); | |||||
} | |||||
library_plan library_plan::create(const sroot& root, const sroot_build_params& params) { | |||||
library_plan library_plan::create(const library& root, const sroot_build_params& params) { | |||||
std::vector<compile_file_plan> compile_files; | std::vector<compile_file_plan> compile_files; | ||||
std::vector<create_archive_plan> create_archives; | std::vector<create_archive_plan> create_archives; | ||||
std::vector<create_exe_plan> link_executables; | std::vector<create_exe_plan> link_executables; | ||||
} | } | ||||
if (!app_sources.empty() || !test_sources.empty()) { | if (!app_sources.empty() || !test_sources.empty()) { | ||||
assert(false && "Apps/tests not implemented on this code path"); | |||||
spdlog::critical("Apps/tests not implemented on this code path"); | |||||
} | } | ||||
if (!lib_sources.empty()) { | if (!lib_sources.empty()) { | ||||
| ranges::views::transform([](auto&& sf) { return sf.path; }) // | | ranges::views::transform([](auto&& sf) { return sf.path; }) // | ||||
| ranges::to_vector; | | ranges::to_vector; | ||||
ar_plan.name = params.main_name; | ar_plan.name = params.main_name; | ||||
ar_plan.out_dir = params.out_dir; | |||||
ar_plan.out_dir = params.out_subdir; | |||||
create_archives.push_back(std::move(ar_plan)); | create_archives.push_back(std::move(ar_plan)); | ||||
} | } | ||||
return library_plan{compile_files, create_archives, link_executables, params.out_dir}; | |||||
return library_plan{compile_files, create_archives, link_executables, params.out_subdir}; | |||||
} | } | ||||
namespace { | namespace { |
#include <dds/build/compile.hpp> | #include <dds/build/compile.hpp> | ||||
#include <dds/build/params.hpp> | #include <dds/build/params.hpp> | ||||
#include <dds/build/sroot.hpp> | #include <dds/build/sroot.hpp> | ||||
#include <dds/library.hpp> | |||||
#include <dds/toolchain.hpp> | #include <dds/toolchain.hpp> | ||||
#include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
std::vector<create_exe_plan> link_executables; | std::vector<create_exe_plan> link_executables; | ||||
fs::path out_subdir; | fs::path out_subdir; | ||||
static library_plan create(const sroot& root, const sroot_build_params& params); | |||||
static library_plan create(const library& lib, const sroot_build_params& params); | |||||
}; | }; | ||||
struct build_plan { | struct build_plan { | ||||
std::vector<library_plan> create_libraries; | std::vector<library_plan> create_libraries; | ||||
// static build_plan generate(const build_params& params); | // static build_plan generate(const build_params& params); | ||||
void add_sroot(const sroot& root, const sroot_build_params& params); | |||||
void add_library(const library& lib, const sroot_build_params& params) { | |||||
create_libraries.push_back(library_plan::create(lib, params)); | |||||
} | |||||
void compile_all(const toolchain& tc, int njobs, path_ref out_prefix) const; | void compile_all(const toolchain& tc, int njobs, path_ref out_prefix) const; | ||||
}; | }; |
#include "./sroot.hpp" | #include "./sroot.hpp" | ||||
using namespace dds; | using namespace dds; | ||||
shared_compile_file_rules sroot::base_compile_rules() const noexcept { | |||||
auto inc_dir = include_dir(); | |||||
auto src_dir = this->src_dir(); | |||||
shared_compile_file_rules ret; | |||||
if (inc_dir.exists()) { | |||||
ret.include_dirs().push_back(inc_dir.path); | |||||
} | |||||
if (src_dir.exists()) { | |||||
ret.include_dirs().push_back(src_dir.path); | |||||
} | |||||
return ret; | |||||
} | |||||
fs::path sroot::public_include_dir() const noexcept { | |||||
auto inc_dir = include_dir(); | |||||
if (inc_dir.exists()) { | |||||
return inc_dir.path; | |||||
} | |||||
return src_dir().path; | |||||
} |
namespace dds { | namespace dds { | ||||
struct sroot { | |||||
fs::path path; | |||||
source_directory src_dir() const noexcept { return source_directory{path / "src"}; }; | |||||
source_directory include_dir() const noexcept { return source_directory{path / "include"}; } | |||||
fs::path public_include_dir() const noexcept; | |||||
shared_compile_file_rules base_compile_rules() const noexcept; | |||||
}; | |||||
struct sroot_build_params { | struct sroot_build_params { | ||||
std::string main_name; | std::string main_name; | ||||
fs::path out_dir; | |||||
fs::path out_subdir; | |||||
bool build_tests = false; | bool build_tests = false; | ||||
bool build_apps = false; | bool build_apps = false; | ||||
std::vector<fs::path> rt_link_libraries; | std::vector<fs::path> rt_link_libraries; |
man.name)); | man.name)); | ||||
} | } | ||||
add_dep_includes(rules, found->second.get().manifest, sd_idx); | add_dep_includes(rules, found->second.get().manifest, sd_idx); | ||||
rules.include_dirs().push_back(sroot{found->second.get().path}.public_include_dir()); | |||||
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 add_sdist_to_dep_plan(build_plan& plan, const sdist& sd, const sdist_index_type& sd_idx) { | void add_sdist_to_dep_plan(build_plan& plan, const sdist& sd, const sdist_index_type& sd_idx) { | ||||
auto root = dds::sroot{sd.path}; | |||||
shared_compile_file_rules comp_rules = root.base_compile_rules(); | |||||
auto lib = dds::library::from_directory(sd.path); | |||||
shared_compile_file_rules comp_rules = lib.base_compile_rules(); | |||||
add_dep_includes(comp_rules, sd.manifest, sd_idx); | add_dep_includes(comp_rules, sd.manifest, sd_idx); | ||||
sroot_build_params params; | sroot_build_params params; | ||||
params.main_name = sd.manifest.name; | params.main_name = sd.manifest.name; | ||||
params.compile_rules = comp_rules; | params.compile_rules = comp_rules; | ||||
plan.add_sroot(root, params); | |||||
plan.add_library(lib, params); | |||||
} | } | ||||
} // namespace | } // namespace |
#include <dds/library.hpp> | #include <dds/library.hpp> | ||||
#include <dds/build/source_dir.hpp> | #include <dds/build/source_dir.hpp> | ||||
#include <dds/build/compile.hpp> | |||||
#include <dds/util/algo.hpp> | #include <dds/util/algo.hpp> | ||||
#include <spdlog/spdlog.h> | #include <spdlog/spdlog.h> | ||||
namespace { | namespace { | ||||
struct pf_info { | |||||
source_list sources; | |||||
fs::path inc_dir; | |||||
fs::path src_dir; | |||||
}; | |||||
pf_info collect_pf_sources(path_ref path) { | |||||
auto collect_pf_sources(path_ref path) { | |||||
auto include_dir = source_directory{path / "include"}; | auto include_dir = source_directory{path / "include"}; | ||||
auto src_dir = source_directory{path / "src"}; | auto src_dir = source_directory{path / "src"}; | ||||
extend(sources, src_sources); | extend(sources, src_sources); | ||||
} | } | ||||
return {std::move(sources), include_dir.path, src_dir.path}; | |||||
return sources; | |||||
} | } | ||||
} // namespace | } // namespace | ||||
library library::from_directory(path_ref lib_dir, std::string_view name) { | library library::from_directory(path_ref lib_dir, std::string_view name) { | ||||
auto [sources, inc_dir, src_dir] = collect_pf_sources(lib_dir); | |||||
auto sources = collect_pf_sources(lib_dir); | |||||
library_manifest man; | library_manifest man; | ||||
auto man_path = lib_dir / "library.dds"; | auto man_path = lib_dir / "library.dds"; | ||||
auto lib = library(lib_dir, name, std::move(sources), std::move(man)); | auto lib = library(lib_dir, name, std::move(sources), std::move(man)); | ||||
if (fs::exists(inc_dir)) { | |||||
lib._pub_inc_dir = inc_dir; | |||||
if (fs::exists(src_dir)) { | |||||
lib._priv_inc_dir = src_dir; | |||||
} | |||||
} else { | |||||
lib._pub_inc_dir = src_dir; | |||||
lib._priv_inc_dir = src_dir; | |||||
} | |||||
return lib; | return lib; | ||||
} | } | ||||
fs::path library::public_include_dir() const noexcept { | |||||
auto inc_dir = include_dir(); | |||||
if (inc_dir.exists()) { | |||||
return inc_dir.path; | |||||
} | |||||
return src_dir().path; | |||||
} | |||||
fs::path library::private_include_dir() const noexcept { return src_dir().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 ret; | |||||
if (inc_dir.exists()) { | |||||
ret.include_dirs().push_back(inc_dir.path); | |||||
} | |||||
if (src_dir.exists()) { | |||||
ret.include_dirs().push_back(src_dir.path); | |||||
} | |||||
return ret; | |||||
} |
#pragma once | #pragma once | ||||
#include <dds/library_manifest.hpp> | #include <dds/library_manifest.hpp> | ||||
#include <dds/build/source_dir.hpp> | |||||
#include <dds/build/compile.hpp> | |||||
#include <dds/source.hpp> | #include <dds/source.hpp> | ||||
#include <optional> | #include <optional> | ||||
}; | }; | ||||
class library { | class library { | ||||
fs::path _base_dir; | |||||
fs::path _path; | |||||
std::string _name; | std::string _name; | ||||
source_list _sources; | source_list _sources; | ||||
fs::path _pub_inc_dir; | |||||
fs::path _priv_inc_dir; | |||||
library_manifest _man; | library_manifest _man; | ||||
library(path_ref dir, std::string_view name, source_list&& src, library_manifest&& man) | library(path_ref dir, std::string_view name, source_list&& src, library_manifest&& man) | ||||
: _base_dir(dir) | |||||
: _path(dir) | |||||
, _name(name) | , _name(name) | ||||
, _sources(std::move(src)) | , _sources(std::move(src)) | ||||
, _man(std::move(man)) {} | , _man(std::move(man)) {} | ||||
auto& manifest() const noexcept { return _man; } | auto& manifest() const noexcept { return _man; } | ||||
path_ref base_dir() const noexcept { return _base_dir; } | |||||
path_ref public_include_dir() const noexcept { return _pub_inc_dir; } | |||||
path_ref private_include_dir() const noexcept { return _priv_inc_dir; } | |||||
source_directory src_dir() const noexcept { return source_directory{path() / "src"}; } | |||||
source_directory include_dir() const noexcept { return source_directory{path() / "include"}; } | |||||
const source_list& sources() const noexcept { return _sources; } | |||||
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; | |||||
}; | }; | ||||
} // namespace dds | } // namespace dds |
const sdist_params& params, | const sdist_params& params, | ||||
browns::md5& hash) { | browns::md5& hash) { | ||||
auto sources_to_keep = // | auto sources_to_keep = // | ||||
lib.sources() // | |||||
lib.all_sources() // | |||||
| ranges::views::filter([&](const source_file& sf) { | | ranges::views::filter([&](const source_file& sf) { | ||||
if (sf.kind == source_kind::app && params.include_apps) { | if (sf.kind == source_kind::app && params.include_apps) { | ||||
return true; | return true; | ||||
ranges::sort(sources_to_keep, std::less<>(), [](auto&& s) { return s.path; }); | ranges::sort(sources_to_keep, std::less<>(), [](auto&& s) { return s.path; }); | ||||
auto lib_dds_path = lib.base_dir() / "library.dds"; | |||||
auto lib_dds_path = lib.path() / "library.dds"; | |||||
if (fs::is_regular_file(lib_dds_path)) { | if (fs::is_regular_file(lib_dds_path)) { | ||||
sdist_export_file(out_root, params.project_dir, lib_dds_path, hash); | sdist_export_file(out_root, params.project_dir, lib_dds_path, hash); | ||||
} | } | ||||
spdlog::info("sdist: Export library from {}", lib.base_dir().string()); | |||||
spdlog::info("sdist: Export library from {}", lib.path().string()); | |||||
fs::create_directories(out_root); | fs::create_directories(out_root); | ||||
for (const auto& source : sources_to_keep) { | for (const auto& source : sources_to_keep) { | ||||
sdist_export_file(out_root, params.project_dir, source.path, hash); | sdist_export_file(out_root, params.project_dir, source.path, hash); |