diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index e3b8145..7de7827 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -11,4 +11,7 @@ DEFINE_EXAMPLE(format) # review.cpp # review_tu2.cpp # ) -# target_link_libraries(example_review PRIVATE rsl_util) \ No newline at end of file +# target_link_libraries(example_review PRIVATE rsl_util) +# + +add_subdirectory(inject) diff --git a/example/inject/CMakeLists.txt b/example/inject/CMakeLists.txt new file mode 100644 index 0000000..ae15836 --- /dev/null +++ b/example/inject/CMakeLists.txt @@ -0,0 +1,18 @@ + +add_executable(injector injection_impl.cpp) +target_link_libraries(injector PRIVATE rsl-util) + + +set(all_injected_file "${CMAKE_CURRENT_SOURCE_DIR}/injected.cpp") +add_custom_command( + OUTPUT ${all_injected_file} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E touch ${all_injected_file} + COMMAND ${CMAKE_COMMAND} -E echo "Running injector from source dir..." + COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR} $ +) +add_library(injected_lib injected.cpp) +add_dependencies(injected_lib injector) + +add_executable(injection_example main.cpp) +target_link_libraries(injection_example PRIVATE injected_lib) diff --git a/example/inject/injection_impl.cpp b/example/inject/injection_impl.cpp new file mode 100644 index 0000000..9f821d9 --- /dev/null +++ b/example/inject/injection_impl.cpp @@ -0,0 +1,15 @@ +#include + + +namespace foo_impl +{ + static constexpr auto target_name = "injected_implementation"; + [[=Inject("demo/file.cpp")]] + std::string generateFunction() + { + return " int foo() { return 42;}"; + } +} // namespace inject + + +RSLINJECT_ENABLE_NS(foo_impl) diff --git a/example/inject/interface.hpp b/example/inject/interface.hpp new file mode 100644 index 0000000..eacbb8d --- /dev/null +++ b/example/inject/interface.hpp @@ -0,0 +1,3 @@ +#pragma once + +int foo(); diff --git a/example/inject/main.cpp b/example/inject/main.cpp new file mode 100644 index 0000000..169be34 --- /dev/null +++ b/example/inject/main.cpp @@ -0,0 +1,7 @@ +#include +#include "interface.hpp" + +auto main(int argc, char *argv[]) -> int { + std::println("{}", foo()); + return 0; +} diff --git a/include/rsl/inject b/include/rsl/inject new file mode 100644 index 0000000..4b684d4 --- /dev/null +++ b/include/rsl/inject @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace __impl { + +struct InjectPath { + char const* msg; +}; +} // namespace __impl + +static consteval auto Inject(char const* msg) { + return __impl::InjectPath{std::define_static_string(msg)}; +}; + +using injections_type = std::unordered_map; + +struct injection_info { + injections_type entries; +}; + +injection_info& injection_info() { + static struct injection_info injected{}; + return injected; +} + +injections_type& injections() { + return injection_info().entries; +} + +std::string generate_cmake() { + std::string out{}; + auto& info = injection_info(); + // boilerplate + + return out; +} + +template +void process_injection() { + constexpr auto vec = rsl::span{std::define_static_array(std::meta::annotations_of(func))}; + constexpr std::string_view annotationInfo = + std::define_static_string(std::meta::extract<__impl::InjectPath>(vec[0]).msg); + auto const path = std::filesystem::path(annotationInfo); + std::format_to(std::back_inserter(injections()[path]), "{}\n", [:func:]()); +} + +void generate_from_injection() { + const auto common_includes_file = std::filesystem::path("injected.cpp"); + std::ofstream all_injections{common_includes_file}; + for (const auto [path, injection] : injections()) { + if (path.has_parent_path()) + std::filesystem::create_directories(path.parent_path()); + std::ofstream file{path}; + if (file) + file << injection; + all_injections << std::format("#include \"{}\"\n", path.string()); + } +} + +template +constexpr bool gather_injections() { + template for (constexpr auto member : + define_static_array(members_of(source, std::meta::access_context::current()))) { + if constexpr (is_function(member)) + process_injection(); + } + return true; +} + +#define RSLINJECT_ENABLE_NS(NS) \ + namespace { \ + [[maybe_unused]] static bool const _rsl_injection_enabled = gather_injections<^^NS>(); \ + } + +int main() { + generate_from_injection(); +}