diff --git a/buildkit/re.yml b/buildkit/re.yml index 1a7c1a7..74b5add 100644 --- a/buildkit/re.yml +++ b/buildkit/re.yml @@ -12,6 +12,7 @@ deps: - vcpkg:yaml-cpp - vcpkg:magic-enum - vcpkg:cpp-httplib + - vcpkg:openssl - github:osdeverr/fmt @re-9.1.0-1 - github:osdeverr/re-ninja@v1.7 [.libtool] - github:osdeverr/semverpp@v1.1.8-no-tests [semverpp] @@ -19,13 +20,9 @@ deps: - github:k2rate/ulib-process ^v1.0.2 [/ulib-process] - github:osdeverr/ulib-env ^1.0.0 [/ulib-env] - github:osdeverr/futile ^3.0.0 [/futile] - -platform.windows: - deps: - - vcpkg:openssl@static-md -platform.!windows: - deps: - - vcpkg:openssl + - github:k2rate/ulib-json ^1.2.5 + - github:k2rate/ulib-yaml-json ^1.0.0 + - github:k2rate/ulib-yaml ^1.0.0 actions: - run: diff --git a/buildkit/re/build/default_build_context.cpp b/buildkit/re/build/default_build_context.cpp index b7feba1..32f2585 100644 --- a/buildkit/re/build/default_build_context.cpp +++ b/buildkit/re/build/default_build_context.cpp @@ -170,31 +170,30 @@ namespace re return target; } - YAML::Node DefaultBuildContext::LoadCachedParams(const fs::path &path) + ulib::yaml DefaultBuildContext::LoadCachedParams(const fs::path &path) { std::ifstream file{path / "re.user.yml"}; if (file.good()) { - auto yaml = YAML::Load(file); + file.close(); - for (const auto &kv : yaml) - mVars.SetVar(mVars.Resolve(kv.first.Scalar()), mVars.Resolve(kv.second.Scalar())); + auto yaml = ulib::yaml::parse(futile::open(path / "re.user.yml").read()); + + for (const auto &kv : yaml.items()) + mVars.SetVar(mVars.Resolve(kv.name()), mVars.Resolve(kv.value().scalar())); return yaml; } - return YAML::Node{YAML::Null}; + return ulib::yaml{}; } - void DefaultBuildContext::SaveCachedParams(const fs::path &path, const YAML::Node &node) + void DefaultBuildContext::SaveCachedParams(const fs::path &path, const ulib::yaml &node) { - std::ofstream file{path / "re.user.yml"}; - - YAML::Emitter emitter; - emitter << node; - - file << emitter.c_str(); + // std::system("pause"); + // fmt::print("Saving: {}\nto: {}\n", node.dump().c_str(), (path / "re.user.yml").u8string().c_str()); + futile::open(path / "re.user.yml", "w").write(node.dump()); } void DefaultBuildContext::ResolveAllTargetDependencies(Target *pRootTarget) @@ -289,13 +288,13 @@ namespace re } // Setting up the package sources for this target - for (const auto &kv : desc.pRootTarget->resolved_config["package-sources"]) + for (const auto &kv : desc.pRootTarget->resolved_config["package-sources"].items()) { - auto repo_id = kv.first.Scalar(); + auto repo_id = kv.name(); - if (kv.second.IsScalar()) + if (kv.value().is_scalar()) { - auto client = RePackageClient{kv.second.Scalar()}; + auto client = RePackageClient{kv.value().scalar()}; auto resolver = std::make_unique(mEnv.get(), this, repo_id, std::move(client)); mEnv->AddDepResolver(repo_id, resolver.get()); @@ -303,13 +302,13 @@ namespace re } else { - auto &settings = kv.second; + auto &settings = kv.value(); - auto client = RePackageClient{settings["url"].Scalar()}; + auto client = RePackageClient{settings["url"].scalar()}; - for (const auto &kv : settings["headers"]) + for (const auto &kv : settings["headers"].items()) { - client.AddRequestHeader(kv.first.Scalar(), kv.second.Scalar()); + client.AddRequestHeader(kv.name(), kv.value().scalar()); } auto resolver = std::make_unique(mEnv.get(), this, repo_id, std::move(client)); @@ -476,7 +475,7 @@ namespace re for (const auto &path : path_cfg) { - auto final_path = desc.pRootTarget->build_var_scope->Resolve(path.Scalar()); + auto final_path = desc.pRootTarget->build_var_scope->Resolve(path.scalar()); ulib::add_path(final_path); } @@ -777,18 +776,10 @@ namespace re if (should_merge_configs) { - std::ifstream t1{dir / "re.yml._old"}; - std::ifstream t2{template_dir / "re.yml"}; - - auto old_config = YAML::Load(t1); - auto new_config = YAML::Load(t2); - - std::ofstream out{dir / "re.yml"}; - - YAML::Emitter emitter; - emitter << MergeYamlNodes(old_config, new_config); + auto old_config = ulib::yaml::parse(futile::open(dir / "re.yml._old").read()); + auto new_config = ulib::yaml::parse(futile::open(template_dir / "re.yml").read()); - out << emitter.c_str(); + futile::open(dir / "re.yml").write(MergeYamlNodes(old_config, new_config).dump()); Warn(fg(fmt::color::light_yellow), "WARN: Merged the existing re.yml with the one specified in the '{}'" diff --git a/buildkit/re/build/default_build_context.h b/buildkit/re/build/default_build_context.h index 54d2fc9..18460b7 100644 --- a/buildkit/re/build/default_build_context.h +++ b/buildkit/re/build/default_build_context.h @@ -4,6 +4,7 @@ #include #include "environment_var_namespace.h" +#include namespace re { @@ -20,23 +21,23 @@ namespace re return mVars; } - inline void SetVar(const std::string &key, std::string value) + inline void SetVar(ulib::string_view key, std::string value) { mVars.SetVar(key, value); } - inline std::optional GetVar(const std::string &key) + inline std::optional GetVar(ulib::string_view key) { return mVars.GetVar(key); } - inline void RemoveVar(const std::string &key) + inline void RemoveVar(ulib::string_view key) { mVars.RemoveVar(key); } Target &LoadTarget(const fs::path &path); - YAML::Node LoadCachedParams(const fs::path &path); - void SaveCachedParams(const fs::path &path, const YAML::Node &node); + ulib::yaml LoadCachedParams(const fs::path &path); + void SaveCachedParams(const fs::path &path, const ulib::yaml &node); void ResolveAllTargetDependencies(Target *pRootTarget); diff --git a/buildkit/re/build/environment_var_namespace.cpp b/buildkit/re/build/environment_var_namespace.cpp index dc38d52..d43e956 100644 --- a/buildkit/re/build/environment_var_namespace.cpp +++ b/buildkit/re/build/environment_var_namespace.cpp @@ -4,7 +4,7 @@ namespace re { - std::optional EnvironmentVarNamespace::GetVar(const std::string &key) const + std::optional EnvironmentVarNamespace::GetVar(ulib::string_view key) const { if (auto var = ulib::getenv(ulib::u8(key))) return ulib::sstr(*var); diff --git a/buildkit/re/build/environment_var_namespace.h b/buildkit/re/build/environment_var_namespace.h index 4629fc9..588eb33 100644 --- a/buildkit/re/build/environment_var_namespace.h +++ b/buildkit/re/build/environment_var_namespace.h @@ -5,6 +5,6 @@ namespace re { struct EnvironmentVarNamespace : public IVarNamespace { - std::optional GetVar(const std::string& key) const; + std::optional GetVar(ulib::string_view key) const; }; } diff --git a/buildkit/re/build/ninja_gen.cpp b/buildkit/re/build/ninja_gen.cpp index 7f60d12..f5c3cb0 100644 --- a/buildkit/re/build/ninja_gen.cpp +++ b/buildkit/re/build/ninja_gen.cpp @@ -4,6 +4,10 @@ #include +#include +#include +#include + namespace re { class FmtOstreamWrapper diff --git a/buildkit/re/build_desc.h b/buildkit/re/build_desc.h index a23d704..1ede85a 100644 --- a/buildkit/re/build_desc.h +++ b/buildkit/re/build_desc.h @@ -20,16 +20,16 @@ namespace re struct BuildTool { - std::string name; - std::string path; + ulib::string name; + ulib::string path; }; struct BuildRule { - std::string name; - std::string tool; - std::string cmdline; - std::string description; + ulib::string name; + ulib::string tool; + ulib::string cmdline; + ulib::string description; BuildVars vars; }; @@ -46,13 +46,13 @@ namespace re { BuildTargetType type; - std::string rule; - std::string in; - std::string out; + ulib::string rule; + ulib::string in; + ulib::string out; BuildVars vars; - std::vector deps; + std::vector deps; const Target *pSourceTarget = nullptr; const SourceFile *pSourceFile = nullptr; @@ -62,8 +62,8 @@ namespace re { fs::path out_dir; - std::string object_out_format; - std::string artifact_out_format; + ulib::string object_out_format; + ulib::string artifact_out_format; // Vars that go in the very beginning of the build file BuildVars init_vars; @@ -78,7 +78,7 @@ namespace re std::vector rules; std::vector targets; - std::vector subninjas; + std::vector subninjas; Target *pRootTarget = nullptr; Target *pBuildTarget = nullptr; @@ -87,17 +87,17 @@ namespace re tsl::ordered_map artifacts; - std::string GetObjectDirectory(const std::string &module) const + ulib::string GetObjectDirectory(ulib::string_view module) const { return init_vars.at("re_target_object_directory_" + module); } - std::string GetArtifactDirectory(const std::string &module) const + ulib::string GetArtifactDirectory(ulib::string_view module) const { return init_vars.at("re_target_artifact_directory_" + module); } - bool HasArtifactsFor(const std::string &module) const + bool HasArtifactsFor(ulib::string_view module) const { return init_vars.find("re_target_artifact_directory_" + module) != init_vars.end(); } diff --git a/buildkit/re/buildenv.cpp b/buildkit/re/buildenv.cpp index 7efb714..82ea475 100644 --- a/buildkit/re/buildenv.cpp +++ b/buildkit/re/buildenv.cpp @@ -19,9 +19,15 @@ #include +#include +#include +#include + +#include + namespace re { - void PopulateTargetChildSet(Target *pTarget, std::vector &to) + void PopulateTargetChildSet(Target *pTarget, ulib::list &to) { to.push_back(pTarget); @@ -29,31 +35,36 @@ namespace re PopulateTargetChildSet(child.get(), to); } - void PopulateTargetDependencySet(Target *pTarget, std::vector &to, TargetDepResolver dep_resolver, + void PopulateTargetDependencySet(Target *pTarget, ulib::list &to, TargetDepResolver dep_resolver, bool throw_on_missing) { if (std::find(to.begin(), to.end(), pTarget) != to.end()) return; - if (pTarget->resolved_config && !pTarget->resolved_config["enabled"].as()) + // std::cout << pTarget->resolved_config << std::endl; + + if (pTarget->resolved_config.is_map() && !pTarget->resolved_config["enabled"].get()) { RE_TRACE(" PopulateTargetDependencySet: Skipping '{}' because it's not enabled\n", pTarget->module); return; } - for (auto &[name, dep] : pTarget->used_mapping) - { - RE_TRACE(" PopulateTargetDependencySet: Attempting to resolve uses-mapping '{}' <- '{}'\n", pTarget->module, - dep->ToString()); + // for (auto &[name, dep] : pTarget->used_mapping) + // { + // RE_TRACE(" PopulateTargetDependencySet: Attempting to resolve uses-mapping '{}' <- '{}'\n", pTarget->module, + // dep->ToString()); - if (!dep_resolver(*pTarget, *dep, dep->resolved)) - { - RE_TRACE(" failed\n"); + // fmt::print("dep: {}\n", dep->ToString()); - if (throw_on_missing) - RE_THROW TargetDependencyException(pTarget, "unresolved uses-map dependency {}", dep->name); - } - } + // if (dep->resolved.empty() && !dep_resolver(*pTarget, *dep, dep->resolved)) + // { + // fmt::print("failed dep: {}\n", dep->ToString()); + // RE_TRACE(" failed\n"); + + // if (throw_on_missing) + // RE_THROW TargetDependencyException(pTarget, "unresolved uses-map dependency {}", dep->name); + // } + // } for (auto &dep : pTarget->dependencies) { @@ -73,7 +84,7 @@ namespace re { PopulateTargetDependencySet(t, to, dep_resolver, throw_on_missing); - std::vector kids; + ulib::list kids; PopulateTargetChildSet(t, kids); for (auto &needed : kids) @@ -83,7 +94,7 @@ namespace re } /* - std::vector dependents_needed; + ulib::list dependents_needed; PopulateTargetDependencySet(t, dependents_needed, dep_resolver, throw_on_missing); @@ -107,7 +118,7 @@ namespace re if (std::find(to.begin(), to.end(), pTarget) != to.end()) return; - if (pTarget->resolved_config && !pTarget->resolved_config["enabled"].as()) + if (pTarget->resolved_config.is_map() && !pTarget->resolved_config["enabled"].get()) { RE_TRACE(" PopulateTargetDependencySetNoResolve: Skipping '{}' because it's not enabled\n", pTarget->module); @@ -142,6 +153,39 @@ namespace re std::unique_ptr BuildEnv::LoadFreeTarget(const fs::path &path, const Target *ancestor, const TargetDependency *dep_source) { + // { + // const Target *p = ancestor; + // if (p) + // { + // fmt::print("\nancestor:\n"); + // fmt::print("p->name: {}\n", p->name); + // fmt::print("p->path: {}\n", p->path.generic_string()); + // fmt::print("p->module: {}\n", p->module); + // fmt::print("p->type: {}\n", TargetTypeToString(p->type)); + // fmt::print("p: 0x{:X}\n", uint64_t(p)); + + // if (p->parent) + // { + // fmt::print("p->parent->name: {}\n", p->parent->name); + // fmt::print("p->parent->path: {}\n", p->parent->path.generic_string()); + // fmt::print("p->parent->module: {}\n", p->parent->module); + // fmt::print("p->parent->type: {}\n", TargetTypeToString(p->parent->type)); + // fmt::print("p->parent: 0x{:X}\n", uint64_t(p->parent)); + // } + + // if (p->root) + // { + // fmt::print("p->root->name: {}\n", p->root->name); + // fmt::print("p->root->path: {}\n", p->root->path.generic_string()); + // fmt::print("p->root->module: {}\n", p->root->module); + // fmt::print("p->root->type: {}\n", TargetTypeToString(p->root->type)); + // fmt::print("p->root: 0x{:X}\n", uint64_t(p->root)); + // } + + // fmt::print("\n"); + // } + // } + std::unique_ptr target = nullptr; for (auto &middleware : mTargetLoadMiddlewares) @@ -166,7 +210,11 @@ namespace re target = std::make_unique(path, mTheCoreProjectTarget.get()); } - target->parent = mTheCoreProjectTarget.get(); + if (mRootTargets.size() > 0) + target->parent = target->root = mRootTargets.front().get(); + else + target->parent = mTheCoreProjectTarget.get(); + target->root = target.get(); return target; @@ -217,23 +265,23 @@ namespace re return mTheCoreProjectTarget.get(); } - std::vector BuildEnv::GetSingleTargetDepSet(Target *pTarget) + ulib::list BuildEnv::GetSingleTargetDepSet(Target *pTarget) { - std::vector result; + ulib::list result; AppendDepsAndSelf(pTarget, result); return result; } - std::vector BuildEnv::GetSingleTargetLocalDepSet(Target *pTarget) + ulib::list BuildEnv::GetSingleTargetLocalDepSet(Target *pTarget) { - std::vector result; + ulib::list result; AppendDepsAndSelf(pTarget, result, false, false); return result; } - std::vector BuildEnv::GetTargetsInDependencyOrder() + ulib::list BuildEnv::GetTargetsInDependencyOrder() { - std::vector result; + ulib::list result; for (auto &target : mRootTargets) AppendDepsAndSelf(target.get(), result); @@ -241,12 +289,12 @@ namespace re return result; } - void BuildEnv::AddLangProvider(std::string_view name, ILangProvider *provider) + void BuildEnv::AddLangProvider(ulib::string_view name, ILangProvider *provider) { mLangProviders[name.data()] = provider; } - ILangProvider *BuildEnv::GetLangProvider(std::string_view name) + ILangProvider *BuildEnv::GetLangProvider(ulib::string_view name) { return mLangProviders[name.data()]; } @@ -254,25 +302,25 @@ namespace re ILangProvider *BuildEnv::InitializeTargetLinkEnv(Target *target, NinjaBuildDesc &desc) { auto link_cfg = target->GetCfgEntry("link-with", re::CfgEntryKind::Recursive) - .value_or(YAML::Node{YAML::NodeType::Null}); + .value_or(ulib::yaml{ulib::yaml::value_t::null}); std::optional link_language; - if (link_cfg.IsMap()) + if (link_cfg.is_map()) { - if (auto value = link_cfg[TargetTypeToString(target->type)]) + if (auto value = link_cfg.search(TargetTypeToString(target->type))) { - if (!value.IsNull()) - link_language = value.as(); + if (!value->is_null()) + link_language = value->scalar(); } - else if (auto value = link_cfg["default"]) + else if (auto value = link_cfg.search("default")) { - if (!value.IsNull()) - link_language = value.as(); + if (!value->is_null()) + link_language = value->scalar(); } } - else if (!link_cfg.IsNull()) + else if (!link_cfg.is_null()) { - link_language = link_cfg.as(); + link_language = link_cfg.scalar(); } ILangProvider *link_provider = link_language ? GetLangProvider(*link_language) : nullptr; @@ -304,7 +352,7 @@ namespace re void BuildEnv::InitializeTargetLinkEnvWithDeps(Target *target, NinjaBuildDesc &desc) { - std::vector deps; + ulib::list deps; AppendDepsAndSelf(target, deps, false, false); for (auto &dep : deps) @@ -314,11 +362,11 @@ namespace re void BuildEnv::PopulateBuildDesc(Target *target, NinjaBuildDesc &desc) { auto langs = target->GetCfgEntry("langs", CfgEntryKind::Recursive) - .value_or(TargetConfig{YAML::NodeType::Sequence}); + .value_or(TargetConfig{ulib::yaml::value_t::sequence}); ILangProvider *link_provider = InitializeTargetLinkEnv(target, desc); - if (target->resolved_config && !target->resolved_config["enabled"].as()) + if (target->resolved_config.is_map() && !target->resolved_config["enabled"].get()) { RE_TRACE(" PopulateBuildDesc: Skipping '{}' because it's not enabled\n", target->module); return; @@ -326,7 +374,7 @@ namespace re for (const auto &lang : langs) { - auto lang_id = lang.as(); + auto lang_id = lang.scalar(); auto provider = GetLangProvider(lang_id); if (!provider) @@ -365,7 +413,7 @@ namespace re } void BuildEnv::PerformCopyToDependentsImpl(const Target &target, const Target *dependent, - const NinjaBuildDesc *desc, const fs::path &from, const std::string &to) + const NinjaBuildDesc *desc, const fs::path &from, ulib::string_view to) { auto path = GetEscapedModulePath(*dependent); @@ -412,13 +460,13 @@ namespace re PerformCopyToDependentsImpl(target, inner_dep, desc, from, to); } - void BuildEnv::RunTargetAction(const NinjaBuildDesc *desc, const Target &target, const std::string &type, + void BuildEnv::RunTargetAction(const NinjaBuildDesc *desc, const Target &target, ulib::string_view type, const TargetConfig &data) { if (type == "copy") { - auto from = target.build_var_scope->Resolve(data["from"].as()); - auto to = target.build_var_scope->Resolve(data["to"].as()); + auto from = target.build_var_scope->Resolve(data["from"].scalar()); + auto to = target.build_var_scope->Resolve(data["to"].scalar()); auto from_path = fs::path{from}; auto to_path = fs::path{to}; @@ -433,8 +481,8 @@ namespace re } else if (type == "copy-to-deps") { - auto from = target.build_var_scope->Resolve(data["from"].as()); - auto to = data["to"].as(); + auto from = target.build_var_scope->Resolve(data["from"].scalar()); + auto to = data["to"].scalar(); auto from_path = fs::path{from}; @@ -451,24 +499,26 @@ namespace re } else if (type == "run") { - if (data.IsMap()) + if (data.is_map()) { - auto command = data["command"].as(); + auto command = data["command"].scalar(); - std::vector args; + ulib::list args; args.push_back(target.build_var_scope->Resolve(command)); - for (auto &arg : data["args"]) - args.push_back(target.build_var_scope->Resolve(arg.Scalar())); + if (auto args_field = data.search("args")) + if (args_field->is_sequence()) + for (auto &arg : *args_field) + args.push_back(target.build_var_scope->Resolve(arg.scalar())); RunProcessOrThrow(args.front(), {}, args, true, true, target.path.u8string()); } else { - auto command = target.build_var_scope->Resolve(data.as()); + auto command = target.build_var_scope->Resolve(data.scalar()); - std::vector args; + ulib::list args; std::istringstream iss{command}; std::string temp; @@ -480,13 +530,13 @@ namespace re } else if (type == "shell-run") { - auto command = target.build_var_scope->Resolve(data["command"].as()); + auto command = target.build_var_scope->Resolve(data["command"].scalar()); std::system(command.data()); } else if (type == "command") { - auto command = target.build_var_scope->Resolve(data.as()); + auto command = target.build_var_scope->Resolve(data.scalar()); std::system(command.data()); } else if (type == "install") @@ -496,8 +546,8 @@ namespace re fs::path artifact_dir = desc->out_dir / desc->GetArtifactDirectory(GetEscapedModulePath(target)); fs::path from = desc->out_dir / desc->GetArtifactDirectory(GetEscapedModulePath(target)); - if (data["from"]) - from /= target.build_var_scope->Resolve(data["from"].as()); + if (data.search("from")) + from /= target.build_var_scope->Resolve(data["from"].scalar()); auto do_install = [this, &artifact_dir, &from, &target, desc, style](const std::string &path, bool create_dir) { @@ -516,21 +566,21 @@ namespace re mOut->Info(style, " * Installed {} to:\n", target.module); - if (auto to_v = data["to"]) + if (auto to_v = data.search("to")) { - if (to_v.IsSequence()) - for (const auto &v : to_v) - do_install(v.as(), true); + if (to_v->is_sequence()) + for (const auto &v : *to_v) + do_install(v.scalar(), true); else - do_install(to_v.Scalar(), true); + do_install(to_v->scalar(), true); } - else if (auto to_v = data["to-file"]) + else if (auto to_v = data.search("to-file")) { - if (to_v.IsSequence()) - for (const auto &v : to_v) - do_install(v.as(), false); + if (to_v->is_sequence()) + for (const auto &v : *to_v) + do_install(v.scalar(), false); else - do_install(to_v.Scalar(), false); + do_install(to_v->scalar(), false); } mOut->Info(style, "\n"); @@ -554,7 +604,7 @@ namespace re { if (auto path = pTarget->GetCfgEntry("install", CfgEntryKind::Recursive)) { - auto path_str = path->as(); + auto path_str = path->scalar(); mOut->Info({}, "Installing {} - {} => {}\n", pTarget->module, from.u8string(), path_str); @@ -565,12 +615,12 @@ namespace re } } - void BuildEnv::AddDepResolver(std::string_view name, IDepResolver *resolver) + void BuildEnv::AddDepResolver(ulib::string_view name, IDepResolver *resolver) { mDepResolvers[name.data()] = resolver; } - void BuildEnv::AddTargetFeature(std::string_view name, ITargetFeature *feature) + void BuildEnv::AddTargetFeature(ulib::string_view name, ITargetFeature *feature) { mTargetFeatures[name.data()] = feature; } @@ -585,21 +635,69 @@ namespace re mTargetLoadMiddlewares.push_back(middleware); } + Target *FindDeepNeighborTarget(const Target *target, ulib::string_view name) + { + while (name.size() && name.front() == '.') + name.remove_prefix(1); + + if (!target || !target->parent) + { + return nullptr; + } + + for (auto &child : target->parent->children) + { + // fmt::print("{} -> {}\n", name, child->name); + + ulib::string_view childName = child->name; + while (childName.starts_with('.')) + childName.remove_prefix(1); + + if (childName == name) + { + return child.get(); + } + } + + return FindDeepNeighborTarget(target->parent, name); + } + + Target *GetDeepSiblingDep(const Target *target, ulib::string_view name) + { + while (name.starts_with(".")) + name.remove_prefix(1); + + ulib::list components = name.split("."); + if (components.empty()) + return nullptr; + + auto result = FindDeepNeighborTarget(target, components[0]); + for (size_t i = 1; i < components.size(); i++) + { + result = result->FindChild(components[i]); + if (!result) + return nullptr; + } + + return result; + } + bool BuildEnv::ResolveTargetDependencyImpl(const Target &target, const TargetDependency &dep, - std::vector &out, bool use_external) + ulib::list &out, bool use_external) { out.clear(); if (dep.ns.empty()) { - auto result = GetTargetOrNull(dep.name); + auto result = GetDeepSiblingDep(&target, dep.name); + // fmt::print("ResolveTargetDependencyImpl: target: {}\n", target.name); // Arch coercion - this is SOMETIMES very useful if (result) { if (dep.extra_config_hash) { - auto ecfg_name = fmt::format("ecfg-local.{}.{}", dep.name, dep.extra_config_hash); + auto ecfg_name = ulib::format("ecfg-local.{}.{}", dep.name, dep.extra_config_hash); auto ecfg_existing = GetTargetOrNull(ecfg_name); if (!ecfg_existing) @@ -624,6 +722,8 @@ namespace re result = ecfg_existing; } + // fmt::print("target.build_var_scope = {}, result->build_var_scope = {}\n", target.build_var_scope.has_value(), result->build_var_scope.has_value()); + if (target.build_var_scope && result->build_var_scope) { auto target_arch = target.build_var_scope->ResolveLocal("arch"); @@ -664,7 +764,7 @@ namespace re if (filter.front() == '/') continue; - ulib::list parts = ulib::split(filter, "."); + ulib::list parts = filter.split("."); auto temp = result; for (auto &part : parts) @@ -696,7 +796,7 @@ namespace re if (!used) RE_THROW TargetDependencyException(&target, "uses-dependency '{}' not found", dep.ToString()); - std::vector result; + ulib::list result; if (!ResolveTargetDependencyImpl(target, *used, result, use_external)) RE_THROW TargetDependencyException(&target, "unresolved uses-dependency '{}' <- '{}'", @@ -762,19 +862,30 @@ namespace re result->config["root-dir"] = result->path.generic_u8string(); result->config["is-external-dep"] = "true"; - if (result->resolved_config) + if (result->resolved_config.is_map()) result->resolved_config["is-external-dep"] = "true"; auto [scope, context] = target.GetBuildVarScope(); - if (scope.ResolveLocal("inherit-caller-in-deps") == "true") + // if (scope.ResolveLocal("inherit-caller-in-deps") == "true") { // EVIL HACK - result->root = target.root; - result->parent = result->root; + // if (target.root && !target.root->name.empty()) + // { + // ulib::string rootParentName = "[nullptr]"; + // if (target.root->parent) + // rootParentName = target.root->parent->name; + + // fmt::print("EVIL HACK PAUSE. name: {}, root->name: {}, root->parent.name: {}\n", target.name, + // target.root->name, rootParentName); + // // std::system("pause"); + // } + + // result->root = target.root; + // result->parent = result->root; } - if (!result->resolved_config) + if (!result->resolved_config.is_map()) { auto re_arch = scope.ResolveLocal("arch"); auto re_platform = scope.ResolveLocal("platform"); @@ -823,105 +934,127 @@ namespace re PopulateTargetMap(child.get()); } - void BuildEnv::AppendDepsAndSelf(Target *pTarget, std::vector &to, bool throw_on_missing, + void BuildEnv::AppendDepsAndSelf(Target *pTarget, ulib::list &to, bool throw_on_missing, bool use_external) { PopulateTargetDependencySet( pTarget, to, [this, &to, pTarget, throw_on_missing, use_external](const Target &target, const TargetDependency &dep, - std::vector &out) { + ulib::list &out) { return ResolveTargetDependencyImpl(target, dep, out, use_external); }, throw_on_missing); } void BuildEnv::RunActionList(const NinjaBuildDesc *desc, Target *target, const TargetConfig &list, - std::string_view run_type, const std::string &default_run_type) + ulib::string_view run_type, ulib::string_view default_run_type) { auto old_path = ulib::getpath(); - auto path_cfg = target->resolved_config["env-path"]; + if (auto path_cfg = target->resolved_config.search("env-path")) + if (path_cfg->is_sequence()) + for (const auto &path : *path_cfg) + { + try + { + auto final_path = target->build_var_scope->Resolve(path.scalar()); + ulib::add_path(final_path); + } + catch (re::VarSubstitutionException &ex) + { + if (!std::filesystem::exists("out")) + std::filesystem::create_directory("out"); - for (const auto &path : path_cfg) - { - auto final_path = target->build_var_scope->Resolve(path.Scalar()); - ulib::add_path(final_path); - } + futile::open("out/warnings.log", "a") + .write(ulib::format("[RunActionList] [{}]: Can't resolve: {}. Full Exception: {}\n", target->name, + ulib::str(path.scalar()).c_str(), ex.what())); - for (const auto &v : list) + // this->mOut->Trace(fmt::fg(fmt::color::yellow), + // "[RunActionList] [{}]: Can't resolve: {}\n", target->name, + // ulib::str(path.scalar()).c_str()); + } + } + + if (list.is_sequence()) { - for (const auto &kv : v) + for (const auto &v : list) { - auto type = kv.first.as(); - auto &data = kv.second; + for (const auto &kv : v.items()) + { + auto type = kv.name(); + auto &data = kv.value(); - std::string run = default_run_type; - RE_TRACE("{} -> action {}\n", target->module, type); + std::string run = default_run_type; + RE_TRACE("{} -> action {}\n", target->module, type); - bool should_run = (run_type == default_run_type); + bool should_run = (run_type == default_run_type); - if (data.IsMap()) - { - if (auto run_val = data["on"]) + if (data.is_map()) { - should_run = false; + if (auto run_val = data.search("on")) + { + should_run = false; - if (run_val.IsScalar()) - should_run = (run_type == run_val.as()); - else - for (const auto &v : run_val) - if (run_type == v.as()) - { - should_run = true; - break; - } + if (run_val->is_scalar()) + should_run = (run_type == run_val->scalar()); + else + for (const auto &v : *run_val) + if (run_type == v.scalar()) + { + should_run = true; + break; + } + } } - } - if (should_run) - RunTargetAction(desc, *target, type, data); + if (should_run) + RunTargetAction(desc, *target, type, data); + } } } ulib::setpath(old_path); } - void BuildEnv::RunActionsCategorized(Target *target, const NinjaBuildDesc *desc, std::string_view run_type) + void BuildEnv::RunActionsCategorized(Target *target, const NinjaBuildDesc *desc, ulib::string_view run_type) { - if (auto actions = (target->resolved_config ? target->resolved_config : target->config)["actions"]) + auto &cfg = (target->resolved_config.is_map() ? target->resolved_config : target->config); + if (auto actions = cfg.search("actions")) { - if (actions.IsMap()) + if (actions->is_map()) { - for (const auto &kv : actions) + for (const auto &kv : actions->items()) { - auto type = kv.first.as(); - auto &data = kv.second; + auto type = kv.name(); + auto &data = kv.value(); RunActionList(desc, target, data, run_type, type); } } else { - RunActionList(desc, target, actions, run_type, "post-build"); + RunActionList(desc, target, *actions, run_type, "post-build"); } } } - void BuildEnv::RunAutomaticStructuredTasks(Target *target, const NinjaBuildDesc *desc, std::string_view stage) + void BuildEnv::RunAutomaticStructuredTasks(Target *target, const NinjaBuildDesc *desc, ulib::string_view stage) { if (target->parent) RunAutomaticStructuredTasks(target->parent, desc, stage); - if (auto tasks = (target->resolved_config ? target->resolved_config : target->config)["tasks"]) + auto &cfg = (target->resolved_config.is_map() ? target->resolved_config : target->config); + if (auto tasks = cfg.search("tasks")) { - for (auto kv : tasks) + for (auto &kv : tasks->items()) { - auto name = kv.first.as(); - auto &task = kv.second; + auto name = kv.name(); + auto &task = kv.value(); - if (task.IsMap()) + if (task.is_map()) { - if (task["run"] && task["run"].Scalar() == "always") + auto run_field = task.search("run"); + if (run_field && run_field->scalar() == "always") { RunStructuredTaskData(target, desc, task, name, stage); } @@ -930,60 +1063,62 @@ namespace re } } - void BuildEnv::RunStructuredTask(Target *target, const NinjaBuildDesc *desc, std::string_view name, - std::string_view stage) + void BuildEnv::RunStructuredTask(Target *target, const NinjaBuildDesc *desc, ulib::string_view name, + ulib::string_view stage) { - if (auto tasks = (target->resolved_config ? target->resolved_config : target->config)["tasks"]) + auto &cfg = (target->resolved_config.is_map() ? target->resolved_config : target->config); + if (auto tasks = cfg.search("tasks")) { - if (auto task = tasks[name.data()]) + if (auto task = tasks->search(name.data())) { - RunStructuredTaskData(target, desc, task, name, stage); + RunStructuredTaskData(target, desc, *task, name, stage); } } } void BuildEnv::RunStructuredTaskData(Target *target, const NinjaBuildDesc *desc, const TargetConfig &task, - std::string_view name, std::string_view stage) + ulib::string_view name, ulib::string_view stage) { // TODO: this is problematic and needs to be improved somehow - if (auto deps = task["deps"]) + if (auto deps = task.search("deps")) { - for (auto dep_task : deps) + for (auto dep_task : *deps) { if (desc) { for (auto &dep : GetSingleTargetDepSet(desc->pBuildTarget)) - RunStructuredTask(dep, desc, dep_task.Scalar(), stage); + RunStructuredTask(dep, desc, dep_task.scalar(), stage); } else { - RunStructuredTask(target, desc, dep_task.Scalar(), stage); + RunStructuredTask(target, desc, dep_task.scalar(), stage); } } } - if (auto stage_actions = task[stage.data()]) + if (auto stage_actions = task.search(stage.data())) { - auto completion_key = fmt::format("{} / {} [{}]", target->module, name, stage); + auto completion_key = ulib::format("{} / {} [{}]", target->module, name, stage); if (mCompletedActions.find(completion_key) != mCompletedActions.end()) return; const auto kStyle = fg(fmt::color::blue_violet) | fmt::emphasis::bold; - if (!task["silent"] || task["silent"].as() != true) + auto silent_field = task.search("silent"); + if (!silent_field || silent_field->get() != true) { mOut->Info(kStyle, " - Running task "); mOut->Info(kStyle | fmt::emphasis::underline, "{}\n\n", completion_key); } - RunActionList(desc, target, stage_actions, stage, stage.data()); + RunActionList(desc, target, *stage_actions, stage, stage.data()); mCompletedActions.insert(completion_key); } } - IDepResolver *BuildEnv::GetDepResolver(const std::string &name) + IDepResolver *BuildEnv::GetDepResolver(ulib::string_view name) { return mDepResolvers[name]; } @@ -1088,9 +1223,7 @@ namespace re if (mVars.GetVar("target-configs").value_or("false") == "true") { - YAML::Emitter emitter; - emitter << pTarget->resolved_config; - mOut->Info({}, "{}", emitter.c_str()); + mOut->Info({}, "{}", pTarget->resolved_config.dump().c_str()); } } } diff --git a/buildkit/re/buildenv.h b/buildkit/re/buildenv.h index 1c18053..7d7f63f 100644 --- a/buildkit/re/buildenv.h +++ b/buildkit/re/buildenv.h @@ -31,7 +31,7 @@ namespace re /** * @brief A function capable of resolving target dependencies. */ - using TargetDepResolver = std::function &)>; + using TargetDepResolver = std::function &)>; /** * @brief Populates the specified collection with a flat target dependency set, resolving all target dependences in @@ -42,7 +42,7 @@ namespace re * @param dep_resolver The dependency resolver to use * @param throw_on_missing Throw exceptions if any dependency is missing */ - void PopulateTargetDependencySet(Target *pTarget, std::vector &to, TargetDepResolver dep_resolver = {}, + void PopulateTargetDependencySet(Target *pTarget, ulib::list &to, TargetDepResolver dep_resolver = {}, bool throw_on_missing = true); /** @@ -123,12 +123,12 @@ namespace re */ bool CanLoadTargetFrom(const fs::path &path); - std::vector GetSingleTargetDepSet(Target *pTarget); - std::vector GetSingleTargetLocalDepSet(Target *pTarget); - std::vector GetTargetsInDependencyOrder(); + ulib::list GetSingleTargetDepSet(Target *pTarget); + ulib::list GetSingleTargetLocalDepSet(Target *pTarget); + ulib::list GetTargetsInDependencyOrder(); - void AddLangProvider(std::string_view name, ILangProvider *provider); - ILangProvider *GetLangProvider(std::string_view name) override; + void AddLangProvider(ulib::string_view name, ILangProvider *provider); + ILangProvider *GetLangProvider(ulib::string_view name) override; ILangProvider *InitializeTargetLinkEnv(Target *target, NinjaBuildDesc &desc); void InitializeTargetLinkEnvWithDeps(Target *target, NinjaBuildDesc &desc); @@ -137,30 +137,30 @@ namespace re void PopulateBuildDescWithDeps(Target *target, NinjaBuildDesc &desc); void PopulateFullBuildDesc(NinjaBuildDesc &desc); - void RunTargetAction(const NinjaBuildDesc *desc, const Target &target, const std::string &type, + void RunTargetAction(const NinjaBuildDesc *desc, const Target &target, ulib::string_view type, const TargetConfig &data); - void RunActionsCategorized(Target *target, const NinjaBuildDesc *desc, std::string_view run_type); + void RunActionsCategorized(Target *target, const NinjaBuildDesc *desc, ulib::string_view run_type); - void RunAutomaticStructuredTasks(Target *target, const NinjaBuildDesc *desc, std::string_view stage); + void RunAutomaticStructuredTasks(Target *target, const NinjaBuildDesc *desc, ulib::string_view stage); - void RunStructuredTask(Target *target, const NinjaBuildDesc *desc, std::string_view name, - std::string_view stage); + void RunStructuredTask(Target *target, const NinjaBuildDesc *desc, ulib::string_view name, + ulib::string_view stage); void RunStructuredTaskData(Target *target, const NinjaBuildDesc *desc, const TargetConfig &task, - std::string_view name, std::string_view stage); + ulib::string_view name, ulib::string_view stage); void RunPostBuildActions(Target *target, const NinjaBuildDesc &desc); void RunInstallActions(Target *target, const NinjaBuildDesc &desc); - void AddDepResolver(std::string_view name, IDepResolver *resolver); + void AddDepResolver(ulib::string_view name, IDepResolver *resolver); - void AddTargetFeature(std::string_view name, ITargetFeature *feature); + void AddTargetFeature(ulib::string_view name, ITargetFeature *feature); void AddTargetFeature(ITargetFeature *feature); void AddTargetLoadMiddleware(ITargetLoadMiddleware *middleware); - IDepResolver *GetDepResolver(const std::string &name); + IDepResolver *GetDepResolver(ulib::string_view name); void DebugShowVisualBuildInfo(const Target *pTarget = nullptr, int depth = 0); @@ -171,7 +171,7 @@ namespace re */ void SetDepsVersionCache(DepsVersionCache *cache); - inline Target *GetTargetOrNull(const std::string &module) + inline Target *GetTargetOrNull(ulib::string_view module) { auto it = mTargetMap.find(module); @@ -184,14 +184,14 @@ namespace re private: std::unique_ptr mTheCoreProjectTarget; - std::vector> mRootTargets; + ulib::list> mRootTargets; std::unordered_map mTargetMap; std::unordered_map mLangProviders; std::unordered_map mDepResolvers; std::unordered_map mTargetFeatures; - std::vector mTargetLoadMiddlewares; + ulib::list mTargetLoadMiddlewares; LocalVarScope mVars; IUserOutput *mOut; @@ -202,18 +202,18 @@ namespace re void PopulateTargetMap(Target *pTarget); - void AppendDepsAndSelf(Target *pTarget, std::vector &to, bool throw_on_missing = true, + void AppendDepsAndSelf(Target *pTarget, ulib::list &to, bool throw_on_missing = true, bool use_external = true); void RunActionList(const NinjaBuildDesc *desc, Target *target, const TargetConfig &list, - std::string_view run_type, const std::string &default_run_type); + ulib::string_view run_type, ulib::string_view default_run_type); void InstallPathToTarget(const Target *pTarget, const fs::path &from); - bool ResolveTargetDependencyImpl(const Target &target, const TargetDependency &dep, std::vector &out, + bool ResolveTargetDependencyImpl(const Target &target, const TargetDependency &dep, ulib::list &out, bool use_external = true); void PerformCopyToDependentsImpl(const Target &target, const Target *dependent, const NinjaBuildDesc *desc, - const fs::path &from, const std::string &to); + const fs::path &from, ulib::string_view to); }; } // namespace re diff --git a/buildkit/re/debug.cpp b/buildkit/re/debug.cpp index 94fedad..98f5a4e 100644 --- a/buildkit/re/debug.cpp +++ b/buildkit/re/debug.cpp @@ -1,6 +1,7 @@ #include "debug.h" #include +#include namespace re { @@ -22,7 +23,7 @@ namespace re ); } - std::string PerfProfile::ToString() const + ulib::string PerfProfile::ToString() const { auto point = mFinished ? mEndTime : std::chrono::high_resolution_clock::now(); auto delta = point - mBeginTime; @@ -31,7 +32,7 @@ namespace re auto ms = std::chrono::duration_cast(delta).count(); auto s = ms / 1000.f; - return fmt::format( + return ulib::format( "{}s / {}ms / {}ns", s, ms, ns ); } diff --git a/buildkit/re/debug.h b/buildkit/re/debug.h index 8fb7637..019439d 100644 --- a/buildkit/re/debug.h +++ b/buildkit/re/debug.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include @@ -26,10 +26,10 @@ namespace re void Print(); - std::string ToString() const; + ulib::string ToString() const; private: - std::string mName; + ulib::string mName; std::chrono::high_resolution_clock::time_point mBeginTime = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point mEndTime; diff --git a/buildkit/re/deps/conan_dep_resolver.cpp b/buildkit/re/deps/conan_dep_resolver.cpp index 6094f20..6646ec5 100644 --- a/buildkit/re/deps/conan_dep_resolver.cpp +++ b/buildkit/re/deps/conan_dep_resolver.cpp @@ -5,6 +5,10 @@ #include #include +#include + +#include +#include namespace re { @@ -41,11 +45,17 @@ namespace re auto conan_arch = re_arch; auto conan_build_type = re_config; - if (auto overridden = target.resolved_config["conan-arch-name"]) - conan_arch = overridden.Scalar(); + if (auto overridden = scope.GetVar("conan-arch-name")) + conan_arch = *overridden; + + if (auto overridden = scope.GetVar("conan-build-type")) + conan_build_type = *overridden; - if (auto overridden = target.resolved_config["conan-build-type"]) - conan_build_type = overridden.Scalar(); + // fmt::print("conan arch: {}\n", conan_arch); + // fmt::print("target.name: {}\n", target.name); + // fmt::print("scope.ResolveLocal: {}\n", scope.ResolveLocal("conan-arch-name")); + // fmt::print("resolved_config: \n"); + // std::cout << target.resolved_config << std::endl; fs::create_directories(pkg_cached); @@ -55,7 +65,7 @@ namespace re conanfile << "[requires]\n"; - conanfile << dep.name << "/"; + conanfile << std::string_view{dep.name} << "/"; if (dep.version_kind == DependencyVersionKind::RawTag) { @@ -65,12 +75,12 @@ namespace re } else { - conanfile << dep.version; + conanfile << std::string_view{dep.version}; } } else { - conanfile << "[" << dep.version_kind_str << dep.version << "]"; + conanfile << "[" << std::string_view{dep.version_kind_str} << std::string_view{dep.version} << "]"; } conanfile << "\n"; @@ -96,7 +106,7 @@ namespace re } } - conanfile << dep.name << ":" << s << "\n"; + conanfile << std::string_view{dep.name} << ":" << std::string_view{s} << "\n"; } } @@ -136,56 +146,70 @@ namespace re "[{}] Package {} already available\n", target.module, dep.raw); } - std::ifstream build_info_file{build_info_path}; + ulib::yaml build_info = ulib::yaml::parse(futile::open(build_info_path).read()); - YAML::Node build_info = YAML::Load(build_info_file); + ulib::string conan_lib_suffix = ""; + if (auto suffix = scope.GetVar("conan-lib-suffix")) + conan_lib_suffix = *suffix; - auto conan_lib_suffix = target.resolved_config["conan-lib-suffix"].Scalar(); + // auto conan_lib_suffix = target.resolved_config["conan-lib-suffix"].scalar(); auto load_conan_dependency = [this, conan_lib_suffix, &re_arch, &re_platform, &re_config, &bv_scope, - &target](YAML::Node data) { + &target](ulib::yaml data) { auto [scope, context] = bv_scope; - auto name = data["name"].Scalar(); - auto version = data["version"].Scalar(); - auto path = data["rootpath"].Scalar(); + auto name = data["name"].scalar(); + auto version = data["version"].scalar(); + auto path = data["rootpath"].scalar(); - auto cache_path = fmt::format("conan-dep.{}_{}-{}-{}-{}", name, version, re_arch, re_platform, re_config); + auto cache_path = ulib::format("conan-dep.{}_{}-{}-{}-{}", name, version, re_arch, re_platform, re_config); if (auto &cached = mTargetCache[cache_path]) return cached.get(); - YAML::Node config{YAML::NodeType::Map}; + ulib::yaml config{ulib::yaml::value_t::map}; config["name"] = name; config["version"] = version; config["is-external-dep"] = "true"; - for (auto inc_path : data["include_paths"]) - config["cxx-include-dirs"].push_back(inc_path.Scalar()); + if (auto paths = data.search("include_paths")) + if (paths->is_sequence()) + for (auto inc_path : *paths) + config["cxx-include-dirs"].push_back(inc_path.scalar()); - for (auto lib_path : data["lib_paths"]) - config["cxx-lib-dirs"].push_back(lib_path.Scalar()); + if (auto paths = data.search("lib_paths")) + if (paths->is_sequence()) + for (auto lib_path : *paths) + config["cxx-lib-dirs"].push_back(lib_path.scalar()); - for (auto bin_path : data["bin_paths"]) - { - YAML::Node entry{YAML::NodeType::Map}; + if (auto paths = data.search("bin_paths")) + if (paths->is_sequence()) + for (auto bin_path : *paths) + { + ulib::yaml entry{ulib::yaml::value_t::map}; - entry["copy-to-deps"]["from"] = bin_path.Scalar(); - entry["copy-to-deps"]["to"] = "."; + entry["copy-to-deps"]["from"] = bin_path.scalar(); + entry["copy-to-deps"]["to"] = "."; - config["actions"].push_back(entry); - } + config["actions"].push_back(entry); + } - for (auto lib : data["libs"]) - config["cxx-link-deps"].push_back(lib.Scalar() + conan_lib_suffix); + if (auto libs = data.search("libs")) + if (libs->is_sequence()) + for (auto lib : data["libs"]) + config["cxx-link-deps"].push_back(lib.scalar() + conan_lib_suffix.ToView()); // TODO: This will not work properly on Windows! - for (auto lib : data["system_libs"]) - config["cxx-global-link-deps"].push_back(lib.Scalar() + conan_lib_suffix); + if (auto libs = data.search("system_libs")) + if (libs->is_sequence()) + for (auto lib : *libs) + config["cxx-global-link-deps"].push_back(lib.scalar() + conan_lib_suffix.ToView()); - for (auto def : data["defines"]) - config["cxx-compile-definitions"][def.Scalar()] = "1"; + if (auto defs = data.search("defines")) + if (defs->is_sequence()) + for (auto def : *defs) + config["cxx-compile-definitions"][def.scalar()] = "1"; auto dep_target = std::make_unique(path, cache_path, TargetType::StaticLibrary, config); @@ -207,7 +231,7 @@ namespace re return result.get(); }; - YAML::Node config{YAML::NodeType::Map}; + ulib::yaml config{ulib::yaml::value_t::map}; config["is-external-dep"] = "true"; @@ -237,7 +261,7 @@ namespace re package_target->config["platform"] = re_platform; package_target->config["configuration"] = re_config; - if (dep.extra_config) + if (!dep.extra_config.is_null()) MergeYamlNode(package_target->config, dep.extra_config); package_target->resolved_config = package_target->config; @@ -254,21 +278,16 @@ namespace re bool ConanDepResolver::SaveDependencyToPath(const TargetDependency &dep, const fs::path &path) { - YAML::Node config; + ulib::yaml config; config["type"] = "project"; config["name"] = dep.name; - config["deps"] = YAML::Node{YAML::NodeType::Sequence}; + config["deps"] = ulib::yaml{ulib::yaml::value_t::sequence}; config["deps"].push_back(dep.ToString()); - YAML::Emitter emitter; - emitter << config; - fs::create_directories(path); - - std::ofstream of{path / "re.yml"}; - of << emitter.c_str(); + futile::open(path / "re.yml", "w").write(config.dump()); return true; } diff --git a/buildkit/re/deps/fs_dep_resolver.cpp b/buildkit/re/deps/fs_dep_resolver.cpp index 60168ad..a83da4a 100644 --- a/buildkit/re/deps/fs_dep_resolver.cpp +++ b/buildkit/re/deps/fs_dep_resolver.cpp @@ -42,7 +42,7 @@ namespace re result->config["platform"] = re_platform; result->config["configuration"] = re_config; - if (dep.extra_config) + if (!dep.extra_config.is_null()) MergeYamlNode(result->config, dep.extra_config); result->var_parent = target.var_parent; diff --git a/buildkit/re/deps/git_dep_resolver.cpp b/buildkit/re/deps/git_dep_resolver.cpp index 78abb99..7622dd4 100644 --- a/buildkit/re/deps/git_dep_resolver.cpp +++ b/buildkit/re/deps/git_dep_resolver.cpp @@ -25,7 +25,7 @@ namespace re } Target *GitDepResolver::ResolveGitDependency(const Target &target, const TargetDependency &dep, - std::string_view url, std::string branch, DepsVersionCache *cache) + ulib::string_view url, ulib::string branch, DepsVersionCache *cache) { if (cache) { @@ -165,7 +165,7 @@ namespace re result->config["platform"] = re_platform; result->config["configuration"] = re_config; - if (dep.extra_config) + if (!dep.extra_config.is_null()) MergeYamlNode(result->config, dep.extra_config); result->var_parent = target.var_parent; @@ -182,17 +182,17 @@ namespace re return result.get(); } - void GitDepResolver::DownloadGitDependency(std::string_view url, std::string_view branch, const fs::path &to) + void GitDepResolver::DownloadGitDependency(ulib::string_view url, ulib::string_view branch, const fs::path &to) { - std::vector cmdline = {"git", "clone", "--depth", "1"}; + ulib::list cmdline = {"git", "clone", "--depth", "1"}; if (!branch.empty()) { cmdline.emplace_back("--branch"); - cmdline.emplace_back(branch.data()); + cmdline.emplace_back(branch); } - cmdline.emplace_back(url.data()); + cmdline.emplace_back(url); cmdline.emplace_back(to.u8string()); RunProcessOrThrow("git", {}, cmdline, false, true); diff --git a/buildkit/re/deps/git_dep_resolver.h b/buildkit/re/deps/git_dep_resolver.h index 5ef7116..0a7ea91 100644 --- a/buildkit/re/deps/git_dep_resolver.h +++ b/buildkit/re/deps/git_dep_resolver.h @@ -16,8 +16,8 @@ namespace re {} Target* ResolveTargetDependency(const Target& target, const TargetDependency& dep, DepsVersionCache* cache); - Target* ResolveGitDependency(const Target& target, const TargetDependency& dep, std::string_view url, std::string branch, DepsVersionCache* cache); - void DownloadGitDependency(std::string_view url, std::string_view branch, const fs::path& to); + Target* ResolveGitDependency(const Target& target, const TargetDependency& dep, ulib::string_view url, ulib::string branch, DepsVersionCache* cache); + void DownloadGitDependency(ulib::string_view url, ulib::string_view branch, const fs::path& to); virtual bool SaveDependencyToPath(const TargetDependency& dep, const fs::path& path); diff --git a/buildkit/re/deps/re_package_dep_resolver.cpp b/buildkit/re/deps/re_package_dep_resolver.cpp index 45364d4..9467af4 100644 --- a/buildkit/re/deps/re_package_dep_resolver.cpp +++ b/buildkit/re/deps/re_package_dep_resolver.cpp @@ -53,7 +53,7 @@ namespace re auto &version = package->versions.at(latest_version); - version.link; + version.link; // :) } else { diff --git a/buildkit/re/deps/re_package_dep_resolver.h b/buildkit/re/deps/re_package_dep_resolver.h index dcbad9b..a88cded 100644 --- a/buildkit/re/deps/re_package_dep_resolver.h +++ b/buildkit/re/deps/re_package_dep_resolver.h @@ -13,7 +13,7 @@ namespace re class RePackageDepResolver : public IDepResolver { public: - RePackageDepResolver(ITargetLoader *pLoader, IUserOutput *pOut, const std::string &repo_id, + RePackageDepResolver(ITargetLoader *pLoader, IUserOutput *pOut, ulib::string_view repo_id, RePackageClient &&client) : mLoader{pLoader}, mOut{pOut}, mRepoId{repo_id}, mClient{std::move(client)} { @@ -25,7 +25,7 @@ namespace re ITargetLoader *mLoader; IUserOutput *mOut; - std::string mRepoId; + ulib::string mRepoId; RePackageClient mClient; std::unordered_map> mTargetCache; diff --git a/buildkit/re/deps/target_name_appender.cpp b/buildkit/re/deps/target_name_appender.cpp index 2b8edbb..1d74163 100644 --- a/buildkit/re/deps/target_name_appender.cpp +++ b/buildkit/re/deps/target_name_appender.cpp @@ -2,10 +2,10 @@ namespace re { - void AppendTargetNameSuffix(Target *pTarget, const std::string &suffix) + void AppendTargetNameSuffix(Target *pTarget, ulib::string_view suffix) { pTarget->name += suffix; - pTarget->config["name"] = pTarget->config["name"].Scalar() + suffix; + pTarget->config["name"] = pTarget->config["name"].scalar() + suffix; for (auto &child : pTarget->children) AppendTargetNameSuffix(child.get(), suffix); diff --git a/buildkit/re/deps/target_name_appender.h b/buildkit/re/deps/target_name_appender.h index ad6d016..7fdeb36 100644 --- a/buildkit/re/deps/target_name_appender.h +++ b/buildkit/re/deps/target_name_appender.h @@ -3,5 +3,5 @@ namespace re { - void AppendTargetNameSuffix(Target *pTarget, const std::string &suffix); + void AppendTargetNameSuffix(Target *pTarget, ulib::string_view suffix); } diff --git a/buildkit/re/deps/vcpkg_dep_resolver.cpp b/buildkit/re/deps/vcpkg_dep_resolver.cpp index 2187e4f..2f3e448 100644 --- a/buildkit/re/deps/vcpkg_dep_resolver.cpp +++ b/buildkit/re/deps/vcpkg_dep_resolver.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace re { @@ -118,7 +119,7 @@ namespace re "[{}] Package {} already available\n", target.module, dep_str); } - YAML::Node config{YAML::NodeType::Map}; + ulib::yaml config{ulib::yaml::value_t::map}; if (fs::exists(path / "include")) { @@ -146,7 +147,7 @@ namespace re if (fs::exists(path / "bin")) { - YAML::Node entry{YAML::NodeType::Map}; + ulib::yaml entry{ulib::yaml::value_t::map}; entry["copy-to-deps"]["from"] = (path / "bin").u8string(); entry["copy-to-deps"]["to"] = "."; @@ -157,43 +158,43 @@ namespace re auto package_target = std::make_unique(path.u8string(), "vcpkg." + cache_path, TargetType::StaticLibrary, config); - YAML::Node vcpkg_json = YAML::LoadFile((vcpkg_root / "ports" / dep.name / "vcpkg.json").u8string()); + ulib::yaml vcpkg_json = ulib::yaml::parse(futile::open(vcpkg_root / "ports" / dep.name / "vcpkg.json").read()); - auto append_deps_from = [this, &dep, &target, &package_target, &re_platform, cache](auto json) { - if (auto deps = json["dependencies"]) + auto append_deps_from = [this, &dep, &target, &package_target, &re_platform, cache](ulib::yaml json) { + if (auto deps = json.search("dependencies")) { - for (auto vcdep : deps) + for (auto &vcdep : *deps) { TargetDependency pkg_dep; pkg_dep.ns = "vcpkg-dep"; - if (vcdep.IsMap()) + if (vcdep.is_map()) { - pkg_dep.name = vcdep["name"].Scalar(); - - if (auto ver = vcdep["version"]) - pkg_dep.version = ver.Scalar(); - else if (auto ver = vcdep["version>="]) - pkg_dep.version = ">=" + ver.Scalar(); - else if (auto ver = vcdep["version>"]) - pkg_dep.version = ">" + ver.Scalar(); - else if (auto ver = vcdep["version<="]) - pkg_dep.version = "<=" + ver.Scalar(); - else if (auto ver = vcdep["version<"]) - pkg_dep.version = "<" + ver.Scalar(); - - if (auto platform = vcdep["platform"]) + pkg_dep.name = vcdep["name"].scalar(); + + if (auto ver = vcdep.search("version")) + pkg_dep.version = ver->scalar(); + else if (auto ver = vcdep.search("version>=")) + pkg_dep.version = ulib::string{">="} + ver->scalar(); + else if (auto ver = vcdep.search("version>")) + pkg_dep.version = ulib::string{">"} + ver->scalar(); + else if (auto ver = vcdep.search("version<=")) + pkg_dep.version = ulib::string{"<="} + ver->scalar(); + else if (auto ver = vcdep.search("version<")) + pkg_dep.version = ulib::string{"<"} + ver->scalar(); + + if (auto platform = vcdep.search("platform")) { auto eligible = true; - auto str = platform.Scalar(); + auto str = platform->scalar(); if (str.front() == '!') { - if (re_platform == str.substr(1)) + if (str.substr(1) == re_platform) eligible = false; } - else if (re_platform != str) + else if (str != re_platform) { eligible = false; } @@ -201,14 +202,14 @@ namespace re if (!eligible) { // fmt::print(" ! EVIL dep {} has wrong platform '{}'\n", pkg_dep.name, - // platform.Scalar()); + // platform.scalar()); continue; } } } else { - pkg_dep.name = vcdep.Scalar(); + pkg_dep.name = vcdep.scalar(); } pkg_dep.raw = fmt::format("{}:{}@{}", pkg_dep.ns, pkg_dep.name, pkg_dep.version); @@ -229,10 +230,12 @@ namespace re append_deps_from(vcpkg_json); - for (auto feature : vcpkg_json["default-features"]) - { - append_deps_from(vcpkg_json["features"][feature.Scalar()]); - } + if (auto features = vcpkg_json.search("default-features")) + if (features->is_sequence()) + for (auto feature : *features) + { + append_deps_from(vcpkg_json["features"][feature.scalar()]); + } package_target->root_path = target.root_path; @@ -244,7 +247,7 @@ namespace re package_target->config["platform"] = re_platform; package_target->config["configuration"] = re_config; - if (dep.extra_config) + if (!dep.extra_config.is_null()) MergeYamlNode(package_target->config, dep.extra_config); package_target->resolved_config = package_target->config; @@ -275,21 +278,16 @@ namespace re bool VcpkgDepResolver::SaveDependencyToPath(const TargetDependency &dep, const fs::path &path) { - YAML::Node config; + ulib::yaml config; config["type"] = "project"; config["name"] = dep.name; - config["deps"] = YAML::Node{YAML::NodeType::Sequence}; + config["deps"] = ulib::yaml{ulib::yaml::value_t::sequence}; config["deps"].push_back(dep.ToString()); - YAML::Emitter emitter; - emitter << config; - fs::create_directories(path); - - std::ofstream of{path / "re.yml"}; - of << emitter.c_str(); + futile::open(path / "re.yml", "w").write(config.dump()); return true; } diff --git a/buildkit/re/deps_version_cache.cpp b/buildkit/re/deps_version_cache.cpp index 7a9ff87..eec636c 100644 --- a/buildkit/re/deps_version_cache.cpp +++ b/buildkit/re/deps_version_cache.cpp @@ -2,14 +2,14 @@ namespace re { - std::string DepsVersionCache::GetLatestVersionMatchingRequirements( - const Target &target, const TargetDependency &dep, std::string_view name, - std::function(const re::TargetDependency &, std::string_view)> get_available_versions) + ulib::string DepsVersionCache::GetLatestVersionMatchingRequirements( + const Target &target, const TargetDependency &dep, ulib::string_view name, + std::function(const re::TargetDependency &, const std::string&)> get_available_versions) { if (dep.version_kind == DependencyVersionKind::RawTag) return dep.version; - std::string kind_str = "@"; + ulib::string kind_str = "@"; switch (dep.version_kind) { @@ -36,7 +36,7 @@ namespace re break; }; - auto existing_key = fmt::format("{}:{}{}{}", dep.ns, dep.name, kind_str, dep.version); + auto existing_key = ulib::format("{}:{}{}{}", dep.ns, dep.name, kind_str, dep.version); auto &existing = mData[existing_key]; @@ -53,7 +53,7 @@ namespace re [&pred, &value](const auto &x) { try { - return !(pred(semverpp::version{x}, value)); + return !(pred(semverpp::version{std::string(x)}, value)); } catch (semverpp::invalid_version) { @@ -114,7 +114,7 @@ namespace re fmt::print("\n # result: {} -> [\n", dep.raw); for (auto &ver : available) - fmt::print(" {} @ {}\n", ver, semverpp::version{ver}.string()); + fmt::print(" {} @ {}\n", ver, semverpp::version{std::string(ver)}.string()); fmt::print("]\n"); diff --git a/buildkit/re/deps_version_cache.h b/buildkit/re/deps_version_cache.h index 51cbab8..0426ce2 100644 --- a/buildkit/re/deps_version_cache.h +++ b/buildkit/re/deps_version_cache.h @@ -55,11 +55,11 @@ namespace re * * @return std::string The most recent version that matches the specified requirements */ - std::string GetLatestVersionMatchingRequirements( + ulib::string GetLatestVersionMatchingRequirements( const Target& target, const TargetDependency& dep, - std::string_view name, - std::function(const re::TargetDependency&, std::string_view)> get_available_versions + ulib::string_view name, + std::function(const re::TargetDependency &, const std::string&)> get_available_versions ); /** diff --git a/buildkit/re/error.h b/buildkit/re/error.h index b7d8873..b11ca98 100644 --- a/buildkit/re/error.h +++ b/buildkit/re/error.h @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -77,7 +77,7 @@ namespace re */ template Exception(const F &format, Args &&...args) - : std::runtime_error{fmt::format(format, std::forward(args)...)} + : std::runtime_error{ulib::format(format, std::forward(args)...)} { } }; diff --git a/buildkit/re/lang_locator.h b/buildkit/re/lang_locator.h index 7f4816f..3de4da4 100644 --- a/buildkit/re/lang_locator.h +++ b/buildkit/re/lang_locator.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include "lang_provider.h" namespace re @@ -9,6 +9,6 @@ namespace re public: virtual ~ILangLocator() = default; - virtual ILangProvider* GetLangProvider(std::string_view name) = 0; + virtual ILangProvider* GetLangProvider(ulib::string_view name) = 0; }; } diff --git a/buildkit/re/langs/cmake/cmake_lang_provider.cpp b/buildkit/re/langs/cmake/cmake_lang_provider.cpp index a74a443..8d57146 100644 --- a/buildkit/re/langs/cmake/cmake_lang_provider.cpp +++ b/buildkit/re/langs/cmake/cmake_lang_provider.cpp @@ -22,9 +22,19 @@ namespace re auto &target_vars = target.target_var_scope.emplace(&target.local_var_ctx, "target", &target); auto &vars = target.build_var_scope.emplace(&target.local_var_ctx, "build", &target_vars); - vars.SetVar("arch", target.config["arch"].Scalar()); - vars.SetVar("configuration", target.config["configuration"].Scalar()); - vars.SetVar("platform", target.config["platform"].Scalar()); + auto set_config_var_or_null = [&](ulib::string_view key) { + if (auto arch = target.config.search(key)) + { + if (arch->is_scalar()) + vars.SetVar(key, arch->scalar()); + else + vars.SetVar(key, ""); + } + }; + + set_config_var_or_null("arch"); + set_config_var_or_null("configuration"); + set_config_var_or_null("platform"); std::unordered_map configuration = { {"arch", vars.ResolveLocal("arch")}, @@ -37,15 +47,16 @@ namespace re bool CMakeLangProvider::InitBuildTargetRules(NinjaBuildDesc &desc, const Target &target) { - if (auto build_script = target.resolved_config["cmake-out-build-script"]) + if (auto build_script = target.resolved_config.search("cmake-out-build-script")) { - if (std::find(desc.subninjas.begin(), desc.subninjas.end(), build_script.Scalar()) == desc.subninjas.end()) - desc.subninjas.push_back(build_script.Scalar()); + if (std::find(desc.subninjas.begin(), desc.subninjas.end(), std::string{build_script->scalar()}) == + desc.subninjas.end()) + desc.subninjas.push_back(build_script->scalar()); } - if (auto cmake_meta = target.resolved_config["cmake-meta"]["targets"][target.name]) - if (auto location = cmake_meta["location"]) - desc.artifacts[&target] = location.Scalar(); + if (auto cmake_meta = target.resolved_config["cmake-meta"]["targets"].search(target.name)) + if (auto location = cmake_meta->search("location")) + desc.artifacts[&target] = location->scalar(); return true; } diff --git a/buildkit/re/langs/cmake/cmake_target_load_middleware.cpp b/buildkit/re/langs/cmake/cmake_target_load_middleware.cpp index 8fd96da..3048bc0 100644 --- a/buildkit/re/langs/cmake/cmake_target_load_middleware.cpp +++ b/buildkit/re/langs/cmake/cmake_target_load_middleware.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace re { @@ -55,11 +56,11 @@ namespace re if (auto flags = scope.GetVar("platform-link-paths")) link_flags += scope.Resolve(*flags); - if (auto standard = ancestor->resolved_config["cxx-standard"]) - cxx_std_override = standard.Scalar(); + if (auto standard = ancestor->resolved_config.search("cxx-standard")) + cxx_std_override = standard->scalar(); - if (auto build_type = ancestor->resolved_config["cmake-build-type"]) - config = build_type.Scalar(); + if (auto build_type = ancestor->resolved_config.search("cmake-build-type")) + config = build_type->scalar(); } // HACK: PLEASE add something better later @@ -80,17 +81,16 @@ namespace re if (ancestor && ancestor->build_var_scope->GetVar("cmake-reconfigure").value_or("false") == "true") should_rebuild = true; - YAML::Node cmake_meta{YAML::NodeType::Undefined}; + ulib::yaml cmake_meta{ulib::yaml::value_t::null}; if (fs::exists(meta_path)) { - std::ifstream file{meta_path}; - cmake_meta = YAML::Load(file); + cmake_meta = ulib::yaml::parse(futile::open(meta_path).read()); should_rebuild = false; if (!should_rebuild && dep_source && - cmake_meta["last-build-ecfg-hash"].as() != dep_source->extra_config_data_hash) + cmake_meta["last-build-ecfg-hash"].get() != dep_source->extra_config_data_hash) should_rebuild = true; } @@ -98,24 +98,24 @@ namespace re { mOut->Info(fg(fmt::color::dim_gray) | fmt::emphasis::bold, " Rebuilding CMake cache...\n\n"); - std::vector cmdline = {"cmake", "-G", "Ninja"}; + ulib::list cmdline = {"cmake", "-G", "Ninja"}; cmdline.emplace_back("-DRE_ORIGINAL_CMAKE_DIR=" + canonical_path.generic_u8string()); cmdline.emplace_back("-DRE_BIN_OUT_DIR=" + bin_dir.generic_u8string()); cmdline.emplace_back("-DRE_ADAPTED_META_FILE=" + meta_path.generic_u8string()); cmdline.emplace_back("-DCMAKE_BUILD_TYPE=" + config); - if (dep_source && dep_source->extra_config) + if (dep_source && !dep_source->extra_config.is_null()) { - auto parse_config_for_target = [&cmdline, &arch, &platform, - &config](YAML::Node node, const std::vector &targets) { + auto parse_config_for_target = [&cmdline, &arch, &platform, &config]( + const ulib::yaml &node, const ulib::list &targets) { std::string defs_private, defs_public; - for (auto kv : node["cxx-compile-definitions"]) - defs_private.append(fmt::format("{}={};", kv.first.Scalar(), kv.second.Scalar())); + for (auto &kv : node["cxx-compile-definitions"].items()) + defs_private.append(fmt::format("{}={};", kv.name(), kv.value().scalar())); - for (auto kv : node["cxx-compile-definitions-public"]) - defs_public.append(fmt::format("{}={};", kv.first.Scalar(), kv.second.Scalar())); + for (auto &kv : node["cxx-compile-definitions-public"].items()) + defs_public.append(fmt::format("{}={};", kv.name(), kv.value().scalar())); for (auto &target : targets) { @@ -125,8 +125,8 @@ namespace re fmt::format("-DRE_CUSTOM_COMPILE_DEFINITIONS_PUBLIC_{}={}", target, defs_public)); } - for (auto kv : node["cmake-extra-options"]) - cmdline.emplace_back(fmt::format("-D{}={}", kv.first.Scalar(), kv.second.Scalar())); + for (auto kv : node["cmake-extra-options"].items()) + cmdline.emplace_back(fmt::format("-D{}={}", kv.name(), kv.value().scalar())); }; auto resolved = GetFlatResolvedTargetCfg(dep_source->extra_config, @@ -137,12 +137,12 @@ namespace re else parse_config_for_target(resolved, dep_source->filters); - for (auto kv : resolved) + for (auto &kv : resolved.items()) { constexpr auto kCMakeTargetPrefix = "cmake-target."; - if (kv.first.Scalar().find(kCMakeTargetPrefix) == 0) - parse_config_for_target(kv.second, {kv.first.Scalar().substr(sizeof kCMakeTargetPrefix)}); + if (kv.name().find(kCMakeTargetPrefix) == 0) + parse_config_for_target(kv.value(), {kv.name().substr(sizeof kCMakeTargetPrefix)}); } } @@ -177,9 +177,9 @@ namespace re } std::ifstream file{meta_path}; - cmake_meta = YAML::Load(file); + cmake_meta = ulib::yaml::parse(futile::open(meta_path).read()); - TargetConfig target_config{YAML::NodeType::Map}; + TargetConfig target_config{ulib::yaml::value_t::map}; target_config["arch"] = arch; target_config["configuration"] = config; @@ -198,13 +198,13 @@ namespace re target->name = target->module = fmt::format("cmake.{}.{}", path_hash, canonical_path.filename().generic_u8string()); - for (auto kv : cmake_meta["targets"]) + for (auto &kv : cmake_meta["targets"].items()) { - TargetConfig child_config{YAML::NodeType::Map}; + TargetConfig child_config{ulib::yaml::value_t::map}; TargetType type = TargetType::Custom; - auto cmake_type = kv.second["cmake-type"].Scalar(); + auto cmake_type = kv.value()["cmake-type"].scalar(); if (cmake_type == "STATIC_LIBRARY" || cmake_type == "INTERFACE_LIBRARY") type = TargetType::StaticLibrary; @@ -215,43 +215,50 @@ namespace re else continue; - if (auto location = kv.second["location"]) - child_config["cxx-link-deps"].push_back(location.Scalar()); + if (auto location = kv.value().search("location")) + child_config["cxx-link-deps"].push_back(location->scalar()); - for (auto dir : kv.second["include-dirs"]) + for (auto dir : kv.value()["include-dirs"]) { - auto s = dir.Scalar(); + if (dir.is_scalar()) + { + auto s = dir.scalar(); - if (!s.empty()) - child_config["cxx-include-dirs"].push_back(s); + if (!s.empty()) + child_config["cxx-include-dirs"].push_back(s); + } } - auto child = std::make_unique(path, kv.first.Scalar(), type, child_config); + auto child = std::make_unique(path, kv.name(), type, child_config); child->parent = target.get(); target->children.emplace_back(std::move(child)); } - for (auto kv : cmake_meta["targets"]) + for (auto kv : cmake_meta["targets"].items()) { - if (auto child = target->FindChild(kv.first.Scalar())) + if (auto child = target->FindChild(kv.name())) { - for (auto dep_str : kv.second["cmake-deps"]) + if (auto cmake_deps = kv.value().search("cmake-deps")) { - if (dep_str.Scalar().empty() || dep_str.Scalar().find('-') == 0) - continue; - - if (auto target_dep = target->FindChild(dep_str.Scalar())) - { - auto dependency = ParseTargetDependency("cmake-ref:" + dep_str.Scalar()); - dependency.resolved = {target_dep}; - child->dependencies.emplace_back(dependency); - } - else + for (auto dep_str : *cmake_deps) { - mOut->Warn(fg(fmt::color::dim_gray) | fmt::emphasis::bold, - " ! CMakeTargetLoadMiddleware: Target '{}' has unknown CMake dependency '{}' - this " - "may or may not be an error\n", - child->name, dep_str.Scalar()); + if (dep_str.scalar().empty() || dep_str.scalar().find('-') == 0) + continue; + + if (auto target_dep = target->FindChild(dep_str.scalar())) + { + auto dependency = ParseTargetDependency(ulib::string_view{"cmake-ref:"} + dep_str.scalar()); + dependency.resolved = {target_dep}; + child->dependencies.emplace_back(dependency); + } + else + { + mOut->Warn( + fg(fmt::color::dim_gray) | fmt::emphasis::bold, + " ! CMakeTargetLoadMiddleware: Target '{}' has unknown CMake dependency '{}' - this " + "may or may not be an error\n", + child->name, dep_str.scalar()); + } } } } diff --git a/buildkit/re/langs/cxx/cxx_lang_provider.cpp b/buildkit/re/langs/cxx/cxx_lang_provider.cpp index 4acb632..1b424f7 100644 --- a/buildkit/re/langs/cxx/cxx_lang_provider.cpp +++ b/buildkit/re/langs/cxx/cxx_lang_provider.cpp @@ -6,9 +6,11 @@ #include #include -#include - #include +#include +#include +#include +#include namespace re { @@ -16,7 +18,7 @@ namespace re { inline TargetConfig GetRecursiveMapCfg(const Target &leaf, std::string_view key) { - auto result = TargetConfig{YAML::NodeType::Map}; + auto result = TargetConfig{ulib::yaml::value_t::map}; auto p = &leaf; while (p) @@ -32,7 +34,7 @@ namespace re inline TargetConfig GetRecursiveSeqCfg(const Target &leaf, std::string_view key) { - auto result = TargetConfig{YAML::NodeType::Sequence}; + auto result = TargetConfig{ulib::yaml::value_t::sequence}; auto p = &leaf; while (p) @@ -49,45 +51,44 @@ namespace re inline void AppendIncludeDirs(const Target &target, const TargetConfig &cfg, std::unordered_set &dirs, const LocalVarScope &vars) { - if (target.type != TargetType::Project && !cfg["no-auto-include-dirs"]) + if (target.type != TargetType::Project && !cfg.search("no-auto-include-dirs")) { - auto root_path = cfg["cxx-root-include-path"].Scalar(); + auto root_path = cfg["cxx-root-include-path"].scalar(); // fmt::print("AppendIncludeDirs: {} => root: {}\n", target.module, root_path); dirs.insert(root_path); } - auto extra_includes = cfg["cxx-include-dirs"]; - - for (const auto &v : extra_includes) - { - const auto &v_s = v.Scalar(); + if (auto extra_includes = cfg.search("cxx-include-dirs")) + if (extra_includes->is_sequence()) + for (const auto &v : *extra_includes) + { + const auto &v_s = v.scalar(); - auto dir = fs::path{vars.Resolve(v_s)}; + auto dir = fs::path{vars.Resolve(v_s)}; - if (!dir.is_absolute()) - dir = target.path / dir; + if (!dir.is_absolute()) + dir = target.path / dir; - dirs.insert(dir.u8string()); - } + dirs.insert(dir.u8string()); + } } inline void AppendLinkFlags(const Target &target, const TargetConfig &cfg, const std::string &cxx_lib_dir_tpl, std::vector &out_flags, std::vector &out_deps, const LocalVarScope &vars) { - auto link_lib_dirs = cfg["cxx-lib-dirs"]; - - for (const auto &dir : link_lib_dirs) - { - auto formatted = vars.Resolve(dir.as()); - - out_flags.push_back(fmt::format(cxx_lib_dir_tpl, fmt::arg("directory", formatted))); - } - - auto extra_link_deps = cfg["cxx-link-deps"]; + auto link_lib_dirs = cfg.search("cxx-lib-dirs"); + if (link_lib_dirs && link_lib_dirs->is_sequence()) + for (const auto &dir : *link_lib_dirs) + { + auto formatted = vars.Resolve(dir.scalar()); + out_flags.push_back(fmt::format(cxx_lib_dir_tpl, fmt::arg("directory", formatted))); + } - for (const auto &dep : extra_link_deps) - out_deps.push_back(fmt::format("\"{}\"", vars.Resolve(dep.as()))); + auto extra_link_deps = cfg.search("cxx-link-deps"); + if (extra_link_deps && extra_link_deps->is_sequence()) + for (const auto &dep : *extra_link_deps) + out_deps.push_back(fmt::format("\"{}\"", vars.Resolve(dep.scalar()))); } } // namespace @@ -120,12 +121,12 @@ namespace re // Choose and load the correct build environment. - auto env_cfg = target.resolved_config["cxx-env"]; + auto env_cfg = target.resolved_config.search("cxx-env"); if (!env_cfg) RE_THROW TargetLoadException(&target, "C++ environment type not specified anywhere in the target tree"); auto &env_cached_name = desc.state["re_cxx_env_for_" + path]; - env_cached_name = vars.Resolve(env_cfg.Scalar()); + env_cached_name = vars.Resolve(env_cfg->scalar()); ///////////////////////////////////////////////////////////////// @@ -134,11 +135,11 @@ namespace re // CxxBuildEnvData &env = LoadEnvOrThrow(env_cached_name, target); - if (auto vars_cfg = env["vars"]) - for (const auto &kv : vars_cfg) + if (auto vars_cfg = env.search("vars")) + for (const auto &kv : vars_cfg->items()) { - auto key = kv.first.as(); - auto value = kv.second.as(); + auto key = kv.name(); + auto value = kv.value().scalar(); vars.SetVar(key, value); @@ -149,8 +150,8 @@ namespace re */ } - for (const auto &kv : env["default-flags"]) - vars.SetVar("platform-default-flags-" + kv.first.Scalar(), vars.Resolve(kv.second.Scalar())); + for (const auto &kv : env["default-flags"].items()) + vars.SetVar(ulib::string{"platform-default-flags-"} + kv.name(), vars.Resolve(kv.value().scalar())); cond_desc["arch"] = vars.ResolveLocal("arch"); cond_desc["runtime"] = vars.ResolveLocal("runtime"); @@ -169,19 +170,21 @@ namespace re vars.SetVar("target-root", vars.GetVar("root-dir").value()); vars.SetVar("build-root", desc.pRootTarget->path.u8string()); - for (auto with : target.resolved_config["with"]) + if (auto withs_ref = target.resolved_config.search("with")) { - fs::path path = vars.Resolve(with.Scalar()); - - if (!path.is_absolute()) - path = target.path / path; + auto withs = *withs_ref; + for (auto &with : withs) + { + fs::path path = vars.Resolve(with.scalar()); - std::ifstream file{path}; + if (!path.is_absolute()) + path = target.path / path; - auto config = YAML::Load(file); + auto config = ulib::yaml::parse(futile::open(path).read()); - MergeYamlNode(target.config, config); - target.resolved_config = GetResolvedTargetCfg(target, cond_desc); + MergeYamlNode(target.config, config); + target.resolved_config = GetResolvedTargetCfg(target, cond_desc); + } } auto &meta = desc.meta["targets"][target.path.u8string()]; @@ -200,8 +203,9 @@ namespace re std::string extension = ""; - if (auto out_ext = target.resolved_config["out-ext"]) - extension = out_ext.Scalar(); + if (auto out_ext = target.resolved_config.search("out-ext")) + if (out_ext->is_scalar()) + extension = out_ext->scalar(); if (!extension.empty()) { @@ -215,15 +219,15 @@ namespace re target.resolved_config["cxx-root-include-path"] = target.path.u8string(); // Forward the C++ build tools definitions to the build system - for (const auto &kv : env["tools"]) + for (const auto &kv : env["tools"].items()) { - auto name = kv.first.Scalar(); - auto tool_path = vars.Resolve(kv.second.Scalar()); + auto name = kv.name(); + auto tool_path = vars.Resolve(kv.value().scalar()); - desc.tools.push_back(BuildTool{"cxx_" + name + "_" + path, tool_path}); + desc.tools.push_back(BuildTool{ulib::string{"cxx_"} + name + "_" + path, tool_path}); meta["tools"][name] = tool_path; - vars.SetVar("cxx.tool." + name, tool_path); + vars.SetVar(ulib::string{"cxx.tool."} + name, tool_path); } } @@ -242,8 +246,7 @@ namespace re // fmt::print(" *** '{}' -> {}={}\n", target.module, k, v); auto &config = target.resolved_config; - - if (!config["enabled"].as()) + if (!config["enabled"].get()) return false; auto &meta = desc.meta["targets"][target.path.u8string()]["cxx"]; @@ -251,10 +254,15 @@ namespace re TargetConfig definitions = config["cxx-compile-definitions"]; TargetConfig definitions_pub = config["cxx-compile-definitions-public"]; + if (!definitions.is_map()) + definitions = TargetConfig{ulib::yaml::value_t::map}; + if (!definitions_pub.is_map()) + definitions_pub = TargetConfig{ulib::yaml::value_t::map}; + // Make the local definitions supersede all platform ones - for (const auto &def : env["platform-definitions"]) - if (!definitions[def.first]) - definitions[def.first] = def.second; + for (const auto &def : env["platform-definitions"].items()) + if (!definitions.search(def.name())) + definitions[def.name()] = def.value(); std::vector include_deps; PopulateTargetDependencySetNoResolve(&target, include_deps); @@ -267,23 +275,23 @@ namespace re std::vector extra_flags; - std::string cpp_std = config["cxx-standard"].Scalar(); + std::string cpp_std = config["cxx-standard"].scalar(); if (cpp_std == "20" && env_name == "gcc") // HACK cpp_std = "2a"; meta["standard"] = "c++" + cpp_std; - extra_flags.push_back(fmt::format(templates["cxx-module-output"].as(), - fmt::arg("directory", fmt::format("$re_target_object_directory_{}", path)))); + extra_flags.push_back(ulib::format(templates["cxx-module-output"].scalar(), + fmt::arg("directory", fmt::format("$re_target_object_directory_{}", path)))); - auto cxx_include_dir = templates["cxx-include-dir"].as(); - auto cxx_module_lookup_dir = templates["cxx-module-lookup-dir"].as(); + auto cxx_include_dir = templates["cxx-include-dir"].scalar(); + auto cxx_module_lookup_dir = templates["cxx-module-lookup-dir"].scalar(); std::vector deps_list; std::vector extra_link_flags; - auto cxx_lib_dir = templates["cxx-lib-dir"].as(); + auto cxx_lib_dir = templates["cxx-lib-dir"].scalar(); std::unordered_set include_dirs; @@ -293,28 +301,32 @@ namespace re { auto &config = target->resolved_config; - if (!config) + if (!config.is_map()) { // fmt::print(" Target '{}' does not have a resolved config.\n", target->module); continue; } - auto dependency_defines = config["cxx-compile-definitions-public"]; + // auto &dependency_defines = config["cxx-compile-definitions-public"]; - for (const std::pair &kv : dependency_defines) + if (auto dependency_defines = config.search("cxx-compile-definitions-public")) { - auto name = kv.first.as(); - auto value = kv.second.as(); + if (dependency_defines->is_map()) + for (const auto &kv : dependency_defines->items()) + { + auto name = kv.name(); + auto value = kv.value().scalar(); - if (!definitions_pub[name]) - definitions_pub[name] = value; + if (!definitions_pub.search(name)) + definitions_pub[name] = value; + } } AppendIncludeDirs(*target, config, include_dirs, vars); // TODO: Make this only work with modules enabled??? - extra_flags.push_back( - fmt::format(cxx_module_lookup_dir, fmt::arg("directory", fmt::format("$builddir/{}", target->module)))); + extra_flags.push_back(ulib::format(cxx_module_lookup_dir, + fmt::arg("directory", fmt::format("$builddir/{}", target->module)))); // Link stuff @@ -332,106 +344,128 @@ namespace re AppendLinkFlags(*target, config, cxx_lib_dir, extra_link_flags, deps_list, dep_vars); - for (const auto &dep : config["cxx-global-link-deps"]) - global_link_deps.push_back(fmt::format("-l{}", vars.Resolve(dep.as()))); + if (auto deps = config.search("cxx-global-link-deps")) + if (deps->is_sequence()) + for (const auto &dep : *deps) + global_link_deps.push_back(fmt::format("-l{}", vars.Resolve(dep.scalar()))); } - auto parse_build_flags = [&extra_flags, &extra_link_flags, &vars, &target](auto extra) { + auto parse_build_flags = [&extra_flags, &extra_link_flags, &vars, &target](ulib::yaml extra) { constexpr auto kCompiler = "compiler"; constexpr auto kLinker = "linker"; constexpr auto kLinkerNoStatic = "linker.nostatic"; - if (auto flags = extra[kCompiler]) + if (extra.is_map()) { - if (flags.IsScalar()) - extra_flags.push_back(vars.Resolve(flags.Scalar())); - else - for (const auto &flag : flags) - extra_flags.push_back(vars.Resolve(flag.Scalar())); - } - - if (auto flags = extra[kLinker]) - { - if (flags.IsScalar()) - extra_link_flags.push_back(vars.Resolve(flags.Scalar())); - else - for (const auto &flag : flags) - extra_link_flags.push_back(vars.Resolve(flag.Scalar())); - } + if (auto flags = extra.search(kCompiler)) + { + if (flags->is_scalar()) + extra_flags.push_back(vars.Resolve(flags->scalar())); + else + for (const auto &flag : *flags) + extra_flags.push_back(vars.Resolve(flag.scalar())); + } - if (target.type != TargetType::StaticLibrary) - { - if (auto flags = extra[kLinkerNoStatic]) + if (auto flags = extra.search(kLinker)) { - if (flags.IsScalar()) - extra_link_flags.push_back(vars.Resolve(flags.Scalar())); + if (flags->is_scalar()) + extra_link_flags.push_back(vars.Resolve(flags->scalar())); else - for (const auto &flag : flags) - extra_link_flags.push_back(vars.Resolve(flag.Scalar())); + for (const auto &flag : *flags) + extra_link_flags.push_back(vars.Resolve(flag.scalar())); + } + + if (target.type != TargetType::StaticLibrary) + { + if (auto flags = extra.search(kLinkerNoStatic)) + { + if (flags->is_scalar()) + extra_link_flags.push_back(vars.Resolve(flags->scalar())); + else + for (const auto &flag : *flags) + extra_link_flags.push_back(vars.Resolve(flag.scalar())); + } } } }; - YAML::Node extra_build_flags{YAML::NodeType::Map}; + ulib::yaml extra_build_flags{ulib::yaml::value_t::map}; - if (const auto &extra = config["cxx-build-flags"]) - MergeYamlNode(extra_build_flags, extra); + if (const auto extra = config.search("cxx-build-flags")) + MergeYamlNode(extra_build_flags, *extra); - if (const auto &opts = config["cxx-build-options"]) + if (const auto opts = config.search("cxx-build-options")) { - for (auto kv : opts) - { - if (kv.second.IsNull()) - continue; + // if (opts->is_null()) + // extra_build_flags = ulib::yaml{ulib::yaml::value_t::null}; - if (auto def = env["build-options"][kv.first.Scalar()]) + if (opts->is_map()) + { + for (auto &kv : opts->items()) { - if (def.IsMap()) + if (kv.value().is_null()) + continue; + + if (auto def = env["build-options"].search(kv.name())) { - if (auto value = def[kv.second.Scalar()]) - { - MergeYamlNode(extra_build_flags, value); - } - else if (auto value = def["$value"]) + if (def->is_map()) { - // HACK: Format the value argument + if (auto value = def->search(kv.value().scalar())) + { + MergeYamlNode(extra_build_flags, *value); + } + else if (auto value = def->search("$value")) + { + // HACK: Format the value argument - auto cloned = YAML::Clone(value); + auto cloned = *value; - for (auto def_kv : cloned) - { - if (def_kv.second.IsSequence()) - { - for (auto v : def_kv.second) - (YAML::Node) v = fmt::format(v.Scalar(), fmt::arg("value", kv.second.Scalar())); - } - else + for (auto &def_kv : cloned.items()) { - def_kv.second = - fmt::format(def_kv.second.Scalar(), fmt::arg("value", kv.second.Scalar())); + if (def_kv.value().is_sequence()) + { + for (auto &v : def_kv.value()) + v = fmt::format(std::string{v.scalar()}, + fmt::arg("value", kv.value().scalar())); + } + else + { + def_kv.value() = fmt::format(std::string{def_kv.value().scalar()}, + fmt::arg("value", kv.value().scalar())); + } } - } - MergeYamlNode(extra_build_flags, cloned); - } - else if (auto default_option = def["default"]) - { - MergeYamlNode(extra_build_flags, default_option); - } - else - { - RE_THROW TargetConfigException(&target, "Unknown build option value '{}' = {}", - kv.first.Scalar(), kv.second.Scalar()); + MergeYamlNode(extra_build_flags, cloned); + } + else if (auto default_option = def->search("default")) + { + MergeYamlNode(extra_build_flags, *default_option); + } + else + { + RE_THROW TargetConfigException(&target, "Unknown build option value '{}' = {}", + kv.name(), kv.value().scalar()); + } } } - } - else - { - RE_THROW TargetConfigException(&target, "Unknown build option '{}'", kv.first.Scalar()); + else + { + RE_THROW TargetConfigException(&target, "Unknown build option '{}'", kv.name()); + } } } + + // if (opts->is_null()) + // extra_build_flags = *opts; } + // ulib::list list{extra_flags.begin(), extra_flags.end()}; + // fmt::print("ky\n"); + + // fmt::print("extra flags: {}\n", ulib::join(extra_flags, ", ")); + // fmt::print("extra build flags: {}\n", extra_build_flags.dump()); + // fmt::print("config: {}\n", config.dump()); + parse_build_flags(extra_build_flags); // YAML::Emitter em; @@ -439,41 +473,41 @@ namespace re // fmt::print("{}\n", em.c_str()); for (auto &dir : include_dirs) - extra_flags.push_back(fmt::format(cxx_include_dir, fmt::arg("directory", dir))); + extra_flags.push_back(ulib::format(cxx_include_dir, fmt::arg("directory", dir))); meta["include_dirs"] = include_dirs; - for (const std::pair &kv : definitions_pub) + for (const auto &kv : definitions_pub.items()) { - auto name = kv.first.as(); - auto value = kv.second.as(); + auto name = kv.name(); + auto value = kv.value().scalar(); - if (!definitions[name]) + if (!definitions.search(name)) definitions[name] = value; } ///////////////////////////////////////////////////////////////// - auto cxx_compile_definition = templates["cxx-compile-definition"].as(); - auto cxx_compile_definition_no_value = templates["cxx-compile-definition-no-value"].as(); + auto cxx_compile_definition = templates["cxx-compile-definition"].scalar(); + auto cxx_compile_definition_no_value = templates["cxx-compile-definition-no-value"].scalar(); - for (const auto &kv : definitions) + for (const auto &kv : definitions.items()) { - auto name = vars.Resolve(kv.first.Scalar()); + auto name = vars.Resolve(kv.name()); - if (kv.second.IsScalar()) + if (kv.value().is_scalar()) { - auto value = vars.Resolve(kv.second.Scalar()); + auto value = vars.Resolve(kv.value().scalar()); extra_flags.push_back( - fmt::format(cxx_compile_definition, fmt::arg("name", name), fmt::arg("value", value))); + ulib::format(cxx_compile_definition, fmt::arg("name", name), fmt::arg("value", value))); meta["definitions"].push_back(name + "=" + value); } else { extra_flags.push_back( - fmt::format(cxx_compile_definition_no_value, fmt::arg("name", vars.Resolve(name)))); + ulib::format(cxx_compile_definition_no_value, fmt::arg("name", vars.Resolve(name)))); meta["definitions"].push_back(name); } @@ -491,7 +525,7 @@ namespace re // Create build rules - auto use_rspfiles = env["use-rspfiles"].as(); + auto use_rspfiles = env["use-rspfiles"].get(); BuildRule rule_cxx; @@ -499,7 +533,7 @@ namespace re rule_cxx.tool = "cxx_compiler_" + path; rule_cxx.cmdline = - fmt::format(vars.Resolve(templates["compiler-cmdline"].as()), fmt::arg("flags", flags_base), + fmt::format(vars.Resolve(templates["compiler-cmdline"].scalar()).c_str(), fmt::arg("flags", flags_base), fmt::arg("input", "$in"), fmt::arg("output", "$out")); if (use_rspfiles) @@ -511,9 +545,9 @@ namespace re rule_cxx.description = "Building C++ source $in"; - if (auto rule_vars = env["custom-rule-vars"]) - for (const auto &var : rule_vars) - rule_cxx.vars[var.first.as()] = vars.Resolve(var.second.as()); + if (auto rule_vars = env.search("custom-rule-vars")) + for (const auto &var : rule_vars->items()) + rule_cxx.vars[var.name()] = vars.Resolve(var.value().scalar()); std::string extra_link_flags_str = ""; @@ -545,7 +579,7 @@ namespace re rule_link.tool = "cxx_linker_" + path; rule_link.cmdline = fmt::format( - vars.Resolve(templates["linker-cmdline"].as()), + vars.Resolve(templates["linker-cmdline"].scalar()).c_str(), fmt::arg("flags", "$target_custom_flags " + extra_link_flags_str), fmt::arg("link_deps", deps_input), fmt::arg("global_link_deps", global_deps_input), fmt::arg("input", "$in"), fmt::arg("output", "$out")); @@ -564,7 +598,7 @@ namespace re rule_lib.tool = "cxx_archiver_" + path; rule_lib.cmdline = fmt::format( - vars.Resolve(templates["archiver-cmdline"].as()), + vars.Resolve(templates["archiver-cmdline"].scalar()).c_str(), fmt::arg("flags", "$target_custom_flags " + extra_link_flags_str), fmt::arg("link_deps", deps_input), fmt::arg("global_link_deps", global_deps_input), fmt::arg("input", "$in"), fmt::arg("output", "$out")); @@ -597,13 +631,17 @@ namespace re bool eligible = false; - for (const auto &ext : env["supported-extensions"]) - if (file.extension == ext.as()) - eligible = true; + if (auto exts = env.search("supported-extensions")) + if (exts->is_sequence()) + for (const auto &ext : *exts) + if (ext.scalar() == file.extension) + eligible = true; - for (const auto &ext : target.resolved_config["cxx-supported-extensions"]) - if (file.extension == ext.as()) - eligible = true; + if (auto exts = env.search("cxx-supported-extensions")) + if (exts->is_sequence()) + for (const auto &ext : *exts) + if (ext.scalar() == file.extension) + eligible = true; if (!eligible) return; @@ -617,7 +655,7 @@ namespace re auto local_path = fs::relative(file.path, target.path).generic_u8string(); - auto extension = env["default-extensions"]["object"].as(); + auto extension = env["default-extensions"]["object"].scalar(); BuildTarget build_target; @@ -633,22 +671,21 @@ namespace re if (file.extension == "c") { - build_target.vars["target_custom_flags"].append(env["templates"]["compile-as-c"].Scalar()); + build_target.vars["target_custom_flags"].append(env["templates"]["compile-as-c"].scalar()); - std::string c_std = target.resolved_config["c-standard"].Scalar(); + std::string c_std = target.resolved_config["c-standard"].scalar(); - auto c_std_flag = fmt::format(env["templates"]["c-standard"].as(), fmt::arg("version", c_std)); - build_target.vars["target_custom_flags"].append(" " + c_std_flag); + auto c_std_flag = ulib::format(env["templates"]["c-standard"].scalar(), fmt::arg("version", c_std)); + build_target.vars["target_custom_flags"].append(ulib::string{" "} + c_std_flag); } else { - std::string cpp_std = target.resolved_config["cxx-standard"].Scalar(); + std::string cpp_std = target.resolved_config["cxx-standard"].scalar(); - auto cpp_std_flag = - fmt::format(env["templates"]["cxx-standard"].as(), fmt::arg("version", cpp_std)); - build_target.vars["target_custom_flags"].append(" " + cpp_std_flag); + auto cpp_std_flag = ulib::format(env["templates"]["cxx-standard"].scalar(), fmt::arg("version", cpp_std)); + build_target.vars["target_custom_flags"].append(ulib::string{" "} + cpp_std_flag); - // build_target.vars["target_custom_flags"].append(env["templates"]["compile-as-cpp"].Scalar()); + // build_target.vars["target_custom_flags"].append(env["templates"]["compile-as-cpp"].scalar()); } // fmt::print(" [DBG] Target '{}' has object '{}'->'{}'\n", path, build_target.in, build_target.out); @@ -683,8 +720,7 @@ namespace re break; case TargetType::SharedLibrary: link_target.vars["target_custom_flags"].append(" "); - link_target.vars["target_custom_flags"].append( - env["templates"]["link-as-shared-library"].as()); + link_target.vars["target_custom_flags"].append(env["templates"]["link-as-shared-library"].scalar()); break; case TargetType::Project: link_target.rule = "phony"; @@ -736,17 +772,17 @@ namespace re { // std::ifstream stream{ (mEnvSearchPath / name.data() / ".yml") }; - auto &data = - (mEnvCache[name.data()] = YAML::LoadFile(mEnvSearchPath.u8string() + "/" + name.data() + ".yml")); + auto &data = (mEnvCache[name.data()] = ulib::yaml::parse( + futile::open(mEnvSearchPath.u8string() + "/" + name.data() + ".yml").read())); - if (auto inherits = data["inherits"]) - for (const auto &v : inherits) + if (auto inherits = data.search("inherits")) + for (const auto &v : *inherits) { - auto &other = LoadEnvOrThrow(v.as(), invokee); + auto &other = LoadEnvOrThrow(v.scalar(), invokee); - for (const auto &pair : other) - if (!data[pair.first]) - data[pair.first] = pair.second; + for (const auto &pair : other.items()) + if (!data.search(pair.name())) + data[pair.name()] = pair.value(); } return data; diff --git a/buildkit/re/langs/cxx/cxx_lang_provider.h b/buildkit/re/langs/cxx/cxx_lang_provider.h index 8a91573..b29c50a 100644 --- a/buildkit/re/langs/cxx/cxx_lang_provider.h +++ b/buildkit/re/langs/cxx/cxx_lang_provider.h @@ -11,7 +11,7 @@ namespace re { - using CxxBuildEnvData = YAML::Node; + using CxxBuildEnvData = ulib::yaml; class CxxLangProvider : public ILangProvider { diff --git a/buildkit/re/langs/cxx/features/source_translation.cpp b/buildkit/re/langs/cxx/features/source_translation.cpp index 4f52d83..9580ca9 100644 --- a/buildkit/re/langs/cxx/features/source_translation.cpp +++ b/buildkit/re/langs/cxx/features/source_translation.cpp @@ -3,8 +3,8 @@ #include // #include -#include #include +#include namespace re { @@ -20,59 +20,66 @@ namespace re continue; auto in_path = source.path; - auto base_path = source.path.lexically_relative(target.path).u8string(); + ulib::string base_path = source.path.lexically_relative(target.path).u8string(); int num_steps = 0; - for (auto step : target.resolved_config["source-translation-steps"]) + if (auto steps = target.resolved_config.search("source-translation-steps")) { - auto vars = LocalVarScope{&*target.build_var_scope, "translation"}; + if (steps->is_sequence()) + { + for (auto step : *steps) + { + auto vars = LocalVarScope{&*target.build_var_scope, "translation"}; - auto step_suffix = fmt::format("_st_step{}", num_steps); + auto step_suffix = ulib::format("_st_step{}", num_steps); - auto step_name = step["name"]; + auto step_name = step["name"]; - auto out_ext_node = step["out-extension"]; - auto out_ext = out_ext_node ? out_ext_node.Scalar() : source.extension; + auto out_ext_node = step["out-extension"]; + ulib::string out_ext = + !out_ext_node.is_null() ? out_ext_node.scalar() : ulib::string_view{source.extension}; - auto out_path = out_root / (base_path + step_suffix + "." + out_ext); + auto out_path = out_root / (base_path + step_suffix + "." + out_ext); - vars.SetVar("source-file", in_path.generic_u8string()); - vars.SetVar("out-file", out_path.generic_u8string()); - - auto extensions = step["extensions"]; + vars.SetVar("source-file", in_path.generic_u8string()); + vars.SetVar("out-file", out_path.generic_u8string()); - bool supported = false; + bool supported = false; - if (extensions) - { - for (auto extension : extensions) - { - if (source.extension == extension.Scalar()) + auto extensions = step.search("extensions"); + if (extensions) + { + for (auto extension : *extensions) + { + if (extension.scalar() == source.extension) + { + supported = true; + break; + } + } + } + else { supported = true; - break; } - } - } - else - { - supported = true; - } - if (!supported) - continue; + if (!supported) + continue; - // fmt::print("translating {} -> {}\n", source.path.generic_u8string(), out_path.generic_u8string()); + // fmt::print("translating {} -> {}\n", source.path.generic_u8string(), + // out_path.generic_u8string()); - target.unused_sources.push_back(source); + target.unused_sources.push_back(source); - source.path = out_path; - source.extension = out_ext; + source.path = out_path; + source.extension = out_ext; - in_path = out_path; + in_path = out_path; - num_steps++; + num_steps++; + } + } } } } @@ -86,7 +93,7 @@ namespace re for (auto &source : target.unused_sources) { auto in_path = source.path; - auto base_path = source.path.lexically_relative(target.path).u8string(); + ulib::string base_path = source.path.lexically_relative(target.path).u8string(); int num_steps = 0; @@ -94,12 +101,10 @@ namespace re { auto vars = LocalVarScope{&*target.build_var_scope, "translation_exec"}; - auto step_suffix = fmt::format("_st_step{}", num_steps); - - auto step_name = step["name"]; + ulib::string step_suffix = ulib::format("_st_step{}", num_steps); - auto out_ext_node = step["out-extension"]; - auto out_ext = out_ext_node ? out_ext_node.Scalar() : source.extension; + auto out_ext_node = step.search("out-extension"); + auto out_ext = out_ext_node ? out_ext_node->scalar() : ulib::string_view{source.extension}; auto out_path = out_root / (base_path + step_suffix + "." + out_ext); @@ -108,7 +113,7 @@ namespace re auto extensions = step["extensions"]; - ulib::string sc = step["command"].Scalar(); + ulib::string sc = step["command"].scalar(); ulib::list command = sc.split(" "); for (auto &part : command) @@ -116,11 +121,9 @@ namespace re fs::create_directories(out_path.parent_path()); - std::vector ccommand; - for (auto &str : command) - ccommand.push_back(str); - - re::RunProcessOrThrow(step_name ? step_name.Scalar() : step_suffix.substr(1), {}, ccommand, true, true); + auto step_name = step.search("name"); + re::RunProcessOrThrow(step_name ? step_name->scalar() : step_suffix.substr(1), {}, command, true, + true); // fmt::print("translating {} -> {}\n", source.path.generic_u8string(), out_path.generic_u8string()); diff --git a/buildkit/re/process_util.cpp b/buildkit/re/process_util.cpp index ccda6d8..eafad5d 100644 --- a/buildkit/re/process_util.cpp +++ b/buildkit/re/process_util.cpp @@ -5,12 +5,14 @@ #include "ulib/process_exceptions.h" #include +#include +#include #include namespace re { - int RunProcessOrThrow(std::string_view program_name, const fs::path &path, std::vector cmdline, + int RunProcessOrThrow(ulib::string_view program_name, const fs::path &path, const ulib::list& cmdline, bool output, bool throw_on_bad_exit, std::optional working_directory) { ulib::list cmdline_u8; @@ -21,7 +23,7 @@ namespace re if (path_proc.empty()) { path_proc = fs::path{cmdline.front()}; - cmdline_u8.erase(0); + cmdline_u8.erase(0, 1); } ulib::process process; @@ -41,7 +43,7 @@ namespace re if (throw_on_bad_exit && exit_code != 0) { - RE_THROW ProcessRunException("{} failed: exit_code={}", program_name, exit_code); + RE_THROW ProcessRunException("{} {} failed: exit_code={}", program_name, cmdline_u8, exit_code); } return exit_code; diff --git a/buildkit/re/process_util.h b/buildkit/re/process_util.h index 18373b9..e781bba 100644 --- a/buildkit/re/process_util.h +++ b/buildkit/re/process_util.h @@ -8,10 +8,11 @@ #include "error.h" #include "fs.h" +#include namespace re { - int RunProcessOrThrow(std::string_view program_name, const fs::path &path, std::vector cmdline, + int RunProcessOrThrow(ulib::string_view program_name, const fs::path &path, const ulib::list& cmdline, bool output, bool throw_on_bad_exit, std::optional working_directory = std::nullopt); // #ifdef WIN32 diff --git a/buildkit/re/target.cpp b/buildkit/re/target.cpp index 3663379..5cfc52e 100644 --- a/buildkit/re/target.cpp +++ b/buildkit/re/target.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace re { @@ -18,7 +19,7 @@ namespace re return std::tolower(lhs) == std::tolower(rhs); }; - TargetType TargetTypeFromString(const std::string &type) + TargetType TargetTypeFromString(ulib::string_view type) { if (type == "project") return TargetType::Project; @@ -63,9 +64,7 @@ namespace re RE_TRACE(" ***** LOADING TARGET: path = {}\n", path.generic_u8string()); config_path = path / kTargetConfigFilename; - - std::ifstream f{config_path}; - config = YAML::Load(f); + config = ulib::yaml::parse(futile::open(config_path).read()); // Load all config partitions @@ -75,9 +74,7 @@ namespace re if (name.ends_with(".re.yml")) { - std::ifstream merge_f{entry.path()}; - auto merge_c = YAML::Load(merge_f); - + auto merge_c = ulib::yaml::parse(futile::open(entry.path()).read()); MergeYamlNode(config, merge_c); } } @@ -117,14 +114,12 @@ namespace re if (!name.empty() && name.front() == '.') { name.erase(0, 1); - - if (parent) - module = ModulePathCombine(parent->module, name); } + + if (parent) + module = ModulePathCombine(parent->module, name); else - { module = name; - } if (parent) root_path = parent->root_path; @@ -135,9 +130,9 @@ namespace re auto used_key = key.empty() ? "deps" : key; // Use the relevant config instance. - auto deps = resolved_config ? resolved_config[used_key.data()] : config[used_key.data()]; + auto& deps = resolved_config.is_map() ? resolved_config[used_key.data()] : config[used_key.data()]; - if (deps) + if (!deps.is_null()) { for (auto node : deps) { @@ -156,13 +151,13 @@ namespace re } } - if (resolved_config && build_var_scope) + if (resolved_config.is_map() && build_var_scope) { - if (auto uses = resolved_config["uses"]) + if (auto uses = resolved_config.search("uses")) { - for (const auto &kv : uses) + for (const auto &kv : uses->items()) { - auto key = kv.first.Scalar(); + auto key = kv.name(); // fmt::print("{}\n", key); @@ -171,7 +166,7 @@ namespace re // TODO: Move to ParseTargetDependencyNode if (!mapping) mapping = std::make_unique( - ParseTargetDependency(build_var_scope->Resolve(kv.second.Scalar()), this)); + ParseTargetDependency(build_var_scope->Resolve(kv.value().scalar()), this)); } } } @@ -186,9 +181,10 @@ namespace re // features.clear(); - for (auto v : resolved_config["features"]) - if (!features[v.Scalar()]) - features[v.Scalar()] = nullptr; + if (auto features_ = resolved_config.search("features")) + for (auto v : *features_) + if (!features[v.scalar()]) + features[v.scalar()] = nullptr; } void Target::LoadMiscConfig() @@ -202,7 +198,7 @@ namespace re for (const auto& lang : *langs) { - auto id = lang.as(); + auto id = lang.scalar(); auto found = false; for (auto& provider : lang_providers) @@ -214,7 +210,7 @@ namespace re if (auto provider = lang_locator->GetLangProvider(id)) lang_providers.push_back(provider); else - throw TargetLoadException("language provider " + lang.as() + " not found"); + throw TargetLoadException("language provider " + lang.scalar() + " not found"); } } } @@ -290,7 +286,7 @@ namespace re file << out.c_str(); } - std::optional Target::GetVar(const std::string &key) const + std::optional Target::GetVar(ulib::string_view key) const { // fmt::print("target '{}'/'{}': ", module, key); @@ -299,22 +295,29 @@ namespace re else if (key == "module") return module; - auto used_config = resolved_config ? resolved_config : config; + auto used_config = resolved_config.is_map() ? resolved_config : config; + auto vars = used_config.search("vars"); - if (used_config["vars"] && used_config["vars"][key].IsDefined()) + if (auto var = vars ? vars->search(key) : nullptr) { + if (!var->is_scalar()) + return std::nullopt; + // fmt::print("found in vars"); - return used_config["vars"][key].as(); + return var->scalar(); } - else if (used_config[key]) + else if (auto var = used_config.search(key)) { + if (!var->is_scalar()) + return std::nullopt; + // fmt::print("found in used vars"); - return used_config[key].as(); + return var->scalar(); } else if (auto entry = GetCfgEntry(key, CfgEntryKind::Recursive)) { // fmt::print("found in config with entry='{}'", entry.value()); - return entry; + return *entry; } else if (auto var = parent ? parent->GetVar(key) : std::nullopt) { @@ -343,7 +346,7 @@ namespace re RE_THROW TargetConfigException(this, "reached top of hierarchy without finding a valid build var scope"); } - TargetDependency *Target::GetUsedDependency(const std::string &name) const + TargetDependency *Target::GetUsedDependency(ulib::string_view name) const { auto it = used_mapping.find(name); @@ -371,11 +374,12 @@ namespace re const std::regex kTargetDepRegex{ R"(\s?(?:([a-zA-Z0-9.-]*)(?::))?\s?([^\s@=<>~\^]*)\s*(?:(@|==|<|<=|>|>=|~|\^)\s*([a-zA-Z0-9._-]*))?\s*(?:(?:\[)(.+)(?:\]))?)"}; - TargetDependency ParseTargetDependency(const std::string &str, const Target *pTarget) + TargetDependency ParseTargetDependency(ulib::string_view str, const Target *pTarget) { std::smatch match; - if (!std::regex_match(str, match, kTargetDepRegex)) + const std::string rstr{str}; + if (!std::regex_match(rstr, match, kTargetDepRegex)) RE_THROW TargetDependencyException(pTarget, "dependency '{}' does not meet the format requirements", str); TargetDependency dep; @@ -383,8 +387,9 @@ namespace re dep.raw = str; dep.ns = match[1].str(); dep.name = match[2].str(); + dep.version_kind_str = match[3].str(); - auto &kind_str = (dep.version_kind_str = match[3].str()); + auto &kind_str = dep.version_kind_str; if (kind_str == "@" || kind_str == "") dep.version_kind = DependencyVersionKind::RawTag; @@ -408,7 +413,7 @@ namespace re dep.version = match[4].str(); if (dep.version_kind != DependencyVersionKind::RawTag) - dep.version_sv = semverpp::version{dep.version}; + dep.version_sv = semverpp::version{std::string(dep.version)}; if (match[5].matched) { @@ -424,30 +429,27 @@ namespace re if (dep.name.empty()) RE_THROW TargetDependencyException(pTarget, "dependency {} does not have a name specified", str); - if (pTarget) - dep.name = ResolveTargetParentRef(dep.name, pTarget); + // if (pTarget) + // dep.name = ResolveTargetParentRef(dep.name, pTarget); return dep; } - TargetDependency ParseTargetDependencyNode(YAML::Node node, const Target *pTarget) + TargetDependency ParseTargetDependencyNode(const ulib::yaml& node, const Target *pTarget) { - if (node.IsScalar()) + if (node.is_scalar()) { - return ParseTargetDependency(node.Scalar(), pTarget); + return ParseTargetDependency(node.scalar(), pTarget); } - else if (node.IsMap()) + else if (node.is_map()) { // HACK: This YAML library sucks. - for (auto kv : node) + for (auto& kv : node.items()) { - auto result = ParseTargetDependency(kv.first.Scalar(), pTarget); - - result.extra_config = YAML::Clone(kv.second); + auto result = ParseTargetDependency(kv.name(), pTarget); - YAML::Emitter emitter; - emitter << result.extra_config; - result.extra_config_data_hash = std::hash{}(emitter.c_str()); + result.extra_config = kv.value(); + result.extra_config_data_hash = std::hash{}(result.extra_config.dump()); if (pTarget) { @@ -463,14 +465,13 @@ namespace re } else { - auto mark = node.Mark(); - RE_THROW TargetDependencyException(pTarget, "dependency node at {}:{} must be string or map", mark.line, - mark.column); + // auto mark = node.Mark(); + RE_THROW TargetDependencyException(pTarget, "dependency node must be string or map"); return {}; // Unreachable but the compiler complains } } - std::string TargetDependency::ToString() const + ulib::string TargetDependency::ToString() const { return raw; } diff --git a/buildkit/re/target.h b/buildkit/re/target.h index 4b09268..1bafaba 100644 --- a/buildkit/re/target.h +++ b/buildkit/re/target.h @@ -25,6 +25,8 @@ #include +#include + namespace re { /** @@ -67,7 +69,7 @@ namespace re * * @throws Exception Thrown if the string does not represent a valid target type. */ - TargetType TargetTypeFromString(const std::string &type); + TargetType TargetTypeFromString(ulib::string_view type); /** * @brief Converts a TargetType to a string. @@ -77,7 +79,7 @@ namespace re */ const char *TargetTypeToString(TargetType type); - using TargetConfig = YAML::Node; + using TargetConfig = ulib::yaml; /** * @brief An option determining whether to search a target config option recursively in the target's parents. @@ -171,22 +173,22 @@ namespace re /** * @brief The dependency's original string representation. */ - std::string raw; + ulib::string raw; /** * @brief The dependency namespace to search in. */ - std::string ns; + ulib::string ns; /** * @brief The dependency's name (can include just a name, a path, a link or anything) */ - std::string name; + ulib::string name; /** * @brief The dependency's version. This should ideally be a valid SemVer value. */ - std::string version; + ulib::string version; /** * @brief The dependency's version as a SemVer value. @@ -201,14 +203,14 @@ namespace re /** * @brief The dependency's version kind as a string. */ - std::string version_kind_str; + ulib::string version_kind_str; /** * @brief A list of "filters" for the dependency. * * These are in most cases subtargets to depend on, so as to not build parts of the dependency you don't need. */ - std::vector filters; + ulib::list filters; /** * @brief This dependency's resulting resolved target list. @@ -216,7 +218,7 @@ namespace re * This is filled at dependency resolution time. Dependencies whose TargetDependency::resolved * isn't empty are considered resolved and ignored in subsequent resolution passes. */ - std::vector resolved = {}; + ulib::list resolved = {}; /** * @brief The extra config (eCfg) for this dependency. @@ -224,7 +226,7 @@ namespace re * Extra configs allow dependents to manually override dependencies' target config fields. * This creates a _new_ target for every unique eCfg node there is under the hood. */ - YAML::Node extra_config{YAML::NodeType::Undefined}; + ulib::yaml extra_config{ulib::yaml::value_t::null}; /** * @brief A unique value identifying this dependency's extra config node owner. @@ -241,7 +243,7 @@ namespace re * * @return std::string The resulting string. */ - std::string ToString() const; + ulib::string ToString() const; }; /** @@ -256,7 +258,7 @@ namespace re * * @throws TargetDependencyException Thrown if the string has an invalid format */ - TargetDependency ParseTargetDependency(const std::string &str, const Target *pTarget = nullptr); + TargetDependency ParseTargetDependency(ulib::string_view str, const Target *pTarget = nullptr); /** * @brief Parses a YAML node into a TargetDependency object. @@ -271,7 +273,7 @@ namespace re * * @throws TargetDependencyException Thrown if the node's depstring has an invalid format */ - TargetDependency ParseTargetDependencyNode(YAML::Node node, const Target *pTarget = nullptr); + TargetDependency ParseTargetDependencyNode(const ulib::yaml& node, const Target *pTarget = nullptr); /** * @brief Combines two target module paths with respect to their possible emptiness. @@ -285,14 +287,14 @@ namespace re * * @return std::string A module path that combines the two passed to this function. */ - inline std::string ModulePathCombine(const std::string &a, const std::string &b) + inline ulib::string ModulePathCombine(ulib::string_view a, ulib::string_view b) { if (a.empty()) return b; else if (b.empty()) return a; else - return a + "." + b; + return ulib::str(a) + "." + b; } class Target; @@ -573,7 +575,7 @@ namespace re * Resolved configs are only built once and are "flattened" with respect to their conditional sections and * inheritance. */ - TargetConfig resolved_config{YAML::NodeType::Undefined}; + TargetConfig resolved_config{ulib::yaml::value_t::null}; /** * @brief A set of targets that depend on this target. @@ -615,11 +617,11 @@ namespace re */ std::unordered_map features; - std::optional GetVar(const std::string &key) const; + std::optional GetVar(ulib::string_view key) const; std::pair GetBuildVarScope() const; - TargetDependency *GetUsedDependency(const std::string &name) const; + TargetDependency *GetUsedDependency(ulib::string_view name) const; Target *FindChild(std::string_view name) const; @@ -662,12 +664,12 @@ namespace re template std::optional GetCfgEntry(std::string_view key, CfgEntryKind kind = CfgEntryKind::NonRecursive) const { - if (auto node = config[key.data()]) + if (auto node = config.search(key.data())) { if constexpr (!std::is_same_v) - return node.template as(); + return node->get(); else - return node; + return *node; } else if (kind == CfgEntryKind::Recursive && parent) return parent->GetCfgEntry(key, kind); diff --git a/buildkit/re/target_cfg_utils.cpp b/buildkit/re/target_cfg_utils.cpp index 6ccce2d..e41df97 100644 --- a/buildkit/re/target_cfg_utils.cpp +++ b/buildkit/re/target_cfg_utils.cpp @@ -6,6 +6,8 @@ // #include #include #include +#include + namespace re { @@ -13,20 +15,19 @@ namespace re const std::unordered_map &mappings) { // recurse the ky - auto result = Clone(cfg); + auto result = cfg; - if (cfg.IsMap()) + if (cfg.is_map()) { - for (auto &kv : cfg) + for (const auto &kv : cfg.items()) { - std::string key = kv.first.as(); + ulib::string_view key = kv.name(); for (const auto &[category, value] : mappings) { if (key.find(category + ".") == 0) { - ulib::string raw = key.substr(category.size() + 1); - + ulib::string_view raw = key.substr(category.size() + 1); ulib::list categories = raw.split("|"); bool supported = (raw == "any"); @@ -50,21 +51,22 @@ namespace re if (supported) { - if (kv.second.IsScalar() && kv.second.Scalar() == "unsupported") + if (kv.value().is_scalar() && kv.value().scalar() == "unsupported") RE_THROW Exception("unsupported {} '{}'", category, value); - auto cloned = GetFlatResolvedTargetCfg(kv.second, mappings); + auto cloned = GetFlatResolvedTargetCfg(kv.value(), mappings); - if (cloned.IsMap()) + if (cloned.is_map()) { - for (auto inner_kv : cloned) - inner_kv.second = GetFlatResolvedTargetCfg(inner_kv.second, mappings); + for (auto& inner_kv : cloned.items()) + inner_kv.value() = GetFlatResolvedTargetCfg(inner_kv.value(), mappings); } MergeYamlNode(result, cloned); } - result.remove(key); + if (result.is_map()) + result.remove(key); break; } } @@ -82,28 +84,59 @@ namespace re // Deps and uses are automatically recursed by Target facilities: // copying parent deps and uses into children would lead to a performance impact due to redundant regex parsing - auto top_deps = Clone(leaf_cfg["deps"]); + auto top_deps = leaf_cfg["deps"]; // auto top_uses = Clone(leaf_cfg["uses"]); - auto top_actions = Clone(leaf_cfg["actions"]); - auto top_tasks = Clone(leaf_cfg["tasks"]); + auto top_actions = leaf_cfg["actions"]; + auto top_tasks = leaf_cfg["tasks"]; std::vector genealogy = {&leaf}; while (p) { genealogy.insert(genealogy.begin(), p); + if (std::find(genealogy.begin(), genealogy.end(), p->parent) != genealogy.end()) + { + std::system("pause"); + + if (p->parent) + { + fmt::print("p->name: {}\n", p->name); + fmt::print("p->path: {}\n", p->path.generic_string()); + fmt::print("p->module: {}\n", p->module); + fmt::print("p->type: {}\n", TargetTypeToString(p->type)); + + // fmt::print("p->parent->name: {}\n", p->parent->name); + // fmt::print("p->parent->path: {}\n", p->parent->path.generic_string()); + // fmt::print("p->parent->module: {}\n", p->parent->module); + // fmt::print("p->parent->type: {}\n", TargetTypeToString(p->parent->type)); + + // fmt::print("p->parent->resolved_config:\n"); + // std::cout << p->parent->resolved_config << std::endl; + + // fmt::print("p->parent->config:\n"); + // std::cout << p->parent->config << std::endl; + + } + + break; + } + + p = p->parent; } - TargetConfig result{YAML::NodeType::Map}; + + + + TargetConfig result{ulib::yaml::value_t::map}; for (auto &target : genealogy) MergeYamlNode(result, GetFlatResolvedTargetCfg(target->config, mappings)); // Everything is always inherited from the core config target in the root target if (leaf.parent && - (!leaf.parent->config["is-core-config"] || leaf.parent->config["is-core-config"].as() != true)) + (!leaf.parent->config.search("is-core-config") || leaf.parent->config["is-core-config"].get() != true)) { result["deps"] = top_deps; // result["uses"] = top_uses; diff --git a/buildkit/re/target_loader.h b/buildkit/re/target_loader.h index a532b27..342f1c0 100644 --- a/buildkit/re/target_loader.h +++ b/buildkit/re/target_loader.h @@ -25,6 +25,6 @@ namespace re virtual Target* GetCoreTarget() = 0; virtual void RegisterLocalTarget(Target* pTarget) = 0; - virtual IDepResolver* GetDepResolver(const std::string& name) = 0; + virtual IDepResolver* GetDepResolver(ulib::string_view name) = 0; }; } diff --git a/buildkit/re/vars.cpp b/buildkit/re/vars.cpp index e930261..f1f1816 100644 --- a/buildkit/re/vars.cpp +++ b/buildkit/re/vars.cpp @@ -11,16 +11,17 @@ namespace re const auto kOuterVarRegex = boost::xpressive::sregex::compile(R"(\$\{(.*?)\})"); const auto kVarRegex = boost::xpressive::sregex::compile(R"((?:([^:|]+)?:\s*)?([^|\s]*)(?:\s*\|\s*(.*))?)"); - std::string GetVarValue(const VarContext &ctx, const std::string &original, const std::string &var, - const std::string &default_namespace) + ulib::string GetVarValue(const VarContext &ctx, ulib::string_view original, ulib::string_view var, + ulib::string_view default_namespace) { - std::string ns = default_namespace; - std::string key = ""; - std::string fallback = ""; + ulib::string ns = default_namespace; + ulib::string key = ""; + ulib::string fallback = ""; boost::xpressive::smatch match; - if (!boost::xpressive::regex_match(var, match, kVarRegex)) + std::string vvv{var}; + if (!boost::xpressive::regex_match(vvv, match, kVarRegex)) RE_THROW VarSubstitutionException("invalid variable definition\n in string '{}'", original); ////////////////////////////////////// @@ -42,10 +43,10 @@ namespace re if (it == ctx.end()) { - std::string namespaces; + ulib::string namespaces; for (auto &[key, _] : ctx) - namespaces += fmt::format("\n {}", key); + namespaces += ulib::format("\n {}", key); RE_THROW VarSubstitutionException( "var namespace '{}' not found\n in string '{}'\n\n Available namespaces:{}", ns, original, @@ -74,20 +75,20 @@ namespace re } } // namespace - std::string VarSubstitute(const VarContext &ctx, const std::string &str, const std::string &default_namespace) + ulib::string VarSubstitute(const VarContext &ctx, ulib::string_view str, ulib::string_view default_namespace) { using namespace boost::xpressive; return regex_replace( - str, kOuterVarRegex, + std::string{str}, kOuterVarRegex, [&str, &ctx, &default_namespace](const smatch &match) { return GetVarValue(ctx, str, match[1].str(), default_namespace); }, regex_constants::match_any); } - LocalVarScope::LocalVarScope(VarContext *context, const std::string &alias, const IVarNamespace *parent, - const std::string &parent_alias) + LocalVarScope::LocalVarScope(VarContext *context, ulib::string_view alias, const IVarNamespace *parent, + ulib::string_view parent_alias) : mContext{context}, mAlias{alias}, mParent{parent}, mParentAlias{parent_alias} { Init(); @@ -129,23 +130,23 @@ namespace re Init(); } - void LocalVarScope::AddNamespace(const std::string &name, IVarNamespace *ns) + void LocalVarScope::AddNamespace(ulib::string_view name, IVarNamespace *ns) { // fmt::print(" * [{}] Adding var namespace '{}'\n", mLocalName, name); (*mContext)[name] = ns; } - void LocalVarScope::SetVar(const std::string &key, std::string value) + void LocalVarScope::SetVar(ulib::string_view key, std::string value) { mVars[key] = std::move(value); } - void LocalVarScope::RemoveVar(const std::string &key) + void LocalVarScope::RemoveVar(ulib::string_view key) { mVars.erase(key); } - std::optional LocalVarScope::GetVar(const std::string &key) const + std::optional LocalVarScope::GetVar(ulib::string_view key) const { if (auto value = GetVarNoRecurse(key)) return value; @@ -153,7 +154,7 @@ namespace re return mParent ? mParent->GetVar(key) : std::nullopt; } - std::optional LocalVarScope::GetVarNoRecurse(const std::string &key) const + std::optional LocalVarScope::GetVarNoRecurse(ulib::string_view key) const { auto it = mVars.find(key); diff --git a/buildkit/re/vars.h b/buildkit/re/vars.h index d8c7d64..362ed63 100644 --- a/buildkit/re/vars.h +++ b/buildkit/re/vars.h @@ -13,7 +13,7 @@ namespace re { virtual ~IVarNamespace() = default; - virtual std::optional GetVar(const std::string &key) const = 0; + virtual std::optional GetVar(ulib::string_view key) const = 0; }; using VarContext = std::unordered_map; @@ -28,20 +28,20 @@ namespace re } }; - std::string VarSubstitute(const VarContext &ctx, const std::string &str, const std::string &default_namespace = ""); + ulib::string VarSubstitute(const VarContext &ctx, ulib::string_view str, ulib::string_view default_namespace = ""); class LocalVarScope : public IVarNamespace { public: - explicit LocalVarScope(VarContext *context, const std::string &alias = "", - const IVarNamespace *parent = nullptr, const std::string &parent_alias = ""); + explicit LocalVarScope(VarContext *context, ulib::string_view alias = "", + const IVarNamespace *parent = nullptr, ulib::string_view parent_alias = ""); - explicit LocalVarScope(const LocalVarScope *parent, const std::string &alias = "") + explicit LocalVarScope(const LocalVarScope *parent, ulib::string_view alias = "") : LocalVarScope{parent ? parent->mContext : nullptr, alias, parent} { } - explicit LocalVarScope(const std::string &alias) : LocalVarScope{{}, alias, nullptr} + explicit LocalVarScope(ulib::string_view alias) : LocalVarScope{{}, alias, nullptr} { } @@ -52,17 +52,17 @@ namespace re void Adopt(VarContext *context, IVarNamespace *parent); - void AddNamespace(const std::string &name, IVarNamespace *ns); + void AddNamespace(ulib::string_view name, IVarNamespace *ns); - void SetVar(const std::string &key, std::string value); + void SetVar(ulib::string_view key, std::string value); - void RemoveVar(const std::string &key); + void RemoveVar(ulib::string_view key); - std::optional GetVar(const std::string &key) const; + std::optional GetVar(ulib::string_view key) const; - std::optional GetVarNoRecurse(const std::string &key) const; + std::optional GetVarNoRecurse(ulib::string_view key) const; - inline std::string Resolve(const std::string &str) const + inline ulib::string Resolve(ulib::string_view str) const { // fmt::print(" * Resolving '{}': ", str); auto result = VarSubstitute(*mContext, str, mLocalName); @@ -70,7 +70,7 @@ namespace re return result; } - inline std::string ResolveLocal(const std::string &key) const + inline std::string ResolveLocal(ulib::string_view key) const { if (auto var = GetVar(key)) return Resolve(*var); @@ -80,7 +80,7 @@ namespace re mAlias, mParentAlias); } - inline LocalVarScope Subscope(const std::string &alias = "") + inline LocalVarScope Subscope(ulib::string_view alias = "") { return LocalVarScope{mContext, alias, this}; } @@ -94,9 +94,9 @@ namespace re VarContext *mContext; const IVarNamespace *mParent = nullptr; - std::string mLocalName; - std::string mAlias; - std::string mParentAlias; + ulib::string mLocalName; + ulib::string mAlias; + ulib::string mParentAlias; std::unordered_map mVars; diff --git a/buildkit/re/yaml_merge.cpp b/buildkit/re/yaml_merge.cpp index 5a90928..6ee8293 100644 --- a/buildkit/re/yaml_merge.cpp +++ b/buildkit/re/yaml_merge.cpp @@ -8,77 +8,71 @@ namespace re { - void MergeYamlNode(YAML::Node target, const YAML::Node &source, bool overridden) + void MergeYamlNode(ulib::yaml& target, const ulib::yaml &source, bool overridden) { - switch (source.Type()) + switch (source.type()) { - case YAML::NodeType::Scalar: - target = source.Scalar(); - break; - case YAML::NodeType::Map: + case ulib::yaml::value_t::map: MergeYamlMap(target, source, overridden); break; - case YAML::NodeType::Sequence: + case ulib::yaml::value_t::sequence: MergeYamlSequences(target, source, overridden); break; - case YAML::NodeType::Null: + default: target = source; break; - // throw std::runtime_error("merge_node: Null source nodes not supported"); - case YAML::NodeType::Undefined: - RE_THROW std::runtime_error("MergeNode: Undefined source nodes not supported"); } } - void MergeYamlMap(YAML::Node &target, const YAML::Node &source, bool overridden) + void MergeYamlMap(ulib::yaml &target, const ulib::yaml &source, bool overridden) { if (overridden) { - target = Clone(source); + target = source; return; } - for (const auto &j : source) + for (const auto &j : source.items()) { - auto key = j.first.Scalar(); + auto key = j.name(); constexpr auto kOverridePrefix = "override."; if (overridden || key.find(kOverridePrefix) == 0) { RE_TRACE("OVERRIDE PREFIX found on {}\n", key); - MergeYamlNode(target[key.substr(sizeof kOverridePrefix + 1)], j.second, true); + MergeYamlNode(target[key.substr(sizeof kOverridePrefix + 1)], j.value(), true); } else { RE_TRACE("Not overriding {}\n", key); - MergeYamlNode(target[key], j.second); + MergeYamlNode(target[key], j.value()); } } } - void MergeYamlSequences(YAML::Node &target, const YAML::Node &source, bool overridden) + void MergeYamlSequences(ulib::yaml &target, const ulib::yaml &source, bool overridden) { if (overridden) { - RE_TRACE("{} - override enabled, will copy over\n", target.Scalar()); + RE_TRACE("{} - override enabled, will copy over\n", target.scalar()); - target = YAML::Clone(source); + target = source; return; } else - RE_TRACE("{} - override disabled\n", target.Scalar()); + RE_TRACE("{} - override disabled\n", target.scalar()); for (std::size_t i = 0; i != source.size(); ++i) { - RE_TRACE(" Adding {}\n", source[i].Scalar()); - target.push_back(YAML::Clone(source[i])); + RE_TRACE(" Adding {}\n", source[i].scalar()); + target.push_back(source[i]); } } - YAML::Node MergeYamlNodes(const YAML::Node &defaultNode, const YAML::Node &overrideNode) + ulib::yaml MergeYamlNodes(const ulib::yaml &defaultNode, const ulib::yaml &overrideNode) { - auto cloned = Clone(defaultNode); + auto cloned = defaultNode; MergeYamlNode(cloned, overrideNode); return cloned; } diff --git a/buildkit/re/yaml_merge.h b/buildkit/re/yaml_merge.h index 85392aa..ddc81eb 100644 --- a/buildkit/re/yaml_merge.h +++ b/buildkit/re/yaml_merge.h @@ -1,13 +1,11 @@ #pragma once -#include +#include namespace re { - void MergeYamlNode(YAML::Node target, const YAML::Node& source, bool overridden = false); + void MergeYamlNode(ulib::yaml& target, const ulib::yaml& source, bool overridden = false); + void MergeYamlMap(ulib::yaml& target, const ulib::yaml& source, bool overridden = false); + void MergeYamlSequences(ulib::yaml& target, const ulib::yaml& source, bool overridden = false); - void MergeYamlMap(YAML::Node& target, const YAML::Node& source, bool overridden = false); - - void MergeYamlSequences(YAML::Node& target, const YAML::Node& source, bool overridden = false); - - YAML::Node MergeYamlNodes(const YAML::Node& defaultNode, const YAML::Node& overrideNode); + ulib::yaml MergeYamlNodes(const ulib::yaml& defaultNode, const ulib::yaml& overrideNode); } diff --git a/re-deps-lock.json b/re-deps-lock.json index 8cec032..693ff4c 100644 --- a/re-deps-lock.json +++ b/re-deps-lock.json @@ -1,8 +1,13 @@ { - "github:k2rate/ulib-fmt^5.0.0": "v5.0.4", + "github:k2rate/fops^1.0.0": "v1.0.1", + "github:k2rate/ulib-fmt^5.0.0": "v5.0.5", + "github:k2rate/ulib-json^1.0.0": "v1.3.7", + "github:k2rate/ulib-json^1.2.5": "v1.3.7", "github:k2rate/ulib-process^v1.0.2": "v1.0.3", - "github:k2rate/ulib^5.0.0": "v5.6.1", - "github:k2rate/ulib^5.0.1": "v5.6.1", - "github:osdeverr/futile^3.0.0": "v3.1.2", + "github:k2rate/ulib-yaml-json^1.0.0": "v1.1.0", + "github:k2rate/ulib-yaml^1.0.0": "v1.0.2", + "github:k2rate/ulib^5.0.0": "v5.10.1", + "github:k2rate/ulib^5.0.1": "v5.10.1", + "github:osdeverr/futile^3.0.0": "v3.1.4", "github:osdeverr/ulib-env^1.0.0": "v1.0.0" } \ No newline at end of file diff --git a/re.yml b/re.yml index 1a59394..0a09b86 100644 --- a/re.yml +++ b/re.yml @@ -2,6 +2,8 @@ type: project name: re platform.windows: + # runtime: static + # cxx-env: clang-cl cxx-build-flags: compiler: diff --git a/tool/main.cpp b/tool/main.cpp index 0499c6b..82e762e 100644 --- a/tool/main.cpp +++ b/tool/main.cpp @@ -115,6 +115,8 @@ int main(int argc, const char **argv) #endif + // std::system("pause"); + // auto code = __std_fs_code_page(); // __std_fs_code_page(); // sizeof(code); @@ -417,10 +419,7 @@ int main(int argc, const char **argv) { // Print the current config and quit. - YAML::Emitter emitter; - emitter << yaml; - - fmt::print("{}\n", emitter.c_str()); + fmt::print("{}\n", yaml.dump()); return 0; } @@ -502,7 +501,7 @@ int main(int argc, const char **argv) targets.erase(std::remove_if(targets.begin(), targets.end(), [&context](auto pTarget) { return !pTarget->build_var_scope || - pTarget->resolved_config["is-external-dep"].Scalar() == "true"; + pTarget->resolved_config["is-external-dep"].scalar() == "true"; }), targets.end()); } @@ -638,7 +637,7 @@ int main(int argc, const char **argv) { auto &exe_path = it->second; - std::vector run_args(args.begin() + 2, args.end()); + ulib::list run_args(args.begin() + 2, args.end()); auto working_dir = context.GetVar("working-dir").value_or(exe_path.parent_path().u8string()); @@ -678,7 +677,9 @@ int main(int argc, const char **argv) auto maybe_partial_build = handle_partial_build(&target, partial_build_filter); auto desc = context.GenerateBuildDescForTarget(target, maybe_partial_build); - std::vector run_args(args.begin() + 2, args.end()); + ulib::list run_args; + for (auto it = args.begin() + 2; it != args.end(); it++) + run_args.push_back(*it); auto working_dir = context.GetVar("working-dir").value_or("."); return re::RunProcessOrThrow("tool", "", run_args, true, false, working_dir); @@ -795,7 +796,7 @@ int main(int argc, const char **argv) for (const auto& arg : env_cfg["args"]) { auto index = i++; - auto& name = arg_names.emplace_back(arg.as()); + auto& name = arg_names.emplace_back(arg.scalar()); if (args.size() < index) throw std::runtime_error("missing argument '" + name + "'"); @@ -805,7 +806,7 @@ int main(int argc, const char **argv) for (const auto& cmd : env_cfg["run"]) { - auto expanded = fmt::vformat(cmd.as(), store); + auto expanded = fmt::vformat(cmd.scalar(), store); auto code = std::system(expanded.data()); if (code != 0) diff --git a/tool/re.yml b/tool/re.yml index e34db02..03a35a3 100644 --- a/tool/re.yml +++ b/tool/re.yml @@ -1,8 +1,10 @@ type: executable name: .tool + artifact-name: re + deps: - .buildkit - .resources