diff options
Diffstat (limited to 'src/configure.cc')
-rw-r--r-- | src/configure.cc | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/src/configure.cc b/src/configure.cc new file mode 100644 index 0000000..ab2f837 --- /dev/null +++ b/src/configure.cc @@ -0,0 +1,301 @@ +#include "configure.h" + +#include <iostream> +#include <filesystem> +#include <fstream> + +#include <getoptpp/getoptpp.hpp> + +#include "settings.h" +#include "execute.h" +#include "libcppbuild.h" +#include "tasks.h" + +std::filesystem::path configurationFile("configuration.cc"); +std::filesystem::path configHeaderFile("config.h"); + +const std::map<std::string, std::string> default_configuration{}; +const std::map<std::string, std::string>& __attribute__((weak)) configuration() +{ + return default_configuration; +} + +bool hasConfiguration(const std::string& key) +{ + const auto& c = configuration(); + return c.find(key) != c.end(); +} + +const std::string& getConfiguration(const std::string& key, + const std::string& defaultValue) +{ + const auto& c = configuration(); + if(hasConfiguration(key)) + { + return c.at(key); + } + + return defaultValue; +} + +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 {}; +} + +int configure(int argc, char* argv[]) +{ + Settings settings; + + settings.builddir = "build"; + + std::string cmd_str; + for(int i = 0; i < argc; ++i) + { + if(i > 0) + { + cmd_str += " "; + } + cmd_str += argv[i]; + } + + dg::Options opt; + int key{128}; + + std::string build_arch; + std::string build_path; + std::string host_arch; + std::string host_path; + std::string cc_prog = "gcc"; + std::string cxx_prog = "g++"; + std::string ar_prog = "ar"; + std::string ld_prog = "ld"; + + opt.add("build-dir", required_argument, 'b', + "Set output directory for build files (default: '" + + settings.builddir + "').", + [&]() { + settings.builddir = optarg; + return 0; + }); + + opt.add("verbose", no_argument, 'v', + "Be verbose. Add multiple times for more verbosity.", + [&]() { + settings.verbose++; + return 0; + }); + + opt.add("cc", required_argument, key++, + "Use specified c-compiler instead of gcc.", + [&]() { + cc_prog = optarg; + return 0; + }); + + opt.add("cxx", required_argument, key++, + "Use specified c++-compiler instead of g++.", + [&]() { + cxx_prog = optarg; + return 0; + }); + + opt.add("ar", required_argument, key++, + "Use specified archiver instead of ar.", + [&]() { + ar_prog = optarg; + return 0; + }); + + opt.add("ld", required_argument, key++, + "Use specified linker instead of ld.", + [&]() { + ld_prog = optarg; + return 0; + }); + + opt.add("build", required_argument, key++, + "Configure for building on specified architecture.", + [&]() { + build_arch = optarg; + return 0; + }); + + opt.add("build-path", required_argument, key++, + "Set path to build tool-chain.", + [&]() { + build_path = optarg; + return 0; + }); + + opt.add("host", required_argument, key++, + "Cross-compile to build programs to run on specified architecture.", + [&]() { + host_arch = optarg; + return 0; + }); + + opt.add("host-path", required_argument, key++, + "Set path to cross-compile tool-chain.", + [&]() { + host_path = optarg; + return 0; + }); + + opt.add("help", no_argument, 'h', + "Print this help text.", + [&]() { + std::cout << "configure usage stuff\n"; + opt.help(); + exit(0); + return 0; + }); + + opt.process(argc, argv); + + if(host_arch.empty()) + { + host_arch = build_arch; + } + + auto tasks = getTasks(settings); +/* + bool needs_cpp{false}; + bool needs_c{false}; + bool needs_ar{false}; + bool needs_asm{false}; + for(const auto& task :tasks) + { + switch(task->sourceLanguage()) + { + case Language::Auto: + std::cerr << "TargetLanguage not deduced!\n"; + exit(1); + break; + case Language::C: + needs_cpp = false; + break; + case Language::Cpp: + needs_c = true; + break; + case Language::Asm: + needs_asm = true; + break; + } + } +*/ + auto cc_env = getenv("CC"); + if(cc_env) + { + cmd_str = std::string("CC=") + cc_env + " " + cmd_str; + cc_prog = cc_env; + } + + auto cxx_env = getenv("CXX"); + if(cxx_env) + { + cmd_str = std::string("CXX=") + cxx_env + " " + cmd_str; + cxx_prog = cxx_env; + } + + auto ar_env = getenv("AR"); + if(ar_env) + { + cmd_str = std::string("AR=") + ar_env + " " + cmd_str; + ar_prog = ar_env; + } + + auto ld_env = getenv("LD"); + if(ld_env) + { + cmd_str = std::string("LD=") + ld_env + " " + cmd_str; + ld_prog = ld_env; + } + + 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); + + std::cout << "Writing results to: " << configurationFile.string() << "\n"; + { + std::ofstream istr(configurationFile); + istr << "#include \"libcppbuild.h\"\n\n"; + istr << "const std::map<std::string, std::string>& configuration()\n"; + istr << "{\n"; + istr << " static std::map<std::string, std::string> c =\n"; + istr << " {\n"; + istr << " { \"cmd\", \"" << cmd_str << "\" },\n"; + istr << " { \"" << cfg::builddir << "\", \"" << settings.builddir << "\" },\n"; + istr << " { \"" << cfg::host_cc << "\", \"" << host_cc << "\" },\n"; + istr << " { \"" << cfg::host_cxx << "\", \"" << host_cxx << "\" },\n"; + istr << " { \"" << cfg::host_ar << "\", \"" << host_ar << "\" },\n"; + istr << " { \"" << cfg::host_ld << "\", \"" << host_ld << "\" },\n"; + istr << " { \"" << cfg::build_cc << "\", \"" << build_cc << "\" },\n"; + istr << " { \"" << cfg::build_cxx << "\", \"" << build_cxx << "\" },\n"; + istr << " { \"" << cfg::build_ar << "\", \"" << build_ar << "\" },\n"; + istr << " { \"" << cfg::build_ld << "\", \"" << build_ld << "\" },\n"; + istr << " };\n"; + istr << " return c;\n"; + istr << "}\n"; + } + + { + std::ofstream istr(configHeaderFile); + istr << "#pragma once\n\n"; + istr << "#define HAS_FOO 1\n"; + istr << "//#define HAS_BAR 1\n"; + } + + return 0; +} |