diff options
Diffstat (limited to 'tools/minicargo/build.cpp')
-rw-r--r-- | tools/minicargo/build.cpp | 155 |
1 files changed, 137 insertions, 18 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"); |