From 3cbadb8f5c55020ece96fab0fc8f4f51da01888e Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 19 Jan 2023 14:22:51 +0100 Subject: Make extension deduction architecture-aware. --- src/tools.cc | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 200 insertions(+), 31 deletions(-) (limited to 'src/tools.cc') diff --git a/src/tools.cc b/src/tools.cc index a83f115..be94794 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -8,6 +8,7 @@ #include #include +#include #include "util.h" @@ -115,7 +116,8 @@ ctor::toolchain getToolChain(const std::string& compiler) return ctor::toolchain::clang; } else if(cc_cmd.find("g++") != std::string::npos || - cc_cmd.find("gcc") != std::string::npos) + cc_cmd.find("gcc") != std::string::npos || + cc_cmd.find("mingw") != std::string::npos) { return ctor::toolchain::gcc; } @@ -146,9 +148,95 @@ ctor::toolchain getToolChain(ctor::output_system system) } namespace gcc { +std::string get_arch(ctor::output_system system) +{ + std::string cmd; + + const auto& c = ctor::get_configuration(); + switch(system) + { + case ctor::output_system::host: + cmd = c.get(ctor::cfg::host_cxx, "/usr/bin/g++"); + break; + case ctor::output_system::build: + cmd = c.get(ctor::cfg::build_cxx, "/usr/bin/g++"); + break; + } + + cmd += " -v"; + cmd += " 2>&1"; + auto pipe = popen(cmd.data(), "r"); + if(!pipe) + { + std::cerr << "Could not run compiler " << cmd << "\n"; + return {};//ctor::arch::unknown; + } + + std::string arch; + while(!feof(pipe)) + { + char buf[1024]; + if(fgets(buf, sizeof(buf), pipe) != nullptr) + { + arch = buf; + if(arch.starts_with("Target:")) + { + break; + } + } + } + + pclose(pipe); + + // Remove trailing newline + if(arch.ends_with("\n")) + { + arch = arch.substr(0, arch.length() - 1); + } + + // Remove 'Target: ' prefix + arch = arch.substr(8); + return arch; +} + +ctor::arch get_arch(const std::string& str) +{ + // gcc -v 2>&1 | grep Target + // Target: x86_64-apple-darwin19.6.0 + // Target: x86_64-pc-linux-gnu + // Target: arm-linux-gnueabihf + // Target: x86_64-linux-gnu + // Target: x86_64-unknown-freebsd13.1 + // # x86_64-w64-mingw32-c++-win32 -v 2>&1 | grep Target + // Target: x86_64-w64-mingw32 + // # i686-w64-mingw32-c++-win32 -v 2>&1 | grep Target + // Target: i686-w64-mingw32 + + if(str.find("apple") != std::string::npos || + str.find("darwin") != std::string::npos) + { + return ctor::arch::apple; + } + + if(str.find("linux") != std::string::npos || + str.find("bsd") != std::string::npos) + { + return ctor::arch::unix; + } + + if(str.find("mingw") != std::string::npos) + { + return ctor::arch::windows; + } + + std::cerr << "Could not deduce gcc arch from '" << str << "'" << std::endl; + + return ctor::arch::unknown; +} + ctor::c_flag c_option(const std::string& flag) { - if(flag.substr(0, 2) == "-I") + if(flag.starts_with("-I")) { std::string path = flag.substr(2); path.erase(0, path.find_first_not_of(' ')); @@ -160,7 +248,7 @@ ctor::c_flag c_option(const std::string& flag) ctor::cxx_flag cxx_option(const std::string& flag) { - if(flag.substr(0, 2) == "-I") + if(flag.starts_with("-I")) { std::string path = flag.substr(2); path.erase(0, path.find_first_not_of(' ')); @@ -172,7 +260,7 @@ ctor::cxx_flag cxx_option(const std::string& flag) ctor::ld_flag ld_option(const std::string& flag) { - if(flag.substr(0, 2) == "-L") + if(flag.starts_with("-L")) { std::string path = flag.substr(2); path.erase(0, path.find_first_not_of(' ')); @@ -320,34 +408,37 @@ std::vector asm_option(ctor::asm_opt opt, const std::string& arg) std::cerr << "Unsupported compiler option.\n"; return {}; } +} // gcc:: -std::string extension(ctor::target_type target_type) +std::string get_arch(ctor::output_system system) { - switch(target_type) + auto toolchain = getToolChain(system); + switch(toolchain) { - case ctor::target_type::automatic: - break; - case ctor::target_type::executable: - return ""; - case ctor::target_type::static_library: - return ".a"; - case ctor::target_type::dynamic_library: - return ".so"; - case ctor::target_type::object: - return ".o"; - case ctor::target_type::unit_test: - return ""; - case ctor::target_type::unit_test_library: - return ".a"; - case ctor::target_type::function: - break; - case ctor::target_type::unknown: + case ctor::toolchain::clang: + case ctor::toolchain::gcc: + return gcc::get_arch(system); + case ctor::toolchain::any: + case ctor::toolchain::none: break; } return {}; } -} // gcc:: +ctor::arch get_arch(ctor::output_system system, const std::string& str) +{ + auto toolchain = getToolChain(system); + switch(toolchain) + { + case ctor::toolchain::clang: + case ctor::toolchain::gcc: + return gcc::get_arch(str); + case ctor::toolchain::any: + case ctor::toolchain::none: + break; + } + return ctor::arch::unknown; +} std::vector c_option(ctor::toolchain toolchain, ctor::c_opt opt, @@ -746,6 +837,7 @@ ctor::target_type target_type_from_extension(ctor::toolchain toolchain, std::filesystem::path extension(ctor::toolchain toolchain, ctor::target_type target_type, + ctor::output_system system, const std::filesystem::path& file) { auto type = target_type_from_extension(toolchain, file); @@ -755,16 +847,93 @@ std::filesystem::path extension(ctor::toolchain toolchain, return file; } + const auto& c = ctor::get_configuration(); + ctor::arch arch{}; + switch(system) + { + case ctor::output_system::host: + arch = c.host_arch; + break; + case ctor::output_system::build: + arch = c.build_arch; + break; + } + + // This might be before configure - so detection is needed for boostrap + if(arch == ctor::arch::unknown) + { + arch = get_arch(system, get_arch(system)); + } + std::string ext{file.extension().string()}; - switch(toolchain) + switch(target_type) { - case ctor::toolchain::gcc: - case ctor::toolchain::clang: - ext = gcc::extension(target_type); + case ctor::target_type::automatic: + break; + case ctor::target_type::executable: + case ctor::target_type::unit_test: + switch(arch) + { + case ctor::arch::unix: + case ctor::arch::apple: + ext = ""; + break; + case ctor::arch::windows: + ext = ".exe"; + break; + case ctor::arch::unknown: + break; + } + break; + case ctor::target_type::static_library: + case ctor::target_type::unit_test_library: + switch(arch) + { + case ctor::arch::unix: + case ctor::arch::apple: + ext = ".a"; + break; + case ctor::arch::windows: + ext = ".lib"; + break; + case ctor::arch::unknown: + break; + } + break; + case ctor::target_type::dynamic_library: + switch(arch) + { + case ctor::arch::unix: + ext = ".so"; + break; + case ctor::arch::apple: + ext = ".dylib"; + break; + case ctor::arch::windows: + ext = ".dll"; + break; + case ctor::arch::unknown: + break; + } + break; + case ctor::target_type::object: + switch(arch) + { + case ctor::arch::unix: + case ctor::arch::apple: + ext = ".o"; + break; + case ctor::arch::windows: + ext = ".obj"; + break; + case ctor::arch::unknown: + break; + } + break; + case ctor::target_type::function: + break; + case ctor::target_type::unknown: break; - case ctor::toolchain::any: - case ctor::toolchain::none: - return file; } auto output{file}; -- cgit v1.2.3