diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/common/path.h | 7 | ||||
-rw-r--r-- | tools/common/target_detect.h | 11 | ||||
-rw-r--r-- | tools/common/toml.cpp | 85 | ||||
-rw-r--r-- | tools/common/toml.h | 21 | ||||
-rw-r--r-- | tools/minicargo/build.cpp | 76 | ||||
-rw-r--r-- | tools/minicargo/main.cpp | 4 | ||||
-rw-r--r-- | tools/minicargo/manifest.cpp | 6 |
7 files changed, 154 insertions, 56 deletions
diff --git a/tools/common/path.h b/tools/common/path.h index eae4951f..1ad6f506 100644 --- a/tools/common/path.h +++ b/tools/common/path.h @@ -38,6 +38,13 @@ public: return m_str != ""; } + bool operator==(const path& p) const { + return m_str == p.m_str; + } + bool operator!=(const path& p) const { + return m_str != p.m_str; + } + path& operator/=(const path& p) { if(!p.is_valid()) diff --git a/tools/common/target_detect.h b/tools/common/target_detect.h index a4c44ba4..1bfc7dd9 100644 --- a/tools/common/target_detect.h +++ b/tools/common/target_detect.h @@ -24,6 +24,8 @@ # define DEFAULT_TARGET_NAME "arm-linux-gnu" # elif defined(__i386__) # define DEFAULT_TARGET_NAME "i586-linux-gnu" +# elif defined(__m68k__) +# define DEFAULT_TARGET_NAME "m68k-linux-gnu" # else # warning "Unable to detect a suitable default target (linux-gnu)" # endif @@ -73,6 +75,15 @@ // - Apple devices #elif defined(__APPLE__) # define DEFAULT_TARGET_NAME "x86_64-apple-macosx" +// - Haiku +#elif defined(__HAIKU__) +# if defined(__x86_64__) +# define DEFAULT_TARGET_NAME "x86_64-unknown-haiku" +# elif defined(__arm__) +# define DEFAULT_TARGET_NAME "arm-unknown-haiku" +# else +# warning "Unable to detect a suitable default target (Haiku)" +# endif // - Unknown #else # warning "Unable to detect a suitable default target" diff --git a/tools/common/toml.cpp b/tools/common/toml.cpp index 7e24b610..4e8e6da6 100644 --- a/tools/common/toml.cpp +++ b/tools/common/toml.cpp @@ -80,11 +80,8 @@ struct Token }; TomlFile::TomlFile(const ::std::string& filename): - m_if(filename) + m_lexer(filename) { - if( !m_if.is_open() ) { - throw ::std::runtime_error("Unable to open file '" + filename + "'"); - } } TomlFileIter TomlFile::begin() { @@ -99,12 +96,14 @@ TomlFileIter TomlFile::end() TomlKeyValue TomlFile::get_next_value() { - auto t = Token::lex_from(m_if); + auto t = m_lexer.get_token(); if(m_current_composite.empty()) { while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); + { + t = m_lexer.get_token(); + } // Expect '[', a string, or an identifier switch(t.m_type) @@ -116,32 +115,32 @@ TomlKeyValue TomlFile::get_next_value() m_current_block.clear(); do { - t = Token::lex_from(m_if); + t = m_lexer.get_token(); bool is_array = false; if(t.m_type == Token::Type::SquareOpen) { is_array = true; - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } assert(t.m_type == Token::Type::Ident || t.m_type == Token::Type::String); m_current_block.push_back(t.as_string()); if(is_array) { m_current_block.push_back(::format(m_array_counts[t.as_string()]++)); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); assert(t.m_type == Token::Type::SquareClose); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } while(t.m_type == Token::Type::Dot); if( t.m_type != Token::Type::SquareClose ) { - throw ::std::runtime_error(::format("Unexpected token in block header - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in block header - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if (t.m_type != Token::Type::Newline) { - throw ::std::runtime_error(::format("Unexpected token after block block - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after block block - ", t)); } DEBUG("Start block " << m_current_block); // Recurse! @@ -156,7 +155,7 @@ TomlKeyValue TomlFile::get_next_value() if( t.m_type == Token::Type::Eof ) { // EOF isn't allowed here - throw ::std::runtime_error(::format("Unexpected EOF in composite")); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected EOF in composite")); } } switch (t.m_type) @@ -165,14 +164,14 @@ TomlKeyValue TomlFile::get_next_value() case Token::Type::Ident: break; default: - throw ::std::runtime_error(::format("Unexpected token for key - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token for key - ", t)); } ::std::string key_name = t.as_string(); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if(t.m_type != Token::Type::Assign) - throw ::std::runtime_error(::format("Unexpected token after key - ", t)); - t = Token::lex_from(m_if); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after key - ", t)); + t = m_lexer.get_token(); // --- Value --- TomlKeyValue rv; @@ -193,10 +192,12 @@ TomlKeyValue TomlFile::get_next_value() rv.path.push_back(key_name); rv.value.m_type = TomlValue::Type::List; - while( (t = Token::lex_from(m_if)).m_type != Token::Type::SquareClose ) + while( (t = m_lexer.get_token()).m_type != Token::Type::SquareClose ) { while( t.m_type == Token::Type::Newline ) - t = Token::lex_from(m_if); + { + t = m_lexer.get_token(); + } if( t.m_type == Token::Type::SquareClose ) break; @@ -208,15 +209,15 @@ TomlKeyValue TomlFile::get_next_value() rv.value.m_sub_values.push_back(TomlValue { t.as_string() }); break; default: - throw ::std::runtime_error(::format("Unexpected token in array value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in array value position - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); if(t.m_type != Token::Type::Comma) break; } if(t.m_type != Token::Type::SquareClose) - throw ::std::runtime_error(::format("Unexpected token after array - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after array - ", t)); break; case Token::Type::BraceOpen: m_current_composite.push_back(key_name); @@ -228,7 +229,7 @@ TomlKeyValue TomlFile::get_next_value() 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_intval }; - return rv; + break; case Token::Type::Ident: if( t.m_data == "true" ) { @@ -247,33 +248,57 @@ TomlKeyValue TomlFile::get_next_value() } else { - throw ::std::runtime_error(::format("Unexpected identifier in value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected identifier in value position - ", t)); } break; default: - throw ::std::runtime_error(::format("Unexpected token in value position - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in value position - ", t)); } - t = Token::lex_from(m_if); + t = m_lexer.get_token(); while (!m_current_composite.empty() && t.m_type == Token::Type::BraceClose) { DEBUG("Leave composite block " << m_current_block << ", " << m_current_composite); m_current_composite.pop_back(); - t = Token::lex_from(m_if); + t = m_lexer.get_token(); } if( m_current_composite.empty() ) { if(t.m_type != Token::Type::Newline && t.m_type != Token::Type::Eof) - throw ::std::runtime_error(::format("Unexpected token in TOML file after entry - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after entry - ", t)); } else { if( t.m_type != Token::Type::Comma ) - throw ::std::runtime_error(::format("Unexpected token in TOML file after composite entry - ", t)); + throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after composite entry - ", t)); } return rv; } +TomlLexer::TomlLexer(const ::std::string& filename) + :m_if(filename) + ,m_filename(filename) + ,m_line(1) +{ + if( !m_if.is_open() ) { + throw ::std::runtime_error("Unable to open file '" + filename + "'"); + } +} +Token TomlLexer::get_token() +{ + auto rv = Token::lex_from(m_if); + if( rv.m_type == Token::Type::Newline ) + { + m_line ++; + } + return rv; +} +::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x) +{ + os << x.m_filename << ":" << x.m_line; + return os; +} + Token Token::lex_from(::std::ifstream& is) { auto rv = Token::lex_from_inner(is); diff --git a/tools/common/toml.h b/tools/common/toml.h index 4c97e7f2..17e05142 100644 --- a/tools/common/toml.h +++ b/tools/common/toml.h @@ -15,11 +15,28 @@ class TomlFileIter; struct TomlKeyValue; -class TomlFile +struct Token; +class TomlLexer { + friend class TomlFile; /// Input file stream ::std::ifstream m_if; + ::std::string m_filename; + unsigned m_line; +protected: + TomlLexer(const ::std::string& filename); + Token get_token(); + +public: + friend ::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x); +}; + +class TomlFile +{ + /// Input file stream + TomlLexer m_lexer; + /// Name of the current `[]` block ::std::vector<::std::string> m_current_block; @@ -40,6 +57,8 @@ public: // Obtain the next value in the file TomlKeyValue get_next_value(); + + const TomlLexer& lexer() const; }; struct TomlValue diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp index 04a9a507..5eb07104 100644 --- a/tools/minicargo/build.cpp +++ b/tools/minicargo/build.cpp @@ -31,6 +31,7 @@ extern int _putenv_s(const char*, const char*); # include <mutex> # include <condition_variable> #endif +#include <fstream> #include <climits> #include <cassert> #ifdef _WIN32 @@ -67,6 +68,9 @@ class Builder ::helpers::path m_compiler_path; size_t m_total_targets; mutable size_t m_targets_built; +#ifndef _WIN32 + mutable ::std::mutex chdir_mutex; +#endif public: Builder(const BuildOptions& opts, size_t total_targets); @@ -78,7 +82,7 @@ public: private: ::helpers::path get_crate_path(const PackageManifest& manifest, const PackageTarget& target, bool is_for_host, const char** crate_type, ::std::string* out_crate_suffix) 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; + bool spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile, const ::helpers::path& working_directory={}) const; ::helpers::path build_and_run_script(const PackageManifest& manifest, bool is_for_host) const; @@ -566,6 +570,11 @@ Builder::Builder(const BuildOptions& opts, size_t total_targets): m_total_targets(total_targets), m_targets_built(0) { + if( const char* override_path = getenv("MRUSTC_PATH") ) { + m_compiler_path = override_path; + return ; + } + // TODO: Clean this stuff up #ifdef _WIN32 char buf[1024]; size_t s = GetModuleFileName(NULL, buf, sizeof(buf)-1); @@ -1000,6 +1009,10 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& args.push_back("--crate-type"); args.push_back("bin"); args.push_back("-o"); args.push_back(outfile); args.push_back("-L"); args.push_back(this->get_output_dir(true).str()); // NOTE: Forces `is_for_host` to true here. + if( true ) + { + args.push_back("-g"); + } for(const auto& d : m_opts.lib_search_dirs) { args.push_back("-L"); @@ -1102,23 +1115,31 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& } //auto _ = ScopedChdir { manifest.directory() }; - #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) ) + if( !this->spawn_process(script_exe_abs.str().c_str(), {}, env, out_file, /*working_directory=*/manifest.directory()) ) { - rename(out_file.str().c_str(), (out_file+"_failed").str().c_str()); + auto failed_filename = out_file+"_failed.txt"; + remove(failed_filename.str().c_str()); + rename(out_file.str().c_str(), failed_filename.str().c_str()); + + ::std::cerr << "Calling " << script_exe_abs << " failed" << ::std::endl; + { + ::std::ifstream ifs(failed_filename); + char linebuf[1024]; + while( ifs.good() && !ifs.eof() ) + { + ifs.getline(linebuf, sizeof(linebuf)-1); + if( strncmp(linebuf, "cargo:", 6) == 0 ) { + continue; + } + ::std::cerr << "> " << linebuf << ::std::endl; + } + } + // Build failed, return an invalid path - return ::helpers::path();; + return ::helpers::path(); } - #if _WIN32 - #else - fchdir(fd_cwd); - #endif } - + return out_file; } bool Builder::build_library(const PackageManifest& manifest, bool is_for_host, size_t index) const @@ -1154,7 +1175,7 @@ bool Builder::spawn_process_mrustc(const StringList& args, StringListKV env, con //env.push_back("MRUSTC_DEBUG", ""); return spawn_process(m_compiler_path.str().c_str(), args, env, logfile); } -bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile) const +bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile, const ::helpers::path& working_directory/*={}*/) const { #ifdef _WIN32 ::std::stringstream cmdline; @@ -1206,14 +1227,14 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL); } PROCESS_INFORMATION pi = { 0 }; - CreateProcessA(exe_name, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + CreateProcessA(exe_name, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, (working_directory != ::helpers::path() ? working_directory.str().c_str() : 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); + DEBUG("Process exited with non-zero exit status " << status); return false; } #else @@ -1270,12 +1291,23 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const // }); envp.push_back(nullptr); - if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.get_vec().data()) != 0 ) + // TODO: Acquire a lock { - ::std::cerr << "Unable to run process '" << exe_name << "' - " << strerror(errno) << ::std::endl; - DEBUG("Unable to spawn executable"); - posix_spawn_file_actions_destroy(&fa); - return false; + ::std::lock_guard<::std::mutex> lh { this->chdir_mutex }; + auto fd_cwd = open(".", O_DIRECTORY); + if( working_directory != ::helpers::path() ) { + chdir(working_directory.str().c_str()); + } + if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.get_vec().data()) != 0 ) + { + ::std::cerr << "Unable to run process '" << exe_name << "' - " << strerror(errno) << ::std::endl; + DEBUG("Unable to spawn executable"); + posix_spawn_file_actions_destroy(&fa); + return false; + } + if( working_directory != ::helpers::path() ) { + fchdir(fd_cwd); + } } posix_spawn_file_actions_destroy(&fa); int status = -1; diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp index 7065b7f5..4e929653 100644 --- a/tools/minicargo/main.cpp +++ b/tools/minicargo/main.cpp @@ -9,9 +9,9 @@ #include <iostream> #include <cstring> // strcmp #include <map> -#include "debug.h" +#include <debug.h> #include "manifest.h" -#include "helpers.h" +#include <helpers.h> #include "repository.h" #include "build.h" diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp index 8c0a7f44..edebd71a 100644 --- a/tools/minicargo/manifest.cpp +++ b/tools/minicargo/manifest.cpp @@ -317,7 +317,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) rv.m_targets.push_back(PackageTarget { PackageTarget::Type::Lib }); } } - // - If there's no binary section, but src/main.rs exists, add one + // - If there's no binary section, but src/main.rs exists, add as a binary if( ! ::std::any_of(rv.m_targets.begin(), rv.m_targets.end(), [](const auto& x){ return x.m_type == PackageTarget::Type::Bin; }) ) { // No library, add one pointing to lib.rs @@ -327,6 +327,10 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) rv.m_targets.push_back(PackageTarget { PackageTarget::Type::Bin }); } } + if( rv.m_targets.empty() ) + { + throw ::std::runtime_error(format("Manifest file ", path, " didn't specify any targets (and src/{main,lib}.rs doesn't exist)")); + } // Default target names for(auto& tgt : rv.m_targets) |