@@ -20,8 +20,14 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons | |||
// Build up the link command | |||
link_exe_spec spec; | |||
spec.output = calc_executable_path(env); | |||
spec.inputs = _input_libs; | |||
dds_log(debug, "Performing link for {}", spec.output.string()); | |||
// The main object should be a linker input, of course. | |||
auto main_obj = _main_compile.calc_object_file_path(env); | |||
dds_log(trace, "Add entry point object file: {}", main_obj.string()); | |||
spec.inputs.push_back(std::move(main_obj)); | |||
for (const lm::usage& links : _links) { | |||
dds_log(trace, " - Link with: {}/{}", links.name, links.namespace_); | |||
extend(spec.inputs, env.ureqs.link_paths(links)); | |||
@@ -36,17 +42,6 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons | |||
dds_log(trace, "Executable has no corresponding archive library input"); | |||
} | |||
// The main object should be a linker input, of course. | |||
auto main_obj = _main_compile.calc_object_file_path(env); | |||
dds_log(trace, "Add entry point object file: {}", main_obj.string()); | |||
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, dds::fs::current_path(), env.knobs); |
@@ -27,8 +27,6 @@ struct test_failure { | |||
* 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; | |||
/// Usage requirements for this executable | |||
std::vector<lm::usage> _links; | |||
/// The compilation plan for the entry-point source file | |||
@@ -41,19 +39,16 @@ class link_executable_plan { | |||
public: | |||
/** | |||
* Create a new instance | |||
* @param in_libs Linker inputs for the executable | |||
* @param links The library identifiers that the executable should link with | |||
* @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, | |||
std::vector<lm::usage> links, | |||
link_executable_plan(std::vector<lm::usage> links, | |||
compile_file_plan cfp, | |||
path_ref out_subdir, | |||
std::string name_) | |||
: _input_libs(std::move(in_libs)) | |||
, _links(std::move(links)) | |||
: _links(std::move(links)) | |||
, _main_compile(std::move(cfp)) | |||
, _out_subdir(out_subdir) | |||
, _name(std::move(name_)) {} |
@@ -100,10 +100,6 @@ library_plan library_plan::create(const library_root& lib, | |||
extend(links, lib.manifest().uses); | |||
extend(links, lib.manifest().links); | |||
// Linker inputs for tests may contain additional code for test execution | |||
std::vector<fs::path> link_libs; | |||
std::vector<fs::path> test_link_libs = params.test_link_files; | |||
// There may also be additional usage requirements for tests | |||
auto test_rules = compile_rules.clone(); | |||
auto test_links = links; | |||
@@ -114,6 +110,14 @@ library_plan library_plan::create(const library_root& lib, | |||
std::vector<link_executable_plan> link_executables; | |||
for (const source_file& source : ranges::views::concat(app_sources, test_sources)) { | |||
const bool is_test = source.kind == source_kind::test; | |||
if (is_test && !params.build_tests) { | |||
// This is a test, but we don't want to build tests | |||
continue; | |||
} | |||
if (!is_test && !params.build_apps) { | |||
// This is an app, but we don't want to build apps | |||
continue; | |||
} | |||
// Pick a subdir based on app/test | |||
const auto subdir_base = is_test ? params.out_subdir / "test" : params.out_subdir; | |||
// Put test/app executables in a further subdirectory based on the source file path | |||
@@ -121,11 +125,9 @@ library_plan library_plan::create(const library_root& lib, | |||
// Pick compile rules based on app/test | |||
auto rules = is_test ? test_rules : compile_rules; | |||
// Pick input libs based on app/test | |||
auto& exe_link_libs = is_test ? test_link_libs : link_libs; | |||
auto& exe_links = is_test ? test_links : links; | |||
auto& exe_links = is_test ? test_links : links; | |||
// TODO: Apps/tests should only see the _public_ include dir, not both | |||
auto exe = link_executable_plan{exe_link_libs, | |||
exe_links, | |||
auto exe = link_executable_plan{exe_links, | |||
compile_file_plan(rules, | |||
source, | |||
qual_name, |
@@ -30,8 +30,6 @@ struct library_build_params { | |||
/// Directories that should be on the #include search path when compiling tests | |||
std::vector<fs::path> test_include_dirs; | |||
/// Files that should be added as inputs when linking test executables | |||
std::vector<fs::path> test_link_files; | |||
/// Libraries that are used by tests | |||
std::vector<lm::usage> test_uses; |