Skip to content

Commit 7abcb32

Browse files
committed
feat: Add ZRTL plugin build scripts and staticlib support
- Add build_zrtl.sh for generating .zrtl dynamic libraries - Add build_static.sh for arch-dependent static libraries (.a files) - Scripts auto-discover plugins from subdirectories - Extract versions from each plugin's Cargo.toml for manifests - Add staticlib crate-type to all plugins for AOT linking support
1 parent 046b564 commit 7abcb32

8 files changed

Lines changed: 541 additions & 6 deletions

File tree

plugins/build_static.sh

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
#!/bin/bash
2+
#
3+
# ZRTL Static Library Build Script
4+
#
5+
# Builds architecture-dependent static libraries (.a files) for AOT static linking.
6+
# Supports cross-compilation for multiple architectures.
7+
#
8+
# Plugins are automatically discovered from the workspace Cargo.toml.
9+
#
10+
# Usage:
11+
# ./build_static.sh # Build for host architecture
12+
# ./build_static.sh --all # Build for all supported targets
13+
# ./build_static.sh --target aarch64-apple-darwin
14+
# ./build_static.sh --release --output lib/
15+
16+
set -e
17+
18+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19+
PLUGINS_DIR="$SCRIPT_DIR"
20+
cd "$PLUGINS_DIR"
21+
22+
# Default values
23+
PROFILE="release" # Static libs are usually release
24+
OUTPUT_DIR="$SCRIPT_DIR/target/static"
25+
BUILD_ALL=false
26+
TARGETS=()
27+
28+
# Supported targets for cross-compilation
29+
SUPPORTED_TARGETS=(
30+
# macOS
31+
"x86_64-apple-darwin"
32+
"aarch64-apple-darwin"
33+
# Linux
34+
"x86_64-unknown-linux-gnu"
35+
"aarch64-unknown-linux-gnu"
36+
"x86_64-unknown-linux-musl"
37+
"aarch64-unknown-linux-musl"
38+
# Windows
39+
"x86_64-pc-windows-gnu"
40+
"x86_64-pc-windows-msvc"
41+
)
42+
43+
# Parse arguments
44+
while [[ $# -gt 0 ]]; do
45+
case $1 in
46+
--release)
47+
PROFILE="release"
48+
shift
49+
;;
50+
--debug)
51+
PROFILE="debug"
52+
shift
53+
;;
54+
--output)
55+
OUTPUT_DIR="$2"
56+
shift 2
57+
;;
58+
--target)
59+
TARGETS+=("$2")
60+
shift 2
61+
;;
62+
--all)
63+
BUILD_ALL=true
64+
shift
65+
;;
66+
--list-targets)
67+
echo "Supported targets:"
68+
for t in "${SUPPORTED_TARGETS[@]}"; do
69+
echo " $t"
70+
done
71+
exit 0
72+
;;
73+
--help|-h)
74+
echo "Usage: $0 [OPTIONS]"
75+
echo ""
76+
echo "Options:"
77+
echo " --release Build in release mode (default)"
78+
echo " --debug Build in debug mode"
79+
echo " --output dir Output directory (default: target/static)"
80+
echo " --target TARGET Build for specific target (can be repeated)"
81+
echo " --all Build for all supported targets"
82+
echo " --list-targets List all supported cross-compilation targets"
83+
echo ""
84+
echo "Plugins are auto-discovered from subdirectories"
85+
echo ""
86+
echo "Examples:"
87+
echo " $0 # Build for host"
88+
echo " $0 --target aarch64-apple-darwin # Build for Apple Silicon"
89+
echo " $0 --target x86_64-unknown-linux-musl # Build for Linux musl"
90+
echo " $0 --all # Build all targets"
91+
exit 0
92+
;;
93+
*)
94+
echo "Unknown option: $1"
95+
exit 1
96+
;;
97+
esac
98+
done
99+
100+
# Discover plugins - subdirectories in the plugins directory with a Cargo.toml
101+
discover_plugins() {
102+
for dir in "$PLUGINS_DIR"/*/; do
103+
dir="${dir%/}"
104+
name="$(basename "$dir")"
105+
if [ -f "$dir/Cargo.toml" ]; then
106+
echo "$name"
107+
fi
108+
done | sort
109+
}
110+
111+
# Get version from a plugin's Cargo.toml
112+
get_plugin_version() {
113+
local plugin=$1
114+
grep -E '^version\s*=' "$PLUGINS_DIR/$plugin/Cargo.toml" 2>/dev/null | head -1 | sed 's/.*"\([^"]*\)".*/\1/'
115+
}
116+
117+
# Discover plugins
118+
PLUGINS=($(discover_plugins))
119+
120+
if [ ${#PLUGINS[@]} -eq 0 ]; then
121+
echo "Error: No plugins found"
122+
exit 1
123+
fi
124+
125+
# If no targets specified and not building all, use host target
126+
if [ ${#TARGETS[@]} -eq 0 ] && [ "$BUILD_ALL" = false ]; then
127+
HOST_TARGET=$(rustc -vV | grep host | cut -d' ' -f2)
128+
TARGETS=("$HOST_TARGET")
129+
fi
130+
131+
# If building all, use supported targets
132+
if [ "$BUILD_ALL" = true ]; then
133+
TARGETS=("${SUPPORTED_TARGETS[@]}")
134+
fi
135+
136+
echo "======================================"
137+
echo "ZRTL Static Library Builder"
138+
echo "======================================"
139+
echo "Profile: $PROFILE"
140+
echo "Output: $OUTPUT_DIR"
141+
echo "Discovered ${#PLUGINS[@]} plugins: ${PLUGINS[*]}"
142+
echo "Targets: ${TARGETS[*]}"
143+
echo ""
144+
145+
# Create base output directory
146+
mkdir -p "$OUTPUT_DIR"
147+
148+
# Build flags
149+
BUILD_FLAGS=""
150+
if [ "$PROFILE" = "release" ]; then
151+
BUILD_FLAGS="--release"
152+
fi
153+
154+
# Function to check if target is installed
155+
check_target() {
156+
local target=$1
157+
if ! rustup target list --installed | grep -q "^$target$"; then
158+
echo " Installing target: $target"
159+
rustup target add "$target" 2>/dev/null || {
160+
echo " Warning: Failed to install target $target, skipping..."
161+
return 1
162+
}
163+
fi
164+
return 0
165+
}
166+
167+
# Function to get static lib name
168+
get_staticlib_name() {
169+
local plugin=$1
170+
local target=$2
171+
172+
case "$target" in
173+
*-windows-*)
174+
echo "${plugin}.lib"
175+
;;
176+
*)
177+
echo "lib${plugin}.a"
178+
;;
179+
esac
180+
}
181+
182+
# Build for each target
183+
for target in "${TARGETS[@]}"; do
184+
echo "======================================"
185+
echo "Building for: $target"
186+
echo "======================================"
187+
188+
# Check/install target
189+
if ! check_target "$target"; then
190+
continue
191+
fi
192+
193+
# Create target-specific output directory
194+
TARGET_OUTPUT="$OUTPUT_DIR/$target"
195+
mkdir -p "$TARGET_OUTPUT"
196+
197+
# Build each plugin
198+
for plugin in "${PLUGINS[@]}"; do
199+
echo " Building $plugin..."
200+
201+
# Build as staticlib (need to modify Cargo.toml or use RUSTFLAGS)
202+
RUSTFLAGS="-C target-feature=+crt-static" \
203+
cargo build -p "$plugin" $BUILD_FLAGS --target "$target" 2>&1 | grep -v "^ Compiling" || true
204+
205+
# Source path - static lib is in deps directory
206+
src_dir="$SCRIPT_DIR/target/$target/$PROFILE"
207+
lib_name=$(get_staticlib_name "$plugin" "$target")
208+
209+
# Try to find the static lib (might be in deps/)
210+
src="$src_dir/$lib_name"
211+
if [ ! -f "$src" ]; then
212+
src="$src_dir/deps/$lib_name"
213+
fi
214+
if [ ! -f "$src" ]; then
215+
# Try without lib prefix
216+
src="$src_dir/${plugin}.a"
217+
fi
218+
if [ ! -f "$src" ]; then
219+
src="$src_dir/deps/${plugin}.a"
220+
fi
221+
222+
# For rlib (Rust library format)
223+
rlib="$src_dir/lib${plugin}.rlib"
224+
if [ ! -f "$src" ] && [ -f "$rlib" ]; then
225+
src="$rlib"
226+
lib_name="lib${plugin}.rlib"
227+
fi
228+
229+
# Destination
230+
dst="$TARGET_OUTPUT/$lib_name"
231+
232+
if [ -f "$src" ]; then
233+
cp "$src" "$dst"
234+
size=$(ls -lh "$dst" | awk '{print $5}')
235+
echo " -> $lib_name ($size)"
236+
else
237+
echo " Warning: Static lib not found for $plugin"
238+
echo " Searched: $src_dir/{,deps/}lib${plugin}.{a,rlib}"
239+
fi
240+
done
241+
242+
# Create archive manifest for this target
243+
MANIFEST="$TARGET_OUTPUT/libs.json"
244+
cat > "$MANIFEST" << EOF
245+
{
246+
"target": "$target",
247+
"profile": "$PROFILE",
248+
"libs": [
249+
EOF
250+
251+
first=true
252+
for plugin in "${PLUGINS[@]}"; do
253+
lib_name=$(get_staticlib_name "$plugin" "$target")
254+
lib_file="$TARGET_OUTPUT/$lib_name"
255+
256+
# Also check for rlib
257+
if [ ! -f "$lib_file" ]; then
258+
lib_name="lib${plugin}.rlib"
259+
lib_file="$TARGET_OUTPUT/$lib_name"
260+
fi
261+
262+
if [ -f "$lib_file" ]; then
263+
size=$(stat -f%z "$lib_file" 2>/dev/null || stat -c%s "$lib_file" 2>/dev/null || echo "0")
264+
version=$(get_plugin_version "$plugin")
265+
266+
if [ "$first" = true ]; then
267+
first=false
268+
else
269+
echo "," >> "$MANIFEST"
270+
fi
271+
272+
cat >> "$MANIFEST" << EOF
273+
{
274+
"name": "$plugin",
275+
"version": "$version",
276+
"file": "$lib_name",
277+
"size": $size
278+
}
279+
EOF
280+
fi
281+
done
282+
283+
cat >> "$MANIFEST" << 'EOF'
284+
]
285+
}
286+
EOF
287+
288+
echo ""
289+
done
290+
291+
# Generate combined manifest
292+
COMBINED_MANIFEST="$OUTPUT_DIR/manifest.json"
293+
echo "Generating combined manifest..."
294+
295+
cat > "$COMBINED_MANIFEST" << 'EOF'
296+
{
297+
"type": "static",
298+
"targets": [
299+
EOF
300+
301+
first_target=true
302+
for target in "${TARGETS[@]}"; do
303+
TARGET_OUTPUT="$OUTPUT_DIR/$target"
304+
if [ -d "$TARGET_OUTPUT" ]; then
305+
if [ "$first_target" = true ]; then
306+
first_target=false
307+
else
308+
echo "," >> "$COMBINED_MANIFEST"
309+
fi
310+
echo " \"$target\"" >> "$COMBINED_MANIFEST"
311+
fi
312+
done
313+
314+
cat >> "$COMBINED_MANIFEST" << 'EOF'
315+
],
316+
"plugins": [
317+
EOF
318+
319+
first_plugin=true
320+
for plugin in "${PLUGINS[@]}"; do
321+
version=$(get_plugin_version "$plugin")
322+
if [ "$first_plugin" = true ]; then
323+
first_plugin=false
324+
else
325+
echo "," >> "$COMBINED_MANIFEST"
326+
fi
327+
cat >> "$COMBINED_MANIFEST" << EOF
328+
{
329+
"name": "$plugin",
330+
"version": "$version"
331+
}
332+
EOF
333+
done
334+
335+
cat >> "$COMBINED_MANIFEST" << 'EOF'
336+
]
337+
}
338+
EOF
339+
340+
echo ""
341+
echo "======================================"
342+
echo "Build complete!"
343+
echo "======================================"
344+
echo "Output directory: $OUTPUT_DIR"
345+
echo ""
346+
echo "Directory structure:"
347+
find "$OUTPUT_DIR" -type f -name "*.a" -o -name "*.rlib" -o -name "*.lib" -o -name "*.json" 2>/dev/null | head -30

0 commit comments

Comments
 (0)