summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-08-28 13:33:05 +0800
committerJohn Hodge <tpg@mutabah.net>2017-08-31 16:31:24 +0800
commit773c7e17fea5b6f43357a5ed125ba0cdd82ac72d (patch)
tree7c828eccdebe95d72725070b2f5c516e41609bbb
parent0f3b5722d594bec8c425dd64cecbd63e3b5ca228 (diff)
downloadmrust-773c7e17fea5b6f43357a5ed125ba0cdd82ac72d.tar.gz
minicargo - Features and build scripts (draft)
-rw-r--r--tools/minicargo/build.cpp71
-rw-r--r--tools/minicargo/build.h4
-rw-r--r--tools/minicargo/main.cpp1
-rw-r--r--tools/minicargo/manifest.cpp108
-rw-r--r--tools/minicargo/manifest.h15
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);