diff options
-rw-r--r-- | tools/minicargo/build.cpp | 71 | ||||
-rw-r--r-- | tools/minicargo/build.h | 4 | ||||
-rw-r--r-- | tools/minicargo/main.cpp | 1 | ||||
-rw-r--r-- | tools/minicargo/manifest.cpp | 108 | ||||
-rw-r--r-- | tools/minicargo/manifest.h | 15 |
5 files changed, 169 insertions, 30 deletions
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp index 3cdea3b3..f3cc74b4 100644 --- a/tools/minicargo/build.cpp +++ b/tools/minicargo/build.cpp @@ -8,12 +8,14 @@ #include <sstream> // stringstream #ifdef _WIN32 # include <Windows.h> +# define EXESUF ".exe" #else # include <spawn.h> # include <sys/types.h> # include <sys/stat.h> # include <sys/wait.h> # include <fcntl.h> +# define EXESUF "" #endif struct BuildList @@ -24,8 +26,8 @@ struct BuildList }; ::std::vector<BuildEnt> m_list; - void add_dependencies(const PackageManifest& p, unsigned level); - void add_package(const PackageManifest& p, unsigned level); + void add_dependencies(const PackageManifest& p, unsigned level, bool include_build); + void add_package(const PackageManifest& p, unsigned level, bool include_build); void sort_list(); struct Iter { @@ -154,7 +156,7 @@ void MiniCargo_Build(const PackageManifest& manifest, ::helpers::path override_p { BuildList list; - list.add_dependencies(manifest, 0); + list.add_dependencies(manifest, 0, !override_path.is_valid()); list.sort_list(); // dedup? @@ -177,20 +179,28 @@ void MiniCargo_Build(const PackageManifest& manifest, ::helpers::path override_p builder.build_library(manifest); } -void BuildList::add_dependencies(const PackageManifest& p, unsigned level) +void BuildList::add_dependencies(const PackageManifest& p, unsigned level, bool include_build) { TRACE_FUNCTION_F(p.name()); for (const auto& dep : p.dependencies()) { - if( dep.is_optional() ) + if( dep.is_disabled() ) { continue ; } DEBUG("Depenency " << dep.name()); - add_package(dep.get_package(), level+1); + add_package(dep.get_package(), level+1, include_build); + } + + if( p.build_script() != "" && include_build ) + { + for(const auto& dep : p.build_dependencies()) + { + add_package(dep.get_package(), level+1, include_build); + } } } -void BuildList::add_package(const PackageManifest& p, unsigned level) +void BuildList::add_package(const PackageManifest& p, unsigned level, bool include_build) { TRACE_FUNCTION_F(p.name()); // If the package is already loaded @@ -204,7 +214,7 @@ void BuildList::add_package(const PackageManifest& p, unsigned level) // Keep searching (might already have a higher entry) } m_list.push_back({ &p, level }); - add_dependencies(p, level); + add_dependencies(p, level, include_build); } void BuildList::sort_list() { @@ -284,7 +294,23 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& } // TODO: Environment variables (rustc_env) - return this->spawn_process(args, outfile + "_dbg.txt"); + return this->spawn_process_mrustc(args, outfile + "_dbg.txt"); +} +::std::string Builder::build_build_script(const PackageManifest& manifest) const +{ + auto outfile = m_output_dir / manifest.name() + "_build" EXESUF; + + StringList args; + args.push_back( ::helpers::path(manifest.manifest_path()).parent() / ::helpers::path(manifest.build_script()) ); + args.push_back("--crate-name"); args.push_back("build"); + //args.push_back("--crate-type"); args.push_back("bin"); + args.push_back("-o"); args.push_back(outfile); + args.push_back("-L"); args.push_back(m_output_dir.str().c_str()); + + if( this->spawn_process_mrustc(args, outfile + "_dbg.txt") ) + return outfile; + else + return ""; } bool Builder::build_library(const PackageManifest& manifest) const { @@ -303,21 +329,31 @@ bool Builder::build_library(const PackageManifest& manifest) const { // Otherwise, compile and run build script // - Load dependencies for the build script + // - TODO: Should this have already been done // - Build the script itself - //this->build_build_script( manifest ); + auto script_exe = this->build_build_script( manifest ); + if( script_exe == "" ) + return false; // - Run the script and put output in the right dir - //manifest.load_build_script( m_output_dir / "build_" + manifest.name().c_str() + ".txt" ); - throw ::std::runtime_error("TODO: Build script for " + manifest.name()); + auto out_file = m_output_dir / "build_" + manifest.name().c_str() + ".txt"; + if( !this->spawn_process(script_exe.c_str(), {}, out_file) ) + return false; + // - Load + const_cast<PackageManifest&>(manifest).load_build_script( out_file.str() ); } } return this->build_target(manifest, manifest.get_library()); } -bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfile) const +bool Builder::spawn_process_mrustc(const StringList& args, const ::helpers::path& logfile) const +{ + return spawn_process(MRUSTC_PATH, args, logfile); +} +bool Builder::spawn_process(const char* exe_name, const StringList& args, const ::helpers::path& logfile) const { #ifdef _WIN32 ::std::stringstream cmdline; - cmdline << "mrustc.exe"; + cmdline << exe_name; for (const auto& arg : args.get_vec()) cmdline << " " << arg; auto cmdline_str = cmdline.str(); @@ -340,9 +376,6 @@ bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfi WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL); } PROCESS_INFORMATION pi = { 0 }; - char env[] = - "MRUSTC_DEBUG=""\0" - ; CreateProcessA(MRUSTC_PATH, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); CloseHandle(si.hStdOutput); WaitForSingleObject(pi.hProcess, INFINITE); @@ -369,7 +402,7 @@ bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfi // Generate `argv` auto argv = args.get_vec(); - argv.insert(argv.begin(), "mrustc"); + argv.insert(argv.begin(), exe_name); //DEBUG("Calling " << argv); Debug_Print([&](auto& os){ os << "Calling"; @@ -387,7 +420,7 @@ bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfi } envp.push_back(nullptr); - if( posix_spawn(&pid, "../bin/mrustc", &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.data()) != 0 ) + if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.data()) != 0 ) { perror("posix_spawn"); DEBUG("Unable to spawn compiler"); diff --git a/tools/minicargo/build.h b/tools/minicargo/build.h index 10b3ac46..950fd539 100644 --- a/tools/minicargo/build.h +++ b/tools/minicargo/build.h @@ -22,9 +22,11 @@ public: bool build_target(const PackageManifest& manifest, const PackageTarget& target) const; bool build_library(const PackageManifest& manifest) const; + ::std::string build_build_script(const PackageManifest& manifest) const; private: - bool spawn_process(const StringList& args, const ::helpers::path& logfile) const; + bool spawn_process(const char* exe_name, const StringList& args, const ::helpers::path& logfile) const; + bool spawn_process_mrustc(const StringList& args, const ::helpers::path& logfile) const; Timestamp get_timestamp(const ::helpers::path& path) const; diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp index d65fb75f..2c1188c8 100644 --- a/tools/minicargo/main.cpp +++ b/tools/minicargo/main.cpp @@ -115,6 +115,7 @@ int ProgramOptions::parse(int argc, const char* argv[]) } else { ::std::cerr << "Unknown flag " << arg << ::std::endl; + return 1; } } } diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp index cd3d02c2..67c4e8a6 100644 --- a/tools/minicargo/manifest.cpp +++ b/tools/minicargo/manifest.cpp @@ -88,6 +88,10 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) { // Informational only, ignore } + else if( key == "links" ) + { + // TODO: Add "-l <thisname>" to command line + } else { // Unknown value in `package` @@ -146,7 +150,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) // Find/create dependency descriptor auto it = ::std::find_if(rv.m_dependencies.begin(), rv.m_dependencies.end(), [&](const auto& x) { return x.m_name == depname; }); bool was_added = (it == rv.m_dependencies.end()); - if (it == rv.m_dependencies.end()) + if( was_added ) { it = rv.m_dependencies.insert(it, PackageRef{ depname }); } @@ -155,7 +159,19 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) } else if( section == "build-dependencies" ) { - // TODO: Build deps + assert(key_val.path.size() > 1); + + const auto& depname = key_val.path[1]; + + // Find/create dependency descriptor + auto it = ::std::find_if(rv.m_build_dependencies.begin(), rv.m_build_dependencies.end(), [&](const auto& x) { return x.m_name == depname; }); + bool was_added = (it == rv.m_build_dependencies.end()); + if(was_added) + { + it = rv.m_build_dependencies.insert(it, PackageRef{ depname }); + } + + it->fill_from_kv(was_added, key_val, 2); } else if( section == "dev-dependencies" ) { @@ -172,7 +188,21 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) } else if( section == "features" ) { + const auto& name = key_val.path[1]; // TODO: Features + ::std::vector<::std::string>* list; + if(name == "default") { + list = &rv.m_default_features; + } + else { + auto tmp = rv.m_features.insert(::std::make_pair(name, ::std::vector<::std::string>())); + list = &tmp.first->second; + } + + for(const auto& sv : key_val.value.m_sub_values) + { + list->push_back( sv.as_string() ); + } } else if( section == "workspace" ) { @@ -206,7 +236,17 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) { if(tgt.m_name == "") { - tgt.m_name = rv.m_name; + tgt.m_name.reserve(rv.m_name.size()); + for(auto c : rv.m_name) + tgt.m_name += (c == '-' ? '_' : c); + } + } + + for(const auto& dep : rv.m_dependencies) + { + if( dep.m_optional ) + { + rv.m_features.insert(::std::make_pair( dep.m_name, ::std::vector<::std::string>() )); } } @@ -350,7 +390,7 @@ void PackageRef::fill_from_kv(bool was_added, const TomlKeyValue& key_val, size_ else if( attr == "default-features" ) { assert(key_val.path.size() == base_idx+1); - //this->m_use_default_features = key_val.value.as_bool(); + this->m_use_default_features = key_val.value.as_bool(); } else if( attr == "features" ) { @@ -377,21 +417,74 @@ const PackageTarget& PackageManifest::get_library() const return *it; } +void PackageManifest::set_features(const ::std::vector<::std::string>& features, bool enable_default) +{ + // TODO. + size_t start = m_active_features.size(); + // 1. Install features + if(enable_default && start == 0) + { + DEBUG("Including default features [" << m_default_features << "]"); + for(const auto& feat : m_default_features) + { + m_active_features.push_back(feat); + } + } + + for(const auto& feat : features) + { + auto it = ::std::find(m_active_features.begin(), m_active_features.end(), feat); + if(it == m_active_features.end()) + continue ; + m_active_features.push_back(feat); + } + + for(size_t i = start; i < m_active_features.size(); i ++) + { + const auto& featname = m_active_features[i]; + // Look up this feature + auto it = m_features.find(featname); + if( it != m_features.end() ) + { + DEBUG("Activating feature " << featname << " = [" << it->second << "]"); + for(const auto& sub_feat : it->second) + { + TODO("Activate feature flag " << sub_feat << " for feature " << featname); + } + } + auto it2 = ::std::find_if(m_dependencies.begin(), m_dependencies.end(), [&](const auto& x){ return x.m_name == featname; }); + if(it2 != m_dependencies.end()) + { + it2->m_optional_enabled = true; + } + } +} void PackageManifest::load_dependencies(Repository& repo) { + TRACE_FUNCTION_F(m_name); DEBUG("Loading depencencies for " << m_name); auto base_path = ::helpers::path(m_manifest_path).parent(); // 2. Recursively load dependency manifests for(auto& dep : m_dependencies) { - if( dep.m_optional ) + if( dep.m_optional && !dep.m_optional_enabled ) { - // TODO: Check for feature that enables this (option to a feature with no '/') continue ; } dep.load_manifest(repo, base_path); } + + // TODO: Only enable if build script overrides aren't enabled. + // - Loading it doesn't matter much + if( m_build_script != "" /*&& false*/ ) + { + for(auto& dep : m_build_dependencies) + { + assert( !dep.m_optional ); + dep.load_manifest(repo, base_path); + } + } } void PackageManifest::load_build_script(const ::std::string& path) @@ -491,8 +584,7 @@ void PackageRef::load_manifest(Repository& repo, const ::helpers::path& base_pat assert(m_manifest); } - // TODO: Set features on this dependency - + m_manifest->set_features(this->m_features, this->m_use_default_features); m_manifest->load_dependencies(repo); } diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h index cd39f6c4..71eb066d 100644 --- a/tools/minicargo/manifest.h +++ b/tools/minicargo/manifest.h @@ -2,6 +2,7 @@ #include <string> #include <vector> +#include <map> #include <memory> #include "path.h" @@ -120,8 +121,9 @@ class PackageRef ::std::string m_path; // Features requested by this reference - ::std::vector<::std::string> m_features; bool m_use_default_features = true; + ::std::vector<::std::string> m_features; + bool m_optional_enabled = false; ::std::shared_ptr<PackageManifest> m_manifest; @@ -137,7 +139,7 @@ public: //const ::std::string& get_repo_name() const { return m_repo; } const PackageVersionSpec& get_version() const { return m_version; } - bool is_optional() const { return m_optional; } + bool is_disabled() const { return m_optional && !m_optional_enabled; } const bool has_path() const { return m_path != ""; } const ::std::string& path() const { return m_path; } @@ -221,11 +223,16 @@ class PackageManifest ::std::string m_build_script; ::std::vector<PackageRef> m_dependencies; + ::std::vector<PackageRef> m_build_dependencies; ::std::vector<PackageTarget> m_targets; BuildScriptOutput m_build_script_output; + ::std::map<::std::string, ::std::vector<::std::string>> m_features; + ::std::vector<::std::string> m_default_features; + ::std::vector<::std::string> m_active_features; + PackageManifest(); public: @@ -249,7 +256,11 @@ public: const ::std::vector<PackageRef>& dependencies() const { return m_dependencies; } + const ::std::vector<PackageRef>& build_dependencies() const { + return m_build_dependencies; + } + void set_features(const ::std::vector<::std::string>& features, bool enable_default); void load_dependencies(Repository& repo); void load_build_script(const ::std::string& path); |