summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-08-20 22:16:09 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-08-20 22:16:09 +0800
commit739443094434e2622abd1fea5d2b5a03bc1ba0ef (patch)
treedbc593a8fd14e95c2c73dd441e513aee21d03824
parent10e0d9a2609cc2b4d30c38e7f1f20e11de432fd6 (diff)
parenta99e49b7505d2912d8699d4c791b8b30c194024b (diff)
downloadmrust-739443094434e2622abd1fea5d2b5a03bc1ba0ef.tar.gz
Merge branch 'master' of https://github.com/thepowersgang/mrustc
-rw-r--r--.gitignore1
-rw-r--r--src/ast/crate.cpp23
-rw-r--r--src/ast/crate.hpp3
-rw-r--r--src/expand/format_args.cpp2
-rw-r--r--src/hir/from_ast_expr.cpp2
-rw-r--r--src/main.cpp11
-rw-r--r--src/trans/codegen_c.cpp246
-rw-r--r--tools/minicargo/Makefile6
-rw-r--r--tools/minicargo/build.cpp230
-rw-r--r--tools/minicargo/debug.h4
-rw-r--r--tools/minicargo/helpers.h191
-rw-r--r--tools/minicargo/main.cpp39
-rw-r--r--tools/minicargo/manifest.cpp174
-rw-r--r--tools/minicargo/manifest.h52
-rw-r--r--tools/minicargo/repository.cpp70
-rw-r--r--tools/minicargo/repository.h29
-rw-r--r--tools/minicargo/toml.cpp13
-rw-r--r--tools/minicargo/toml.h21
-rw-r--r--vsproject/minicargo/minicargo.vcxproj2
-rw-r--r--vsproject/minicargo/minicargo.vcxproj.filters6
-rw-r--r--vsproject/mrustc.sln3
-rw-r--r--vsproject/mrustc.vcxproj.filters180
22 files changed, 1036 insertions, 272 deletions
diff --git a/.gitignore b/.gitignore
index 4488f48c..b1d89c5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,4 @@
/bnf/rust.tab.h
/bnf/rust.output
/bnf/test.bin
+/vsproject/output
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp
index 394cd47b..f003a00b 100644
--- a/src/ast/crate.cpp
+++ b/src/ast/crate.cpp
@@ -8,6 +8,9 @@
#include <hir/main_bindings.hpp> // HIR_Deserialise
#include <fstream>
+::std::vector<::std::string> AST::g_crate_load_dirs = { };
+::std::map<::std::string, ::std::string> AST::g_crate_overrides;
+
namespace {
bool check_item_cfg(const ::AST::MetaItems& attrs)
{
@@ -99,15 +102,23 @@ void Crate::load_externs()
void Crate::load_extern_crate(Span sp, const ::std::string& name)
{
DEBUG("Loading crate '" << name << "'");
- // TODO: Search a list of load paths for the crate
- ::std::vector< ::std::string> paths { "output/", "output/test_deps/" };
::std::string path;
- for(const auto& p : paths){
- path = p + "lib" + name + ".hir";
+ auto it = g_crate_overrides.find(name);
+ if(it != g_crate_overrides.end())
+ {
+ path = it->second;
+ }
+ else
+ {
+ // Search a list of load paths for the crate
+ for(const auto& p : g_crate_load_dirs)
+ {
+ path = p + "/lib" + name + ".hir";
- if( ::std::ifstream(path).good() ) {
- break ;
+ if( ::std::ifstream(path).good() ) {
+ break ;
+ }
}
}
if( !::std::ifstream(path).good() ) {
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
index f9594a83..53dea1b9 100644
--- a/src/ast/crate.hpp
+++ b/src/ast/crate.hpp
@@ -89,4 +89,7 @@ public:
const MacroRules* find_macro_rules(const ::std::string& name) const;
};
+extern ::std::vector<::std::string> g_crate_load_dirs;
+extern ::std::map<::std::string, ::std::string> g_crate_overrides;
+
} // namespace AST
diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp
index 92afcbb2..e4c02b8b 100644
--- a/src/expand/format_args.cpp
+++ b/src/expand/format_args.cpp
@@ -477,7 +477,7 @@ class CFormatArgsExpander:
auto expr_tt = TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, Parse_Expr0(lex).release()) ));
- auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), named_args.size()) );
+ auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), static_cast<unsigned>(named_args.size())) );
if( ins_rv.second == false ) {
ERROR(sp, E0000, "Duplicate definition of named argument `" << ins_rv.first->first << "`");
}
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index 9bbb0418..545873ed 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -441,6 +441,8 @@ struct LowerHIR_ExprNode_Visitor:
case CORETYPE_U32: return ::HIR::CoreType::U32;
case CORETYPE_I64: return ::HIR::CoreType::I64;
case CORETYPE_U64: return ::HIR::CoreType::U64;
+ case CORETYPE_I128: return ::HIR::CoreType::I128;
+ case CORETYPE_U128: return ::HIR::CoreType::U128;
case CORETYPE_INT: return ::HIR::CoreType::Isize;
case CORETYPE_UINT: return ::HIR::CoreType::Usize;
diff --git a/src/main.cpp b/src/main.cpp
index 7b1d94be..b883a828 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -224,6 +224,11 @@ int main(int argc, char *argv[])
// Load external crates.
CompilePhaseV("LoadCrates", [&]() {
+ // Hacky!
+ for(const auto& ld : params.lib_search_dirs)
+ {
+ AST::g_crate_load_dirs.push_back(ld);
+ }
crate.load_externs();
});
@@ -570,6 +575,12 @@ int main(int argc, char *argv[])
// ::std::cerr << "Internal Compiler Error: " << e << ::std::endl;
// return 2;
//}
+
+ // TODO: Make this conditional
+#if 0
+ ::std::cout << "Press enter to exit..." << ::std::endl;
+ ::std::cin.get();
+#endif
return 0;
}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 973aa33a..b7c3806a 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -499,7 +499,9 @@ namespace {
break;
case Compiler::Msvc:
is_windows = true;
+ // TODO: Look up these paths in the registry and use CreateProcess instead of system
args.push_back(cache_str( detect_msvc().path_vcvarsall ));
+ //args.push_back("amd64");
args.push_back("&");
args.push_back("cl.exe");
args.push_back("/nologo");
@@ -568,8 +570,9 @@ namespace {
}
//DEBUG("- " << cmd_ss.str());
::std::cout << "Running comamnd - " << cmd_ss.str() << ::std::endl;
- if( system(cmd_ss.str().c_str()) )
+ if( system(cmd_ss.str().c_str()) != 0 )
{
+ ::std::cerr << "C Compiler failed to execute" << ::std::endl;
abort();
}
}
@@ -2036,82 +2039,17 @@ namespace {
if( e.flag_idx != ~0u )
m_of << indent << "}\n";
break; }
- case ::MIR::Statement::TAG_Asm: {
- const auto& e = stmt.as_Asm();
-
- struct H {
- static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) {
- return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x){return x==des;}) != flags.end();
- }
- static const char* convert_reg(const char* r) {
- if( ::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0 ) {
- return "a";
- }
- else {
- return r;
- }
- }
- };
- bool is_volatile = H::has_flag(e.flags, "volatile");
- bool is_intel = H::has_flag(e.flags, "intel");
-
- m_of << indent << "__asm__ ";
- if(is_volatile) m_of << "__volatile__";
- // TODO: Convert format string?
- // TODO: Use a C-specific escaper here.
- m_of << "(\"" << (is_intel ? ".syntax intel; " : "");
- for(auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
- {
- if( *it == '\n' )
- m_of << ";\\n";
- else if( *it == '"' )
- m_of << "\\\"";
- else if( *it == '\\' )
- m_of << "\\\\";
- else if( *it == '/' && *(it+1) == '/' )
- {
- while( it != e.tpl.end() || *it == '\n' )
- ++it;
- -- it;
- }
- else if( *it == '%' && *(it+1) == '%' )
- m_of << "%";
- else if( *it == '%' && !isdigit(*(it+1)) )
- m_of << "%%";
- else
- m_of << *it;
- }
- m_of << (is_intel ? ".syntax att; " : "") << "\"";
- m_of << ": ";
- for(unsigned int i = 0; i < e.outputs.size(); i ++ )
- {
- const auto& v = e.outputs[i];
- if( i != 0 ) m_of << ", ";
- m_of << "\"";
- switch(v.first[0])
- {
- case '=': m_of << "="; break;
- case '+': m_of << "+"; break;
- default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'");
- }
- m_of << H::convert_reg(v.first.c_str()+1);
- m_of << "\"("; emit_lvalue(v.second); m_of << ")";
- }
- m_of << ": ";
- for(unsigned int i = 0; i < e.inputs.size(); i ++ )
- {
- const auto& v = e.inputs[i];
- if( i != 0 ) m_of << ", ";
- m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")";
- }
- m_of << ": ";
- for(unsigned int i = 0; i < e.clobbers.size(); i ++ )
+ case ::MIR::Statement::TAG_Asm:
+ switch(m_compiler)
{
- if( i != 0 ) m_of << ", ";
- m_of << "\"" << e.clobbers[i] << "\"";
+ case Compiler::Gcc:
+ this->emit_asm_gcc(mir_res, stmt.as_Asm(), indent_level);
+ break;
+ case Compiler::Msvc:
+ this->emit_asm_msvc(mir_res, stmt.as_Asm(), indent_level);
+ break;
}
- m_of << ");\n";
- break; }
+ break;
case ::MIR::Statement::TAG_Assign: {
const auto& e = stmt.as_Assign();
DEBUG("- " << e.dst << " = " << e.src);
@@ -2815,6 +2753,121 @@ namespace {
}
m_of << " );\n";
}
+ void emit_asm_gcc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level)
+ {
+ auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) };
+ struct H {
+ static bool has_flag(const ::std::vector<::std::string>& flags, const char* des) {
+ return ::std::find_if(flags.begin(), flags.end(), [des](const auto&x) {return x == des; }) != flags.end();
+ }
+ static const char* convert_reg(const char* r) {
+ if (::std::strcmp(r, "{eax}") == 0 || ::std::strcmp(r, "{rax}") == 0) {
+ return "a";
+ }
+ else {
+ return r;
+ }
+ }
+ };
+ bool is_volatile = H::has_flag(e.flags, "volatile");
+ bool is_intel = H::has_flag(e.flags, "intel");
+
+
+ m_of << indent << "__asm__ ";
+ if (is_volatile) m_of << "__volatile__";
+ // TODO: Convert format string?
+ // TODO: Use a C-specific escaper here.
+ m_of << "(\"" << (is_intel ? ".syntax intel; " : "");
+ for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
+ {
+ if (*it == '\n')
+ m_of << ";\\n";
+ else if (*it == '"')
+ m_of << "\\\"";
+ else if (*it == '\\')
+ m_of << "\\\\";
+ else if (*it == '/' && *(it + 1) == '/')
+ {
+ while (it != e.tpl.end() || *it == '\n')
+ ++it;
+ --it;
+ }
+ else if (*it == '%' && *(it + 1) == '%')
+ m_of << "%";
+ else if (*it == '%' && !isdigit(*(it + 1)))
+ m_of << "%%";
+ else
+ m_of << *it;
+ }
+ m_of << (is_intel ? ".syntax att; " : "") << "\"";
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.outputs.size(); i++)
+ {
+ const auto& v = e.outputs[i];
+ if (i != 0) m_of << ", ";
+ m_of << "\"";
+ switch (v.first[0])
+ {
+ case '=': m_of << "="; break;
+ case '+': m_of << "+"; break;
+ default: MIR_TODO(mir_res, "Handle asm! output leader '" << v.first[0] << "'");
+ }
+ m_of << H::convert_reg(v.first.c_str() + 1);
+ m_of << "\"("; emit_lvalue(v.second); m_of << ")";
+ }
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.inputs.size(); i++)
+ {
+ const auto& v = e.inputs[i];
+ if (i != 0) m_of << ", ";
+ m_of << "\"" << v.first << "\"("; emit_lvalue(v.second); m_of << ")";
+ }
+ m_of << ": ";
+ for (unsigned int i = 0; i < e.clobbers.size(); i++)
+ {
+ if (i != 0) m_of << ", ";
+ m_of << "\"" << e.clobbers[i] << "\"";
+ }
+ m_of << ");\n";
+ }
+ void emit_asm_msvc(const ::MIR::TypeResolve& mir_res, const ::MIR::Statement::Data_Asm& e, unsigned indent_level)
+ {
+ auto indent = RepeatLitStr{ "\t", static_cast<int>(indent_level) };
+
+ if( !e.inputs.empty() || !e.outputs.empty() )
+ {
+ MIR_TODO(mir_res, "Inputs/outputs in msvc inline assembly");
+#if 0
+ m_of << indent << "{\n";
+ for(size_t i = 0; i < e.inputs.size(); i ++)
+ {
+ m_of << indent << "auto asm_i_" << i << " = ";
+ emit_lvalue(e.inputs[i]);
+ }
+#endif
+ }
+
+ m_of << indent << "__asm {\n";
+
+ m_of << indent << "\t";
+ for (auto it = e.tpl.begin(); it != e.tpl.end(); ++it)
+ {
+ if (*it == ';')
+ {
+ m_of << "\n";
+ m_of << indent << "\t";
+ }
+ else
+ m_of << *it;
+ }
+
+ m_of << "\n" << indent << "}";
+ if (!e.inputs.empty() || !e.outputs.empty())
+ {
+ m_of << "}";
+ }
+ m_of << ";\n";
+ }
private:
const ::HIR::TypeRef& monomorphise_fcn_return(::HIR::TypeRef& tmp, const ::HIR::Function& item, const Trans_Params& params)
{
@@ -2960,6 +3013,7 @@ namespace {
m_of << ", "<<o_succ<<", "<<o_fail<<")";
break;
case Compiler::Msvc:
+ emit_lvalue(e.ret_val); m_of << "._0 = ";
emit_msvc_atomic_op("InterlockedCompareExchange", ""); // TODO: Use ordering
if(params.m_types.at(0) == ::HIR::CoreType::Usize || params.m_types.at(0) == ::HIR::CoreType::Isize)
{
@@ -2969,6 +3023,8 @@ namespace {
{
emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ", "; emit_param(e.args.at(2)); m_of << ")";
}
+ m_of << ";\n\t";
+ emit_lvalue(e.ret_val); m_of << "._1 = ("; emit_lvalue(e.ret_val); m_of << "._0 == "; emit_param(e.args.at(2)); m_of << ")";
break;
}
};
@@ -3349,7 +3405,16 @@ namespace {
{
m_of << "shl128";
if(params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
- m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", ";
+ emit_param(e.args.at(1));
+ // If the shift type is a u128/i128, get the inner
+ ::HIR::TypeRef tmp;
+ const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1));
+ if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 )
+ {
+ m_of << ".lo";
+ }
+ m_of << ")";
}
else
{
@@ -3362,7 +3427,16 @@ namespace {
{
m_of << "shr128";
if (params.m_types.at(0) == ::HIR::CoreType::I128) m_of << "s";
- m_of << "("; emit_param(e.args.at(0)); m_of << ", "; emit_param(e.args.at(1)); m_of << ")";
+ m_of << "("; emit_param(e.args.at(0)); m_of << ", ";
+ emit_param(e.args.at(1));
+ // If the shift type is a u128/i128, get the inner
+ ::HIR::TypeRef tmp;
+ const auto& shift_ty = mir_res.get_param_type(tmp, e.args.at(1));
+ if( shift_ty == ::HIR::CoreType::I128 || shift_ty == ::HIR::CoreType::U128 )
+ {
+ m_of << ".lo";
+ }
+ m_of << ")";
}
else
{
@@ -4154,13 +4228,21 @@ namespace {
m_of << "\", " << ::std::dec << c.size() << ")";
),
(Const,
- // TODO: This should have been eliminated?
- // NOTE: GCC hack - statement expressions
+ // TODO: This should have been eliminated? ("MIR Cleanup" should have removed all inline Const references)
::HIR::TypeRef ty;
const auto& lit = get_literal_for_const(c.p, ty);
- m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; ";
- assign_from_literal([&](){ m_of << "v"; }, ty, lit);
- m_of << "; v;})";
+ if(lit.is_Integer() || lit.is_Float() || lit.is_String())
+ {
+ emit_literal(ty, lit, {});
+ }
+ else
+ {
+ // NOTE: GCC hack - statement expressions
+ MIR_ASSERT(*m_mir_res, m_compiler == Compiler::Gcc, "TODO: Support inline constants without statement expressions");
+ m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; ";
+ assign_from_literal([&](){ m_of << "v"; }, ty, lit);
+ m_of << "; v;})";
+ }
),
(ItemAddr,
TU_MATCHA( (c.m_data), (pe),
diff --git a/tools/minicargo/Makefile b/tools/minicargo/Makefile
index ff7a5f4f..ab3f8531 100644
--- a/tools/minicargo/Makefile
+++ b/tools/minicargo/Makefile
@@ -9,10 +9,11 @@ V ?= @
OBJDIR := .obj/
BIN := ../bin/minicargo
-OBJS := main.o
+OBJS := main.o build.o manifest.o repository.o
+OBJS += toml.o
LINKFLAGS :=
-CXXFLAGS := -Wall
+CXXFLAGS := -Wall -std=c++14
OBJS := $(OBJS:%=$(OBJDIR)%)
@@ -29,6 +30,7 @@ $(BIN): $(OBJS)
$V$(CXX) -o $@ $(OBJS) $(LINKFLAGS)
$(OBJDIR)%.o: %.cpp
+ @mkdir -p $(dir $@)
@echo [CXX] $<
$V$(CXX) -o $@ -c $< $(CXXFLAGS) -MMD -MP -MF $@.dep
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp
index 1d9b30ba..8127fbf0 100644
--- a/tools/minicargo/build.cpp
+++ b/tools/minicargo/build.cpp
@@ -1,8 +1,20 @@
/*
*/
#include "manifest.h"
+#include "debug.h"
#include <vector>
#include <algorithm>
+#include <sstream> // stringstream
+#include "helpers.h" // path
+#ifdef _WIN32
+# include <Windows.h>
+#else
+# include <spawn.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/wait.h>
+# include <fcntl.h>
+#endif
struct BuildList
{
@@ -12,6 +24,7 @@ struct BuildList
};
::std::vector<BuildEnt> m_list;
+ void add_dependencies(const PackageManifest& p, unsigned level);
void add_package(const PackageManifest& p, unsigned level);
void sort_list();
@@ -41,28 +54,79 @@ struct BuildList
}
};
+class Builder
+{
+ class StringList
+ {
+ ::std::vector<::std::string> m_cached;
+ ::std::vector<const char*> m_strings;
+ public:
+ StringList()
+ {
+ }
+
+ const ::std::vector<const char*>& get_vec() const
+ {
+ return m_strings;
+ }
+
+ void push_back(::std::string s)
+ {
+ m_cached.push_back(::std::move(s));
+ m_strings.push_back(m_cached.back().c_str());
+ }
+ void push_back(const char* s)
+ {
+ m_strings.push_back(s);
+ }
+ };
+
+public:
+ bool build_target(const PackageManifest& manifest, const PackageTarget& target) const;
+ bool build_library(const PackageManifest& manifest) const;
+
+private:
+ bool spawn_process(const StringList& args, const ::helpers::path& logfile) const;
+};
+
void MiniCargo_Build(const PackageManifest& manifest)
{
BuildList list;
- // Generate sorted dependency list
- for (const auto& dep : manifest.dependencies())
+
+ list.add_dependencies(manifest, 0);
+
+ list.sort_list();
+ // dedup?
+ for(const auto& p : list.iter())
{
- list.add_package(dep.get_package(), 1);
+ DEBUG("WILL BUILD " << p.name() << " from " << p.manifest_path());
}
-
// Build dependencies
+ Builder builder;
for(const auto& p : list.iter())
{
- if( ! p.build_lib() )
- return ;
+ if( ! builder.build_library(p) )
+ {
+ return;
+ }
}
- if( ! manifest.build_lib() )
- return ;
// TODO: If the manifest doesn't have a library, build the binary
+ builder.build_library(manifest);
}
+void BuildList::add_dependencies(const PackageManifest& p, unsigned level)
+{
+ for (const auto& dep : p.dependencies())
+ {
+ if( dep.is_optional() )
+ {
+ continue ;
+ }
+ add_package(dep.get_package(), level+1);
+ }
+}
void BuildList::add_package(const PackageManifest& p, unsigned level)
{
for(auto& ent : m_list)
@@ -82,4 +146,154 @@ void BuildList::add_package(const PackageManifest& p, unsigned level)
void BuildList::sort_list()
{
::std::sort(m_list.begin(), m_list.end(), [](const auto& a, const auto& b){ return a.level < b.level; });
+
+ for(auto it = m_list.begin(); it != m_list.end(); )
+ {
+ auto it2 = ::std::find_if(m_list.begin(), it, [&](const auto& x){ return x.package == it->package; });
+ if( it2 != it )
+ {
+ it = m_list.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& target) const
+{
+ auto outdir = ::helpers::path("output");
+ auto outfile = outdir / ::format("lib", target.m_name, ".hir");
+
+ // TODO: Determine if it needs re-running
+ // Rerun if:
+ // > `outfile` is missing
+ // > mrustc/minicargo is newer than `outfile`
+ // > build script has changed
+ // > any input file has changed (requires depfile from mrustc)
+
+ StringList args;
+ args.push_back(::helpers::path(manifest.manifest_path()).parent() / ::helpers::path(target.m_path));
+ args.push_back("--crate-name"); args.push_back(target.m_name.c_str());
+ args.push_back("--crate-type"); args.push_back("rlib");
+ args.push_back("-o"); args.push_back(outfile);
+ args.push_back("-L"); args.push_back(outdir);
+ //for(const auto& dir : manifest.build_script.rustc_link_search) {
+ // args.push_back("-L"); args.push_back(dir.second.c_str());
+ //}
+ //for(const auto& lib : manifest.build_script.rustc_link_lib) {
+ // args.push_back("-l"); args.push_back(lib.second.c_str());
+ //}
+ //for(const auto& cfg : manifest.build_script.rustc_cfg) {
+ // args.push_back("--cfg"); args.push_back(cfg.c_str());
+ //}
+ //for(const auto& flag : manifest.build_script.rustc_flags) {
+ // args.push_back(flag.c_str());
+ //}
+ // TODO: Environment variables (rustc_env)
+
+ return this->spawn_process(args, outfile + "_dbg.txt");
+}
+bool Builder::build_library(const PackageManifest& manifest) const
+{
+ if( manifest.build_script() != "" )
+ {
+ // Locate a build script override file
+ // > Note, override file can specify a list of commands to run.
+ //manifest.script_output = BuildScript::load( override_file );
+ // Otherwise, compile and run build script
+ //manifest.script_output = BuildScript::load( ::helpers::path("output") / "build_" + manifest.name + ".txt" );
+ // Parse build script output.
+ throw ::std::runtime_error("TODO: Build script");
+ }
+
+ return this->build_target(manifest, manifest.get_library());
+}
+bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfile) const
+{
+#ifdef _WIN32
+ ::std::stringstream cmdline;
+ cmdline << "mrustc.exe";
+ for (const auto& arg : args.get_vec())
+ cmdline << " " << arg;
+ auto cmdline_str = cmdline.str();
+ DEBUG("Calling " << cmdline_str);
+
+ CreateDirectory(static_cast<::std::string>(logfile.parent()).c_str(), NULL);
+
+ STARTUPINFO si = { 0 };
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = NULL;
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ {
+ SECURITY_ATTRIBUTES sa = { 0 };
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ si.hStdOutput = CreateFile( static_cast<::std::string>(logfile).c_str(), GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+ DWORD tmp;
+ WriteFile(si.hStdOutput, cmdline_str.data(), cmdline_str.size(), &tmp, NULL);
+ WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL);
+ }
+ PROCESS_INFORMATION pi = { 0 };
+ char env[] =
+ "MRUSTC_DEBUG=""\0"
+ ;
+ CreateProcessA("x64\\Release\\mrustc.exe", (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
+ CloseHandle(si.hStdOutput);
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ DWORD status = 1;
+ GetExitCodeProcess(pi.hProcess, &status);
+ if (status != 0)
+ {
+ DEBUG("Compiler exited with non-zero exit status " << status);
+ return false;
+ }
+#else
+
+ // Create logfile output directory
+ mkdir(static_cast<::std::string>(logfile.parent()).c_str(), 0755);
+
+ // Create handles such that the log file is on stdout
+ ::std::string logfile_str = logfile;
+ pid_t pid;
+ posix_spawn_file_actions_t fa;
+ {
+ posix_spawn_file_actions_init(&fa);
+ posix_spawn_file_actions_addopen(&fa, 1, logfile_str.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644);
+ }
+
+ // Generate `argv`
+ auto argv = args.get_vec();
+ argv.insert(argv.begin(), "mrustc");
+ DEBUG("Calling " << argv);
+ argv.push_back(nullptr);
+
+ // Generate `envp`
+ ::std::vector<const char*> envp;
+ extern char **environ;
+ for(auto p = environ; *p; p++)
+ {
+ envp.push_back(*p);
+ }
+ envp.push_back(nullptr);
+
+ if( posix_spawn(&pid, "../bin/mrustc", &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.data()) != 0 )
+ {
+ perror("posix_spawn");
+ DEBUG("Unable to spawn compiler");
+ posix_spawn_file_actions_destroy(&fa);
+ return false;
+ }
+ posix_spawn_file_actions_destroy(&fa);
+ int status = -1;
+ waitpid(pid, &status, 0);
+ if( WEXITSTATUS(status) != 0 )
+ {
+ DEBUG("Compiler exited with non-zero exit status " << WEXITSTATUS(status));
+ return false;
+ }
+#endif
+ return true;
}
diff --git a/tools/minicargo/debug.h b/tools/minicargo/debug.h
index 5cc338e3..bff9ddf3 100644
--- a/tools/minicargo/debug.h
+++ b/tools/minicargo/debug.h
@@ -10,10 +10,10 @@ extern void Debug_Print(::std::function<void(::std::ostream& os)> cb);
#define TODO(fmt) do { Debug_Print([&](auto& os){ os << "DEBUG: " << fmt; }); abort(); } while(0)
namespace {
- static void format_to_stream(::std::ostream& os) {
+ static inline void format_to_stream(::std::ostream& os) {
}
template<typename T, typename... A>
- static void format_to_stream(::std::ostream& os, const T& v, const A&... a) {
+ static inline void format_to_stream(::std::ostream& os, const T& v, const A&... a) {
os << v;
format_to_stream(os, a...);
}
diff --git a/tools/minicargo/helpers.h b/tools/minicargo/helpers.h
index d811f21a..f2679ef4 100644
--- a/tools/minicargo/helpers.h
+++ b/tools/minicargo/helpers.h
@@ -1,17 +1,41 @@
#pragma once
#include <string>
+#include <cstring>
namespace helpers {
+class string_view
+{
+ const char* m_start;
+ const size_t m_len;
+public:
+ string_view(const char* s, size_t n):
+ m_start(s), m_len(n)
+ {
+ }
+
+ bool operator==(const ::std::string& s) const {
+ return *this == s.c_str();
+ }
+ bool operator==(const char* s) const {
+ if(::std::strncmp(m_start, s, m_len) != 0)
+ return false;
+ return s[m_len] == '\0';
+ }
+ friend ::std::string& operator+=(::std::string& x, const string_view& sv) {
+ x.append(sv.m_start, sv.m_start+sv.m_len);
+ return x;
+ }
+};
/// Path helper class (because I don't want to include boost)
class path
{
#ifdef _WIN32
- const char SEP = '\\';
+ static const char SEP = '\\';
#else
- const char SEP = '/';
+ static const char SEP = '/';
#endif
::std::string m_str;
@@ -56,13 +80,25 @@ public:
throw ::std::runtime_error("Appending an absolute path to another path");
return *this / p.m_str.c_str();
}
+ /// Append a relative path
path operator/(const char* o) const
{
+ if (o[0] == '/')
+ throw ::std::runtime_error("Appending an absolute path to another path");
auto rv = *this;
rv.m_str.push_back(SEP);
rv.m_str.append(o);
return rv;
}
+ /// Add an arbitary string to the final component
+ path operator+(const char* o) const
+ {
+ if( ::std::strchr(o, SEP) != nullptr )
+ throw ::std::runtime_error("Appending a string containing the path separator (with operator+)");
+ auto rv = *this;
+ rv.m_str.append(o);
+ return rv;
+ }
path parent() const
{
@@ -84,10 +120,159 @@ public:
return m_str;
}
+ class ComponentsIter
+ {
+ const path& p;
+ size_t pos;
+ size_t end;
+
+ friend class path;
+ ComponentsIter(const path& p, size_t i): p(p), pos(i) {
+ end = p.m_str.find(SEP, pos);
+ if(end == ::std::string::npos)
+ end = p.m_str.size();
+ }
+ public:
+ string_view operator*() const {
+ return string_view(p.m_str.c_str() + pos, end - pos);
+ }
+ void operator++() {
+ if(end == p.m_str.size())
+ pos = end;
+ else
+ {
+ pos = end+1;
+ end = p.m_str.find(SEP, pos);
+ if(end == ::std::string::npos)
+ end = p.m_str.size();
+ }
+ }
+ bool operator!=(const ComponentsIter& x) const {
+ return pos != x.pos;
+ }
+ };
+ ComponentsIter begin() const {
+ return ComponentsIter(*this, 0);
+ }
+ ComponentsIter end() const {
+ return ComponentsIter(*this, m_str.size());
+ }
+
+ path normalise() const
+ {
+ path rv;
+ rv.m_str.reserve( m_str.size()+1 );
+
+ for(auto comp : *this)
+ {
+ if( comp == "." ) {
+ // Ignore.
+ }
+ else if( comp == ".." )
+ {
+ // If the path is empty, OR the last element is a "..", push the element
+ if( rv.m_str.empty()
+ || (rv.m_str.size() == 3 && rv.m_str[0] == '.' && rv.m_str[1] == '.' && rv.m_str[2] == SEP)
+ || (rv.m_str.size() > 4 && *(rv.m_str.end()-4) == SEP && *(rv.m_str.end()-3) == '.' && *(rv.m_str.end()-2) == '.' && *(rv.m_str.end()-1) == SEP )
+ )
+ {
+ // Push
+ rv.m_str += comp;
+ rv.m_str += SEP;
+ }
+ else
+ {
+ rv.m_str.pop_back();
+ auto pos = rv.m_str.find_last_of(SEP);
+ if(pos == ::std::string::npos)
+ {
+ rv.m_str.resize(0);
+ }
+ else if( pos == 0 )
+ {
+ // Keep.
+ }
+ else
+ {
+ rv.m_str.resize(pos+1);
+ }
+ }
+ }
+ else {
+ rv.m_str += comp;
+ rv.m_str += SEP;
+ }
+ }
+ rv.m_str.pop_back();
+ return rv;
+ }
+#if 0
+ void normalise_in_place()
+ {
+ size_t insert_point = 0;
+
+ for(size_t read_pos = 0; read_pos < m_str.size(); read_pos ++)
+ {
+ auto pos = m_str.find_first_of(SEP, read_pos);
+ if(pos == ::std::string::npos)
+ pos = m_str.size();
+ auto comp = string_view(m_str.c_str() + read_pos, pos - read_pos);
+
+ bool append;
+ if(comp == ".")
+ {
+ // Advance read without touching insert
+ append = false;
+ }
+ else if( comp == ".." )
+ {
+ // Consume parent (if not a relative component already)
+ // Move insertion point back to the previous separator
+ auto pos = m_str.find_last_of(SEP, insert_point);
+ if(pos == ::std::string::npos)
+ {
+ // Only one component currently (or empty)
+ append = true;
+ }
+ else if(string_view(m_str.c_str() + pos+1, insert_point - pos-1) == "..")
+ {
+ // Last component is ".." - keep adding
+ append = true;
+ }
+ else
+ {
+ insert_point = pos;
+ append = false;
+ }
+ }
+ else
+ {
+ append = true;
+ }
+
+ if(append)
+ {
+ if( read_pos != insert_point )
+ {
+ //assert(read_pos > insert_point);
+ while(read_pos < pos)
+ {
+ m_str[insert_point++] = m_str[read_pos++];
+ }
+ }
+ }
+ else
+ {
+ read_pos = pos;
+ }
+ }
+ }
+#endif
+
friend ::std::ostream& operator<<(::std::ostream& os, const path& p)
{
return os << p.m_str;
}
};
-} // namespace helpers \ No newline at end of file
+} // namespace helpers
diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp
index c2fe4c2e..236b9d77 100644
--- a/tools/minicargo/main.cpp
+++ b/tools/minicargo/main.cpp
@@ -6,9 +6,11 @@
*/
#include <iostream>
#include <cstring> // strcmp
+#include <map>
#include "debug.h"
#include "manifest.h"
#include "helpers.h"
+#include "repository.h"
extern void MiniCargo_Build(const PackageManifest& manifest);
@@ -22,6 +24,8 @@ struct ProgramOptions
const char* output_directory = nullptr;
+ const char* vendor_dir = nullptr;
+
int parse(int argc, const char* argv[]);
void usage() const;
};
@@ -33,19 +37,34 @@ int main(int argc, const char* argv[])
return 1;
}
- // 1. Load the Cargo.toml file from the passed directory
- auto m = PackageManifest::load_from_toml( ::helpers::path(opts.directory ? opts.directory : ".") / "Cargo.toml" );
+ try
+ {
+ // Load package database
+ Repository repo;
+ // TODO: load repository from a local cache
+ if( opts.vendor_dir )
+ {
+ repo.load_vendored(opts.vendor_dir);
+ }
+
+ // 1. Load the Cargo.toml file from the passed directory
+ auto dir = ::helpers::path(opts.directory ? opts.directory : ".");
+ auto m = PackageManifest::load_from_toml( dir / "Cargo.toml" );
+
+ m.load_dependencies(repo);
- // 2. Recursively load dependency manifests
- for(const auto& dep : m.dependencies())
+ // 3. Build dependency tree
+ MiniCargo_Build(m);
+ }
+ catch(const ::std::exception& e)
{
- throw "TODO: Deps";
+ ::std::cerr << "EXCEPTION: " << e.what() << ::std::endl;
+ ::std::cout << "Press enter to exit..." << ::std::endl;
+ ::std::cin.get();
+ return 1;
}
- // 3. Build dependency tree
- MiniCargo_Build(m);
-
- ::std::cout << "Press any key to exit..." << ::std::endl;
+ ::std::cout << "Press enter to exit..." << ::std::endl;
::std::cin.get();
return 0;
}
@@ -106,9 +125,9 @@ void ProgramOptions::usage() const
}
-
void Debug_Print(::std::function<void(::std::ostream& os)> cb)
{
cb(::std::cout);
::std::cout << ::std::endl;
}
+
diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp
index 22b63005..1bb815d8 100644
--- a/tools/minicargo/manifest.cpp
+++ b/tools/minicargo/manifest.cpp
@@ -6,10 +6,7 @@
#include "helpers.h"
#include <cassert>
#include <algorithm>
-#include <sstream>
-#ifdef _WIN32
-#include <Windows.h>
-#endif
+#include "repository.h"
static ::std::vector<::std::shared_ptr<PackageManifest>> g_loaded_manifests;
@@ -25,13 +22,14 @@ namespace
PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
{
PackageManifest rv;
- rv.m_manmifest_path = path;
+ rv.m_manifest_path = path;
TomlFile toml_file(path);
for(auto key_val : toml_file)
{
assert(key_val.path.size() > 0);
+ DEBUG(key_val.path << " = " << key_val.value);
const auto& section = key_val.path[0];
if( section == "package" )
{
@@ -40,6 +38,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
if(key == "authors")
{
// TODO: Use the `authors` key
+ // - Ignore ofr now.
}
else if( key == "name" )
{
@@ -59,6 +58,20 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
{
rv.m_version = PackageVersion::from_string(key_val.value.as_string());
}
+ else if( key == "build" )
+ {
+ if(rv.m_build_script != "" )
+ {
+ // TODO: Warn/error
+ throw ::std::runtime_error("Build script path set twice");
+ }
+ rv.m_build_script = key_val.value.as_string();
+ if(rv.m_build_script == "")
+ {
+ // TODO: Error
+ throw ::std::runtime_error("Build script path cannot be empty");
+ }
+ }
else
{
// Unknown value in `package`
@@ -67,12 +80,12 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
}
else if( section == "lib" )
{
- // TODO: Parse information related to use as a library
// 1. Find (and add if needed) the `lib` descriptor
auto it = ::std::find_if(rv.m_targets.begin(), rv.m_targets.end(), [](const auto& x){ return x.m_type == PackageTarget::Type::Lib; });
if(it == rv.m_targets.end())
it = rv.m_targets.insert(it, PackageTarget { PackageTarget::Type::Lib });
+ // 2. Parse from the key-value pair
target_edit_from_kv(*it, key_val, 1);
}
else if( section == "bin" )
@@ -97,6 +110,17 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
target_edit_from_kv(*it, key_val, 2);
}
+ else if (section == "bench")
+ {
+ assert(key_val.path.size() > 1);
+ unsigned idx = ::std::stoi(key_val.path[1]);
+
+ auto it = ::std::find_if(rv.m_targets.begin(), rv.m_targets.end(), [&idx](const auto& x) { return x.m_type == PackageTarget::Type::Bench && idx-- == 0; });
+ if (it == rv.m_targets.end())
+ it = rv.m_targets.insert(it, PackageTarget{ PackageTarget::Type::Bench });
+
+ target_edit_from_kv(*it, key_val, 2);
+ }
else if( section == "dependencies" )
{
assert(key_val.path.size() > 1);
@@ -133,22 +157,28 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
// Set path specification of the named depenency
ref.m_path = key_val.value.as_string();
}
- else if (attr == "git")
+ else if( attr == "git" )
{
// Load from git repo.
TODO("Support git dependencies");
}
- else if (attr == "branch")
+ else if( attr == "branch" )
{
// Specify git branch
TODO("Support git dependencies (branch)");
}
- else if( attr == "version")
+ else if( attr == "version" )
{
assert(key_val.path.size() == 3);
// Parse version specifier
ref.m_version = PackageVersionSpec::from_string(key_val.value.as_string());
}
+ else if( attr == "optional" )
+ {
+ assert(key_val.path.size() == 3);
+ ref.m_optional = key_val.value.as_bool();
+ // TODO: Add a feature with the same name as the dependency.
+ }
else
{
// TODO: Error
@@ -156,13 +186,31 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
}
}
}
+ else if( section == "build-dependencies" )
+ {
+ // TODO: Build deps
+ }
+ else if( section == "dev-dependencies" )
+ {
+ // TODO: Developemnt (test/bench) deps
+ }
else if( section == "patch" )
{
//const auto& repo = key_val.path[1];
+ TODO("Support repository patches");
+ }
+ else if( section == "target" )
+ {
+ // TODO: Target opts?
+ }
+ else if( section == "features" )
+ {
+ // TODO: Features
}
else
{
// Unknown manifest section
+ TODO("Unknown manifest section " << section);
}
}
@@ -189,36 +237,40 @@ namespace
assert(kv.path.size() == base_idx + 1);
target.m_enable_test = kv.value.as_bool();
}
- else if (key == "doctest")
+ else if( key == "doctest" )
{
assert(kv.path.size() == base_idx + 1);
target.m_enable_doctest = kv.value.as_bool();
}
- else if (key == "bench")
+ else if( key == "bench" )
{
assert(kv.path.size() == base_idx + 1);
target.m_enable_bench = kv.value.as_bool();
}
- else if (key == "doc")
+ else if( key == "doc" )
{
assert(kv.path.size() == base_idx + 1);
target.m_enable_doc = kv.value.as_bool();
}
- else if (key == "plugin")
+ else if( key == "plugin" )
{
assert(kv.path.size() == base_idx + 1);
target.m_is_plugin = kv.value.as_bool();
}
- else if (key == "proc-macro")
+ else if( key == "proc-macro" )
{
assert(kv.path.size() == base_idx + 1);
target.m_is_proc_macro = kv.value.as_bool();
}
- else if (key == "harness")
+ else if( key == "harness" )
{
assert(kv.path.size() == base_idx + 1);
target.m_is_own_harness = kv.value.as_bool();
}
+ else if( key == "crate-type" )
+ {
+ // TODO: Support crate types
+ }
else
{
throw ::std::runtime_error( ::format("TODO: Handle target option `", key, "`") );
@@ -226,67 +278,59 @@ namespace
}
}
-
-bool PackageManifest::build_lib() const
+const PackageTarget& PackageManifest::get_library() const
{
auto it = ::std::find_if(m_targets.begin(), m_targets.end(), [](const auto& x) { return x.m_type == PackageTarget::Type::Lib; });
if (it == m_targets.end())
{
throw ::std::runtime_error(::format("Package ", m_name, " doesn't have a library"));
}
+ return *it;
+}
- auto outfile = ::helpers::path("output") / ::format("lib", it->m_name, ".hir");
-
- ::std::vector<::std::string> args;
- args.push_back( ::helpers::path(m_manmifest_path).parent() / ::helpers::path(it->m_path) );
- args.push_back("--crate-name"); args.push_back(it->m_name);
- args.push_back("--crate-type"); args.push_back("rlib");
- args.push_back("-o"); args.push_back( ::helpers::path("output") / ::format("lib", it->m_name, ".hir") );
-#ifdef _WIN32
- ::std::stringstream cmdline;
- cmdline << "mrustc.exe";
- for(const auto& arg : args)
- cmdline << " " << arg;
- auto cmdline_str = cmdline.str();
- DEBUG("Calling " << cmdline_str);
+void PackageManifest::load_dependencies(Repository& repo)
+{
+ DEBUG("Loading depencencies for " << m_name);
+ auto base_path = ::helpers::path(m_manifest_path).parent();
- CreateDirectory(static_cast<::std::string>(outfile.parent()).c_str(), NULL);
+ // 2. Recursively load dependency manifests
+ for(auto& dep : m_dependencies)
+ {
+ if( dep.m_optional )
+ {
+ // TODO: Check for feature that enables this (option to a feature with no '/')
+ continue ;
+ }
+ dep.load_manifest(repo, base_path);
+ }
+}
- STARTUPINFO si = {0};
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = NULL;
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+void PackageRef::load_manifest(Repository& repo, const ::helpers::path& base_path)
+{
+ // If the path isn't set, check for:
+ // - Git (checkout and use)
+ // - Version and repository (check vendored, check cache, download into cache)
+ if( ! this->has_path() )
{
- SECURITY_ATTRIBUTES sa = {0};
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- si.hStdOutput = CreateFile( (static_cast<::std::string>(outfile) + "_dbg.txt").c_str(), GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
- DWORD tmp;
- WriteFile(si.hStdOutput, cmdline_str.data(), cmdline_str.size(), &tmp, NULL);
- WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL);
+ if( this->has_git() )
+ {
+ DEBUG("Load dependency " << this->name() << " from git");
+ throw "TODO: Git";
+ }
+ else
+ {
+ DEBUG("Load dependency " << this->name() << " from repo");
+ m_manifest = repo.find(this->name(), this->get_version());
+ }
}
- PROCESS_INFORMATION pi = {0};
- CreateProcessA("x64\\Release\\mrustc.exe", (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, "MRUSTC_DEBUG=Parse\0", NULL, &si, &pi);
- CloseHandle(si.hStdOutput);
- WaitForSingleObject(pi.hProcess, INFINITE);
- DWORD status = 1;
- GetExitCodeProcess(pi.hProcess, &status);
- if(status != 0)
+ else
{
- DEBUG("Compiler exited with non-zero exit status " << status);
- return false;
+ DEBUG("Load dependency " << m_name << " from path " << m_path);
+ // Search for a copy of this already loaded
+ m_manifest = repo.from_path(base_path / ::helpers::path(m_path) / "Cargo.toml");
}
-#elif defined(__posix__)
- //spawn();
-#else
-#endif
- return true;
-}
-const PackageManifest& PackageRef::get_package() const
-{
- throw "";
+ m_manifest->load_dependencies(repo);
}
PackageVersion PackageVersion::from_string(const ::std::string& s)
@@ -308,4 +352,8 @@ PackageVersionSpec PackageVersionSpec::from_string(const ::std::string& s)
PackageVersionSpec rv;
throw "";
return rv;
-} \ No newline at end of file
+}
+bool PackageVersionSpec::accepts(const PackageVersion& v) const
+{
+ throw "";
+}
diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h
index 108a8d2b..428a9721 100644
--- a/tools/minicargo/manifest.h
+++ b/tools/minicargo/manifest.h
@@ -3,8 +3,10 @@
#include <string>
#include <vector>
#include <memory>
+#include "helpers.h"
class PackageManifest;
+class Repository;
struct PackageVersion
{
@@ -13,6 +15,15 @@ struct PackageVersion
unsigned patch;
static PackageVersion from_string(const ::std::string& s);
+ bool operator<(const PackageVersion& x) const {
+ if( major < x.major ) return true;
+ if( major > x.major ) return false;
+ if( minor < x.minor ) return true;
+ if( minor > x.minor ) return false;
+ if( minor < x.patch ) return true;
+ if( patch > x.patch ) return false;
+ return false;
+ }
};
struct PackageVersionSpec
{
@@ -28,10 +39,14 @@ struct PackageVersionSpec
Type ty;
PackageVersion ver;
};
+ // TODO: Just upper and lower?
::std::vector<Bound> m_bounds;
- // TODO: Just upper and lower?
+ // Construct from a string
static PackageVersionSpec from_string(const ::std::string& s);
+
+ /// Check if this spec accepts the passed version
+ bool accepts(const PackageVersion& v) const;
};
class PackageRef
@@ -40,6 +55,7 @@ class PackageRef
::std::string m_name;
PackageVersionSpec m_version;
+ bool m_optional = false;
::std::string m_path;
::std::shared_ptr<PackageManifest> m_manifest;
@@ -49,7 +65,22 @@ class PackageRef
}
public:
- const PackageManifest& get_package() const;
+ const ::std::string& name() const { return m_name; }
+ //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; }
+
+ const bool has_path() const { return m_path != ""; }
+ const ::std::string& path() const { return m_path; }
+ const bool has_git() const { return false; }
+
+ const PackageManifest& get_package() const {
+ if(!m_manifest) throw ::std::runtime_error("Manifest not loaded for package " + m_name);
+ return *m_manifest;
+ }
+
+ void load_manifest(Repository& repo, const ::helpers::path& base_path);
};
struct PackageTarget
@@ -93,11 +124,13 @@ struct PackageTarget
class PackageManifest
{
- ::std::string m_manmifest_path;
+ ::std::string m_manifest_path;
::std::string m_name;
PackageVersion m_version;
+ ::std::string m_build_script;
+
::std::vector<PackageRef> m_dependencies;
::std::vector<PackageTarget> m_targets;
@@ -109,9 +142,20 @@ class PackageManifest
PackageManifest();
public:
static PackageManifest load_from_toml(const ::std::string& path);
- bool build_lib() const;
+ const PackageTarget& get_library() const;
+
+
+ const ::std::string& manifest_path() const {
+ return m_manifest_path;
+ }
+ const ::std::string& name() const {
+ return m_name;
+ }
+ const ::std::string& build_script() const { return m_build_script; }
const ::std::vector<PackageRef>& dependencies() const {
return m_dependencies;
}
+
+ void load_dependencies(Repository& repo);
};
diff --git a/tools/minicargo/repository.cpp b/tools/minicargo/repository.cpp
new file mode 100644
index 00000000..0a097f66
--- /dev/null
+++ b/tools/minicargo/repository.cpp
@@ -0,0 +1,70 @@
+/*
+ */
+#include "repository.h"
+#include "debug.h"
+
+void Repository::load_cache(const ::helpers::path& path)
+{
+ throw "";
+}
+void Repository::load_vendored(const ::helpers::path& path)
+{
+ // Enumerate folders in this folder, try to open Cargo.toml files
+ // Extract package name and version from each manifest
+}
+
+::std::shared_ptr<PackageManifest> Repository::from_path(::helpers::path path)
+{
+ DEBUG("Repository::from_path(" << path << ")");
+ // 1. Normalise path
+ path = path.normalise();
+ DEBUG("path = " << path);
+
+ auto it = m_path_cache.find(path);
+ if(it == m_path_cache.end())
+ {
+ ::std::shared_ptr<PackageManifest> rv ( new PackageManifest(PackageManifest::load_from_toml(path)) );
+
+ m_path_cache.insert( ::std::make_pair(::std::move(path), rv) );
+
+ return rv;
+ }
+ else
+ {
+ return it->second;
+ }
+}
+::std::shared_ptr<PackageManifest> Repository::find(const ::std::string& name, const PackageVersionSpec& version)
+{
+ auto itp = m_cache.equal_range(name);
+
+ Entry* best = nullptr;
+ for(auto i = itp.first; i != itp.second; ++i)
+ {
+ if( version.accepts(i->second.version) )
+ {
+ if( !best || best->version < i->second.version )
+ {
+ best = &i->second;
+ }
+ }
+ }
+
+ if( best )
+ {
+ if( !best->loaded_manifest )
+ {
+ if( best->manifest_path == "" )
+ {
+ throw "TODO: Download package";
+ }
+ best->loaded_manifest = ::std::shared_ptr<PackageManifest>( new PackageManifest(PackageManifest::load_from_toml(best->manifest_path)) );
+ }
+
+ return best->loaded_manifest;
+ }
+ else
+ {
+ return {};
+ }
+}
diff --git a/tools/minicargo/repository.h b/tools/minicargo/repository.h
new file mode 100644
index 00000000..0b186077
--- /dev/null
+++ b/tools/minicargo/repository.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <string>
+#include <map>
+#include "helpers.h"
+#include "manifest.h"
+
+class Repository
+{
+ struct Entry
+ {
+ /// Path to the Cargo.toml file in the package root
+ ::std::string manifest_path;
+ /// Package version
+ PackageVersion version;
+ /// (Cached) loaded manifest
+ ::std::shared_ptr<PackageManifest> loaded_manifest;
+ };
+
+ ::std::multimap<::std::string, Entry> m_cache;
+ // path => manifest
+ ::std::map<::std::string, ::std::shared_ptr<PackageManifest>> m_path_cache;
+public:
+ void load_cache(const ::helpers::path& path);
+ void load_vendored(const ::helpers::path& path);
+
+ ::std::shared_ptr<PackageManifest> from_path(::helpers::path path);
+ ::std::shared_ptr<PackageManifest> find(const ::std::string& name, const PackageVersionSpec& version);
+};
diff --git a/tools/minicargo/toml.cpp b/tools/minicargo/toml.cpp
index 7d4b0685..fe81fa3c 100644
--- a/tools/minicargo/toml.cpp
+++ b/tools/minicargo/toml.cpp
@@ -158,14 +158,14 @@ TomlKeyValue TomlFile::get_next_value()
{
case Token::Type::String:
rv.path = m_current_block;
- rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end());
+ rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end());
rv.path.push_back(key_name);
rv.value = TomlValue { t.m_data };
break;
case Token::Type::SquareOpen:
rv.path = m_current_block;
- rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end());
+ rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end());
rv.path.push_back(key_name);
rv.value.m_type = TomlValue::Type::List;
@@ -197,14 +197,14 @@ TomlKeyValue TomlFile::get_next_value()
if( t.m_data == "true" )
{
rv.path = m_current_block;
- rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end());
+ rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end());
rv.path.push_back(key_name);
rv.value = TomlValue { true };
}
else if( t.m_data == "false" )
{
rv.path = m_current_block;
- rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end());
+ rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end());
rv.path.push_back(key_name);
rv.value = TomlValue { false };
@@ -242,7 +242,7 @@ TomlKeyValue TomlFile::get_next_value()
Token Token::lex_from(::std::ifstream& is)
{
auto rv = Token::lex_from_inner(is);
- DEBUG("lex_from: " << rv);
+ //DEBUG("lex_from: " << rv);
return rv;
}
Token Token::lex_from_inner(::std::ifstream& is)
@@ -307,7 +307,7 @@ Token Token::lex_from_inner(::std::ifstream& is)
if(isalpha(c))
{
// Identifier
- while(isalnum(c) || c == '-')
+ while(isalnum(c) || c == '-' || c == '_')
{
str += (char)c;
c = is.get();
@@ -317,6 +317,7 @@ Token Token::lex_from_inner(::std::ifstream& is)
}
else
{
+ throw ::std::runtime_error(::format("Unexpected chracter '", (char)c, "' in file"));
throw "";
}
}
diff --git a/tools/minicargo/toml.h b/tools/minicargo/toml.h
index 1c8f90d5..6f145a2e 100644
--- a/tools/minicargo/toml.h
+++ b/tools/minicargo/toml.h
@@ -2,6 +2,7 @@
#include <fstream>
#include <vector>
+#include <string>
#include <unordered_map>
class TomlFileIter;
@@ -54,7 +55,7 @@ struct TomlValue
{
}
- const char* what() const override {
+ const char* what() const noexcept override {
return "toml type error";
}
};
@@ -91,6 +92,24 @@ struct TomlValue
}
return m_int_value != 0;
}
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TomlValue& x) {
+ switch(x.m_type)
+ {
+ case Type::Boolean: os << (x.m_int_value != 0 ? "true" : "false"); break;
+ case Type::Integer: os << x.m_int_value; break;
+ case Type::List:
+ os << "[";
+ for(auto& e : x.m_sub_values)
+ os << e << ",";
+ os << "]";
+ break;
+ case Type::String:
+ os << "\"" << x.m_str_value << "\"";
+ break;
+ }
+ return os;
+ }
};
struct TomlKeyValue
diff --git a/vsproject/minicargo/minicargo.vcxproj b/vsproject/minicargo/minicargo.vcxproj
index 9c82ff56..9fe4e4a7 100644
--- a/vsproject/minicargo/minicargo.vcxproj
+++ b/vsproject/minicargo/minicargo.vcxproj
@@ -113,12 +113,14 @@
<ClCompile Include="..\..\tools\minicargo\build.cpp" />
<ClCompile Include="..\..\tools\minicargo\main.cpp" />
<ClCompile Include="..\..\tools\minicargo\manifest.cpp" />
+ <ClCompile Include="..\..\tools\minicargo\repository.cpp" />
<ClCompile Include="..\..\tools\minicargo\toml.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\minicargo\debug.h" />
<ClInclude Include="..\..\tools\minicargo\helpers.h" />
<ClInclude Include="..\..\tools\minicargo\manifest.h" />
+ <ClInclude Include="..\..\tools\minicargo\repository.h" />
<ClInclude Include="..\..\tools\minicargo\toml.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/vsproject/minicargo/minicargo.vcxproj.filters b/vsproject/minicargo/minicargo.vcxproj.filters
index b21142bb..be88124d 100644
--- a/vsproject/minicargo/minicargo.vcxproj.filters
+++ b/vsproject/minicargo/minicargo.vcxproj.filters
@@ -27,6 +27,9 @@
<ClCompile Include="..\..\tools\minicargo\toml.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\tools\minicargo\repository.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\tools\minicargo\helpers.h">
@@ -41,5 +44,8 @@
<ClInclude Include="..\..\tools\minicargo\debug.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\tools\minicargo\repository.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/vsproject/mrustc.sln b/vsproject/mrustc.sln
index 3aebce2e..abeaf785 100644
--- a/vsproject/mrustc.sln
+++ b/vsproject/mrustc.sln
@@ -8,6 +8,9 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tu_test", "tu_test\tu_test.vcxproj", "{F0A80ABB-A11A-492C-B5FC-E26C29A988D8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minicargo", "minicargo\minicargo.vcxproj", "{15F3D38B-14FF-4872-805D-6D9C52920842}"
+ ProjectSection(ProjectDependencies) = postProject
+ {12AA9964-C1BD-406A-9545-43EE63230EBE} = {12AA9964-C1BD-406A-9545-43EE63230EBE}
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/vsproject/mrustc.vcxproj.filters b/vsproject/mrustc.vcxproj.filters
index e5afb22e..cfcdb9b9 100644
--- a/vsproject/mrustc.vcxproj.filters
+++ b/vsproject/mrustc.vcxproj.filters
@@ -57,6 +57,18 @@
<Filter Include="Header Files\mir">
<UniqueIdentifier>{1233e2f6-7b44-4379-9f43-d572b8944ba0}</UniqueIdentifier>
</Filter>
+ <Filter Include="Header Files\parse">
+ <UniqueIdentifier>{3709226c-e95b-4da0-9735-42e2a5cad1a7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\expand">
+ <UniqueIdentifier>{c78c419b-2b25-4c6f-8f91-95a9d0142fff}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\trans">
+ <UniqueIdentifier>{6bbfdfb3-9557-43a9-bddd-07a243569fa3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\hir">
+ <UniqueIdentifier>{e3219c19-8898-418e-b2ba-84254977a792}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\debug.cpp">
@@ -382,63 +394,21 @@
<ClInclude Include="..\src\coretypes.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\ast\crate.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\ast\pattern.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\expand\cfg.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\expand\macro_rules.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\hir\crate_ptr.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\expr.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\expr_ptr.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\from_ast.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\generic_params.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\hir.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\hir\path.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\hir\pattern.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\type.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\hir\visitor.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\hir_conv\main_bindings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\hir_expand\main_bindings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\hir_typeck\expr_visit.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\hir_typeck\main_bindings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\hir_typeck\static.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\include\cpp_unpack.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -457,12 +427,6 @@
<ClInclude Include="..\src\include\rustic.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\include\serialise.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\include\serialiser_texttree.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\include\span.hpp">
<Filter>Header Files</Filter>
</ClInclude>
@@ -487,57 +451,21 @@
<ClInclude Include="..\src\macro_rules\pattern_checks.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\mir\from_hir.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\mir\main_bindings.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\parse\eTokenType.enum.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\parse\common.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\parse\interpolated_fragment.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\parse\lex.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\parse\parseerror.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\parse\token.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\parse\tokentree.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\resolve\main_bindings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\parse\ttstream.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\parse\tokenstream.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\trans\codegen.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\trans\main_bindings.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\trans\mangling.hpp">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="..\src\trans\trans_list.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\src\mir\visit_crate_mir.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\src\ast\attrs.hpp">
<Filter>Header Files\ast</Filter>
</ClInclude>
@@ -583,6 +511,90 @@
<ClInclude Include="..\src\ast\types.hpp">
<Filter>Header Files\ast</Filter>
</ClInclude>
+ <ClInclude Include="..\src\ast\crate.hpp">
+ <Filter>Header Files\ast</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\common.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\crate_ptr.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\eTokenType.enum.h">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\expr_ptr.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir_typeck\expr_visit.hpp">
+ <Filter>Header Files\hir_typeck</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\expr.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\mir\main_bindings.hpp">
+ <Filter>Header Files\mir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\include\serialise.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\include\serialiser_texttree.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\expand\cfg.hpp">
+ <Filter>Header Files\expand</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\trans\codegen.hpp">
+ <Filter>Header Files\trans</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\from_ast.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\hir.hpp">
+ <Filter>Header Files\mir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\mir\from_hir.hpp">
+ <Filter>Header Files\mir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\generic_params.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\interpolated_fragment.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\pattern.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\ast\pattern.hpp">
+ <Filter>Header Files\ast</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir_typeck\static.hpp">
+ <Filter>Header Files\hir_typeck</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\type.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\hir\visitor.hpp">
+ <Filter>Header Files\hir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\mir\visit_crate_mir.hpp">
+ <Filter>Header Files\mir</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\token.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\tokenstream.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\trans\trans_list.hpp">
+ <Filter>Header Files\trans</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\ttstream.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\parse\tokentree.hpp">
+ <Filter>Header Files\parse</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />