Kaynağa Gözat

Add arguments that handle the generation of compile dependency information.

default_compile_flags
vector-of-bool 5 yıl önce
ebeveyn
işleme
1fca2fd03f
9 değiştirilmiş dosya ile 117 ekleme ve 33 silme
  1. +9
    -7
      src/dds/build/plan/compile_file.cpp
  2. +4
    -3
      src/dds/build/plan/compile_file.hpp
  3. +2
    -2
      src/dds/compdb.cpp
  4. +21
    -0
      src/dds/toolchain/deps.hpp
  5. +27
    -3
      src/dds/toolchain/from_dds.cpp
  6. +24
    -15
      src/dds/toolchain/from_dds.test.cpp
  7. +4
    -0
      src/dds/toolchain/prep.hpp
  8. +16
    -2
      src/dds/toolchain/toolchain.cpp
  9. +10
    -1
      src/dds/toolchain/toolchain.hpp

+ 9
- 7
src/dds/build/plan/compile_file.cpp Dosyayı Görüntüle

@@ -12,8 +12,7 @@

using namespace dds;

std::vector<std::string> compile_file_plan::generate_compile_command(build_env_ref env) const
noexcept {
compile_command_info compile_file_plan::generate_compile_command(build_env_ref env) const noexcept {
compile_file_spec spec{_source.path, calc_object_file_path(env)};
spec.enable_warnings = _rules.enable_warnings();
extend(spec.include_dirs, _rules.include_dirs());
@@ -21,7 +20,7 @@ std::vector<std::string> compile_file_plan::generate_compile_command(build_env_r
return env.toolchain.create_compile_command(spec);
}

void compile_file_plan::compile(const build_env& env) const {
std::optional<deps_info> compile_file_plan::compile(const build_env& env) const {
const auto obj_path = calc_object_file_path(env);
fs::create_directories(obj_path.parent_path());

@@ -30,13 +29,14 @@ void compile_file_plan::compile(const build_env& env) const {
fs::relative(_source.path, _source.basis_path).string());

spdlog::info(msg);
auto cmd = generate_compile_command(env);
auto&& [dur_ms, compile_res] = timed<std::chrono::milliseconds>([&] { return run_proc(cmd); });
auto cmd = generate_compile_command(env);
auto&& [dur_ms, compile_res]
= timed<std::chrono::milliseconds>([&] { return run_proc(cmd.command); });
spdlog::info("{} - {:>7n}ms", msg, dur_ms.count());

if (!compile_res.okay()) {
spdlog::error("Compilation failed: {}", _source.path.string());
spdlog::error("Subcommand FAILED: {}\n{}", quote_command(cmd), compile_res.output);
spdlog::error("Subcommand FAILED: {}\n{}", quote_command(cmd.command), compile_res.output);
throw compile_failure(fmt::format("Compilation failed for {}", _source.path.string()));
}

@@ -48,9 +48,11 @@ void compile_file_plan::compile(const build_env& env) const {
if (!compile_res.output.empty()) {
spdlog::warn("While compiling file {} [{}]:\n{}",
_source.path.string(),
quote_command(cmd),
quote_command(cmd.command),
compile_res.output);
}

return std::nullopt;
}

fs::path compile_file_plan::calc_object_file_path(const build_env& env) const noexcept {

+ 4
- 3
src/dds/build/plan/compile_file.hpp Dosyayı Görüntüle

@@ -2,6 +2,7 @@

#include <dds/build/plan/base.hpp>
#include <dds/source.hpp>
#include <dds/toolchain/deps.hpp>

#include <memory>

@@ -55,13 +56,13 @@ public:
, _qualifier(qual)
, _subdir(subdir) {}

std::vector<std::string> generate_compile_command(build_env_ref) const noexcept;
compile_command_info generate_compile_command(build_env_ref) const noexcept;

const source_file& source() const noexcept { return _source; }
path_ref source_path() const noexcept { return _source.path; }

fs::path calc_object_file_path(build_env_ref env) const noexcept;
void compile(build_env_ref) const;
fs::path calc_object_file_path(build_env_ref env) const noexcept;
std::optional<deps_info> compile(build_env_ref) const;
};

} // namespace dds

+ 2
- 2
src/dds/compdb.cpp Dosyayı Görüntüle

@@ -12,10 +12,10 @@ void dds::generate_compdb(const build_plan& plan, build_env_ref env) {
auto compdb = nlohmann::json::array();

for (const compile_file_plan& cf : iter_compilations(plan)) {
auto command = cf.generate_compile_command(env);
auto cmd_info = cf.generate_compile_command(env);
auto entry = nlohmann::json::object({
{"directory", env.output_root.string()},
{"arguments", command},
{"arguments", cmd_info.command},
{"file", cf.source_path().string()},
});
compdb.push_back(std::move(entry));

+ 21
- 0
src/dds/toolchain/deps.hpp Dosyayı Görüntüle

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

#include <dds/util/fs.hpp>

#include <vector>

namespace dds {

enum class deps_mode {
none,
msvc,
gnu,
};

struct deps_info {
fs::path output;
std::vector<fs::path> inputs;
std::vector<std::string> command;
};

} // namespace dds

+ 27
- 3
src/dds/toolchain/from_dds.cpp Dosyayı Görüntüle

@@ -90,6 +90,7 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
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;
@@ -128,6 +129,7 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
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},
@@ -170,6 +172,26 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
bool is_msvc = compiler_id_e == msvc;
bool is_gnu_like = is_gnu || is_clang;

const enum deps_mode deps_mode = [&] {
if (!deps_mode_str.has_value()) {
if (is_gnu_like) {
return deps_mode::gnu;
} else if (is_msvc) {
return deps_mode::msvc;
} else {
return deps_mode::none;
}
} else if (deps_mode_str == "GNU") {
return deps_mode::gnu;
} else if (deps_mode_str == "MSVC") {
return deps_mode::msvc;
} else if (deps_mode_str == "None") {
return 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) {
@@ -356,10 +378,10 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
rt_lib = "/MTd";
}
ret.emplace_back(rt_lib);
extend(ret, {"/nologo", "<FLAGS>", "/permissive-", "/c", "<IN>", "/Fo<OUT>"});
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"});
@@ -382,6 +404,8 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
return ret;
};

tc.deps_mode = deps_mode;

tc.c_compile = read_opt(c_compile_file, [&] {
string_seq c;
if (compile_launcher) {
@@ -408,7 +432,7 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
}
if (is_gnu_like) {
return {"-I", "<PATH>"};
} else if (compiler_id == "MSVC") {
} else if (is_msvc) {
return {"/I", "<PATH>"};
}
assert(false && "Include-Template deduction failed");
@@ -421,7 +445,7 @@ toolchain dds::parse_toolchain_dds(const lm::pair_list& pairs, strv context) {
}
if (is_gnu_like) {
return {"-D", "<DEF>"};
} else if (compiler_id == "MSVC") {
} else if (is_msvc) {
return {"/D", "<DEF>"};
}
assert(false && "Define-Template deduction failed");

+ 24
- 15
src/dds/toolchain/from_dds.test.cpp Dosyayı Görüntüle

@@ -18,12 +18,12 @@ void check_tc_compile(std::string_view tc_content,
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);
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);
cf_cmd_str = dds::quote_command(cf_cmd.command);
CHECK(cf_cmd_str == expected_compile_warnings);

dds::archive_spec ar_spec;
@@ -45,37 +45,37 @@ void check_tc_compile(std::string_view tc_content,

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

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

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

check_tc_compile("Compiler-ID: MSVC",
"cl.exe /MT /nologo /permissive- /c foo.cpp /Fofoo.o /EHsc",
"cl.exe /MT /nologo /W4 /permissive- /c foo.cpp /Fofoo.o /EHsc",
"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 /nologo /permissive- /c foo.cpp /Fofoo.o /EHsc",
"cl.exe /Z7 /DEBUG /MTd /nologo /W4 /permissive- /c foo.cpp /Fofoo.o /EHsc",
"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");

@@ -87,31 +87,37 @@ TEST_CASE("Generating toolchain commands") {
cfs.source_path = "foo.cpp";
cfs.out_path = "foo.o";
auto cmd = tc.create_compile_command(cfs);
CHECK(cmd
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-MD",
"-MF",
"foo.o.d",
"-c",
"foo.cpp",
"-ofoo.o"});

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

cfs.include_dirs.push_back("fake-dir");
cmd = tc.create_compile_command(cfs);
CHECK(cmd
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
@@ -120,6 +126,9 @@ TEST_CASE("Generating toolchain commands") {
"fake-dir",
"-D",
"FOO=BAR",
"-MD",
"-MF",
"foo.o.d",
"-c",
"foo.cpp",
"-ofoo.o"});

+ 4
- 0
src/dds/toolchain/prep.hpp Dosyayı Görüntüle

@@ -1,5 +1,7 @@
#pragma once

#include <dds/toolchain/deps.hpp>

#include <string>
#include <vector>

@@ -24,6 +26,8 @@ struct toolchain_prep {
std::string exe_prefix;
std::string exe_suffix;

enum deps_mode deps_mode;

toolchain realize() const;
};


+ 16
- 2
src/dds/toolchain/toolchain.cpp Dosyayı Görüntüle

@@ -32,6 +32,7 @@ toolchain toolchain::realize(const toolchain_prep& prep) {
ret._object_suffix = prep.object_suffix;
ret._exe_prefix = prep.exe_prefix;
ret._exe_suffix = prep.exe_suffix;
ret._deps_mode = prep.deps_mode;
return ret;
}

@@ -99,9 +100,12 @@ vector<string> toolchain::definition_args(std::string_view s) const noexcept {
return replace(_def_template, "<DEF>", s);
}

vector<string> toolchain::create_compile_command(const compile_file_spec& spec) const noexcept {
compile_command_info toolchain::create_compile_command(const compile_file_spec& spec) const
noexcept {
vector<string> flags;

using namespace std::literals;

language lang = spec.lang;
if (lang == language::automatic) {
if (spec.source_path.extension() == ".c" || spec.source_path.extension() == ".C") {
@@ -127,6 +131,16 @@ vector<string> toolchain::create_compile_command(const compile_file_spec& spec)
extend(flags, _warning_flags);
}

std::optional<fs::path> gnu_depfile_path;

if (_deps_mode == deps_mode::gnu) {
gnu_depfile_path = spec.out_path;
gnu_depfile_path->replace_extension(gnu_depfile_path->extension().string() + ".d");
extend(flags, {"-MD"sv, "-MF"sv, std::string_view(gnu_depfile_path->string())});
} else if (_deps_mode == deps_mode::msvc) {
flags.push_back("/showIncludes");
}

vector<string> command;
for (auto arg : cmd_template) {
if (arg == "<FLAGS>") {
@@ -137,7 +151,7 @@ vector<string> toolchain::create_compile_command(const compile_file_spec& spec)
command.push_back(arg);
}
}
return command;
return {command, gnu_depfile_path};
}

vector<string> toolchain::create_archive_command(const archive_spec& spec) const noexcept {

+ 10
- 1
src/dds/toolchain/toolchain.hpp Dosyayı Görüntüle

@@ -1,5 +1,6 @@
#pragma once

#include <dds/toolchain/deps.hpp>
#include <dds/util/fs.hpp>

#include <optional>
@@ -26,6 +27,11 @@ struct compile_file_spec {
bool enable_warnings = false;
};

struct compile_command_info {
std::vector<std::string> command;
std::optional<fs::path> gnu_depfile_path;
};

struct archive_spec {
std::vector<fs::path> input_files;
fs::path out_path;
@@ -56,6 +62,8 @@ class toolchain {
std::string _exe_prefix;
std::string _exe_suffix;

enum deps_mode _deps_mode;

public:
toolchain() = default;

@@ -64,10 +72,11 @@ public:
auto& archive_suffix() const noexcept { return _archive_suffix; }
auto& object_suffix() const noexcept { return _object_suffix; }
auto& executable_suffix() const noexcept { return _exe_suffix; }
auto deps_mode() const noexcept { return _deps_mode; }

std::vector<std::string> definition_args(std::string_view s) const noexcept;
std::vector<std::string> include_args(const fs::path& p) const noexcept;
std::vector<std::string> create_compile_command(const compile_file_spec&) const noexcept;
compile_command_info create_compile_command(const compile_file_spec&) const noexcept;
std::vector<std::string> create_archive_command(const archive_spec&) const noexcept;
std::vector<std::string> create_link_executable_command(const link_exe_spec&) const noexcept;


Yükleniyor…
İptal
Kaydet