From b3a326720bf7b4637bbc9e9f275ca40a8c9eda87 Mon Sep 17 00:00:00 2001 From: Interfiber Date: Mon, 30 Sep 2024 20:15:34 -0400 Subject: [PATCH] work on dynamic extensions --- CMakeLists.txt | 3 +- HConfig | 41 ++++++++++++-- build.ninja | 54 ++++++++++++------- compile_commands.json | 32 ++++++++--- example/HConfig | 46 ---------------- example/compile_commands.json | 32 ----------- example/include/test.h | 3 -- example/main.c | 8 --- example/test.c | 6 --- fusion_ext/HConfig | 18 +++++++ fusion_ext/README.txt | 2 + {example => fusion_ext}/build.ninja | 36 ++++--------- fusion_ext/src/ext_fusion.cc | 10 ++++ include/grbc/ext.h | 18 ++++++- include/grbc/ext_dynamic.h | 7 +++ spec/ext.md | 4 ++ spec/ext/GRBC_EXT_dynamic_extensions.md | 0 src/ext.cc | 9 ++++ src/ext_dynamic.cc | 72 +++++++++++++++++++++++++ src/main.cc | 36 ++++++++++--- src/target_exe.cc | 3 ++ src/target_lib.cc | 7 ++- 22 files changed, 282 insertions(+), 165 deletions(-) delete mode 100644 example/HConfig delete mode 100644 example/compile_commands.json delete mode 100644 example/include/test.h delete mode 100644 example/main.c delete mode 100644 example/test.c create mode 100644 fusion_ext/HConfig create mode 100644 fusion_ext/README.txt rename {example => fusion_ext}/build.ninja (56%) create mode 100644 fusion_ext/src/ext_fusion.cc create mode 100644 include/grbc/ext_dynamic.h create mode 100644 spec/ext/GRBC_EXT_dynamic_extensions.md create mode 100644 src/ext_dynamic.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 83b7477..d4ae944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,8 @@ message(${CMAKE_CXX_FLAGS_RELEASE}) add_subdirectory("vendor/sol2") include_directories("include") +include_directories("vendor/hotwire/src") include_directories("vendor/sol2/include") -add_executable(grbc src/main.cc src/options.cc src/ext_easy.cc src/utils.cc src/file.cc src/target_exe.cc src/platform.cc src/ninja.cc src/generator.cc src/target_lib.cc src/package.cc src/ext.cc src/ext_pkg_config.cc src/task.cc src/ext_profiles.cc) +add_executable(grbc src/ext_dynamic.cc vendor/hotwire/src/dlopen.c src/main.cc src/options.cc src/ext_easy.cc src/utils.cc src/file.cc src/target_exe.cc src/platform.cc src/ninja.cc src/generator.cc src/target_lib.cc src/package.cc src/ext.cc src/ext_pkg_config.cc src/task.cc src/ext_profiles.cc) target_link_libraries(grbc sol2 lua) diff --git a/HConfig b/HConfig index 7b47c37..5c31abe 100644 --- a/HConfig +++ b/HConfig @@ -2,6 +2,34 @@ grbc_want_version("1.0") grbc_ext("GRBC_EXT_pkg_config") grbc_ext("GRBC_EXT_profiles") grbc_ext("GRBC_EXT_easy") +grbc_ext("GRBC_EXT_dynamic_extensions") + +local hotwire = grbc_library(LibraryConfig.new({ + name = "libhotwire", + language_type = LanguageType.C, + files = { + grbc_file("vendor/hotwire/src/dlopen.c") + }, + lib_type = LibraryType.Static, + + requirements = {}, + compile_flags = {}, + linker_flags = {}, + + include_dirs = { + "vendor/hotwire/src", + }, + + package_config = PackageConfig.new({ + name = "libhotwire", + libraries = {}, + include_dirs = { + grbc_file("vendor/hotwire/src") + }, + compile_flags = {}, + linker_flags = {}, + }) +})) local grbc_extensions = grbc_library(LibraryConfig.new({ name = "libgrbc_extensions", @@ -9,7 +37,8 @@ local grbc_extensions = grbc_library(LibraryConfig.new({ files = { grbc_file("src/ext_pkg_config.cc"), grbc_file("src/ext_profiles.cc"), - grbc_file("src/ext_easy.cc") + grbc_file("src/ext_easy.cc"), + grbc_file("src/ext_dynamic.cc") }, lib_type = LibraryType.Static, @@ -19,6 +48,7 @@ local grbc_extensions = grbc_library(LibraryConfig.new({ include_dirs = { "include", + "vendor/hotwire/src", "vendor/sol2/include" }, @@ -52,7 +82,9 @@ local grbc_lib = grbc_library(LibraryConfig.new({ }, lib_type = LibraryType.Static, - requirements = {}, + requirements = { + grbc_pkg("libhotwire") + }, compile_flags = {}, linker_flags = {}, include_dirs = { @@ -82,7 +114,8 @@ local grbc_exe = grbc_executable(ExecutableConfig.new({ requirements = { grbc_pkg_config("lua"), grbc_pkg("libgrbc"), - grbc_pkg("libgrbc_extensions") + grbc_pkg("libgrbc_extensions"), + grbc_pkg("libhotwire") }, compile_flags = {}, linker_flags = {}, @@ -90,4 +123,4 @@ local grbc_exe = grbc_executable(ExecutableConfig.new({ })) -- Output the final build script -grbc_build("ninja") +grbc_build("ninja") \ No newline at end of file diff --git a/build.ninja b/build.ninja index 338faed..1020412 100644 --- a/build.ninja +++ b/build.ninja @@ -1,5 +1,5 @@ ### GENERATED BY THE GRBC BUILT-IN NINJA GENERATOR ### -### GENERATED ON: 1727655668 ### +### GENERATED ON: 1727740849 ### ## Default variables ## @@ -41,79 +41,93 @@ rule archive command = rm -f $out; ar crs $out $in description = Creating static library $out +## Compile: vendor/hotwire/src/dlopen.c ## + +build $builddir/vendor/hotwire/src/dlopen.o: cc vendor/hotwire/src/dlopen.c + p_cflags = -Ivendor/hotwire/src -g -O1 + +## Link: libhotwire.a ## + +build $builddir/libhotwire.a: archive $builddir/vendor/hotwire/src/dlopen.o + ## Compile: src/ext_pkg_config.cc ## build $builddir/src/ext_pkg_config.o: cxx src/ext_pkg_config.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 ## Compile: src/ext_profiles.cc ## build $builddir/src/ext_profiles.o: cxx src/ext_profiles.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 ## Compile: src/ext_easy.cc ## build $builddir/src/ext_easy.o: cxx src/ext_easy.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 + +## Compile: src/ext_dynamic.cc ## + +build $builddir/src/ext_dynamic.o: cxx src/ext_dynamic.cc + p_cflags = -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 ## Link: libgrbc_extensions.a ## -build $builddir/libgrbc_extensions.a: archive $builddir/src/ext_pkg_config.o $builddir/src/ext_profiles.o $builddir/src/ext_easy.o +build $builddir/libgrbc_extensions.a: archive $builddir/src/ext_pkg_config.o $builddir/src/ext_profiles.o $builddir/src/ext_easy.o $builddir/src/ext_dynamic.o ## Compile: src/file.cc ## build $builddir/src/file.o: cxx src/file.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/ninja.cc ## build $builddir/src/ninja.o: cxx src/ninja.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/platform.cc ## build $builddir/src/platform.o: cxx src/platform.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/target_exe.cc ## build $builddir/src/target_exe.o: cxx src/target_exe.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/utils.cc ## build $builddir/src/utils.o: cxx src/utils.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/generator.cc ## build $builddir/src/generator.o: cxx src/generator.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/target_lib.cc ## build $builddir/src/target_lib.o: cxx src/target_lib.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/package.cc ## build $builddir/src/package.o: cxx src/package.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/ext.cc ## build $builddir/src/ext.o: cxx src/ext.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/task.cc ## build $builddir/src/task.o: cxx src/task.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Compile: src/options.cc ## build $builddir/src/options.o: cxx src/options.cc - p_cflags = -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Ivendor/hotwire/src -Iinclude -Ivendor/sol2/include -g -O1 ## Link: libgrbc.a ## @@ -122,12 +136,12 @@ build $builddir/libgrbc.a: archive $builddir/src/file.o $builddir/src/ninja.o $b ## Compile: src/main.cc ## build $builddir/src/main.o: cxx src/main.cc - p_cflags = -Iinclude -Ivendor/sol2/include -Iinclude -Ivendor/sol2/include -g -O1 + p_cflags = -Iinclude -Ivendor/sol2/include -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -Ivendor/hotwire/src -g -O1 ## Link: grbc ## -build $builddir/grbc: link_cxx $builddir/src/main.o | $builddir/libgrbc.a $builddir/libgrbc_extensions.a - p_linker_flags = -llua -lm -ldl build/libgrbc.a build/libgrbc_extensions.a -Lbuild -Wl,-rpath,build:. +build $builddir/grbc: link_cxx $builddir/src/main.o | $builddir/libgrbc.a $builddir/libgrbc_extensions.a $builddir/libhotwire.a + p_linker_flags = -llua -lm -ldl build/libgrbc.a build/libgrbc_extensions.a build/libhotwire.a -Lbuild -Wl,-rpath,build:. p_cflags = -g -O1 ## clean ## @@ -144,6 +158,6 @@ rule compdb_task build compdb: compdb_task -build all: phony $builddir/libgrbc_extensions.a $builddir/libgrbc.a $builddir/grbc +build all: phony $builddir/libhotwire.a $builddir/libgrbc_extensions.a $builddir/libgrbc.a $builddir/grbc default all diff --git a/compile_commands.json b/compile_commands.json index e4786c6..3e05faf 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,25 +1,43 @@ [ { "directory": "/home/interfiber/dev/grbc", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_pkg_config.o -MF build/src/ext_pkg_config.o.d -Iinclude -Ivendor/sol2/include -g -O1 -c src/ext_pkg_config.cc -o build/src/ext_pkg_config.o", + "command": "/usr/lib64/ccache/gcc -MMD -MT build/vendor/hotwire/src/dlopen.o -MF build/vendor/hotwire/src/dlopen.o.d -Ivendor/hotwire/src -g -O1 -c vendor/hotwire/src/dlopen.c -o build/vendor/hotwire/src/dlopen.o", + "file": "vendor/hotwire/src/dlopen.c", + "output": "build/vendor/hotwire/src/dlopen.o" + }, + { + "directory": "/home/interfiber/dev/grbc", + "command": "rm -f build/libhotwire.a; ar crs build/libhotwire.a build/vendor/hotwire/src/dlopen.o", + "file": "build/vendor/hotwire/src/dlopen.o", + "output": "build/libhotwire.a" + }, + { + "directory": "/home/interfiber/dev/grbc", + "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_pkg_config.o -MF build/src/ext_pkg_config.o.d -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 -c src/ext_pkg_config.cc -o build/src/ext_pkg_config.o", "file": "src/ext_pkg_config.cc", "output": "build/src/ext_pkg_config.o" }, { "directory": "/home/interfiber/dev/grbc", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_profiles.o -MF build/src/ext_profiles.o.d -Iinclude -Ivendor/sol2/include -g -O1 -c src/ext_profiles.cc -o build/src/ext_profiles.o", + "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_profiles.o -MF build/src/ext_profiles.o.d -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 -c src/ext_profiles.cc -o build/src/ext_profiles.o", "file": "src/ext_profiles.cc", "output": "build/src/ext_profiles.o" }, { "directory": "/home/interfiber/dev/grbc", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_easy.o -MF build/src/ext_easy.o.d -Iinclude -Ivendor/sol2/include -g -O1 -c src/ext_easy.cc -o build/src/ext_easy.o", + "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_easy.o -MF build/src/ext_easy.o.d -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 -c src/ext_easy.cc -o build/src/ext_easy.o", "file": "src/ext_easy.cc", "output": "build/src/ext_easy.o" }, { "directory": "/home/interfiber/dev/grbc", - "command": "rm -f build/libgrbc_extensions.a; ar crs build/libgrbc_extensions.a build/src/ext_pkg_config.o build/src/ext_profiles.o build/src/ext_easy.o", + "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/ext_dynamic.o -MF build/src/ext_dynamic.o.d -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -g -O1 -c src/ext_dynamic.cc -o build/src/ext_dynamic.o", + "file": "src/ext_dynamic.cc", + "output": "build/src/ext_dynamic.o" + }, + { + "directory": "/home/interfiber/dev/grbc", + "command": "rm -f build/libgrbc_extensions.a; ar crs build/libgrbc_extensions.a build/src/ext_pkg_config.o build/src/ext_profiles.o build/src/ext_easy.o build/src/ext_dynamic.o", "file": "build/src/ext_pkg_config.o", "output": "build/libgrbc_extensions.a" }, @@ -97,20 +115,20 @@ }, { "directory": "/home/interfiber/dev/grbc", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/main.o -MF build/src/main.o.d -Iinclude -Ivendor/sol2/include -Iinclude -Ivendor/sol2/include -g -O1 -c src/main.cc -o build/src/main.o", + "command": "/usr/lib64/ccache/g++ -MMD -MT build/src/main.o -MF build/src/main.o.d -Iinclude -Ivendor/sol2/include -Iinclude -Ivendor/hotwire/src -Ivendor/sol2/include -Ivendor/hotwire/src -g -O1 -c src/main.cc -o build/src/main.o", "file": "src/main.cc", "output": "build/src/main.o" }, { "directory": "/home/interfiber/dev/grbc", - "command": "/usr/lib64/ccache/g++ -g -O1 -o build/grbc build/src/main.o -llua -lm -ldl build/libgrbc.a build/libgrbc_extensions.a -Lbuild -Wl,-rpath,build:. ", + "command": "/usr/lib64/ccache/g++ -g -O1 -o build/grbc build/src/main.o -llua -lm -ldl build/libgrbc.a build/libgrbc_extensions.a build/libhotwire.a -Lbuild -Wl,-rpath,build:. ", "file": "build/src/main.o", "output": "build/grbc" }, { "directory": "/home/interfiber/dev/grbc", "command": "", - "file": "build/libgrbc_extensions.a", + "file": "build/libhotwire.a", "output": "all" } ] diff --git a/example/HConfig b/example/HConfig deleted file mode 100644 index 80f0826..0000000 --- a/example/HConfig +++ /dev/null @@ -1,46 +0,0 @@ -grbc_want_version("1.0") -grbc_ext("GRBC_EXT_profiles") - -local test_lib = grbc_library(LibraryConfig.new({ - name = "libtest", - files = { - grbc_file("test.c") - }, - requirements = {}, - include_dirs = { - grbc_file("include") - }, - lib_type = LibraryType.Shared, - compile_flags = {}, - linker_flags = {}, - package_config = PackageConfig.new({ - name = "libtest", - libraries = {}, - include_dirs = { - grbc_file("include") - }, - compile_flags = {}, - linker_flags = {} - }) -})) - -local hello_world = grbc_executable(ExecutableConfig.new({ - name = "hello_world", - files = { - grbc_file("main.c") - }, - requirements = { - grbc_pkg("libtest") - }, - include_dirs = {}, - compile_flags = {}, - linker_flags = {} -})) - -grbc_task(TaskConfig.new({ - name = "Clean", - task_id = "clean", - shell_script = "ninja -t clean" -})) - -grbc_build("ninja") \ No newline at end of file diff --git a/example/compile_commands.json b/example/compile_commands.json deleted file mode 100644 index d27cc42..0000000 --- a/example/compile_commands.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "directory": "/home/interfiber/dev/grbc/example", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/test.o -MF build/test.o.d -fPIC -Iinclude -c test.c -o build/test.o", - "file": "test.c", - "output": "build/test.o" - }, - { - "directory": "/home/interfiber/dev/grbc/example", - "command": "/usr/lib64/ccache/g++ -o build/libtest.so build/test.o -shared -Lbuild -Wl,-rpath,build:. ", - "file": "build/test.o", - "output": "build/libtest.so" - }, - { - "directory": "/home/interfiber/dev/grbc/example", - "command": "/usr/lib64/ccache/g++ -MMD -MT build/main.o -MF build/main.o.d -Iinclude -c main.c -o build/main.o", - "file": "main.c", - "output": "build/main.o" - }, - { - "directory": "/home/interfiber/dev/grbc/example", - "command": "/usr/lib64/ccache/g++ -o build/hello_world build/main.o build/libtest.so -Lbuild -Wl,-rpath,build:. ", - "file": "build/main.o", - "output": "build/hello_world" - }, - { - "directory": "/home/interfiber/dev/grbc/example", - "command": "", - "file": "build/libtest.so", - "output": "all" - } -] diff --git a/example/include/test.h b/example/include/test.h deleted file mode 100644 index 342ef53..0000000 --- a/example/include/test.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void test_function(); \ No newline at end of file diff --git a/example/main.c b/example/main.c deleted file mode 100644 index 4b1a53c..0000000 --- a/example/main.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include "test.h" - -int main() { - printf("Hello World!\n"); - - test_function(); -} \ No newline at end of file diff --git a/example/test.c b/example/test.c deleted file mode 100644 index 0d0655b..0000000 --- a/example/test.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "test.h" -#include - -void test_function() { - printf("void test_function();\n"); -} \ No newline at end of file diff --git a/fusion_ext/HConfig b/fusion_ext/HConfig new file mode 100644 index 0000000..c2f5a19 --- /dev/null +++ b/fusion_ext/HConfig @@ -0,0 +1,18 @@ +local grbc_extensions = grbc_library(LibraryConfig.new({ + name = "libfusion", + language_type = LanguageType.Cpp, + files = { + grbc_file("src/ext_fusion.cc") + }, + lib_type = LibraryType.Shared, + + requirements = {}, + compile_flags = {}, + linker_flags = {}, + + include_dirs = { + "../vendor/sol2/include" + } +})) + +grbc_build("ninja") \ No newline at end of file diff --git a/fusion_ext/README.txt b/fusion_ext/README.txt new file mode 100644 index 0000000..5937df1 --- /dev/null +++ b/fusion_ext/README.txt @@ -0,0 +1,2 @@ +FUSION GRBC EXTENSION + diff --git a/example/build.ninja b/fusion_ext/build.ninja similarity index 56% rename from example/build.ninja rename to fusion_ext/build.ninja index 1fdfeb8..093abf7 100644 --- a/example/build.ninja +++ b/fusion_ext/build.ninja @@ -1,5 +1,5 @@ ### GENERATED BY THE GRBC BUILT-IN NINJA GENERATOR ### -### GENERATED ON: 1727643213 ### +### GENERATED ON: 1727735253 ### ## Default variables ## @@ -41,35 +41,17 @@ rule archive command = rm -f $out; ar crs $out $in description = Creating static library $out -## Compile: test.c ## +## Compile: src/ext_fusion.cc ## -build $builddir/test.o: cxx test.c - p_cflags = -fPIC -Iinclude +build $builddir/src/ext_fusion.o: cxx src/ext_fusion.cc + p_cflags = -fPIC -I../vendor/sol2/include -## Link: libtest.so ## +## Link: libfusion.so ## -build $builddir/libtest.so: link_cxx $builddir/test.o - p_linker_flags = -shared -O3 -DNDEBUG -Lbuild -Wl,-rpath,build:. - p_cflags = +build $builddir/libfusion.so: link_cxx $builddir/src/ext_fusion.o + p_linker_flags = -shared -Lbuild -Wl,-rpath,build:. + p_cflags = -## Compile: main.c ## - -build $builddir/main.o: cxx main.c - p_cflags = -Iinclude - -## Link: hello_world ## - -build $builddir/hello_world: link_cxx $builddir/main.o | $builddir/libtest.so - p_linker_flags = build/libtest.so -O3 -DNDEBUG -Lbuild -Wl,-rpath,build:. - p_cflags = - -## clean ## -rule clean_task - command = ninja -t clean - description = Running task: Clean (clean) - -build clean: clean_task - -build all: phony $builddir/libtest.so $builddir/hello_world +build all: phony $builddir/libfusion.so default all diff --git a/fusion_ext/src/ext_fusion.cc b/fusion_ext/src/ext_fusion.cc new file mode 100644 index 0000000..cfe2de7 --- /dev/null +++ b/fusion_ext/src/ext_fusion.cc @@ -0,0 +1,10 @@ +#include "grbc/spec.h" +#include + +const char* GRBC_Get_Name() { + return "GRBC_EXT_Fusion"; +} + +void GRBC_Hook_Init(sol::state &lua) { + +} \ No newline at end of file diff --git a/include/grbc/ext.h b/include/grbc/ext.h index fea60b1..2bcd12d 100644 --- a/include/grbc/ext.h +++ b/include/grbc/ext.h @@ -5,12 +5,28 @@ #define GRBC_EXT_pkg_config_NAME "GRBC_EXT_pkg_config" #define GRBC_EXT_profiles_NAME "GRBC_EXT_profiles" #define GRBC_EXT_easy_NAME "GRBC_EXT_easy" +#define GRBC_EXT_dynamic_extensions_NAME "GRBC_EXT_dynamic_extensions" +/// Called when the extension is loaded typedef void (*EXT_HookInit)(sol::state &lua); +/// Called when the build completes +typedef void (*EXT_HookBuildFinish)(); + +/// Called everytime that a file is processed +typedef void (*EXT_HookProcessFile)(const std::string &file); + +/// Called when the extension is invoked from the command line +typedef void (*EXT_HookInvoke)(); + struct Extension { std::string name; bool loaded = false; EXT_HookInit hook_init = nullptr; -}; \ No newline at end of file + EXT_HookBuildFinish build_finish = nullptr; + EXT_HookProcessFile process_file = nullptr; + EXT_HookInvoke invoke = nullptr; +}; + +void grbc_ext_process_file(const std::string &file); \ No newline at end of file diff --git a/include/grbc/ext_dynamic.h b/include/grbc/ext_dynamic.h new file mode 100644 index 0000000..558998b --- /dev/null +++ b/include/grbc/ext_dynamic.h @@ -0,0 +1,7 @@ +#pragma once +#include "grbc/ext.h" + +/** + * Get the grbc dynamic extension + */ +Extension grbc_dynamic(); \ No newline at end of file diff --git a/spec/ext.md b/spec/ext.md index 103d846..2097565 100644 --- a/spec/ext.md +++ b/spec/ext.md @@ -8,8 +8,12 @@ Extensions are built into the grbc executable, and are loaded at runtime as need * GRBC_EXT_pkg_config * GRBC_EXT_profiles * GRBC_EXT_easy +* GRBC_EXT_dynamic_extensions * GRBC_EXT_cmake [NOSUPPORT] +## GRBC_EXT_dynamic_extensions +Allows loading of extensions from shared object files. Extensions are searched for in: ```C:\grbc\ext```, or ```./grbc_ext``` + ## GRBC_EXT_pkg_config Pkg config support. UNIX only diff --git a/spec/ext/GRBC_EXT_dynamic_extensions.md b/spec/ext/GRBC_EXT_dynamic_extensions.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ext.cc b/src/ext.cc index 154475c..f5c83f0 100644 --- a/src/ext.cc +++ b/src/ext.cc @@ -44,4 +44,13 @@ bool grbc_is_ext_loaded(const std::string &extension_name) { } return false; +} + +void grbc_ext_process_file(const std::string &file) { + for (auto &ext : GState::get().extensions) { + if (!ext.loaded || ext.process_file == nullptr) + continue; + + ext.process_file(file); + } } \ No newline at end of file diff --git a/src/ext_dynamic.cc b/src/ext_dynamic.cc new file mode 100644 index 0000000..485d453 --- /dev/null +++ b/src/ext_dynamic.cc @@ -0,0 +1,72 @@ +#include "grbc/ext_dynamic.h" + +extern "C" { +#include "dlopen.h" +} + +#include "grbc/ext.h" +#include "grbc/helpers.h" +#include "grbc/spec.h" +#include + +typedef const char *(*EXT_GetName)(); + +void EXT_dynamic_ext(const std::string &extension_name) { + const std::array extension_paths = {"./grbc_ext", + "C:\\grbc\\ext", "./", "./build"}; + + std::filesystem::path good_extension_path; + + for (size_t i = 0; i < extension_paths.size(); i++) { + std::filesystem::path extension_path = + std::filesystem::path(extension_paths[i]) / + std::filesystem::path(extension_name + ".grbcext"); + + if (std::filesystem::exists(extension_path)) { + good_extension_path = extension_path; + + break; + } else { + log_msg(("no extension at: " + extension_path.generic_string()).c_str()); + } + } + + if (good_extension_path.empty()) + grbc_exception("Failed to find GRBC dynamic extension!"); + + struct hotwire_dll_t dll = hw_dlopen(good_extension_path.c_str(), 0x00002); + + EXT_HookInit hook_init = (EXT_HookInit)hw_dlsym(dll, "GRBC_Hook_Init"); + EXT_GetName get_name = (EXT_GetName)hw_dlsym(dll, "GRBC_Get_Name"); + + if (hook_init == nullptr) + grbc_exception( + "Dynamic extension is missing public GRBC_Hook_Init symbol!"); + + if (get_name == nullptr) + grbc_exception("Dynamic extension is missing public GRBC_Get_Name symbol!"); + + Extension ext{}; + ext.name = get_name(); + ext.hook_init = hook_init; + + log_msg( + ("loaded dynamic extension from: " + good_extension_path.generic_string()) + .c_str()); + + grbc_register_ext(ext); +} + +void grbc_dynamic_init(sol::state &lua) { + lua.set("grbc_dynamic_ext", EXT_dynamic_ext); + + log_msg("dynamic extension support loaded!"); +} + +Extension grbc_dynamic() { + Extension ext{}; + ext.name = GRBC_EXT_dynamic_extensions_NAME; + ext.hook_init = grbc_dynamic_init; + + return ext; +} \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 8783146..02a41ac 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,3 +1,5 @@ +#include "grbc/ext.h" +#include "grbc/ext_dynamic.h" #include "grbc/ext_easy.h" #include "grbc/ext_pkg_config.h" #include "grbc/ext_profiles.h" @@ -15,6 +17,7 @@ void print_help() { printf("Author: Interfiber \n"); printf("Commands:\n"); printf(" gen - Generate build configuration from HConfig\n"); + printf(" ext - Invoke a dynamic extension\n"); } int main(int argc, char **argv) { @@ -44,16 +47,32 @@ int main(int argc, char **argv) { GState::get().options = options; - if (std::string(argv[1]) == "gen") { + log_msg("opening lua libraries..."); + + auto &lua = GState::get().lua; + + lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::string, + sol::lib::io, sol::lib::package, sol::lib::math); + + if (std::string(argv[1]) == "ext") { + if (argc < 3) grbc_exception("expected argument 'dynamic_ext_path'"); + + log_msg("invoking extension..."); + + grbc_register_ext(grbc_dynamic()); // Register dynamic extensions + + grbc_ext(GRBC_EXT_dynamic_extensions_NAME); // Load dynamic extension + + lua.script("grbc_dynamic_ext('" + std::string(argv[2]) + "')"); + + Extension ext = + GState::get() + .extensions.front(); // Only one extension should be loaded! + + ext.invoke(); // Invoke extension + } else if (std::string(argv[1]) == "gen") { log_msg("running grbc generator..."); - log_msg("opening lua libraries..."); - - auto &lua = GState::get().lua; - - lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::string, - sol::lib::io, sol::lib::package, sol::lib::math); - log_msg("setting up runtime..."); // TargetInfo @@ -169,6 +188,7 @@ int main(int argc, char **argv) { grbc_register_ext(grbc_profiles()); grbc_register_ext(grbc_easy()); + grbc_register_ext(grbc_dynamic()); // Detect platform log_msg("autodetecting platform..."); diff --git a/src/target_exe.cc b/src/target_exe.cc index 18d3318..b3ff414 100644 --- a/src/target_exe.cc +++ b/src/target_exe.cc @@ -1,3 +1,4 @@ +#include "grbc/ext.h" #include "grbc/generator.h" #include "grbc/spec.h" #include "grbc/state.h" @@ -50,6 +51,8 @@ TargetInfo grbc_executable(const ExecutableConfig &executable_config) { object_files.push_back(compile_cmd.object_file); target.compile_commands.push_back(compile_cmd); + + grbc_ext_process_file(src_file); } // Final executable link diff --git a/src/target_lib.cc b/src/target_lib.cc index adc9285..bdee5d9 100644 --- a/src/target_lib.cc +++ b/src/target_lib.cc @@ -5,8 +5,9 @@ TargetInfo grbc_library(const LibraryConfig &library_config) { TargetInfo target_config{}; - if (library_config.name[0] != 'l' && library_config.name[1] != 'i' && library_config.name[2] != 'b') { - grbc_exception("library names are mandated to start with 'lib'"); + if (library_config.name[0] != 'l' && library_config.name[1] != 'i' && + library_config.name[2] != 'b') { + grbc_exception("library names are mandated to start with 'lib'"); } std::string lib_name = library_config.name; @@ -50,6 +51,8 @@ TargetInfo grbc_library(const LibraryConfig &library_config) { object_files.push_back(compile_cmd.object_file); target.compile_commands.push_back(compile_cmd); + + grbc_ext_process_file(src_file); } // Libraries which need to be built before us