Skip to content

Commit 11d3762

Browse files
authored
Build a JIT into a shared lib (when you're feeling a little too sane)
1 parent b77b5ff commit 11d3762

22 files changed

+615
-222
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,13 @@ jobs:
3232
matrix:
3333
platform:
3434
- os: 'freebsd'
35-
#~ version: '14.3'
3635
version: '15.0'
3736
prepare_gcc: 'pkg install -y perl5 lang/gcc'
3837
prepare_clang: 'pkg install -y perl5 llvm'
3938
- os: 'openbsd'
4039
version: '7.8'
4140
#~ https://openbsd.app/
42-
prepare_gcc: 'pkg_add gcc-11.2.0p19'
41+
prepare_gcc: 'pkg_add gcc-11.2.0p19 g++-11.2.0p19'
4342
prepare_clang: ''
4443
- os: 'netbsd'
4544
version: '10.1'
@@ -51,7 +50,7 @@ jobs:
5150
version: '11.4'
5251
prepare_gcc: 'pkg install -v --accept perl-538 gcc'
5352
- os: 'omnios'
54-
version: 'r151054'
53+
version: 'r151056'
5554
prepare_gcc: 'pkg install -v --accept perl build-essential'
5655
arch: ['x86_64', 'aarch64', 'riscv64']
5756
toolchain: ['gcc', 'clang']

.github/workflows/unified-tester.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
6060
- name: Build and Test in FreeBSD
6161
if: inputs.runner_type == 'vm' && inputs.os == 'freebsd'
62-
uses: vmactions/freebsd-vm@v1.2.7
62+
uses: vmactions/freebsd-vm@v1.3.7
6363
with:
6464
release: ${{ inputs.os_version }}
6565
usesh: true
@@ -70,7 +70,7 @@ jobs:
7070
7171
- name: Build and Test in OpenBSD
7272
if: inputs.runner_type == 'vm' && inputs.os == 'openbsd'
73-
uses: vmactions/openbsd-vm@v1.2.3
73+
uses: vmactions/openbsd-vm@v1.3.1
7474
with:
7575
release: ${{ inputs.os_version }}
7676
usesh: true
@@ -81,7 +81,7 @@ jobs:
8181
8282
- name: Build and Test in NetBSD
8383
if: inputs.runner_type == 'vm' && inputs.os == 'netbsd'
84-
uses: vmactions/netbsd-vm@v1.2.2
84+
uses: vmactions/netbsd-vm@v1.3.1
8585
with:
8686
release: ${{ inputs.os_version }}
8787
usesh: true
@@ -92,7 +92,7 @@ jobs:
9292
9393
- name: Build and Test in DragonflyBSD
9494
if: inputs.runner_type == 'vm' && inputs.os == 'dragonflybsd'
95-
uses: vmactions/dragonflybsd-vm@v1.1.3
95+
uses: vmactions/dragonflybsd-vm@v1.2.1
9696
with:
9797
release: ${{ inputs.os_version }}
9898
usesh: true
@@ -102,7 +102,7 @@ jobs:
102102
103103
- name: Build and Test in Solaris
104104
if: inputs.runner_type == 'vm' && inputs.os == 'solaris'
105-
uses: vmactions/solaris-vm@v1.1.7
105+
uses: vmactions/solaris-vm@v1.2.6
106106
with:
107107
release: ${{ inputs.os_version }}
108108
usesh: true
@@ -112,7 +112,7 @@ jobs:
112112
113113
- name: Build and Test in OmniOS
114114
if: inputs.runner_type == 'vm' && inputs.os == 'omnios'
115-
uses: vmactions/omnios-vm@v1.1.3
115+
uses: vmactions/omnios-vm@v1.2.1
116116
with:
117117
release: ${{ inputs.os_version }}
118118
usesh: true

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,17 @@ latex/*
3737
leak-*
3838
.tidyall.d/*
3939
docs/api/
40+
41+
# Build artifacts and extensionless binaries
42+
*.so
43+
*.dylib
44+
*.dll
45+
fuzz_*_harness
46+
preprocessed.cpp
47+
48+
# Ignore extensionless binaries in t/ but keep sources and include dir
49+
t/*
50+
!t/include/
51+
!t/*.c
52+
!t/*.cpp
53+
!t/*.h

CMakeLists.txt

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# CMake build script for the infix FFI library
22
cmake_minimum_required(VERSION 3.12)
3-
project(infix VERSION 0.1.0 LANGUAGES C)
3+
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/infix/infix.h" INFIX_MAJOR_LINE REGEX "^#define INFIX_MAJOR")
4+
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/infix/infix.h" INFIX_MINOR_LINE REGEX "^#define INFIX_MINOR")
5+
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/infix/infix.h" INFIX_PATCH_LINE REGEX "^#define INFIX_PATCH")
6+
7+
string(REGEX MATCH "[0-9]+" INFIX_MAJOR "${INFIX_MAJOR_LINE}")
8+
string(REGEX MATCH "[0-9]+" INFIX_MINOR "${INFIX_MINOR_LINE}")
9+
string(REGEX MATCH "[0-9]+" INFIX_PATCH "${INFIX_PATCH_LINE}")
10+
11+
project(infix VERSION ${INFIX_MAJOR}.${INFIX_MINOR}.${INFIX_PATCH} LANGUAGES C CXX)
412

513
# Set the C standard to C17 and make it a requirement.
614
set(CMAKE_C_STANDARD 17)
@@ -9,14 +17,20 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
917
# Use the standard GNUInstallDirs module to define portable installation paths.
1018
include(GNUInstallDirs)
1119

12-
# Add the static library target.
13-
# Since infix uses a unity build, we only need to specify the main infix.c file.
14-
add_library(infix STATIC src/infix.c)
20+
# Add the library target.
21+
# If BUILD_SHARED_LIBS is set to ON, this will generate a shared library.
22+
add_library(infix src/infix.c)
1523

1624
# Default to hidden visibility to avoid polluting the global symbol table
1725
# with internal functions (like _infix_set_error) when linked.
1826
set_target_properties(infix PROPERTIES C_VISIBILITY_PRESET hidden)
1927

28+
# If building as a shared library, define INFIX_BUILDING_DLL to export symbols on Windows.
29+
get_target_property(INFIX_TARGET_TYPE infix TYPE)
30+
if(INFIX_TARGET_TYPE STREQUAL "SHARED_LIBRARY")
31+
target_compile_definitions(infix PRIVATE INFIX_BUILDING_DLL)
32+
endif()
33+
2034
if(INFIX_DEBUG_ENABLED)
2135
target_compile_definitions(infix PRIVATE
2236
INFIX_DEBUG_ENABLED=1
@@ -78,6 +92,20 @@ function(add_infix_test test_name)
7892
target_sources("${test_name}" PRIVATE "fuzz/fuzz_helpers.c")
7993
target_include_directories("${test_name}" PRIVATE fuzz)
8094
endif()
95+
96+
# Special handling for 880_exports: Link against shared library if available
97+
if(test_name STREQUAL "880_exports")
98+
if(BUILD_SHARED_LIBS)
99+
# Force linkage against the shared library target
100+
target_link_libraries("${test_name}" PRIVATE infix)
101+
# Define INFIX_USING_DLL on Windows to ensure correct import
102+
if(WIN32)
103+
target_compile_definitions("${test_name}" PRIVATE INFIX_USING_DLL)
104+
endif()
105+
endif()
106+
# Enable exports from the executable so it can dlsym itself
107+
set_target_properties("${test_name}" PROPERTIES ENABLE_EXPORTS ON)
108+
endif()
81109

82110
target_compile_definitions(${test_name} PRIVATE
83111
DBLTAP_ENABLE=1
@@ -102,7 +130,7 @@ endfunction()
102130

103131
# Add all test targets using the helper function.
104132
# CONFIGURE_DEPENDS ensures CMake re-runs if you add/remove files in this directory.
105-
file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "t/*.c")
133+
file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "t/*.c" "t/*.cpp")
106134

107135
foreach(test_source ${TEST_SOURCES})
108136
# Extract the filename without the extension ("t/001_primitives.c" => "001_primitives")
@@ -113,7 +141,26 @@ foreach(test_source ${TEST_SOURCES})
113141
continue()
114142
endif()
115143

116-
add_infix_test("${test_name}")
144+
# The function add_infix_test assumes .c, but we now have .cpp.
145+
# Let's adjust the logic slightly or handle it here.
146+
# Since add_infix_test is a bit rigid, let's call add_executable directly for C++
147+
# or modify add_infix_test. For minimal changes, let's update add_infix_test to take source.
148+
149+
if (test_source MATCHES "\\.cpp$")
150+
# Manual handling for C++ test
151+
add_executable("${test_name}" "${test_source}")
152+
target_include_directories("${test_name}" PRIVATE "t/include" "${CMAKE_CURRENT_SOURCE_DIR}/src")
153+
target_link_libraries("${test_name}" PRIVATE infix)
154+
if(UNIX)
155+
target_link_libraries("${test_name}" PRIVATE m)
156+
endif()
157+
target_compile_definitions(${test_name} PRIVATE DBLTAP_ENABLE=1 INFIX_DEBUG_ENABLED=1)
158+
159+
# SIMD flags logic duplicated for C++... simpler to just assume standard flags or none for this compat test.
160+
add_test(NAME "${test_name}" COMMAND "${test_name}")
161+
else()
162+
add_infix_test("${test_name}")
163+
endif()
117164
endforeach()
118165

119166
# cmake -DINFIX_DEBUG_ENABLED=1 -B build ; cmake --build build ; ctest --test-dir build --rerun-failed --output-on-failure

Makefile

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55

66
CC := gcc
7+
CXX := g++
78
AR := ar
89
PERL := perl
910
ARFLAGS := rcs
@@ -64,38 +65,52 @@ ifeq ($(OS),Windows_NT)
6465
LIB_TARGET := libinfix.a
6566
LDFLAGS := -lkernel32
6667
CLEAN_CMD := del /F /Q
68+
EXPORT_FLAGS := -Wl,--export-all-symbols
69+
SO_EXT := dll
6770
else
6871
# Native POSIX (Linux, macOS, BSD) Configuration
6972
EXE_EXT :=
70-
LRT_FLAG := $(shell printf '#include <sys/mman.h>\n#include <fcntl.h>\nint main() { shm_open("", 0, 0); return 0; }' > .check_lrt.c; if $(CC) .check_lrt.c -o .check_lrt.out -lrt >/dev/null 2>&1; then printf -- "-lrt"; fi; rm -f .check_lrt.c .check_lrt.out)
73+
LRT_FLAG := $(shell printf '#include <sys/mman.h>\n#include <fcntl.h>\nint main() { shm_open(\"\", 0, 0); return 0; }' > .check_lrt.c; if $(CC) .check_lrt.c -o .check_lrt.out -lrt >/dev/null 2>&1; then printf -- "-lrt"; fi; rm -f .check_lrt.c .check_lrt.out)
7174
ifeq ($(LRT_FLAG),-lrt)
7275
$(info Linker check: -lrt is required and will be added.)
7376
endif
7477
LDFLAGS := -lpthread $(LRT_FLAG) -ldl
7578
LIB_TARGET := libinfix.a
7679
CLEAN_CMD := rm -f
80+
EXPORT_FLAGS := -rdynamic
81+
SO_EXT := so
7782
endif
7883

7984
# Finalize Source and Object Lists
8085
LIB_SRCS := $(BASE_SRCS)
8186
LIB_OBJS := $(LIB_SRCS:.c=.o)
87+
SHARED_LIB_OBJS := $(LIB_SRCS:.c=.shared.o)
8288

83-
TEST_SRCS := $(wildcard t/*.c)
84-
TEST_TARGETS:= $(patsubst %.c,%$(EXE_EXT),$(TEST_SRCS))
89+
TEST_SRCS := $(wildcard t/*.c) $(wildcard t/*.cpp)
90+
TEST_TARGETS:= $(patsubst t/%.c,t/%$(EXE_EXT),$(filter %.c,$(TEST_SRCS)))
91+
TEST_TARGETS+= $(patsubst t/%.cpp,t/%$(EXE_EXT),$(filter %.cpp,$(TEST_SRCS)))
8592

8693
# Target-Specific Variables for Special Test Cases
8794
# Define extra source files and flags needed ONLY for the regression test.
8895
t/850_regression_cases$(EXE_EXT)_EXTRA_SRCS := fuzz/fuzz_helpers.c
8996
t/850_regression_cases$(EXE_EXT)_EXTRA_CFLAGS := -Ifuzz
9097

98+
# 880_exports needs to export its own symbols to test dlsym(NULL)
99+
t/880_exports$(EXE_EXT)_EXTRA_LDFLAGS := $(EXPORT_FLAGS)
100+
91101
# Build Targets
92-
.PHONY: all test clean
102+
.PHONY: all test clean shared
93103

94104
# Default target: Build only the static library.
95105
all: $(LIB_TARGET)
96106
@echo
97107
@echo "Library '$(LIB_TARGET)' built successfully."
98108

109+
# Shared library target
110+
shared: libinfix.$(SO_EXT)
111+
@echo
112+
@echo "Shared Library 'libinfix.$(SO_EXT)' built successfully."
113+
99114
# Test target: Build all test executables, then run them using the embedded Perl script.
100115
test: $(TEST_TARGETS)
101116
@echo
@@ -107,22 +122,37 @@ $(LIB_TARGET): $(LIB_OBJS)
107122
@echo "AR $@"
108123
$(AR) $(ARFLAGS) $@ $^
109124

110-
# Generic pattern rule to build a test executable.
111-
# It uses automatic variables like `$@` (the target) and `$<` (the first prerequisite)
112-
# and also checks for our target-specific variables.
113-
$(TEST_TARGETS): %$(EXE_EXT): %.c $(LIB_TARGET)
125+
# Rule to build the shared library
126+
libinfix.$(SO_EXT): $(SHARED_LIB_OBJS)
114127
@echo "LD $@"
115-
$(CC) $(TEST_CFLAGS) $($(@)_EXTRA_CFLAGS) $< $($(@)_EXTRA_SRCS) -o $@ -L. -linfix $(LDFLAGS)
128+
$(CC) -shared -o $@ $^ $(LDFLAGS)
129+
130+
# Generic pattern rule to build a C test executable.
131+
t/%$(EXE_EXT): t/%.c $(LIB_TARGET)
132+
@echo "LD (C) $@"
133+
$(CC) $(TEST_CFLAGS) $($(@)_EXTRA_CFLAGS) $< $($(@)_EXTRA_SRCS) -o $@ -L. -linfix $(LDFLAGS) $($(@)_EXTRA_LDFLAGS)
134+
135+
# Generic pattern rule to build a C++ test executable.
136+
t/%$(EXE_EXT): t/%.cpp $(LIB_TARGET)
137+
@echo "LD (C++) $@"
138+
$(CXX) $(TEST_CFLAGS) $($(@)_EXTRA_CFLAGS) $< $($(@)_EXTRA_SRCS) -o $@ -L. -linfix $(LDFLAGS) $($(@)_EXTRA_LDFLAGS)
116139

117140
# Generic rule to compile library .c files to .o files, using LIB_CFLAGS
118141
%.o: %.c
119142
@echo "CC $<"
120143
$(CC) $(LIB_CFLAGS) -c $< -o $@
121144

145+
# Rule to compile for shared library (with -fPIC and -DINFIX_BUILDING_DLL)
146+
%.shared.o: %.c
147+
@echo "CC (Shared) $<"
148+
$(CC) $(LIB_CFLAGS) -fPIC -DINFIX_BUILDING_DLL -c $< -o $@
149+
122150
# Clean up build artifacts
123151
clean:
124152
@echo "CLEAN"
125-
-$(CLEAN_CMD) $(subst /,\,$(LIB_OBJS))
126-
-$(CLEAN_CMD) $(subst /,\,$(TEST_TARGETS))
127-
-$(CLEAN_CMD) $(subst /,\,$(LIB_TARGET))
153+
-$(CLEAN_CMD) $(subst /uyễn,uyễn,$(LIB_OBJS))
154+
-$(CLEAN_CMD) $(subst /uyễn,uyễn,$(SHARED_LIB_OBJS))
155+
-$(CLEAN_CMD) $(subst /uyễn,uyễn,$(TEST_TARGETS))
156+
-$(CLEAN_CMD) $(subst /uyễn,uyễn,$(LIB_TARGET))
157+
-$(CLEAN_CMD) libinfix.so libinfix.dll infix.dll infix.lib infix.exp
128158
-rm -f .check_lrt.out

Makefile.win

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,25 @@ LIB_OBJECTS = $(OBJ_DIR)\infix.obj
3030
# --- Main Targets ---
3131
all: $(OBJ_DIR)\$(LIB_NAME)
3232

33+
shared: $(OBJ_DIR)\infix.dll
34+
3335
# --- Build Rules ---
3436

3537
# Rule to create the static library from its object files.
3638
$(OBJ_DIR)\$(LIB_NAME): $(LIB_OBJECTS)
3739
@echo AR $@
3840
$(LIB) /OUT:$@ $(LIB_OBJECTS)
3941

42+
# Rule to create the dynamic library (DLL).
43+
$(OBJ_DIR)\infix.dll: $(LIB_OBJECTS)
44+
@echo LD $@
45+
$(CC) /LD /Fe$@ $(LIB_OBJECTS) /link /DLL
46+
4047
# Inference Rule to build .obj files from .c files found in the core source directory.
4148
{$(SRC_DIR)}.c{$(OBJ_DIR)}.obj:
4249
@if not exist $(OBJ_DIR) mkdir $(OBJ_DIR)
4350
@echo CC $**
44-
$(CC) $(CFLAGS) /c $** /Fo$@
51+
$(CC) $(CFLAGS) /DINFIX_BUILDING_DLL /c $** /Fo$@
4552

4653
# --- Cleanup ---
4754
clean:

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ The easiest way to use `infix` is to add its source directly to your project.
137137
3. Add the `include/` directory to your include paths.
138138
4. `#include <infix/infix.h>` in your code.
139139
140+
> **Note:** If you are linking against `infix` as a shared library (DLL) on Windows, you must define `INFIX_USING_DLL` in your project settings. See the [Installation Guide](docs/INSTALL.md) for details.
141+
140142
For more advanced build options, including building as a standalone library with CMake or xmake, see the [Building and Integration Guide](docs/INSTALL.md).
141143
142144
## Project Philosophy

SECURITY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Security updates are provided for the latest public release. As this is a pre-1.
1010

1111
| Version | Supported |
1212
| ------------- | ------------------ |
13-
| >= 0.1.0 | :white_check_mark: |
14-
| < 0.1.0 | :x: |
13+
| >= 0.1.3 | :white_check_mark: |
14+
| < 0.1.3 | :x: |
1515
| [unversioned] | :white_check_mark: |
1616

1717
## Reporting a Vulnerability

0 commit comments

Comments
 (0)