Skip to content

Commit 7931c30

Browse files
committed
[injection] Create an example implementation
1 parent 7311d76 commit 7931c30

File tree

6 files changed

+131
-1
lines changed

6 files changed

+131
-1
lines changed

example/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ DEFINE_EXAMPLE(format)
1111
# review.cpp
1212
# review_tu2.cpp
1313
# )
14-
# target_link_libraries(example_review PRIVATE rsl_util)
14+
# target_link_libraries(example_review PRIVATE rsl_util)
15+
#
16+
17+
add_subdirectory(inject)

example/inject/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
add_executable(injector injection_impl.cpp)
3+
target_link_libraries(injector PRIVATE rsl-util)
4+
5+
6+
set(all_injected_file "${CMAKE_CURRENT_SOURCE_DIR}/injected.cpp")
7+
add_custom_command(
8+
OUTPUT ${all_injected_file}
9+
POST_BUILD
10+
COMMAND ${CMAKE_COMMAND} -E touch ${all_injected_file}
11+
COMMAND ${CMAKE_COMMAND} -E echo "Running injector from source dir..."
12+
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR} $<TARGET_FILE:injector>
13+
)
14+
add_library(injected_lib injected.cpp)
15+
add_dependencies(injected_lib injector)
16+
17+
add_executable(injection_example main.cpp)
18+
target_link_libraries(injection_example PRIVATE injected_lib)

example/inject/injection_impl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <rsl/inject>
2+
3+
4+
namespace foo_impl
5+
{
6+
static constexpr auto target_name = "injected_implementation";
7+
[[=Inject("demo/file.cpp")]]
8+
std::string generateFunction()
9+
{
10+
return " int foo() { return 42;}";
11+
}
12+
} // namespace inject
13+
14+
15+
RSLINJECT_ENABLE_NS(foo_impl)

example/inject/interface.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int foo();

example/inject/main.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <print>
2+
#include "interface.hpp"
3+
4+
auto main(int argc, char *argv[]) -> int {
5+
std::println("{}", foo());
6+
return 0;
7+
}

include/rsl/inject

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include <meta>
2+
#include <string>
3+
#include <fstream>
4+
#include <filesystem>
5+
#include <format>
6+
#include <unordered_map>
7+
#include <set>
8+
9+
#include <rsl/span>
10+
11+
namespace __impl {
12+
13+
struct InjectPath {
14+
char const* msg;
15+
};
16+
} // namespace __impl
17+
18+
static consteval auto Inject(char const* msg) {
19+
return __impl::InjectPath{std::define_static_string(msg)};
20+
};
21+
22+
using injections_type = std::unordered_map<std::filesystem::path, std::string>;
23+
24+
struct injection_info {
25+
injections_type entries;
26+
};
27+
28+
injection_info& injection_info() {
29+
static struct injection_info injected{};
30+
return injected;
31+
}
32+
33+
injections_type& injections() {
34+
return injection_info().entries;
35+
}
36+
37+
std::string generate_cmake() {
38+
std::string out{};
39+
auto& info = injection_info();
40+
// boilerplate
41+
42+
return out;
43+
}
44+
45+
template <std::meta::info func>
46+
void process_injection() {
47+
constexpr auto vec = rsl::span{std::define_static_array(std::meta::annotations_of(func))};
48+
constexpr std::string_view annotationInfo =
49+
std::define_static_string(std::meta::extract<__impl::InjectPath>(vec[0]).msg);
50+
auto const path = std::filesystem::path(annotationInfo);
51+
std::format_to(std::back_inserter(injections()[path]), "{}\n", [:func:]());
52+
}
53+
54+
void generate_from_injection() {
55+
const auto common_includes_file = std::filesystem::path("injected.cpp");
56+
std::ofstream all_injections{common_includes_file};
57+
for (const auto [path, injection] : injections()) {
58+
if (path.has_parent_path())
59+
std::filesystem::create_directories(path.parent_path());
60+
std::ofstream file{path};
61+
if (file)
62+
file << injection;
63+
all_injections << std::format("#include \"{}\"\n", path.string());
64+
}
65+
}
66+
67+
template <std::meta::info source>
68+
constexpr bool gather_injections() {
69+
template for (constexpr auto member :
70+
define_static_array(members_of(source, std::meta::access_context::current()))) {
71+
if constexpr (is_function(member))
72+
process_injection<member>();
73+
}
74+
return true;
75+
}
76+
77+
#define RSLINJECT_ENABLE_NS(NS) \
78+
namespace { \
79+
[[maybe_unused]] static bool const _rsl_injection_enabled = gather_injections<^^NS>(); \
80+
}
81+
82+
int main() {
83+
generate_from_injection();
84+
}

0 commit comments

Comments
 (0)