Procházet zdrojové kódy

Add `tty_flags`, and only pass -fdiagnostics-color when output is a TTY

default_compile_flags
vector-of-bool před 4 roky
rodič
revize
64706f6da9
17 změnil soubory, kde provedl 136 přidání a 65 odebrání
  1. +8
    -0
      docs/guide/toolchains.rst
  2. +4
    -0
      res/toolchain-schema.json
  3. +10
    -1
      src/dds/build/builder.cpp
  4. +1
    -1
      src/dds/build/plan/archive.cpp
  5. +2
    -0
      src/dds/build/plan/base.hpp
  6. +1
    -1
      src/dds/build/plan/compile_file.cpp
  7. +1
    -1
      src/dds/build/plan/exe.cpp
  8. +21
    -9
      src/dds/toolchain/from_json.cpp
  9. +30
    -36
      src/dds/toolchain/from_json.test.cpp
  10. +1
    -0
      src/dds/toolchain/prep.hpp
  11. +12
    -7
      src/dds/toolchain/toolchain.cpp
  12. +11
    -3
      src/dds/toolchain/toolchain.hpp
  13. +7
    -0
      src/dds/util/output.hpp
  14. +11
    -0
      src/dds/util/output.nix.cpp
  15. +10
    -0
      src/dds/util/output.win.cpp
  16. +2
    -3
      tools/gcc-9.dds
  17. +4
    -3
      tools/gcc-9.jsonc

+ 8
- 0
docs/guide/toolchains.rst Zobrazit soubor

@@ -353,6 +353,14 @@ of an external library.
Override the *command template* for the flags to set a preprocessor definition.


``tty_flags``
-------------

Supply additional flags when compiling/linking that will only be applied if
standard output is an ANSI-capable terminal. (e.g. On GNU and Clang this will
be ``-fdiagnostics-color`` by default.)


``obj_prefix``, ``obj_suffix``, ``archive_prefix``, ``archive_suffix``,
``exe_prefix``, and ``exe_suffix``
----------------------------------

+ 4
- 0
res/toolchain-schema.json Zobrazit soubor

@@ -153,6 +153,10 @@
"description": "Set the command template for linking executable binaries",
"$ref": "#/definitions/command_line_flags"
},
"tty_flags": {
"description": "Set command line flags that will be applied only if stdout is an ANSI-capable terminal",
"$ref": "#/definitions/command_line_flags"
},
"obj_prefix": {
"description": "Set the filename prefix for object files",
"type": "string"

+ 10
- 1
src/dds/build/builder.cpp Zobrazit soubor

@@ -6,6 +6,7 @@
#include <dds/compdb.hpp>
#include <dds/error/errors.hpp>
#include <dds/usage_reqs.hpp>
#include <dds/util/output.hpp>
#include <dds/util/time.hpp>

#include <spdlog/spdlog.h>
@@ -214,7 +215,15 @@ void builder::build(const build_params& params) const {
state st;
auto plan = prepare_build_plan(st, _sdists);
auto ureqs = prepare_ureqs(plan, params.toolchain, params.out_root);
build_env env{params.toolchain, params.out_root, db, ureqs};
build_env env{
params.toolchain,
params.out_root,
db,
toolchain_knobs{
.is_tty = stdout_is_a_tty(),
},
ureqs,
};

if (st.generate_catch2_main) {
auto catch_lib = prepare_test_driver(params, test_lib::catch_main, env);

+ 1
- 1
src/dds/build/plan/archive.cpp Zobrazit soubor

@@ -24,7 +24,7 @@ void create_archive_plan::archive(const build_env& env) const {
archive_spec ar;
ar.input_files = std::move(objects);
ar.out_path = env.output_root / calc_archive_file_path(env.toolchain);
auto ar_cmd = env.toolchain.create_archive_command(ar);
auto ar_cmd = env.toolchain.create_archive_command(ar, env.knobs);

// `out_relpath` is purely for the benefit of the user to have a short name
// in the logs

+ 2
- 0
src/dds/build/plan/base.hpp Zobrazit soubor

@@ -12,6 +12,8 @@ struct build_env {
fs::path output_root;
database& db;

toolchain_knobs knobs;

const usage_requirement_map& ureqs;
};


+ 1
- 1
src/dds/build/plan/compile_file.cpp Zobrazit soubor

@@ -26,7 +26,7 @@ compile_command_info compile_file_plan::generate_compile_command(build_env_ref e
extend(spec.external_include_dirs, env.ureqs.include_paths(use));
}
extend(spec.definitions, _rules.defs());
return env.toolchain.create_compile_command(spec);
return env.toolchain.create_compile_command(spec, env.knobs);
}

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

+ 1
- 1
src/dds/build/plan/exe.cpp Zobrazit soubor

@@ -43,7 +43,7 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons
std::reverse(spec.inputs.begin(), spec.inputs.end());

// Do it!
const auto link_command = env.toolchain.create_link_executable_command(spec);
const auto link_command = env.toolchain.create_link_executable_command(spec, env.knobs);
fs::create_directories(spec.output.parent_path());
auto msg = fmt::format("[{}] Link: {:30}",
lib.qualified_name(),

+ 21
- 9
src/dds/toolchain/from_json.cpp Zobrazit soubor

@@ -80,6 +80,7 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
opt_string_seq cxx_compile_file;
opt_string_seq create_archive;
opt_string_seq link_executable;
opt_string_seq tty_flags;

// For copy-pasting convenience: ‘{}’

@@ -150,6 +151,7 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
KEY_EXTEND_FLAGS(cxx_compile_file),
KEY_EXTEND_FLAGS(create_archive),
KEY_EXTEND_FLAGS(link_executable),
KEY_EXTEND_FLAGS(tty_flags),
KEY_STRING(obj_prefix),
KEY_STRING(obj_suffix),
KEY_STRING(archive_prefix),
@@ -174,6 +176,7 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
"archive_suffix",
"exe_prefix",
"exe_suffix",
"tty_flags",
});
fail(context,
"Unknown toolchain advanced-config key ‘{}’ (Did you mean ‘{}’?)",
@@ -450,14 +453,7 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
if (do_debug.has_value() && *do_debug) {
extend(ret, {"-g"});
}
extend(ret,
{"-fPIC",
"-fdiagnostics-color",
"-pthread",
"<FLAGS>",
"-c",
"<IN>",
"-o<OUT>"});
extend(ret, {"-fPIC", "-pthread", "<FLAGS>", "-c", "<IN>", "-o<OUT>"});
}
if (common_flags) {
extend(ret, *common_flags);
@@ -619,7 +615,6 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
} else if (is_gnu_like) {
ret = {get_compiler_executable_path(language::cxx),
"-fPIC",
"-fdiagnostics-color",
"<IN>",
"-pthread",
"-o<OUT>"};
@@ -631,5 +626,22 @@ toolchain dds::parse_toolchain_json_data(const json5::data& dat, std::string_vie
return ret;
});

tc.tty_flags = read_opt(tty_flags, [&]() -> string_seq {
if (!compiler_id) {
// Don't deduce any flags. This is a non-error, as these flags should be purely
// aesthetic
return {};
}
if (is_msvc) {
// MSVC doesn't have any special TTY flags (yet...)
return {};
} else if (is_gnu_like) {
return {"-fdiagnostics-color"};
} else {
assert(false && "Impossible compiler_id while deducing `tty_flags`");
std::terminate();
}
});

return tc.realize();
}

+ 30
- 36
src/dds/toolchain/from_json.test.cpp Zobrazit soubor

@@ -15,12 +15,12 @@ void check_tc_compile(std::string_view 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 = tc.create_compile_command(cf, dds::toolchain_knobs{});
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 = tc.create_compile_command(cf, dds::toolchain_knobs{});
cf_cmd_str = dds::quote_command(cf_cmd.command);
CHECK(cf_cmd_str == expected_compile_warnings);

@@ -28,7 +28,7 @@ void check_tc_compile(std::string_view tc_content,
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 = tc.create_archive_command(ar_spec, dds::toolchain_knobs{});
auto ar_cmd_str = dds::quote_command(ar_cmd);
CHECK(ar_cmd_str == expected_ar);

@@ -36,7 +36,7 @@ void check_tc_compile(std::string_view tc_content,
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 = tc.create_link_executable_command(exe_spec, dds::toolchain_knobs{});
auto exe_cmd_str = dds::quote_command(exe_cmd);
CHECK(exe_cmd_str == expected_exe);
}
@@ -44,30 +44,27 @@ void check_tc_compile(std::string_view tc_content,
} // namespace

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', debug: 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', debug: true, optimize: 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: 'gnu'}",
"g++ -fPIC -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"g++ -fPIC -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 foo.o bar.a -pthread -omeow.exe");

check_tc_compile("{compiler_id: 'gnu', debug: true}",
"g++ -g -fPIC -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp -ofoo.o",
"g++ -g -fPIC -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 foo.o bar.a -pthread -omeow.exe -g");

check_tc_compile("{compiler_id: 'gnu', debug: true, optimize: true}",
"g++ -O2 -g -fPIC -pthread -MD -MF foo.o.d -MT foo.o -c foo.cpp "
"-ofoo.o",
"g++ -O2 -g -fPIC -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 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",
@@ -91,17 +88,15 @@ TEST_CASE("Generating toolchain commands") {
}

TEST_CASE("Manipulate a toolchain and file compilation") {

auto tc = dds::parse_toolchain_json5("{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);
auto cmd = tc.create_compile_command(cfs, dds::toolchain_knobs{});
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-MD",
"-MF",
@@ -113,12 +108,12 @@ TEST_CASE("Manipulate a toolchain and file compilation") {
"-ofoo.o"});

cfs.definitions.push_back("FOO=BAR");
cmd = tc.create_compile_command(cfs);
cmd = tc.create_compile_command(cfs, dds::toolchain_knobs{.is_tty = true});
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-fdiagnostics-color",
"-D",
"FOO=BAR",
"-MD",
@@ -131,11 +126,10 @@ TEST_CASE("Manipulate a toolchain and file compilation") {
"-ofoo.o"});

cfs.include_dirs.push_back("fake-dir");
cmd = tc.create_compile_command(cfs);
cmd = tc.create_compile_command(cfs, dds::toolchain_knobs{});
CHECK(cmd.command
== std::vector<std::string>{"g++",
"-fPIC",
"-fdiagnostics-color",
"-pthread",
"-I",
"fake-dir",
@@ -149,4 +143,4 @@ TEST_CASE("Manipulate a toolchain and file compilation") {
"-c",
"foo.cpp",
"-ofoo.o"});
}
}

+ 1
- 0
src/dds/toolchain/prep.hpp Zobrazit soubor

@@ -19,6 +19,7 @@ struct toolchain_prep {
string_seq link_archive;
string_seq link_exe;
string_seq warning_flags;
string_seq tty_flags;

std::string archive_prefix;
std::string archive_suffix;

+ 12
- 7
src/dds/toolchain/toolchain.cpp Zobrazit soubor

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

@@ -51,10 +52,8 @@ vector<string> toolchain::definition_args(std::string_view s) const noexcept {
return replace(_def_template, "<DEF>", s);
}

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

compile_command_info toolchain::create_compile_command(const compile_file_spec& spec,
toolchain_knobs knobs) const noexcept {
using namespace std::literals;

language lang = spec.lang;
@@ -66,7 +65,10 @@ toolchain::create_compile_command(const compile_file_spec& spec) const noexcept
}
}

auto& cmd_template = lang == language::c ? _c_compile : _cxx_compile;
vector<string> flags;
if (knobs.is_tty) {
extend(flags, _tty_flags);
}

for (auto&& inc_dir : spec.include_dirs) {
auto inc_args = include_args(inc_dir);
@@ -103,6 +105,7 @@ toolchain::create_compile_command(const compile_file_spec& spec) const noexcept
}

vector<string> command;
auto& cmd_template = lang == language::c ? _c_compile : _cxx_compile;
for (auto arg : cmd_template) {
if (arg == "<FLAGS>") {
extend(command, flags);
@@ -115,7 +118,8 @@ toolchain::create_compile_command(const compile_file_spec& spec) const noexcept
return {command, gnu_depfile_path};
}

vector<string> toolchain::create_archive_command(const archive_spec& spec) const noexcept {
vector<string> toolchain::create_archive_command(const archive_spec& spec,
toolchain_knobs) const noexcept {
vector<string> cmd;
for (auto& arg : _link_archive) {
if (arg == "<IN>") {
@@ -130,7 +134,8 @@ vector<string> toolchain::create_archive_command(const archive_spec& spec) const
return cmd;
}

vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec) const noexcept {
vector<string> toolchain::create_link_executable_command(const link_exe_spec& spec,
toolchain_knobs) const noexcept {
vector<string> cmd;
for (auto& arg : _link_exe) {
if (arg == "<IN>") {

+ 11
- 3
src/dds/toolchain/toolchain.hpp Zobrazit soubor

@@ -16,6 +16,10 @@ enum class language {
cxx,
};

struct toolchain_knobs {
bool is_tty = false;
};

struct compile_file_spec {
fs::path source_path;
fs::path out_path;
@@ -54,6 +58,7 @@ class toolchain {
string_seq _link_archive;
string_seq _link_exe;
string_seq _warning_flags;
string_seq _tty_flags;

std::string _archive_prefix;
std::string _archive_suffix;
@@ -77,9 +82,12 @@ public:
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> external_include_args(const fs::path& p) 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;
compile_command_info create_compile_command(const compile_file_spec&,
toolchain_knobs) const noexcept;
std::vector<std::string> create_archive_command(const archive_spec&,
toolchain_knobs) const noexcept;
std::vector<std::string> create_link_executable_command(const link_exe_spec&,
toolchain_knobs) const noexcept;

static std::optional<toolchain> get_builtin(std::string_view key) noexcept;
static std::optional<toolchain> get_default();

+ 7
- 0
src/dds/util/output.hpp Zobrazit soubor

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

namespace dds {

bool stdout_is_a_tty() noexcept;

} // namespace dds

+ 11
- 0
src/dds/util/output.nix.cpp Zobrazit soubor

@@ -0,0 +1,11 @@
#if !_WIN32

#include <dds/util/output.hpp>

#include <unistd.h>

using namespace dds;

bool dds::stdout_is_a_tty() noexcept { return ::isatty(STDOUT_FILENO) != 0; }

#endif

+ 10
- 0
src/dds/util/output.win.cpp Zobrazit soubor

@@ -0,0 +1,10 @@
#if _WIN32

#include <dds/util/output.hpp>

bool dds::stdout_is_a_tty() noexcept {
// XXX: Newer Windows consoles support ANSI color, so this should be made smarter
return false;
}

#endif

+ 2
- 3
tools/gcc-9.dds Zobrazit soubor

@@ -1,10 +1,9 @@
Compiler-ID: GNU
C++-Version: C++17
C-Compiler: gcc-9
C++-Compiler: g++-9
# Range-v3 0.10.0 contains an accidental conversion warning
Flags: -D SPDLOG_COMPILED_LIB -Werror=return-type -Wno-conversion
C++-Flags: -fconcepts
Flags: -D SPDLOG_COMPILED_LIB -Werror=return-type -Wno-sign-compare -Wno-conversion
C++-Flags: -fconcepts -std=c++2a
# Link-Flags: -static-libgcc -static-libstdc++
Debug: True
#Optimize: True

+ 4
- 3
tools/gcc-9.jsonc Zobrazit soubor

@@ -3,13 +3,14 @@
"compiler_id": "gnu",
"c_compiler": "gcc-9",
"cxx_compiler": "g++-9",
"cxx_version": "c++17",
// "cxx_version": "c++17",
"flags": [
"-DSPDLOG_COMPILED_LIB", // Required to use a compiled spdlog
"-Werror=return-type"
"-Werror=return-type",
],
"cxx_flags": [
"-fconcepts"
"-fconcepts",
"-std=c++2a",
],
// "debug": true,
"optimize": true,

Načítá se…
Zrušit
Uložit