Selaa lähdekoodia

Remove libman-style toolchain code

default_compile_flags
vector-of-bool 4 vuotta sitten
vanhempi
commit
5e3c668f57
5 muutettua tiedostoa jossa 30 lisäystä ja 777 poistoa
  1. +0
    -1
      src/dds.main.cpp
  2. +0
    -589
      src/dds/toolchain/from_dds.cpp
  3. +0
    -18
      src/dds/toolchain/from_dds.hpp
  4. +0
    -146
      src/dds/toolchain/from_dds.test.cpp
  5. +30
    -23
      src/dds/toolchain/toolchain.cpp

+ 0
- 1
src/dds.main.cpp Näytä tiedosto

@@ -5,7 +5,6 @@
#include <dds/error/errors.hpp>
#include <dds/repo/repo.hpp>
#include <dds/source/dist.hpp>
#include <dds/toolchain/from_dds.hpp>
#include <dds/toolchain/from_json.hpp>
#include <dds/util/fs.hpp>
#include <dds/util/paths.hpp>

+ 0
- 589
src/dds/toolchain/from_dds.cpp Näytä tiedosto

@@ -1,589 +0,0 @@
#include "./from_dds.hpp"

#include <dds/dym.hpp>
#include <dds/toolchain/prep.hpp>
#include <dds/toolchain/toolchain.hpp>
#include <dds/util/algo.hpp>
#include <dds/util/shlex.hpp>
#include <libman/parse.hpp>

#include <spdlog/fmt/fmt.h>

#include <map>
#include <optional>
#include <tuple>
#include <vector>

using namespace dds;

using fmt::format;
using std::optional;
using std::string;
using std::vector;
using string_seq = vector<string>;
using opt_string = optional<string>;
using opt_str_seq = optional<string_seq>;
using strv = std::string_view;

toolchain dds::parse_toolchain_dds(strv str, strv context) {
auto kvs = lm::parse_string(str);
return parse_toolchain_dds(kvs, context);
}

namespace {
struct read_argv_acc {
strv my_key;
opt_str_seq& out;

bool operator()(strv, strv key, strv value) const {
if (key != my_key) {
return false;
}
if (!out) {
out.emplace();
}
auto cmd = split_shell_string(value);
extend(*out, cmd);
return true;
}
};

struct read_argv {
strv my_key;
opt_str_seq& out;

bool operator()(strv ctx, strv key, strv value) const {
if (key != my_key) {
return false;
}
if (out.has_value()) {
throw std::runtime_error(
format("{}: More than one value provided for key '{}'", ctx, key));
}
out.emplace(split_shell_string(value));
return true;
}
};

template <typename T, typename Func>
T read_opt(const std::optional<T>& what, Func&& fn) {
if (!what.has_value()) {
return fn();
}
return *what;
}

template <typename... Args>
[[noreturn]] void fail(strv context, strv message, Args&&... args) {
auto fmtd = format(message, args...);
throw std::runtime_error(format("{} - Failed to read toolchain file: {}", context, fmtd));
}
} // namespace

toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
opt_string compiler_id;
opt_string c_compiler_fpath;
opt_string cxx_compiler_fpath;
opt_string c_version;
opt_string cxx_version;
opt_string archive_prefix;
opt_string archive_suffix;
opt_string obj_prefix;
opt_string obj_suffix;
opt_string exe_prefix;
opt_string exe_suffix;
opt_string deps_mode_str;
optional<bool> do_debug;
optional<bool> do_optimize;
opt_str_seq include_template;
opt_str_seq external_include_template;
opt_str_seq define_template;
opt_str_seq warning_flags;
opt_str_seq flags;
opt_str_seq c_flags;
opt_str_seq cxx_flags;
opt_str_seq link_flags;
opt_str_seq c_compile_file;
opt_str_seq cxx_compile_file;
opt_str_seq create_archive;
opt_str_seq link_executable;
opt_str_seq compile_launcher;

lm::read(context,
pairs,
// Base compile info:
lm::read_opt("Compiler-ID", compiler_id),
lm::read_opt("C-Compiler", c_compiler_fpath),
lm::read_opt("C++-Compiler", cxx_compiler_fpath),
// Language options
lm::read_opt("C-Version", c_version),
lm::read_opt("C++-Version", cxx_version),
// Flag templates
read_argv{"Include-Template", include_template},
read_argv{"External-Include-Template", include_template},
read_argv{"Define-Template", define_template},
// Flags
read_argv_acc{"Warning-Flags", warning_flags},
read_argv_acc{"Flags", flags},
read_argv_acc{"C-Flags", c_flags},
read_argv_acc{"C++-Flags", cxx_flags},
read_argv_acc{"Link-Flags", link_flags},
// Options for flags
lm::read_bool("Optimize", do_optimize),
lm::read_bool("Debug", do_debug),
// Miscellaneous
read_argv{"Compiler-Launcher", compile_launcher},
lm::read_opt("Deps-Mode", deps_mode_str),
// Command templates
read_argv{"C-Compile-File", c_compile_file},
read_argv{"C++-Compile-File", cxx_compile_file},
read_argv{"Create-Archive", create_archive},
read_argv{"Link-Executable", link_executable},
// Filename affixes
lm::read_opt("Archive-Prefix", archive_prefix),
lm::read_opt("Archive-Suffix", archive_suffix),
lm::read_opt("Object-Prefix", obj_prefix),
lm::read_opt("Object-Suffix", obj_suffix),
lm::read_opt("Executable-Prefix", exe_prefix),
lm::read_opt("Executable-Suffix", exe_suffix),
// Die:
lm_reject_dym{{
"Compiler-ID",
"C-Compiler",
"C++-Compiler",
"C-Version",
"C++-Version",
"Include-Template",
"External-Include-Template",
"Define-Template",
"Warning-Flags",
"Flags",
"C-Flags",
"C++-Flags",
"Link-Flags",
"Optimize",
"Debug",
"Compiler-Launcher",
"Deps-Mode",
"C-Compile-File",
"C++-Compile-File",
"Create-Archive",
"Link-Executable",
"Archive-Prefix",
"Archive-Suffix",
"Object-Prefix",
"Object-Suffix",
"Executable-Prefix",
"Executable-Suffix",
}});

toolchain_prep tc;

enum compiler_id_e_t {
no_comp_id,
msvc,
clang,
gnu,
} compiler_id_e
= [&] {
if (!compiler_id) {
return no_comp_id;
} else if (compiler_id == "MSVC") {
return msvc;
} else if (compiler_id == "GNU") {
return gnu;
} else if (compiler_id == "Clang") {
return clang;
} else {
fail(context, "Unknown Compiler-ID '{}'", *compiler_id);
}
}();

bool is_gnu = compiler_id_e == gnu;
bool is_clang = compiler_id_e == clang;
bool is_msvc = compiler_id_e == msvc;
bool is_gnu_like = is_gnu || is_clang;

const enum file_deps_mode deps_mode = [&] {
if (!deps_mode_str.has_value()) {
if (is_gnu_like) {
return file_deps_mode::gnu;
} else if (is_msvc) {
return file_deps_mode::msvc;
} else {
return file_deps_mode::none;
}
} else if (deps_mode_str == "GNU") {
return file_deps_mode::gnu;
} else if (deps_mode_str == "MSVC") {
return file_deps_mode::msvc;
} else if (deps_mode_str == "None") {
return file_deps_mode::none;
} else {
fail(context, "Unknown Deps-Mode '{}'", *deps_mode_str);
}
}();

// Now convert the flags we've been given into a real toolchain
auto get_compiler = [&](language lang) -> string {
if (lang == language::cxx && cxx_compiler_fpath) {
return *cxx_compiler_fpath;
}
if (lang == language::c && c_compiler_fpath) {
return *c_compiler_fpath;
}
if (!compiler_id.has_value()) {
fail(context, "Unable to determine what compiler to use.");
}
if (is_gnu) {
return (lang == language::cxx) ? "g++" : "gcc";
}
if (is_clang) {
return (lang == language::cxx) ? "clang++" : "clang";
}
if (is_msvc) {
return "cl.exe";
}
assert(false && "Compiler name deduction failed");
std::terminate();
};

enum c_version_e_t {
c_none,
c89,
c99,
c11,
c18,
} c_version_e
= [&] {
if (!c_version) {
return c_none;
} else if (c_version == "C89") {
return c89;
} else if (c_version == "C99") {
return c99;
} else if (c_version == "C11") {
return c11;
} else if (c_version == "C18") {
return c18;
} else {
fail(context, "Unknown C-Version '{}'", *c_version);
}
}();

enum cxx_version_e_t {
cxx_none,
cxx98,
cxx03,
cxx11,
cxx14,
cxx17,
cxx20,
} cxx_version_e
= [&] {
if (!cxx_version) {
return cxx_none;
} else if (cxx_version == "C++98") {
return cxx98;
} else if (cxx_version == "C++03") {
return cxx03;
} else if (cxx_version == "C++11") {
return cxx11;
} else if (cxx_version == "C++14") {
return cxx14;
} else if (cxx_version == "C++17") {
return cxx17;
} else if (cxx_version == "C++20") {
return cxx20;
} else {
fail(context, "Unknown C++-Version '{}'", *cxx_version);
}
}();

std::map<std::tuple<compiler_id_e_t, c_version_e_t>, string_seq> c_version_flag_table = {
{{msvc, c_none}, {}},
{{msvc, c89}, {}},
{{msvc, c99}, {}},
{{msvc, c11}, {}},
{{msvc, c18}, {}},
{{gnu, c_none}, {}},
{{gnu, c89}, {"-std=c89"}},
{{gnu, c99}, {"-std=c99"}},
{{gnu, c11}, {"-std=c11"}},
{{gnu, c18}, {"-std=c18"}},
{{clang, c_none}, {}},
{{clang, c89}, {"-std=c89"}},
{{clang, c99}, {"-std=c99"}},
{{clang, c11}, {"-std=c11"}},
{{clang, c18}, {"-std=c18"}},
};

auto get_c_version_flags = [&]() -> string_seq {
if (!compiler_id.has_value()) {
fail(context, "Unable to deduce flags for 'C-Version' without setting 'Compiler-ID'");
}
auto c_ver_iter = c_version_flag_table.find({compiler_id_e, c_version_e});
assert(c_ver_iter != c_version_flag_table.end());
return c_ver_iter->second;
};

std::map<std::tuple<compiler_id_e_t, cxx_version_e_t>, string_seq> cxx_version_flag_table = {
{{msvc, cxx_none}, {}},
{{msvc, cxx98}, {}},
{{msvc, cxx03}, {}},
{{msvc, cxx11}, {}},
{{msvc, cxx14}, {"/std:c++14"}},
{{msvc, cxx17}, {"/std:c++17"}},
{{msvc, cxx20}, {"/std:c++latest"}},
{{gnu, cxx_none}, {}},
{{gnu, cxx98}, {"-std=c++98"}},
{{gnu, cxx03}, {"-std=c++03"}},
{{gnu, cxx11}, {"-std=c++11"}},
{{gnu, cxx14}, {"-std=c++14"}},
{{gnu, cxx17}, {"-std=c++17"}},
{{gnu, cxx20}, {"-std=c++20"}},
{{clang, cxx_none}, {}},
{{clang, cxx98}, {"-std=c++98"}},
{{clang, cxx03}, {"-std=c++03"}},
{{clang, cxx11}, {"-std=c++11"}},
{{clang, cxx14}, {"-std=c++14"}},
{{clang, cxx17}, {"-std=c++17"}},
{{clang, cxx20}, {"-std=c++20"}},
};

auto get_cxx_version_flags = [&]() -> string_seq {
if (!compiler_id.has_value()) {
fail(context, "Unable to deduce flags for 'C++-Version' without setting 'Compiler-ID'");
}
auto cxx_ver_iter = cxx_version_flag_table.find({compiler_id_e, cxx_version_e});
assert(cxx_ver_iter != cxx_version_flag_table.end());
return cxx_ver_iter->second;
};

auto get_link_flags = [&]() -> string_seq {
string_seq ret;
if (is_msvc) {
strv rt_lib = "/MT";
if (do_optimize.value_or(false)) {
extend(ret, {"/O2"});
}
if (do_debug.value_or(false)) {
extend(ret, {"/Z7", "/DEBUG"});
rt_lib = "/MTd";
}
ret.emplace_back(rt_lib);
} else if (is_gnu_like) {
if (do_optimize.value_or(false)) {
extend(ret, {"-O2"});
}
if (do_debug.value_or(false)) {
extend(ret, {"-g"});
}
}
if (link_flags) {
extend(ret, *link_flags);
}
return ret;
};

auto get_flags = [&](language lang) -> string_seq {
string_seq ret;
if (lang == language::cxx && cxx_flags) {
extend(ret, *cxx_flags);
}
if (lang == language::cxx && cxx_version) {
extend(ret, get_cxx_version_flags());
}
if (lang == language::c && c_flags) {
extend(ret, *c_flags);
}
if (lang == language::c && c_version) {
extend(ret, get_c_version_flags());
}
if (is_msvc) {
strv rt_lib = "/MT";
if (do_optimize.has_value() && *do_optimize) {
extend(ret, {"/O2"});
}
if (do_debug.has_value() && *do_debug) {
extend(ret, {"/Z7", "/DEBUG"});
rt_lib = "/MTd";
}
ret.emplace_back(rt_lib);
if (lang == language::cxx) {
extend(ret, {"/EHsc"});
}
extend(ret, {"/nologo", "/permissive-", "<FLAGS>", "/c", "<IN>", "/Fo<OUT>"});
} else if (is_gnu_like) {
if (do_optimize.has_value() && *do_optimize) {
extend(ret, {"-O2"});
}
if (do_debug.has_value() && *do_debug) {
extend(ret, {"-g"});
}
extend(ret,
{"-fPIC",
"-fdiagnostics-color",
"-pthread",
"<FLAGS>",
"-c",
"<IN>",
"-o<OUT>"});
}
if (flags) {
extend(ret, *flags);
}
return ret;
};

tc.deps_mode = deps_mode;

tc.c_compile = read_opt(c_compile_file, [&] {
string_seq c;
if (compile_launcher) {
extend(c, *compile_launcher);
}
c.push_back(get_compiler(language::c));
extend(c, get_flags(language::c));
return c;
});

tc.cxx_compile = read_opt(cxx_compile_file, [&] {
string_seq cxx;
if (compile_launcher) {
extend(cxx, *compile_launcher);
}
cxx.push_back(get_compiler(language::cxx));
extend(cxx, get_flags(language::cxx));
return cxx;
});

tc.include_template = read_opt(include_template, [&]() -> string_seq {
if (!compiler_id) {
fail(context, "Cannot deduce 'Include-Template' without 'Compiler-ID'");
}
if (is_gnu_like) {
return {"-I", "<PATH>"};
} else if (is_msvc) {
return {"/I", "<PATH>"};
}
assert(false && "Include-Template deduction failed");
std::terminate();
});

tc.external_include_template = read_opt(external_include_template, [&]() -> string_seq {
if (!compiler_id) {
// Just reuse the include template for regular files
return tc.include_template;
}
if (is_gnu_like) {
return {"-isystem", "<PATH>"};
} else if (is_msvc) {
// MSVC has external-header support inbound, but it is not fully ready yet
return {"/I", "<PATH>"};
}
assert(false && "External-Include-Template deduction failed");
std::terminate();
});

tc.define_template = read_opt(define_template, [&]() -> string_seq {
if (!compiler_id) {
fail(context, "Cannot deduce 'Define-Template' without 'Compiler-ID'");
}
if (is_gnu_like) {
return {"-D", "<DEF>"};
} else if (is_msvc) {
return {"/D", "<DEF>"};
}
assert(false && "Define-Template deduction failed");
std::terminate();
});

tc.archive_prefix = archive_prefix.value_or("lib");
tc.archive_suffix = read_opt(archive_suffix, [&] {
if (!compiler_id) {
fail(context, "Cannot deduce library file extension without Compiler-ID");
}
if (is_gnu_like) {
return ".a";
} else if (is_msvc) {
return ".lib";
}
assert(false && "No archive suffix");
std::terminate();
});

tc.object_prefix = obj_prefix.value_or("");
tc.object_suffix = read_opt(obj_suffix, [&] {
if (!compiler_id) {
fail(context, "Cannot deduce object file extension without Compiler-ID");
}
if (is_gnu_like) {
return ".o";
} else if (is_msvc) {
return ".obj";
}
assert(false && "No object file suffix");
std::terminate();
});

tc.exe_prefix = exe_prefix.value_or("");
tc.exe_suffix = read_opt(exe_suffix, [&] {
#ifdef _WIN32
return ".exe";
#else
return "";
#endif
});

tc.warning_flags = read_opt(warning_flags, [&]() -> string_seq {
if (!compiler_id) {
// No error. Just no warning flags
return {};
}
if (is_msvc) {
return {"/W4"};
} else if (is_gnu_like) {
return {"-Wall", "-Wextra", "-Wpedantic", "-Wconversion"};
}
assert(false && "No warning flags");
std::terminate();
});

tc.link_archive = read_opt(create_archive, [&]() -> string_seq {
if (!compiler_id) {
fail(context, "Unable to deduce archive creation rules without a Compiler-ID");
}
if (is_msvc) {
return {"lib", "/nologo", "/OUT:<OUT>", "<IN>"};
} else if (is_gnu_like) {
return {"ar", "rcs", "<OUT>", "<IN>"};
}
assert(false && "No archive command");
std::terminate();
});

tc.link_exe = read_opt(link_executable, [&]() -> string_seq {
if (!compiler_id) {
fail(context, "Unable to deduce how to link executables without a Compiler-ID");
}
string_seq ret;
if (is_msvc) {
ret = {get_compiler(language::cxx), "/nologo", "/EHsc", "<IN>", "/Fe<OUT>"};
} else if (is_gnu_like) {
ret = {get_compiler(language::cxx),
"-fPIC",
"-fdiagnostics-color",
"<IN>",
"-pthread",
"-o<OUT>"};
} else {
assert(false && "No link-exe command");
std::terminate();
}
extend(ret, get_link_flags());
return ret;
});

return tc.realize();
}

+ 0
- 18
src/dds/toolchain/from_dds.hpp Näytä tiedosto

@@ -1,18 +0,0 @@
#pragma once

#include <dds/toolchain/toolchain.hpp>

#include <libman/parse_fwd.hpp>

#include <string_view>

namespace dds {

class toolchain;

toolchain parse_toolchain_dds(std::string_view str,
std::string_view context = "Loading toolchain file");
toolchain parse_toolchain_dds(const lm::pair_list&,
std::string_view context = "Loading toolchain file");

} // namespace dds

+ 0
- 146
src/dds/toolchain/from_dds.test.cpp Näytä tiedosto

@@ -1,146 +0,0 @@
#include <dds/toolchain/from_dds.hpp>

#include <dds/proc.hpp>

// #include <dds/util.test.hpp>
#include <catch2/catch.hpp>

namespace {

void check_tc_compile(std::string_view tc_content,
std::string_view expected_compile,
std::string_view expected_compile_warnings,
std::string_view expected_ar,
std::string_view expected_exe) {
auto tc = dds::parse_toolchain_dds(tc_content);

dds::compile_file_spec cf;
cf.source_path = "foo.cpp";
cf.out_path = "foo.o";
auto cf_cmd = tc.create_compile_command(cf);
auto cf_cmd_str = dds::quote_command(cf_cmd.command);
CHECK(cf_cmd_str == expected_compile);

cf.enable_warnings = true;
cf_cmd = tc.create_compile_command(cf);
cf_cmd_str = dds::quote_command(cf_cmd.command);
CHECK(cf_cmd_str == expected_compile_warnings);

dds::archive_spec ar_spec;
ar_spec.input_files.push_back("foo.o");
ar_spec.input_files.push_back("bar.o");
ar_spec.out_path = "stuff.a";
auto ar_cmd = tc.create_archive_command(ar_spec);
auto ar_cmd_str = dds::quote_command(ar_cmd);
CHECK(ar_cmd_str == expected_ar);

dds::link_exe_spec exe_spec;
exe_spec.inputs.push_back("foo.o");
exe_spec.inputs.push_back("bar.a");
exe_spec.output = "meow.exe";
auto exe_cmd = tc.create_link_executable_command(exe_spec);
auto exe_cmd_str = dds::quote_command(exe_cmd);
CHECK(exe_cmd_str == expected_exe);
}

TEST_CASE("Generating toolchain commands") {
check_tc_compile(
"Compiler-ID: GNU",
"g++ -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"g++ -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion "
"-MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"ar rcs stuff.a foo.o bar.o",
"g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -omeow.exe");

check_tc_compile(
"Compiler-ID: GNU\nDebug: True",
"g++ -g -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"g++ -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion "
"-MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"ar rcs stuff.a foo.o bar.o",
"g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -omeow.exe -g");

check_tc_compile(
"Compiler-ID: GNU\nDebug: True\nOptimize: True",
"g++ -O2 -g -fPIC -fdiagnostics-color -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp "
"-ofoo.o",
"g++ -O2 -g -fPIC -fdiagnostics-color -pthread -Wall -Wextra -Wpedantic -Wconversion "
"-MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"ar rcs stuff.a foo.o bar.o",
"g++ -fPIC -fdiagnostics-color foo.o bar.a -pthread -omeow.exe -O2 -g");

check_tc_compile("Compiler-ID: MSVC",
"cl.exe /MT /EHsc /nologo /permissive- /showIncludes /c foo.cpp /Fofoo.o",
"cl.exe /MT /EHsc /nologo /permissive- /W4 /showIncludes /c foo.cpp /Fofoo.o",
"lib /nologo /OUT:stuff.a foo.o bar.o",
"cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /MT");

check_tc_compile(
"Compiler-ID: MSVC\nDebug: True",
"cl.exe /Z7 /DEBUG /MTd /EHsc /nologo /permissive- /showIncludes /c foo.cpp /Fofoo.o",
"cl.exe /Z7 /DEBUG /MTd /EHsc /nologo /permissive- /W4 /showIncludes /c foo.cpp /Fofoo.o",
"lib /nologo /OUT:stuff.a foo.o bar.o",
"cl.exe /nologo /EHsc foo.o bar.a /Femeow.exe /Z7 /DEBUG /MTd");

auto tc = dds::parse_toolchain_dds(R"(
Compiler-ID: GNU
)");

dds::compile_file_spec cfs;
cfs.source_path = "foo.cpp";
cfs.out_path = "foo.o";
auto cmd = tc.create_compile_command(cfs);
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-MD",
"-MF",
"foo.o.d",
"-MT",
"foo.o",
"-c",
"foo.cpp",
"-ofoo.o"});

cfs.definitions.push_back("FOO=BAR");
cmd = tc.create_compile_command(cfs);
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-D",
"FOO=BAR",
"-MD",
"-MF",
"foo.o.d",
"-MT",
"foo.o",
"-c",
"foo.cpp",
"-ofoo.o"});

cfs.include_dirs.push_back("fake-dir");
cmd = tc.create_compile_command(cfs);
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-I",
"fake-dir",
"-D",
"FOO=BAR",
"-MD",
"-MF",
"foo.o.d",
"-MT",
"foo.o",
"-c",
"foo.cpp",
"-ofoo.o"});
}

} // namespace

+ 30
- 23
src/dds/toolchain/toolchain.cpp Näytä tiedosto

@@ -1,6 +1,6 @@
#include "./toolchain.hpp"

#include <dds/toolchain/from_dds.hpp>
#include <dds/toolchain/from_json.hpp>
#include <dds/toolchain/prep.hpp>
#include <dds/util/algo.hpp>
#include <dds/util/paths.hpp>
@@ -148,31 +148,32 @@ vector<string> toolchain::create_link_executable_command(const link_exe_spec& sp
std::optional<toolchain> toolchain::get_builtin(std::string_view tc_id) noexcept {
using namespace std::literals;

std::string tc_content;
json5::data tc_data = json5::data::mapping_type();
auto& root_map = tc_data.as_object();

if (starts_with(tc_id, "debug:")) {
tc_id = tc_id.substr("debug:"sv.length());
tc_content += "Debug: True\n";
root_map.emplace("debug", true);
}

if (starts_with(tc_id, "ccache:")) {
tc_id = tc_id.substr("ccache:"sv.length());
tc_content += "Compiler-Launcher: ccache\n";
root_map.emplace("compiler_launcher", "ccache");
}

#define CXX_VER_TAG(str, version) \
if (starts_with(tc_id, str)) { \
tc_id = tc_id.substr(std::string_view(str).length()); \
tc_content += "C++-Version: "s + version + "\n"; \
root_map.emplace("cxx_version", version); \
} \
static_assert(true)

CXX_VER_TAG("c++98:", "C++98");
CXX_VER_TAG("c++03:", "C++03");
CXX_VER_TAG("c++11:", "C++11");
CXX_VER_TAG("c++14:", "C++14");
CXX_VER_TAG("c++17:", "C++17");
CXX_VER_TAG("c++20:", "C++20");
CXX_VER_TAG("c++98:", "c++98");
CXX_VER_TAG("c++03:", "c++03");
CXX_VER_TAG("c++11:", "c++11");
CXX_VER_TAG("c++14:", "c++14");
CXX_VER_TAG("c++17:", "c++17");
CXX_VER_TAG("c++20:", "c++20");

struct compiler_info {
string c;
@@ -187,9 +188,9 @@ std::optional<toolchain> toolchain::get_builtin(std::string_view tc_id) noexcept

const auto [c_compiler_base, cxx_compiler_base, compiler_id] = [&]() -> compiler_info {
if (is_gcc) {
return {"gcc", "g++", "GNU"};
return {"gcc", "g++", "gnu"};
} else if (is_clang) {
return {"clang", "clang++", "Clang"};
return {"clang", "clang++", "clang"};
}
assert(false && "Unreachable");
std::terminate();
@@ -221,7 +222,7 @@ std::optional<toolchain> toolchain::get_builtin(std::string_view tc_id) noexcept
auto cxx_compiler_name = cxx_compiler_base + compiler_suffix;
return compiler_info{c_compiler_name, cxx_compiler_name, compiler_id};
} else if (tc_id == "msvc") {
return compiler_info{"cl.exe", "cl.exe", "MSVC"};
return compiler_info{"cl.exe", "cl.exe", "msvc"};
} else {
return std::nullopt;
}
@@ -231,22 +232,28 @@ std::optional<toolchain> toolchain::get_builtin(std::string_view tc_id) noexcept
return std::nullopt;
}

tc_content += "C-Compiler: "s + opt_triple->c + "\n";
tc_content += "C++-Compiler: "s + opt_triple->cxx + "\n";
tc_content += "Compiler-ID: " + opt_triple->id + "\n";
return parse_toolchain_dds(tc_content);
root_map.emplace("c_compiler", opt_triple->c);
root_map.emplace("cxx_compiler", opt_triple->cxx);
root_map.emplace("compiler_id", opt_triple->id);
return parse_toolchain_json_data(tc_data);
}

std::optional<dds::toolchain> dds::toolchain::get_default() {
auto candidates = {
fs::current_path() / "toolchain.dds",
dds_config_dir() / "toolchain.dds",
user_home_dir() / "toolchain.dds",
fs::current_path() / "toolchain.json5",
fs::current_path() / "toolchain.jsonc",
fs::current_path() / "toolchain.json",
dds_config_dir() / "toolchain.json5",
dds_config_dir() / "toolchain.jsonc",
dds_config_dir() / "toolchain.json",
user_home_dir() / "toolchain.json5",
user_home_dir() / "toolchain.jsonc",
user_home_dir() / "toolchain.json",
};
for (auto&& cand : candidates) {
if (fs::exists(cand)) {
return parse_toolchain_dds(slurp_file(cand));
return parse_toolchain_json5(slurp_file(cand));
}
}
return std::nullopt;
}
}

Loading…
Peruuta
Tallenna