diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2023-01-20 08:37:29 +0100 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2023-01-20 09:02:45 +0100 | 
| commit | a5585150f0ff8d27ddd22792f521f1374a3eedd8 (patch) | |
| tree | 3bb442e835502d452ebe5137ad7fca5f5156bb5f /src | |
| parent | 3cbadb8f5c55020ece96fab0fc8f4f51da01888e (diff) | |
Add env to execute function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/configure.cc | 127 | ||||
| -rw-r--r-- | src/execute.cc | 82 | ||||
| -rw-r--r-- | src/execute.h | 4 | ||||
| -rw-r--r-- | src/task_ar.cc | 2 | ||||
| -rw-r--r-- | src/task_cc.cc | 2 | ||||
| -rw-r--r-- | src/task_ld.cc | 2 | ||||
| -rw-r--r-- | src/task_so.cc | 2 | ||||
| -rw-r--r-- | src/unittest.cc | 2 | ||||
| -rw-r--r-- | src/util.cc | 79 | ||||
| -rw-r--r-- | src/util.h | 6 | 
10 files changed, 224 insertions, 84 deletions
| 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<std::string> 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<char*>  { @@ -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<char*> +{ +public: +	Env(const std::vector<std::string>& 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<std::string>& args, +            const std::map<std::string, std::string>& env,              bool verbose)  {  	std::vector<const char*> 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<std::string> 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<std::string> 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 <string>  #include <vector> +#include <map>  int execute(const std::string& command, -            const std::vector<std::string>& args, +            const std::vector<std::string>& args = {}, +            const std::map<std::string, std::string>& 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<std::shared_ptr<Task>>& 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<std::string> get_paths() +{ +	std::vector<std::string> 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<std::string>& 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 {}; +} @@ -22,3 +22,9 @@ void append(T& a, const T& b)  }  std::string esc(const std::string& in); + +std::vector<std::string> get_paths(); + +std::string locate(const std::string& app, +                   const std::vector<std::string>& paths, +                   const std::string& arch = {}); | 
