소스 검색

Support for using an embedded version of Catch2

default_compile_flags
vector-of-bool 5 년 전
부모
커밋
8f5e74ba0e
8개의 변경된 파일17611개의 추가작업 그리고 6개의 파일을 삭제
  1. +76
    -0
      src/dds/build.cpp
  2. +6
    -0
      src/dds/build/plan/compile_file.hpp
  3. +13
    -2
      src/dds/build/plan/library.cpp
  4. +17478
    -0
      src/dds/catch2_embedded.cpp
  5. +7
    -0
      src/dds/catch2_embedded.hpp
  6. +4
    -0
      src/dds/library.hpp
  7. +20
    -4
      src/dds/package_manifest.cpp
  8. +7
    -0
      src/dds/package_manifest.hpp

+ 76
- 0
src/dds/build.cpp 파일 보기

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

#include <dds/catch2_embedded.hpp>
#include <dds/compdb.hpp>
#include <dds/logging.hpp>
#include <dds/usage_reqs.hpp>
@@ -111,6 +112,76 @@ load_usage_requirements(path_ref project_root, path_ref build_root, path_ref use
return usage_requirement_map::from_lm_index(idx);
}

void prepare_catch2_driver(library_build_params& lib_params,
test_lib test_driver,
const build_params& params,
const package_manifest& man) {
fs::path test_include_root = params.out_root / "_test_inc";
lib_params.test_include_dirs.emplace_back(test_include_root);

auto catch_hpp = test_include_root / "catch2/catch.hpp";
fs::create_directories(catch_hpp.parent_path());
auto hpp_strm = open(catch_hpp, std::ios::out | std::ios::binary);
hpp_strm.write(detail::catch2_embedded_single_header_str,
std::strlen(detail::catch2_embedded_single_header_str));
hpp_strm.close();

if (test_driver == test_lib::catch_) {
// Don't generate a test library helper
}

std::string fname;
std::string definition;

if (test_driver == test_lib::catch_main) {
fname = "catch-main.cpp";
definition = "CATCH_CONFIG_MAIN";
} else if (test_driver == test_lib::catch_runner) {
fname = "catch-runner.cpp";
definition = "CATCH_CONFIG_RUNNER";
} else {
assert(false && "Impossible: Invalid `test_driver` for catch library");
std::terminate();
}

shared_compile_file_rules comp_rules;
comp_rules.defs().push_back(definition);

auto catch_cpp = test_include_root / "catch2" / fname;
auto cpp_strm = open(catch_cpp, std::ios::out | std::ios::binary);
cpp_strm << R"(#include "./catch.hpp"\n)";
cpp_strm.close();

auto sf = source_file::from_path(catch_cpp, test_include_root);
assert(sf.has_value());

compile_file_plan plan{comp_rules, std::move(*sf), "Catch2", "v1"};
build_env env;
env.output_root = params.out_root / "_test-driver";
env.toolchain = params.toolchain;
auto obj_file = plan.calc_object_file_path(env);

if (!fs::exists(obj_file)) {
spdlog::info("Compiling Catch2 test driver (This will only happen once)...");
plan.compile(env);
}

lib_params.test_link_files.push_back(obj_file);
}

void prepare_test_driver(library_build_params& lib_params,
const build_params& params,
const package_manifest& man) {
auto& test_driver = *man.test_driver;
if (test_driver == test_lib::catch_ || test_driver == test_lib::catch_main
|| test_driver == test_lib::catch_runner) {
prepare_catch2_driver(lib_params, test_driver, params, man);
} else {
assert(false && "Unreachable");
std::terminate();
}
}

} // namespace

void dds::build(const build_params& params, const package_manifest& man) {
@@ -130,6 +201,11 @@ void dds::build(const build_params& params, const package_manifest& man) {
lib_params.build_tests = params.build_tests;
lib_params.build_apps = params.build_apps;
lib_params.enable_warnings = params.enable_warnings;

if (man.test_driver) {
prepare_test_driver(lib_params, params, man);
}

for (const library& lib : libs) {
lib_params.out_subdir = fs::relative(lib.path(), params.root);
pkg.add_library(library_plan::create(lib, lib_params, ureqs));

+ 6
- 0
src/dds/build/plan/compile_file.hpp 파일 보기

@@ -23,6 +23,12 @@ class shared_compile_file_rules {
public:
shared_compile_file_rules() = default;

auto clone() const noexcept {
auto cp = *this;
cp._impl = std::make_shared<rules_impl>(*_impl);
return cp;
}

auto& include_dirs() noexcept { return _impl->inc_dirs; }
auto& include_dirs() const noexcept { return _impl->inc_dirs; }


+ 13
- 2
src/dds/build/plan/library.cpp 파일 보기

@@ -63,11 +63,22 @@ library_plan library_plan::create(const library& lib,
extend(in_libs, ureqs.link_paths(link.namespace_, link.name));
}

auto test_in_libs = in_libs;
extend(test_in_libs, params.test_link_files);

auto test_rules = compile_rules.clone();
extend(test_rules.include_dirs(), params.test_include_dirs);
for (const source_file& source : ranges::views::concat(app_sources, test_sources)) {
// Pick a subdir based on app/test
auto subdir
= source.kind == source_kind::test ? params.out_subdir / "test" : params.out_subdir;
link_executables.emplace_back(in_libs,
compile_file_plan(compile_rules,
// Pick compile rules based on app/test
auto rules = source.kind == source_kind::test ? test_rules : compile_rules;
// Pick input libs based on app/test
auto& exe_link_libs = source.kind == source_kind::test ? test_in_libs : in_libs;
// TODO: Apps/tests should only see the _public_ include dir, not both
link_executables.emplace_back(exe_link_libs,
compile_file_plan(rules,
source,
lib.manifest().name,
params.out_subdir / "obj"),

+ 17478
- 0
src/dds/catch2_embedded.cpp
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 7
- 0
src/dds/catch2_embedded.hpp 파일 보기

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

namespace dds::detail {

extern const char* const catch2_embedded_single_header_str;

} // namespace dds::detail

+ 4
- 0
src/dds/library.hpp 파일 보기

@@ -45,6 +45,10 @@ struct library_build_params {
bool build_tests = false;
bool build_apps = false;
bool enable_warnings = false;

// Extras for compiling tests:
std::vector<fs::path> test_include_dirs;
std::vector<fs::path> test_link_files;
};

std::vector<library> collect_libraries(path_ref where);

+ 20
- 4
src/dds/package_manifest.cpp 파일 보기

@@ -11,16 +11,18 @@
using namespace dds;

package_manifest package_manifest::load_from_file(const fs::path& fpath) {
auto kvs = lm::parse_file(fpath);
package_manifest ret;
std::string version_str;
std::vector<std::string> depends_strs;
auto kvs = lm::parse_file(fpath);
package_manifest ret;
std::string version_str;
std::vector<std::string> depends_strs;
std::optional<std::string> opt_test_driver;
lm::read(fmt::format("Reading package manifest '{}'", fpath.string()),
kvs,
lm::read_required("Name", ret.name),
lm::read_opt("Namespace", ret.namespace_),
lm::read_required("Version", version_str),
lm::read_accumulate("Depends", depends_strs),
lm::read_opt("Test-Driver", opt_test_driver),
lm::reject_unknown());

if (ret.name.empty()) {
@@ -31,6 +33,20 @@ package_manifest package_manifest::load_from_file(const fs::path& fpath) {
throw std::runtime_error(
fmt::format("'Version' field in [{}] may not be an empty string", fpath.string()));
}
if (opt_test_driver) {
auto& test_driver_str = *opt_test_driver;
if (test_driver_str == "Catch-Main") {
ret.test_driver = test_lib::catch_main;
} else if (test_driver_str == "Catch-Runner") {
ret.test_driver = test_lib::catch_runner;
} else if (test_driver_str == "Catch") {
ret.test_driver = test_lib::catch_;
} else {
throw std::runtime_error(
fmt::format("Unknown 'Test-Driver': '{}'", test_driver_str));
}
}

if (ret.namespace_.empty()) {
ret.namespace_ = ret.name;
}

+ 7
- 0
src/dds/package_manifest.hpp 파일 보기

@@ -10,9 +10,16 @@

namespace dds {

enum class test_lib {
catch_,
catch_main,
catch_runner,
};

struct package_manifest {
std::string name;
std::string namespace_;
std::optional<test_lib> test_driver;
semver::version version;
std::vector<dependency> dependencies;
static package_manifest load_from_file(path_ref);

Loading…
취소
저장