summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-08-30 21:08:51 +0800
committerJohn Hodge <tpg@mutabah.net>2017-08-31 16:31:24 +0800
commit5dce4fe24f29818b250eda177c68da5e2c7ee487 (patch)
tree5293dec3a5d154634ae211fe60997afd4bbccd67
parent4e9adae0c15e163290426db1c7d1956abc4c56f5 (diff)
downloadmrust-5dce4fe24f29818b250eda177c68da5e2c7ee487.tar.gz
minicargo - Build scripts working (mostly)
-rw-r--r--tools/minicargo/build.cpp155
-rw-r--r--tools/minicargo/build.h5
-rw-r--r--tools/minicargo/helpers.h5
-rw-r--r--tools/minicargo/manifest.cpp44
-rw-r--r--tools/minicargo/manifest.h3
-rw-r--r--tools/minicargo/path.cpp36
-rw-r--r--tools/minicargo/path.h55
7 files changed, 265 insertions, 38 deletions
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp
index f3cc74b4..56f9b076 100644
--- a/tools/minicargo/build.cpp
+++ b/tools/minicargo/build.cpp
@@ -8,14 +8,21 @@
#include <sstream> // stringstream
#ifdef _WIN32
# include <Windows.h>
-# define EXESUF ".exe"
#else
+# include <unistd.h> // getcwd/chdir
# include <spawn.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/wait.h>
# include <fcntl.h>
+#endif
+
+#ifdef _WIN32
+# define EXESUF ".exe"
+# define TARGET "x86_64-windows-msvc"
+#else
# define EXESUF ""
+# define TARGET "x86_64-unknown-linux-gnu"
#endif
struct BuildList
@@ -65,6 +72,7 @@ public:
{
}
StringList(const StringList&) = delete;
+ StringList(StringList&&) = default;
const ::std::vector<const char*>& get_vec() const
{
@@ -108,6 +116,51 @@ public:
m_strings.push_back(s);
}
};
+class StringListKV: private StringList
+{
+ ::std::vector<const char*> m_keys;
+public:
+ StringListKV()
+ {
+ }
+ StringListKV(StringListKV&& x):
+ StringList(::std::move(x)),
+ m_keys(::std::move(x.m_keys))
+ {
+ }
+
+ void push_back(const char* k, ::std::string v)
+ {
+ m_keys.push_back(k);
+ StringList::push_back(v);
+ }
+ void push_back(const char* k, const char* v)
+ {
+ m_keys.push_back(k);
+ StringList::push_back(v);
+ }
+
+ struct Iter {
+ const StringListKV& v;
+ size_t i;
+
+ void operator++() {
+ this->i++;
+ }
+ ::std::pair<const char*,const char*> operator*() {
+ return ::std::make_pair(this->v.m_keys[this->i], this->v.get_vec()[this->i]);
+ }
+ bool operator!=(const Iter& x) const {
+ return this->i != x.i;
+ }
+ };
+ Iter begin() const {
+ return Iter { *this, 0 };
+ }
+ Iter end() const {
+ return Iter { *this, m_keys.size() };
+ }
+};
struct Timestamp
{
@@ -293,8 +346,9 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget&
args.push_back(flag.c_str());
}
// TODO: Environment variables (rustc_env)
+ StringListKV env;
- return this->spawn_process_mrustc(args, outfile + "_dbg.txt");
+ return this->spawn_process_mrustc(args, ::std::move(env), outfile + "_dbg.txt");
}
::std::string Builder::build_build_script(const PackageManifest& manifest) const
{
@@ -307,7 +361,7 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget&
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") )
+ if( this->spawn_process_mrustc(args, {}, outfile + "_dbg.txt") )
return outfile;
else
return "";
@@ -327,17 +381,68 @@ bool Builder::build_library(const PackageManifest& manifest) const
}
else
{
- // Otherwise, compile and run build script
- // - Load dependencies for the build script
- // - TODO: Should this have already been done
- // - Build the script itself
- auto script_exe = this->build_build_script( manifest );
- if( script_exe == "" )
- return false;
- // - Run the script and put output in the right dir
auto out_file = m_output_dir / "build_" + manifest.name().c_str() + ".txt";
- if( !this->spawn_process(script_exe.c_str(), {}, out_file) )
- return false;
+ // If the build script output doesn't exist (TODO: Or is older than ...)
+ bool run_build_script = true;
+ auto ts_result = this->get_timestamp(out_file);
+ if( ts_result == Timestamp::infinite_past() ) {
+ DEBUG("Building " << out_file << " - Missing");
+ }
+ else if( ts_result < this->get_timestamp(MRUSTC_PATH) /*|| ts_result < this->get_timestamp("bin/minicargo")*/ ) {
+ // Rebuild (older than mrustc/minicargo)
+ DEBUG("Building " << out_file << " - Older than mrustc ( " << ts_result << " < " << this->get_timestamp(MRUSTC_PATH) << ")");
+ }
+ else
+ {
+ run_build_script = false;
+ }
+ if( run_build_script )
+ {
+ // Compile and run build script
+ // - Load dependencies for the build script
+ // - TODO: Should this have already been done
+ // - Build the script itself
+ auto script_exe = this->build_build_script( manifest );
+ if( script_exe == "" )
+ return false;
+ auto script_exe_abs = ::helpers::path(script_exe).to_absolute();
+
+ auto output_dir_abs = m_output_dir.to_absolute();
+
+ // - Run the script and put output in the right dir
+ auto out_file = output_dir_abs / "build_" + manifest.name().c_str() + ".txt";
+ // TODO: Environment variables (key-value list)
+ StringListKV env;
+ env.push_back("CARGO_MANIFEST_DIR", manifest.directory().to_absolute());
+ //env.push_back("CARGO_MANIFEST_LINKS", manifest.m_links);
+ //for(const auto& feat : manifest.m_active_features)
+ //{
+ // ::std::string fn = "CARGO_FEATURE_";
+ // for(char c : feat)
+ // fn += c == '-' ? '_' : tolower(c);
+ // env.push_back(fn, manifest.m_links);
+ //}
+ //env.push_back("CARGO_CFG_RELEASE", "");
+ env.push_back("OUT_DIR", output_dir_abs / "build_" + manifest.name().c_str());
+ env.push_back("TARGET", TARGET);
+ env.push_back("HOST", TARGET);
+ env.push_back("NUM_JOBS", "1");
+ env.push_back("OPT_LEVEL", "2");
+ env.push_back("DEBUG", "0");
+ env.push_back("PROFILE", "release");
+
+ #if _WIN32
+ #else
+ auto fd_cwd = open(".", O_DIRECTORY);
+ chdir(manifest.directory().str().c_str());
+ #endif
+ if( !this->spawn_process(script_exe_abs.str().c_str(), {}, env, out_file) )
+ return false;
+ #if _WIN32
+ #else
+ fchdir(fd_cwd);
+ #endif
+ }
// - Load
const_cast<PackageManifest&>(manifest).load_build_script( out_file.str() );
}
@@ -345,11 +450,12 @@ bool Builder::build_library(const PackageManifest& manifest) const
return this->build_target(manifest, manifest.get_library());
}
-bool Builder::spawn_process_mrustc(const StringList& args, const ::helpers::path& logfile) const
+bool Builder::spawn_process_mrustc(const StringList& args, StringListKV env, const ::helpers::path& logfile) const
{
- return spawn_process(MRUSTC_PATH, args, logfile);
+ env.push_back("MRUSTC_DEBUG", "");
+ return spawn_process(MRUSTC_PATH, args, env, logfile);
}
-bool Builder::spawn_process(const char* exe_name, const StringList& args, const ::helpers::path& logfile) const
+bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile) const
{
#ifdef _WIN32
::std::stringstream cmdline;
@@ -358,6 +464,15 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const
cmdline << " " << arg;
auto cmdline_str = cmdline.str();
DEBUG("Calling " << cmdline_str);
+
+ ::std::stringstream environ_str;
+ environ_str << "TEMP=" << getenv("TEMP") << '\0';
+ environ_str << "TMP=" << getenv("TMP") << '\0';
+ for(auto kv : env)
+ {
+ environ_str << kv.first << "=" << kv.second << '\0';
+ }
+ environ_str << '\0';
CreateDirectory(static_cast<::std::string>(logfile.parent()).c_str(), NULL);
@@ -412,15 +527,19 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const
argv.push_back(nullptr);
// Generate `envp`
- ::std::vector<const char*> envp;
+ StringList envp;
extern char **environ;
for(auto p = environ; *p; p++)
{
envp.push_back(*p);
}
+ for(auto kv : env)
+ {
+ envp.push_back(::format(kv.first, "=", kv.second));
+ }
envp.push_back(nullptr);
- if( posix_spawn(&pid, exe_name, &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.get_vec().data()) != 0 )
{
perror("posix_spawn");
DEBUG("Unable to spawn compiler");
diff --git a/tools/minicargo/build.h b/tools/minicargo/build.h
index 950fd539..d81234ec 100644
--- a/tools/minicargo/build.h
+++ b/tools/minicargo/build.h
@@ -4,6 +4,7 @@
#include "path.h"
class StringList;
+class StringListKV;
class Timestamp;
class Builder
@@ -25,8 +26,8 @@ public:
::std::string build_build_script(const PackageManifest& manifest) const;
private:
- 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;
+ bool spawn_process_mrustc(const StringList& args, StringListKV env, const ::helpers::path& logfile) const;
+ bool spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile) const;
Timestamp get_timestamp(const ::helpers::path& path) const;
diff --git a/tools/minicargo/helpers.h b/tools/minicargo/helpers.h
index d913e3c2..9f97b5bb 100644
--- a/tools/minicargo/helpers.h
+++ b/tools/minicargo/helpers.h
@@ -24,6 +24,11 @@ public:
return false;
return s[m_len] == '\0';
}
+
+ char operator[](size_t n) const {
+ return m_start[n];
+ }
+
operator ::std::string() const {
return ::std::string { m_start, m_start + m_len };
}
diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp
index dd7d8d23..5f7ecdf0 100644
--- a/tools/minicargo/manifest.cpp
+++ b/tools/minicargo/manifest.cpp
@@ -510,20 +510,50 @@ void PackageManifest::load_build_script(const ::std::string& path)
}
// cargo:rustc-link-search=foo/bar/baz
else if( key == "rustc-link-search" ) {
- // TODO: Check for an = (otherwise default to dynamic)
- throw ::std::runtime_error("TODO: rustc-link-search");
+ // Check for an = (otherwise default to native)
+ ::std::string value_str = value;
+ auto pos = value_str.find_first_of('=');
+ const char* type = "native";
+ ::std::string name;
+ if(pos == ::std::string::npos) {
+ name = ::std::move(value_str);
+ }
+ else {
+ name = value_str.substr(pos+1);
+ auto ty_str = value_str.substr(0, pos);
+ if( ty_str == "native" ) {
+ type = "native";
+ }
+ else {
+ throw ::std::runtime_error(::format("TODO: rustc-link-search ", ty_str));
+ }
+ }
+ rv.rustc_link_search.push_back(::std::make_pair(type, ::std::move(name)));
}
// cargo:rustc-link-lib=mysql
else if( key == "rustc-link-lib" ) {
- // TODO: Check for an = (otherwise default to dynamic)
- ::std::string lazy = value;
- auto pos = lazy.find_first_of('=');
+ // Check for an = (otherwise default to dynamic)
+ ::std::string value_str = value;
+ auto pos = value_str.find_first_of('=');
+ const char* type = "static";
+ ::std::string name;
if(pos == ::std::string::npos) {
- rv.rustc_link_lib.push_back(::std::make_pair("static", lazy));
+ name = ::std::move(value_str);
}
else {
- throw ::std::runtime_error("TODO: rustc-link-lib");
+ name = value_str.substr(pos+1);
+ auto ty_str = value_str.substr(0, pos);
+ if( ty_str == "static" ) {
+ type = "static";
+ }
+ else if( ty_str == "dynamic" ) {
+ type = "dynamic";
+ }
+ else {
+ throw ::std::runtime_error(::format("TODO: rustc-link-lib ", ty_str));
+ }
}
+ rv.rustc_link_lib.push_back(::std::make_pair(type, ::std::move(name)));
}
// cargo:rustc-cfg=foo
else if( key == "rustc-cfg" ) {
diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h
index a17db929..8baf766e 100644
--- a/tools/minicargo/manifest.h
+++ b/tools/minicargo/manifest.h
@@ -241,6 +241,9 @@ public:
const PackageTarget& get_library() const;
+ const ::helpers::path directory() const {
+ return ::helpers::path(m_manifest_path).parent();
+ }
const ::std::string& manifest_path() const {
return m_manifest_path;
}
diff --git a/tools/minicargo/path.cpp b/tools/minicargo/path.cpp
index d0316548..93281e0f 100644
--- a/tools/minicargo/path.cpp
+++ b/tools/minicargo/path.cpp
@@ -1,6 +1,10 @@
/*
*/
#include "path.h"
+#if _WIN32
+#else
+# include <unistd.h> // getcwd/chdir
+#endif
helpers::path::path(const char* s):
m_str(s)
@@ -28,6 +32,36 @@ helpers::path::path(const char* s):
}
}
+helpers::path helpers::path::to_absolute() const
+{
+ if(!this->is_valid())
+ throw ::std::runtime_error("Calling to_absolute() on an invalid path");
+
+ if(this->m_str[0] == SEP)
+ return *this;
+
+ #if _WIN32
+ #else
+ char cwd[1024];
+ if( !getcwd(cwd, sizeof(cwd)) )
+ throw ::std::runtime_error("Calling getcwd() failed in path::to_absolute()");
+ #endif
+ auto rv = path(cwd);
+ for(auto comp : *this)
+ {
+ if(comp == ".")
+ ;
+ else if( comp == ".." )
+ rv.pop_component();
+ else
+ rv /= comp;
+ }
+ #if _WIN32
+ #else
+ #endif
+ return rv;
+}
+
helpers::path helpers::path::normalise() const
{
path rv;
@@ -154,4 +188,4 @@ void helpers::path::ComponentsIter::operator++()
if(end == ::std::string::npos)
end = p.m_str.size();
}
-} \ No newline at end of file
+}
diff --git a/tools/minicargo/path.h b/tools/minicargo/path.h
index 54cb8f40..833fe90a 100644
--- a/tools/minicargo/path.h
+++ b/tools/minicargo/path.h
@@ -31,26 +31,45 @@ public:
return m_str != "";
}
- path operator/(const path& p) const
+ path& operator/=(const path& p)
{
- if(!this->is_valid())
- throw ::std::runtime_error("Appending to an invalid path");
if(!p.is_valid())
throw ::std::runtime_error("Appending from an invalid path");
- if(p.m_str[0] == '/')
+
+ return *this /= p.m_str.c_str();
+ }
+ path& operator/=(const char* o)
+ {
+ if(!this->is_valid())
+ throw ::std::runtime_error("Appending to an invalid path");
+ if(o[0] == '/')
throw ::std::runtime_error("Appending an absolute path to another path");
- return *this / p.m_str.c_str();
+ this->m_str.push_back(SEP);
+ this->m_str.append(o);
+ return *this;
}
- /// Append a relative path
- path operator/(const char* o) const
+ path& operator/=(const string_view& o)
{
if(!this->is_valid())
throw ::std::runtime_error("Appending to an invalid path");
- if (o[0] == '/')
+ if(o[0] == '/')
throw ::std::runtime_error("Appending an absolute path to another path");
+ this->m_str.push_back(SEP);
+ this->m_str += o;
+ return *this;
+ }
+
+ path operator/(const path& p) const
+ {
auto rv = *this;
- rv.m_str.push_back(SEP);
- rv.m_str.append(o);
+ rv /= p;
+ return rv;
+ }
+ /// Append a relative path
+ path operator/(const char* o) const
+ {
+ auto rv = *this;
+ rv /= o;
return rv;
}
/// Add an arbitary string to the final component
@@ -65,6 +84,21 @@ public:
return rv;
}
+ bool pop_component()
+ {
+ if(!this->is_valid())
+ throw ::std::runtime_error("Calling pop_component() on an invalid path");
+ auto pos = m_str.find_last_of(SEP);
+ if(pos == ::std::string::npos || pos == 0)
+ {
+ return false;
+ }
+ else
+ {
+ this->m_str.resize(pos);
+ return true;
+ }
+ }
path parent() const
{
if(!this->is_valid())
@@ -81,6 +115,7 @@ public:
return rv;
}
}
+ path to_absolute() const;
const ::std::string& str() const
{