diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-05-12 17:09:58 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-05-12 17:09:58 +0800 |
commit | 65fa34c0f38bc1511ff2fee7efc4744d66b15a46 (patch) | |
tree | 9ffca2b85793e5a9c79fbceb88c36573d1c438ae /tools | |
parent | 1345b89c88d32fed62df16e492e18bcf7ded477c (diff) | |
download | mrust-65fa34c0f38bc1511ff2fee7efc4744d66b15a46.tar.gz |
minicargo - dependency file support, planning for dylibs
Diffstat (limited to 'tools')
-rw-r--r-- | tools/minicargo/build.cpp | 141 | ||||
-rw-r--r-- | tools/minicargo/manifest.cpp | 21 | ||||
-rw-r--r-- | tools/minicargo/manifest.h | 9 |
3 files changed, 165 insertions, 6 deletions
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp index 7b2027d4..2bf32ac8 100644 --- a/tools/minicargo/build.cpp +++ b/tools/minicargo/build.cpp @@ -24,6 +24,7 @@ extern int _putenv_s(const char*, const char*); #include <vector> #include <algorithm> #include <sstream> // stringstream +#include <fstream> // ifstream #include <cstdlib> // setenv #ifndef DISABLE_MULTITHREAD # include <thread> @@ -51,8 +52,10 @@ extern int _putenv_s(const char*, const char*); #ifdef _WIN32 # define EXESUF ".exe" +# define DLLSUF ".dll" #else # define EXESUF "" +# define DLLSUF ".so" #endif #include <target_detect.h> // tools/common/target_detect.h #define HOST_TARGET DEFAULT_TARGET_NAME @@ -612,6 +615,8 @@ Builder::Builder(BuildOptions opts, size_t total_targets): if(crate_type) { *crate_type = target.m_is_proc_macro ? "proc-macro" : "rlib"; } + // TODO: Support dylibs (e.g. if target.m_crate_types is just dylib, + // emit a dylib) outfile /= ::format("lib", target.m_name, crate_suffix, ".hir"); break; case PackageTarget::Type::Bin: @@ -619,6 +624,7 @@ Builder::Builder(BuildOptions opts, size_t total_targets): *crate_type = "bin"; outfile /= ::format(target.m_name, EXESUF); break; + break; default: throw ::std::runtime_error("Unknown target type being built"); } @@ -627,11 +633,115 @@ Builder::Builder(BuildOptions opts, size_t total_targets): return outfile; } +namespace { + ::std::map< ::std::string, ::std::vector<helpers::path> > load_depfile(const helpers::path& depfile_path) + { + ::std::map< ::std::string, ::std::vector<helpers::path> > rv; + ::std::ifstream ifp(depfile_path); + if( ifp.good() ) + { + // Load space-separated (backslash-escaped) paths + struct Lexer { + ::std::ifstream ifp; + char m_c; + + Lexer(::std::ifstream ifp) + :ifp(::std::move(ifp)) + ,m_c(0) + { + nextc(); + } + + bool nextc() { + int v = ifp.get(); + if( v == EOF ) { + m_c = '\0'; + return false; + } + else { + m_c = (char)v; + return true; + } + } + ::std::string get_token() { + auto t = get_token_int(); + DEBUG("get_token '" << t << "'"); + return t; + } + ::std::string get_token_int() { + if( ifp.eof() ) + return ""; + while( m_c == ' ' ) + { + if( !nextc() ) + return ""; + } + if( m_c == '\n' ) { + nextc(); + return "\n"; + } + if( m_c == '\t' ) { + nextc(); + return "\t"; + } + ::std::string rv; + do { + if( m_c == '\\' ) + { + nextc(); + if( m_c == ' ' ) { + rv += m_c; + } + else if( m_c == ':' ) { + rv += m_c; + } + // HACK: Only spaces are escaped this way? + else { + rv += '\\'; + rv += m_c; + } + } + else + { + rv += m_c; + } + } while( nextc() && m_c != ' ' && m_c != ':' && m_c != '\n' ); + return rv; + } + } lexer(::std::move(ifp)); + + // Look for <string> ":" [<string>]* "\n" + do { + auto t = lexer.get_token(); + if( t == "" ) + break; + if( t == "\n" ) + continue ; + + auto v = rv.insert(::std::make_pair(t, ::std::vector<helpers::path>())); + auto& list = v.first->second; + auto target = t; + t = lexer.get_token(); + assert(t == ":"); + + do { + t = lexer.get_token(); + if( t == "\n" || t == "" ) + break ; + list.push_back(t); + } while(1); + } while(1); + } + return rv; + } +} + bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& target, bool is_for_host, size_t index) const { const char* crate_type; ::std::string crate_suffix; auto outfile = this->get_crate_path(manifest, target, is_for_host, &crate_type, &crate_suffix); + auto depfile = outfile + ".d"; size_t this_target_idx = (index != ~0u ? m_targets_built++ : ~0u); @@ -655,10 +765,30 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& DEBUG("Building " << outfile << " - Older than mrustc ( " << ts_result << " < " << Timestamp::for_file(m_compiler_path) << ")"); } else { - // TODO: Check dependencies. (from depfile) - // Don't rebuild (no need to) - DEBUG("Not building " << outfile << " - not out of date"); - return true; + // Check dependencies. (from depfile) + auto depfile_ents = load_depfile(depfile); + auto it = depfile_ents.find(outfile); + bool has_new_file = false; + if( it != depfile_ents.end() ) + { + for(const auto& f : it->second) + { + auto dep_ts = Timestamp::for_file(f); + if( ts_result < dep_ts ) + { + has_new_file = true; + DEBUG("Rebuilding " << outfile << ", older than " << f); + break; + } + } + } + + if( !has_new_file ) + { + // Don't rebuild (no need to) + DEBUG("Not building " << outfile << " - not out of date"); + return true; + } } for(const auto& cmd : manifest.build_script_output().pre_build_commands) @@ -682,8 +812,10 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& } StringList args; args.push_back(::helpers::path(manifest.manifest_path()).parent() / ::helpers::path(target.m_path)); + args.push_back("-o"); args.push_back(outfile); args.push_back("--crate-name"); args.push_back(target.m_name.c_str()); args.push_back("--crate-type"); args.push_back(crate_type); + args.push_back("-C"); args.push_back(format("emit-depfile=",depfile)); if( !crate_suffix.empty() ) { args.push_back("--crate-tag"); args.push_back(crate_suffix.c_str() + 1); } @@ -709,7 +841,6 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& args.push_back("-C"); args.push_back("codegen-type=monomir"); } - args.push_back("-o"); args.push_back(outfile); args.push_back("-L"); args.push_back(this->get_output_dir(is_for_host).str()); for(const auto& dir : manifest.build_script_output().rustc_link_search) { args.push_back("-L"); args.push_back(dir.second.c_str()); diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp index 8f49c538..be2e1c77 100644 --- a/tools/minicargo/manifest.cpp +++ b/tools/minicargo/manifest.cpp @@ -434,7 +434,26 @@ namespace } else if( key == "crate-type" ) { - // TODO: Support crate types + //assert_kv_size(kv, base_idx + 1); + //assert_type(kv, base_idx + 1); + assert(kv.path.size() == base_idx + 1); + if( !target.m_crate_types.empty() ) { + // TODO: Error, multiple instances + } + for(const auto& sv : kv.value.m_sub_values) + { + const auto& s = sv.as_string(); + if(s == "rlib") { + target.m_crate_types.push_back(PackageTarget::CrateType::rlib); + } + else if(s == "dylib") { + target.m_crate_types.push_back(PackageTarget::CrateType::dylib); + } + // TODO: Other crate types + else { + throw ::std::runtime_error(format("Unknown crate type - ", s)); + } + } } else if( key == "required-features" ) { diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h index be19a7b1..54374dc2 100644 --- a/tools/minicargo/manifest.h +++ b/tools/minicargo/manifest.h @@ -190,6 +190,14 @@ struct PackageTarget Bench, Example, }; + enum class CrateType + { + dylib, + rlib, + staticlib, + cdylib, + proc_macro, + }; Type m_type; ::std::string m_name; @@ -202,6 +210,7 @@ struct PackageTarget bool m_is_proc_macro = false; bool m_is_own_harness = false; + ::std::vector<CrateType> m_crate_types; ::std::vector<::std::string> m_required_features; PackageTarget(Type ty): |