ソースを参照

Early iteration of config-headers.

This is a very rudimentary version. All it does is copy and rename the
template header file and place it in the build directory in a special
subdirectory that is added as an #include-path.

There is some code duplication and cleanup necessary. There are a
few "magic strings" and "magic paths" that need to be removed as well.
default_compile_flags
vector-of-bool 4年前
コミット
b1e5315a9b
11個のファイルの変更158行の追加24行の削除
  1. +6
    -0
      src/dds/build/builder.cpp
  2. +11
    -0
      src/dds/build/plan/full.cpp
  3. +4
    -0
      src/dds/build/plan/full.hpp
  4. +23
    -6
      src/dds/build/plan/library.cpp
  5. +24
    -3
      src/dds/build/plan/library.hpp
  6. +16
    -0
      src/dds/build/plan/template.cpp
  7. +36
    -0
      src/dds/build/plan/template.hpp
  8. +5
    -0
      tests/basics/config_template/copy_only/src/info.config.hpp
  9. +5
    -0
      tests/basics/config_template/copy_only/src/info.test.cpp
  10. +9
    -0
      tests/basics/config_template/test_config_template.py
  11. +19
    -15
      tests/dds.py

+ 6
- 0
src/dds/build/builder.cpp ファイルの表示

@@ -153,6 +153,10 @@ prepare_ureqs(const build_plan& plan, const toolchain& toolchain, path_ref out_r
if (const auto& arc = lib.archive_plan()) {
lib_reqs.linkable_path = out_root / arc->calc_archive_file_path(toolchain);
}
if (lib.has_generated_headers()) {
lib_reqs.include_paths.push_back(out_root / "__dds/gen"
/ lib.output_subdirectory());
}
}
}
return ureqs;
@@ -225,6 +229,8 @@ void builder::build(const build_params& params) const {
generate_compdb(plan, env);
}

plan.render_all(env);

dds::stopwatch sw;
plan.compile_all(env, params.parallel_jobs);
spdlog::info("Compilation completed in {:n}ms", sw.elapsed_ms().count());

+ 11
- 0
src/dds/build/plan/full.cpp ファイルの表示

@@ -74,6 +74,17 @@ bool parallel_run(Range&& rng, int n_jobs, Fn&& fn) {

} // namespace

void build_plan::render_all(build_env_ref env) const {
auto templates = _packages //
| ranges::view::transform(&package_plan::libraries) //
| ranges::view::join //
| ranges::view::transform(&library_plan::templates) //
| ranges::view::join;
for (const render_template_plan& tmpl : templates) {
tmpl.render(env);
}
}

void build_plan::compile_all(const build_env& env, int njobs) const {
auto okay = dds::compile_all(iter_compilations(*this), env, njobs);
if (!okay) {

+ 4
- 0
src/dds/build/plan/full.hpp ファイルの表示

@@ -28,6 +28,10 @@ public:
* All of the packages in this plan
*/
auto& packages() const noexcept { return _packages; }
/**
* Render all config templates in the plan.
*/
void render_all(const build_env& env) const;
/**
* Compile all files in the plan.
*/

+ 23
- 6
src/dds/build/plan/library.cpp ファイルの表示

@@ -17,6 +17,7 @@ library_plan library_plan::create(const library_root& lib,
std::vector<source_file> app_sources;
std::vector<source_file> test_sources;
std::vector<source_file> lib_sources;
std::vector<source_file> template_sources;

auto qual_name = std::string(qual_name_.value_or(lib.manifest().name));

@@ -34,6 +35,8 @@ library_plan library_plan::create(const library_root& lib,
app_sources.push_back(sfile);
} else if (sfile.kind == source_kind::source) {
lib_sources.push_back(sfile);
} else if (sfile.kind == source_kind::header_template) {
template_sources.push_back(sfile);
} else {
assert(sfile.kind == source_kind::header);
}
@@ -45,6 +48,10 @@ library_plan library_plan::create(const library_root& lib,
compile_rules.enable_warnings() = params.enable_warnings;
compile_rules.uses() = lib.manifest().uses;

if (!template_sources.empty()) {
compile_rules.include_dirs().push_back("__dds/gen" / params.out_subdir);
}

// Convert the library sources into their respective file compilation plans.
auto lib_compile_files = //
lib_sources //
@@ -55,12 +62,12 @@ library_plan library_plan::create(const library_root& lib,

// If we have any compiled library files, generate a static library archive
// for this library
std::optional<create_archive_plan> create_archive;
std::optional<create_archive_plan> archive_plan;
if (!lib_compile_files.empty()) {
create_archive.emplace(lib.manifest().name,
qual_name,
params.out_subdir,
std::move(lib_compile_files));
archive_plan.emplace(lib.manifest().name,
qual_name,
params.out_subdir,
std::move(lib_compile_files));
}

// Collect the paths to linker inputs that should be used when generating executables for this
@@ -104,6 +111,16 @@ library_plan library_plan::create(const library_root& lib,
link_executables.emplace_back(std::move(exe));
}

std::vector<render_template_plan> render_templates;
for (const auto& sf : template_sources) {
render_templates.emplace_back(sf, "__dds/gen" / params.out_subdir);
}

// Done!
return library_plan{lib, qual_name, std::move(create_archive), std::move(link_executables)};
return library_plan{lib,
qual_name,
params.out_subdir,
std::move(archive_plan),
std::move(link_executables),
std::move(render_templates)};
}

+ 24
- 3
src/dds/build/plan/library.hpp ファイルの表示

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

#include <dds/build/plan/archive.hpp>
#include <dds/build/plan/exe.hpp>
#include <dds/build/plan/template.hpp>
#include <dds/library/root.hpp>
#include <dds/usage_reqs.hpp>
#include <dds/util/fs.hpp>
@@ -56,10 +57,14 @@ class library_plan {
library_root _lib;
/// The qualified name of the library
std::string _qual_name;
/// The library's subdirectory within the output directory
fs::path _subdir;
/// The `create_archive_plan` for this library, if applicable
std::optional<create_archive_plan> _create_archive;
/// The executables that should be linked as part of this library's build
std::vector<link_executable_plan> _link_exes;
/// The templates that must be rendered for this library
std::vector<render_template_plan> _templates;

public:
/**
@@ -70,12 +75,16 @@ public:
*/
library_plan(library_root lib,
std::string_view qual_name,
fs::path subdir,
std::optional<create_archive_plan> ar,
std::vector<link_executable_plan> exes)
std::vector<link_executable_plan> exes,
std::vector<render_template_plan> tmpls)
: _lib(std::move(lib))
, _qual_name(qual_name)
, _subdir(std::move(subdir))
, _create_archive(std::move(ar))
, _link_exes(std::move(exes)) {}
, _link_exes(std::move(exes))
, _templates(std::move(tmpls)) {}

/**
* Get the underlying library object
@@ -89,6 +98,10 @@ public:
* Get the qualified name of the library, as if for a libman usage requirement
*/
auto& qualified_name() const noexcept { return _qual_name; }
/**
* The output subdirectory of this library plan
*/
path_ref output_subdirectory() const noexcept { return _subdir; }
/**
* The directory that defines the source root of the library.
*/
@@ -98,6 +111,10 @@ public:
* components
*/
auto& archive_plan() const noexcept { return _create_archive; }
/**
* The template rendering plans for this library.
*/
auto& templates() const noexcept { return _templates; }
/**
* The executables that should be created by this library
*/
@@ -110,6 +127,10 @@ public:
* The library identifiers that are linked by this library
*/
auto& links() const noexcept { return _lib.manifest().links; }
/**
* Return `true` if this object has generated header files
*/
bool has_generated_headers() const noexcept { return !templates().empty(); }

/**
* Named constructor: Create a new `library_plan` automatically from some build-time parameters.
@@ -129,4 +150,4 @@ public:
std::optional<std::string_view> qual_name);
};

} // namespace dds
} // namespace dds

+ 16
- 0
src/dds/build/plan/template.cpp ファイルの表示

@@ -0,0 +1,16 @@
#include <dds/build/plan/template.hpp>

#include <dds/util/fs.hpp>

using namespace dds;

void render_template_plan::render(build_env_ref env) const {
auto content = slurp_file(_source.path);

// Calculate the destination of the template rendering
auto dest = env.output_root / _subdir / _source.relative_path();
dest.replace_filename(dest.stem().stem().filename().string() + dest.extension().string());
fs::create_directories(dest.parent_path());

fs::copy_file(_source.path, dest, fs::copy_options::overwrite_existing);
}

+ 36
- 0
src/dds/build/plan/template.hpp ファイルの表示

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

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

#include <utility>

namespace dds {

class render_template_plan {
/**
* The source file that defines the config template
*/
source_file _source;
/**
* The subdirectory in which the template should be rendered.
*/
fs::path _subdir;

public:
/**
* Create a new instance
* @param sf The source file of the template
* @param subdir The subdirectort into which the template should render
*/
render_template_plan(source_file sf, path_ref subdir)
: _source(std::move(sf))
, _subdir(subdir) {}

/**
* Render the template into its output directory
*/
void render(build_env_ref) const;
};

} // namespace dds

+ 5
- 0
tests/basics/config_template/copy_only/src/info.config.hpp ファイルの表示

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

#include <string>

int config_file_value = 42;

+ 5
- 0
tests/basics/config_template/copy_only/src/info.test.cpp ファイルの表示

@@ -0,0 +1,5 @@
#include <info.hpp>

#include <cassert>

int main() { assert(config_file_value == 42); }

+ 9
- 0
tests/basics/config_template/test_config_template.py ファイルの表示

@@ -0,0 +1,9 @@
import pytest

from tests import DDS, dds_fixture_conf_1


@dds_fixture_conf_1('copy_only')
def test_config_template(dds: DDS):
dds.build()
assert (dds.build_dir / '__dds/gen/info.hpp').is_file()

+ 19
- 15
tests/dds.py ファイルの表示

@@ -52,11 +52,11 @@ class DDS:
full_cmd = itertools.chain([self.dds_exe], cmd)
return proc.run(full_cmd, cwd=cwd or self.source_root)

def run(self, cmd: proc.CommandLine, *,
cwd: Path = None) -> subprocess.CompletedProcess:
def run(self, cmd: proc.CommandLine, *, cwd: Path = None,
check=True) -> subprocess.CompletedProcess:
cmdline = list(proc.flatten_cmd(cmd))
res = self.run_unchecked(cmd, cwd=cwd)
if res.returncode != 0:
if res.returncode != 0 and check:
raise subprocess.CalledProcessError(
res.returncode, [self.dds_exe] + cmdline, res.stdout)
return res
@@ -86,18 +86,22 @@ class DDS:
toolchain: str = None,
apps: bool = True,
warnings: bool = True,
tests: bool = True) -> subprocess.CompletedProcess:
return self.run([
'build',
f'--out={self.build_dir}',
f'--toolchain={toolchain or self.default_builtin_toolchain}',
f'--catalog={self.catalog_path}',
f'--repo-dir={self.repo_dir}',
['--no-tests'] if not tests else [],
['--no-apps'] if not apps else [],
['--no-warnings'] if not warnings else [],
self.project_dir_arg,
])
tests: bool = True,
check: bool = True) -> subprocess.CompletedProcess:
return self.run(
[
'build',
f'--out={self.build_dir}',
f'--toolchain={toolchain or self.default_builtin_toolchain}',
f'--catalog={self.catalog_path}',
f'--repo-dir={self.repo_dir}',
['--no-tests'] if not tests else [],
['--no-apps'] if not apps else [],
['--no-warnings'] if not warnings else [],
self.project_dir_arg,
],
check=check,
)

def sdist_create(self) -> subprocess.CompletedProcess:
return self.run([

読み込み中…
キャンセル
保存