From a5585150f0ff8d27ddd22792f521f1374a3eedd8 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 20 Jan 2023 08:37:29 +0100 Subject: Add env to execute function. --- src/configure.cc | 127 +++++++++++++++++++++++++++++-------------------------- src/execute.cc | 82 ++++++++++++++++++++++++++--------- src/execute.h | 4 +- src/task_ar.cc | 2 +- src/task_cc.cc | 2 +- src/task_ld.cc | 2 +- src/task_so.cc | 2 +- src/unittest.cc | 2 +- src/util.cc | 79 ++++++++++++++++++++++++++++++++++ src/util.h | 6 +++ 10 files changed, 224 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/configure.cc b/src/configure.cc index 10f3056..b2639cb 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -98,57 +98,6 @@ const std::string& ctor::configuration::get(const std::string& key, const std::s return default_value; } -std::string locate(const std::string& arch, const std::string& app) -{ - std::string path_env = std::getenv("PATH"); - //std::cout << path_env << "\n"; - - std::string program = app; - if(!arch.empty()) - { - program = arch + "-" + app; - } - std::cout << "Looking for: " << program << "\n"; - std::vector paths; - - { - std::stringstream ss(path_env); - std::string path; - while (std::getline(ss, path, ':')) - { - paths.push_back(path); - } - } - for(const auto& path_str : paths) - { - std::filesystem::path path(path_str); - auto prog_path = path / program; - if(std::filesystem::exists(prog_path)) - { - std::cout << "Found file " << app << " in path: " << path << "\n"; - auto perms = std::filesystem::status(prog_path).permissions(); - if((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none) - { - //std::cout << " - executable by owner\n"; - } - if((perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none) - { - //std::cout << " - executable by group\n"; - } - if((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none) - { - //std::cout << " - executable by others\n"; - } - - return prog_path.string(); - } - } - - std::cerr << "Could not locate " << app << " for the " << arch << " architecture\n"; - exit(1); - return {}; -} - class Args : public std::vector { @@ -475,11 +424,36 @@ int regenerateCache(ctor::settings& settings, ld_prog = ld_env->second; } + auto paths = get_paths(); + // Host detection - auto host_cc = locate(host_arch_prefix, cc_prog); - auto host_cxx = locate(host_arch_prefix, cxx_prog); - auto host_ar = locate(host_arch_prefix, ar_prog); - auto host_ld = locate(host_arch_prefix, ld_prog); + auto host_cc = locate(cc_prog, paths, host_arch_prefix); + if(host_cc.empty()) + { + std::cerr << "Could not locate host_cc prog" << std::endl; + return 1; + } + + auto host_cxx = locate(cxx_prog, paths, host_arch_prefix); + if(host_cxx.empty()) + { + std::cerr << "Could not locate host_cxx prog" << std::endl; + return 1; + } + + auto host_ar = locate(ar_prog, paths, host_arch_prefix); + if(host_ar.empty()) + { + std::cerr << "Could not locate host_ar prog" << std::endl; + return 1; + } + + auto host_ld = locate(ld_prog, paths, host_arch_prefix); + if(host_ld.empty()) + { + std::cerr << "Could not locate host_ld prog" << std::endl; + return 1; + } auto host_toolchain = getToolChain(host_cxx); auto host_arch_str = get_arch(ctor::output_system::host); @@ -487,11 +461,40 @@ int regenerateCache(ctor::settings& settings, std::cout << "** Host architecture '" << host_arch_str << "': " << host_arch << std::endl; + if(host_arch == ctor::arch::unknown) + { + std::cerr << "Could not detect host architecture" << std::endl; + return 1; + } + // Build detection - auto build_cc = locate(build_arch_prefix, cc_prog); - auto build_cxx = locate(build_arch_prefix, cxx_prog); - auto build_ar = locate(build_arch_prefix, ar_prog); - auto build_ld = locate(build_arch_prefix, ld_prog); + auto build_cc = locate(cc_prog, paths, build_arch_prefix); + if(build_cc.empty()) + { + std::cerr << "Could not locate build_cc prog" << std::endl; + return 1; + } + + auto build_cxx = locate(cxx_prog, paths, build_arch_prefix); + if(build_cxx.empty()) + { + std::cerr << "Could not locate build_cxx prog" << std::endl; + return 1; + } + + auto build_ar = locate(ar_prog, paths, build_arch_prefix); + if(build_ar.empty()) + { + std::cerr << "Could not locate build_ar prog" << std::endl; + return 1; + } + + auto build_ld = locate(ld_prog, paths, build_arch_prefix); + if(build_ld.empty()) + { + std::cerr << "Could not locate build_ld prog" << std::endl; + return 1; + } auto build_toolchain = getToolChain(build_cxx); auto build_arch_str = get_arch(ctor::output_system::build); @@ -499,6 +502,12 @@ int regenerateCache(ctor::settings& settings, std::cout << "** Build architecture '" << build_arch_str << "': " << build_arch << std::endl; + if(build_arch == ctor::arch::unknown) + { + std::cerr << "Could not detect build architecture" << std::endl; + return 1; + } + if(!host_cxx.empty()) { // This is needed for bootstrapping (when running configure for the first time) diff --git a/src/execute.cc b/src/execute.cc index 20a4a02..b4013d0 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -20,6 +20,28 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork- namespace { +class Env + : public std::vector +{ +public: + Env(const std::vector& args) + { + for(const auto& arg : args) + { + push_back(strdup(arg.data())); + } + push_back(nullptr); + } + + ~Env() + { + for(auto ptr : *this) + { + free(ptr); + } + } +}; + int parent_waitpid(pid_t pid) { int status; @@ -33,8 +55,11 @@ int parent_waitpid(pid_t pid) } } // namespace :: +extern char **environ; // see 'man environ' + int execute(const std::string& command, const std::vector& args, + const std::map& env, bool verbose) { std::vector argv; @@ -45,22 +70,22 @@ int execute(const std::string& command, } argv.push_back(nullptr); - if(verbose) + std::string cmd; + for(const auto& arg : argv) { - std::string cmd; - for(const auto& arg : argv) + if(arg == nullptr) { - if(arg == nullptr) - { - break; - } - if(!cmd.empty()) - { - cmd += " "; - } - cmd += arg; + break; } + if(!cmd.empty()) + { + cmd += " "; + } + cmd += arg; + } + if(verbose) + { std::cout << cmd << std::endl; } @@ -68,23 +93,42 @@ int execute(const std::string& command, auto pid = vfork(); if(pid == 0) { - execv(command.data(), (char**)argv.data()); + std::vector venv; + for(const auto& [key, value] : env) + { + venv.push_back(key + "=" + value); + } + + for(auto current = environ; *current; ++current) + { + venv.push_back(*current); + } + + Env penv(venv); + execve(command.data(), (char**)argv.data(), penv.data()); std::cout << "Could not execute " << command << ": " << strerror(errno) << "\n"; - _exit(1); // execv only returns if an error occurred + _exit(1); // execve only returns if an error occurred } - auto ret = parent_waitpid(pid); + return parent_waitpid(pid); #elif 0 pid_t pid; + std::vector venv; + for(const auto& [key, value] : env) + { + venv.push_back(key + "=" + value); + } + Env penv(venv); if(posix_spawn(&pid, command.data(), nullptr, nullptr, - (char**)argv.data(), nullptr)) + (char**)argv.data(), penv.data())) { return 1; } - auto ret = parent_waitpid(pid); + return parent_waitpid(pid); #else - auto ret = system(cmd.data()); + (void)parent_waitpid; + return system(cmd.data()); #endif - return ret; + return 1; } diff --git a/src/execute.h b/src/execute.h index c750a83..336c3ef 100644 --- a/src/execute.h +++ b/src/execute.h @@ -5,7 +5,9 @@ #include #include +#include int execute(const std::string& command, - const std::vector& args, + const std::vector& args = {}, + const std::map& env = {}, bool verbose = true); diff --git a/src/task_ar.cc b/src/task_ar.cc index 605ab17..9cd78d0 100644 --- a/src/task_ar.cc +++ b/src/task_ar.cc @@ -118,7 +118,7 @@ int TaskAR::runInner() break; } - return execute(tool, args, settings.verbose > 0); + return execute(tool, args, {}, settings.verbose > 0); } int TaskAR::clean() diff --git a/src/task_cc.cc b/src/task_cc.cc index 46662ad..2238b67 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -187,7 +187,7 @@ int TaskCC::runInner() targetFile().lexically_normal().string() << std::endl; } - return execute(compiler(), args, settings.verbose > 0); + return execute(compiler(), args, {}, settings.verbose > 0); } int TaskCC::clean() diff --git a/src/task_ld.cc b/src/task_ld.cc index 908b641..a98ef44 100644 --- a/src/task_ld.cc +++ b/src/task_ld.cc @@ -123,7 +123,7 @@ int TaskLD::runInner() } auto tool = compiler(); - return execute(tool, args, settings.verbose > 0); + return execute(tool, args, {}, settings.verbose > 0); } int TaskLD::clean() diff --git a/src/task_so.cc b/src/task_so.cc index 522f6f2..e99205d 100644 --- a/src/task_so.cc +++ b/src/task_so.cc @@ -111,7 +111,7 @@ int TaskSO::runInner() } auto tool = compiler(); - return execute(tool, args, settings.verbose > 0); + return execute(tool, args, {}, settings.verbose > 0); } int TaskSO::clean() diff --git a/src/unittest.cc b/src/unittest.cc index 237b2e3..1e32878 100644 --- a/src/unittest.cc +++ b/src/unittest.cc @@ -24,7 +24,7 @@ int runUnitTests(std::set>& tasks, name = task->target(); } std::cout << name << ": " << std::flush; - auto ret = execute(task->targetFile(), {}, settings.verbose > 0); + auto ret = execute(task->targetFile(), {}, {}, settings.verbose > 0); ok &= ret == 0; if(ret == 0) { diff --git a/src/util.cc b/src/util.cc index fe16471..db5a5f6 100644 --- a/src/util.cc +++ b/src/util.cc @@ -167,3 +167,82 @@ std::string esc(const std::string& in) } return out; } + +std::vector get_paths() +{ + std::vector paths; + + std::string path_env = std::getenv("PATH"); + +#ifdef _WIN32 + const char sep{';'}; +#else + const char sep{':'}; +#endif + + std::stringstream ss(path_env); + std::string path; + while (std::getline(ss, path, sep)) + { + paths.push_back(path); + } + + return paths; +} + +bool check_executable(const std::filesystem::path& prog) +{ + auto perms = std::filesystem::status(prog).permissions(); + + if((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none) + { + return true; + } + + if((perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none) + { + return true; + } + + if((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none) + { + return true; + } + + return false; +} + +std::string locate(const std::string& prog, + const std::vector& paths, + const std::string& arch) +{ + std::string program = prog; + if(!arch.empty()) + { + program = arch + "-" + prog; + } + + // first check if arch contains an absolute path to prog + if(std::filesystem::exists(program)) + { + if(check_executable(program)) + { + return program; + } + } + + for(const auto& path_str : paths) + { + std::filesystem::path path(path_str); + auto prog_path = path / program; + if(std::filesystem::exists(prog_path)) + { + if(check_executable(prog_path)) + { + return prog_path.string(); + } + } + } + + return {}; +} diff --git a/src/util.h b/src/util.h index 9fa6be2..eeb3206 100644 --- a/src/util.h +++ b/src/util.h @@ -22,3 +22,9 @@ void append(T& a, const T& b) } std::string esc(const std::string& in); + +std::vector get_paths(); + +std::string locate(const std::string& app, + const std::vector& paths, + const std::string& arch = {}); -- cgit v1.2.3