Browse Source

Cleanup link_executable_plan

default_compile_flags
vector-of-bool 5 years ago
parent
commit
9d6e12596e
2 changed files with 52 additions and 8 deletions
  1. +14
    -4
      src/dds/build/plan/exe.cpp
  2. +38
    -4
      src/dds/build/plan/exe.hpp

+ 14
- 4
src/dds/build/plan/exe.cpp View File

@@ -16,21 +16,29 @@ fs::path link_executable_plan::calc_executable_path(build_env_ref env) const noe
}

void link_executable_plan::link(build_env_ref env, const library_plan& lib) const {
const auto out_path = calc_executable_path(env);

// Build up the link command
link_exe_spec spec;
spec.output = out_path;
spec.output = calc_executable_path(env);
spec.inputs = _input_libs;
if (lib.create_archive()) {
// The associated library has compiled components. Add the static library a as a linker
// input
spec.inputs.push_back(lib.create_archive()->calc_archive_file_path(env));
}

// The main object should be a linker input, of course.
auto main_obj = _main_compile.calc_object_file_path(env);
spec.inputs.push_back(std::move(main_obj));

// Linker inputs are order-dependent in some cases. The top-most input should appear first, and
// its dependencies should appear later. Because of the way inputs were generated, they appear
// sorted with the dependencies coming earlier than the dependees. We can simply reverse the
// order and linking will work.
std::reverse(spec.inputs.begin(), spec.inputs.end());

// Do it!
const auto link_command = env.toolchain.create_link_executable_command(spec);
fs::create_directories(out_path.parent_path());
fs::create_directories(spec.output.parent_path());
auto msg = fmt::format("[{}] Link: {:30}",
lib.name(),
fs::relative(spec.output, env.output_root).string());
@@ -38,6 +46,8 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons
auto [dur_ms, proc_res]
= timed<std::chrono::milliseconds>([&] { return run_proc(link_command); });
spdlog::info("{} - {:>6n}ms", msg, dur_ms.count());

// Check and throw if errant
if (!proc_res.okay()) {
throw compile_failure(
fmt::format("Failed to link test executable '{}'. Link command [{}] returned {}:\n{}",

+ 38
- 4
src/dds/build/plan/exe.hpp View File

@@ -10,19 +10,37 @@ namespace dds {

class library_plan;

/**
* Represents information about a test failure.
*/
struct test_failure {
fs::path executable_path;
std::string output;
int retc;
};

/**
* Stores information about an executable that should be linked. An executable in DDS consists of a
* single source file defines the entry point and some set of linker inputs.
*/
class link_executable_plan {
/// The linker inputs that should be linked into the executable
std::vector<fs::path> _input_libs;
compile_file_plan _main_compile;
fs::path _out_subdir;
std::string _name;
/// The compilation plan for the entry-point source file
compile_file_plan _main_compile;
/// The subdirectory in which the executable should be generated
fs::path _out_subdir;
/// The name of the executable
std::string _name;

public:
/**
* Create a new instance
* @param in_libs Linker inputs for the executable
* @param cfp The file compilation that defines the entrypoint of the application
* @param out_subdir The subdirectory of the build root in which the executable should be placed
* @param name_ The name of the executable
*/
link_executable_plan(std::vector<fs::path> in_libs,
compile_file_plan cfp,
path_ref out_subdir,
@@ -32,11 +50,27 @@ public:
, _out_subdir(out_subdir)
, _name(std::move(name_)) {}

/**
* Get the compilation of the main source file
*/
auto& main_compile_file() const noexcept { return _main_compile; }

/**
* Calculate the output path of the executable for the given build environment
*/
fs::path calc_executable_path(const build_env& env) const noexcept;

void link(const build_env&, const library_plan&) const;
/**
* Perform the link of the executable
* @param env The build environment to use.
* @param lib The library that owns this executable. If it defines an archive library, it will
* be added as a linker input.
*/
void link(const build_env& env, const library_plan& lib) const;
/**
* Run the executable as a test. If the test fails, then that failure information will be
* returned.
*/
std::optional<test_failure> run_test(build_env_ref) const;

bool is_test() const noexcept;

Loading…
Cancel
Save