summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2023-01-19 14:22:51 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2023-01-19 14:22:51 +0100
commit3cbadb8f5c55020ece96fab0fc8f4f51da01888e (patch)
tree8c2bf1a8bd5426c6f99cf91d1811a10f3999a477
parent79c11f3dbaad391633c2678e85eeaba267df5ee1 (diff)
Make extension deduction architecture-aware.
-rw-r--r--ctor.cc1
-rw-r--r--src/configure.cc69
-rw-r--r--src/ctor.h12
-rw-r--r--src/task_ar.cc2
-rw-r--r--src/task_cc.cc2
-rw-r--r--src/task_ld.cc2
-rw-r--r--src/task_so.cc2
-rw-r--r--src/tools.cc231
-rw-r--r--src/tools.h3
9 files changed, 272 insertions, 52 deletions
diff --git a/ctor.cc b/ctor.cc
index c9faa5e..b2513af 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -10,7 +10,6 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
return
{
{
- .type = ctor::target_type::static_library,
.target = "libctor.a",
.sources = {
"src/build.cc",
diff --git a/src/configure.cc b/src/configure.cc
index a2bb8bc..10f3056 100644
--- a/src/configure.cc
+++ b/src/configure.cc
@@ -193,6 +193,26 @@ std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain)
return stream;
}
+std::ostream& operator<<(std::ostream& stream, const ctor::arch& arch)
+{
+ switch(arch)
+ {
+ case ctor::arch::unix:
+ stream << "ctor::arch::unix";
+ break;
+ case ctor::arch::apple:
+ stream << "ctor::arch::apple";
+ break;
+ case ctor::arch::windows:
+ stream << "ctor::arch::windows";
+ break;
+ case ctor::arch::unknown:
+ stream << "ctor::arch::unknown";
+ break;
+ }
+ return stream;
+}
+
std::ostream& operator<<(std::ostream& ostr, const ctor::c_flag& flag)
{
for(const auto& s : to_strings(ctor::toolchain::any, flag))
@@ -243,9 +263,9 @@ int regenerateCache(ctor::settings& settings,
dg::Options opt;
int key{128};
- std::string build_arch;
+ std::string build_arch_prefix;
std::string build_path;
- std::string host_arch;
+ std::string host_arch_prefix;
std::string host_path;
std::string cc_prog = "gcc";
std::string cxx_prog = "g++";
@@ -302,7 +322,7 @@ int regenerateCache(ctor::settings& settings,
opt.add("build", required_argument, key++,
"Configure for building on specified architecture.",
[&]() {
- build_arch = optarg;
+ build_arch_prefix = optarg;
return 0;
});
@@ -316,7 +336,7 @@ int regenerateCache(ctor::settings& settings,
opt.add("host", required_argument, key++,
"Cross-compile to build programs to run on specified architecture.",
[&]() {
- host_arch = optarg;
+ host_arch_prefix = optarg;
return 0;
});
@@ -399,9 +419,9 @@ int regenerateCache(ctor::settings& settings,
opt.process(vargs.size(), vargs.data());
- if(host_arch.empty())
+ if(host_arch_prefix.empty())
{
- host_arch = build_arch;
+ host_arch_prefix = build_arch_prefix;
}
auto tasks = getTasks(settings, {}, false);
@@ -455,14 +475,29 @@ int regenerateCache(ctor::settings& settings,
ld_prog = ld_env->second;
}
- std::string host_cc = locate(host_arch, cc_prog);
- std::string host_cxx = locate(host_arch, cxx_prog);
- std::string host_ar = locate(host_arch, ar_prog);
- std::string host_ld = locate(host_arch, ld_prog);
- std::string build_cc = locate(build_arch, cc_prog);
- std::string build_cxx = locate(build_arch, cxx_prog);
- std::string build_ar = locate(build_arch, ar_prog);
- std::string build_ld = locate(build_arch, ld_prog);
+ // 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_toolchain = getToolChain(host_cxx);
+ auto host_arch_str = get_arch(ctor::output_system::host);
+ auto host_arch = get_arch(ctor::output_system::host, host_arch_str);
+
+ std::cout << "** Host architecture '" << host_arch_str << "': " << host_arch << std::endl;
+
+ // 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_toolchain = getToolChain(build_cxx);
+ auto build_arch_str = get_arch(ctor::output_system::build);
+ auto build_arch = get_arch(ctor::output_system::build, build_arch_str);
+
+ std::cout << "** Build architecture '" << build_arch_str << "': " << build_arch << std::endl;
if(!host_cxx.empty())
{
@@ -494,8 +529,10 @@ int regenerateCache(ctor::settings& settings,
istr << "{\n";
istr << " static ctor::configuration cfg =\n";
istr << " {\n";
- istr << " .host_toolchain = " << getToolChain(host_cxx) << ",\n";
- istr << " .build_toolchain = " << getToolChain(build_cxx) << ",\n";
+ istr << " .host_toolchain = " << host_toolchain << ",\n";
+ istr << " .host_arch = " << host_arch << ",\n";
+ istr << " .build_toolchain = " << build_toolchain << ",\n";
+ istr << " .build_arch = " << build_arch << ",\n";
istr << " .args = {";
for(const auto& arg : args)
{
diff --git a/src/ctor.h b/src/ctor.h
index 4e0a247..ab486a5 100644
--- a/src/ctor.h
+++ b/src/ctor.h
@@ -43,6 +43,15 @@ enum class output_system
build, // Internal tool during cross-compilation
};
+enum class arch
+{
+ unix, //!< Target platform architecture is unix-based (ie. linux, bsd, etc)
+ apple, //!< Target platform architecture is macos
+ windows, //!< Target platform architecture is windows
+
+ unknown, //!< Target platform architecture has not yet detected or was not possible to detect
+};
+
struct source
{
source(const char* file) : file(file) {}
@@ -256,7 +265,10 @@ struct configuration
const std::string& get(const std::string& key, const std::string& default_value = {}) const;
ctor::toolchain host_toolchain{ctor::toolchain::none};
+ ctor::arch host_arch{ctor::arch::unknown};
+
ctor::toolchain build_toolchain{ctor::toolchain::none};
+ ctor::arch build_arch{ctor::arch::unknown};
std::vector<std::string> args; // vector of arguments used when last calling configure
std::map<std::string, std::string> env; // env used when last calling configure
diff --git a/src/task_ar.cc b/src/task_ar.cc
index b73c6ac..605ab17 100644
--- a/src/task_ar.cc
+++ b/src/task_ar.cc
@@ -26,7 +26,7 @@ TaskAR::TaskAR(const ctor::build_configuration& config,
target_type = ctor::target_type::static_library;
_targetFile = target;
auto toolchain = getToolChain(config.system);
- _targetFile = extension(toolchain, target_type, _targetFile);
+ _targetFile = extension(toolchain, target_type, config.system, _targetFile);
for(const auto& object : objects)
{
std::filesystem::path objectFile = object;
diff --git a/src/task_cc.cc b/src/task_cc.cc
index f16a07f..46662ad 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -62,7 +62,7 @@ TaskCC::TaskCC(const ctor::build_configuration& config, const ctor::settings& se
_targetFile = source.output;
}
auto toolchain = getToolChain(config.system);
- _targetFile = extension(toolchain, target_type, _targetFile);
+ _targetFile = extension(toolchain, target_type, config.system, _targetFile);
depsFile = targetFile().parent_path() / targetFile().stem();
depsFile += ".d";
diff --git a/src/task_ld.cc b/src/task_ld.cc
index e619dfd..908b641 100644
--- a/src/task_ld.cc
+++ b/src/task_ld.cc
@@ -31,7 +31,7 @@ TaskLD::TaskLD(const ctor::build_configuration& config,
_targetFile = target;
auto toolchain = getToolChain(config.system);
- _targetFile = extension(toolchain, target_type, _targetFile);
+ _targetFile = extension(toolchain, target_type, config.system, _targetFile);
for(const auto& object : objects)
{
std::filesystem::path objectFile = object;
diff --git a/src/task_so.cc b/src/task_so.cc
index 9aae7ff..522f6f2 100644
--- a/src/task_so.cc
+++ b/src/task_so.cc
@@ -27,7 +27,7 @@ TaskSO::TaskSO(const ctor::build_configuration& config,
target_type = ctor::target_type::dynamic_library;
_targetFile = base / target;
auto toolchain = getToolChain(config.system);
- _targetFile = extension(toolchain, target_type, _targetFile);
+ _targetFile = extension(toolchain, target_type, config.system, _targetFile);
for(const auto& object : objects)
{
std::filesystem::path objectFile = object;
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 <sstream>
#include <cassert>
+#include <cstdio>
#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<std::string> 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<std::string> 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};
diff --git a/src/tools.h b/src/tools.h
index 4fb6302..188d49f 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -17,6 +17,8 @@ std::ostream& operator<<(std::ostream& stream, const ctor::ld_opt& opt);
std::ostream& operator<<(std::ostream& stream, const ctor::ar_opt& opt);
std::ostream& operator<<(std::ostream& stream, const ctor::asm_opt& opt);
+std::string get_arch(ctor::output_system system);
+ctor::arch get_arch(ctor::output_system system, const std::string& str);
//! Get tool-chain type from compiler path string
ctor::toolchain getToolChain(const std::string& compiler);
@@ -118,4 +120,5 @@ ctor::target_type target_type_from_extension(ctor::toolchain toolchain,
// mingw .exe .lib .dll
std::filesystem::path extension(ctor::toolchain toolchain,
ctor::target_type target_type,
+ ctor::output_system system,
const std::filesystem::path& file);