Skip to content

Commit ee02bb9

Browse files
committed
feat: library for nginx auto/configure integration
A new file, `examples/auto/rust`, can be used in the module projects to simplify the build and hide most of the platform-specific details. `examples/config` and `examples/config.make` are reimplemented using the library.
1 parent c89f77c commit ee02bb9

File tree

3 files changed

+324
-99
lines changed

3 files changed

+324
-99
lines changed

examples/auto/rust

+288
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
#!/bin/sh
2+
#
3+
# Utility library for integration of ngx-rust modules into the NGINX build
4+
# configuration.
5+
#
6+
# Usage:
7+
#
8+
# In "config",
9+
#
10+
# ```sh
11+
# . $ngx_addon_dir/auto/rust
12+
#
13+
# # ngx_addon_name determines the build directory and should be set before
14+
# # any modules are defined
15+
#
16+
# ngx_addon_name="example"
17+
#
18+
# if [ $HTTP = YES ]; then
19+
# # Regular NGINX module options,
20+
# # http://nginx.org/en/docs/dev/development_guide.html#adding_new_modules
21+
#
22+
# ngx_module_type=HTTP
23+
# # Should match the "ngx_module_t" static name(s) exported from the Rust code
24+
# ngx_module_name=ngx_http_example_module
25+
# ngx_module_incs=
26+
# ngx_module_deps=
27+
# ngx_module_libs=
28+
#
29+
# # Options for ngx-rust modules
30+
#
31+
# # Target type: LIB or EXAMPLE
32+
# ngx_rust_target_type=LIB
33+
#
34+
# # Target name: crate name, lib.name or example.name
35+
# ngx_rust_target_name=example
36+
#
37+
# # Space-separated list of cargo features
38+
# # "default" should be specified explicitly if required
39+
# ngx_rust_target_features=
40+
#
41+
# ngx_rust_module
42+
# fi
43+
# ```
44+
#
45+
# In "config.make",
46+
#
47+
# ```sh
48+
# ngx_addon_name="example"
49+
# ngx_cargo_manifest=$ngx_addon_dir/Cargo.toml
50+
#
51+
# # generate Makefile section for all the modules configured earlier
52+
#
53+
# ngx_rust_make_modules
54+
# ```
55+
56+
# Prevent duplicate invocation unless it is a newer library version
57+
if [ "${NGX_RUST_AUTO_VER:-0}" -ge 1 ]; then
58+
return
59+
fi
60+
61+
NGX_RUST_AUTO_VER=1
62+
63+
echo $ngx_n "checking for Rust toolchain ...$ngx_c"
64+
65+
NGX_CARGO=${NGX_CARGO:-cargo}
66+
67+
NGX_RUST_VER=$($NGX_CARGO version 2>&1 \
68+
| grep 'cargo 1\.[0-9][0-9]*\.[0-9]*' 2>&1 \
69+
| sed -e 's/^.* \(1\.[0-9][0-9]*\.[0-9][0.9]*.*\)/\1/')
70+
71+
NGX_RUST_VERSION=${NGX_RUST_VER%% *}
72+
73+
if [ -z "$NGX_RUST_VERSION" ]; then
74+
echo " not found"
75+
echo
76+
echo $0: error: cargo binary $NGX_CARGO is not found
77+
echo
78+
exit 1
79+
fi
80+
81+
echo " found"
82+
echo " + Rust version: $NGX_RUST_VER"
83+
84+
ngx_rust_prefix=lib
85+
ngx_rust_libext=.a
86+
87+
case "$NGX_MACHINE" in
88+
89+
amd64)
90+
RUST_TARGET_ARCH=x86_64
91+
;;
92+
93+
arm64)
94+
RUST_TARGET_ARCH=aarch64
95+
;;
96+
97+
i?86)
98+
RUST_TARGET_ARCH=i686
99+
;;
100+
101+
*)
102+
RUST_TARGET_ARCH=$NGX_MACHINE
103+
;;
104+
105+
esac
106+
107+
case "$NGX_PLATFORM" in
108+
109+
OpenBSD:*)
110+
# ld: error: undefined symbol: _Unwind_...
111+
RUST_LIBS="$RUST_LIBS -lutil"
112+
RUST_LIBS="$RUST_LIBS -lexecinfo"
113+
RUST_LIBS="$RUST_LIBS -lc++abi"
114+
;;
115+
116+
win32)
117+
case "$NGX_CC_NAME" in
118+
119+
msvc)
120+
ngx_rust_prefix=
121+
ngx_rust_libext=.lib
122+
123+
# as suggested by rustc --print native-static-libs,
124+
# excluding entries already present in CORE_LIBS
125+
RUST_LIBS="$RUST_LIBS bcrypt.lib" # ???
126+
RUST_LIBS="$RUST_LIBS ntdll.lib" # std::io, std::sys::pal::windows
127+
RUST_LIBS="$RUST_LIBS userenv.lib" # std::env::home_dir
128+
RUST_LIBS="$RUST_LIBS dbghelp.lib" # backtrace symbolization
129+
130+
RUST_TARGET=$RUST_TARGET_ARCH-pc-windows-msvc
131+
;;
132+
133+
gcc | clang)
134+
RUST_LIBS="$RUST_LIBS -lbcrypt"
135+
RUST_LIBS="$RUST_LIBS -lntdll"
136+
RUST_LIBS="$RUST_LIBS -luserenv"
137+
RUST_LIBS="$RUST_LIBS -ldbghelp"
138+
# gnullvm on arm64?
139+
RUST_TARGET=$RUST_TARGET_ARCH-pc-windows-gnu
140+
;;
141+
142+
esac
143+
;;
144+
145+
esac
146+
147+
148+
# Prepare cargo configuration file
149+
150+
if [ "$NGX_DEBUG" = YES ]; then
151+
ngx_cargo_default_profile=ngx-debug
152+
else
153+
ngx_cargo_default_profile=ngx-release
154+
fi
155+
156+
ngx_cargo_config=$NGX_OBJS/.cargo/config.toml
157+
ngx_cargo_profile=${ngx_cargo_profile:-$ngx_cargo_default_profile}
158+
159+
mkdir -p "$NGX_OBJS/.cargo"
160+
161+
cat << END > "$ngx_cargo_config"
162+
163+
[profile.ngx-debug]
164+
inherits = "dev"
165+
166+
[profile.ngx-release]
167+
inherits = "release"
168+
lto = "thin"
169+
strip = "none"
170+
171+
# compatibility with LIBC=-MT set in auto/cc/msvc
172+
[target.aarch64-pc-windows-msvc]
173+
rustflags = ["-C", "target-feature=+crt-static"]
174+
175+
[target.i686-pc-windows-msvc]
176+
rustflags = ["-C", "target-feature=+crt-static"]
177+
178+
[target.x86_64-pc-windows-msvc]
179+
rustflags = ["-C", "target-feature=+crt-static"]
180+
181+
[env]
182+
NGX_OBJS = { value = ".", force = true, relative = true }
183+
END
184+
185+
if [ "$NGX_PLATFORM" == win32 ] && command -v cygpath >/dev/null; then
186+
printf >> "$ngx_cargo_config" 'NGINX_SOURCE_DIR = "%s"\n' \
187+
"$(cygpath -m "$PWD")"
188+
else
189+
printf >> "$ngx_cargo_config" 'NGINX_SOURCE_DIR = "%s"\n' "$PWD"
190+
fi
191+
192+
193+
# Reconstructs path to a static lib built with cargo rustc,
194+
# relative to the --target-dir
195+
196+
ngx_rust_target_path () {
197+
ngx_rust_obj=$(echo "$ngx_rust_target_name" | tr - _)
198+
199+
if [ "$ngx_rust_target_type" = EXAMPLE ]; then
200+
ngx_rust_obj=examples/$ngx_rust_prefix$ngx_rust_obj$ngx_rust_libext
201+
else
202+
ngx_rust_obj=$ngx_rust_prefix$ngx_rust_obj$ngx_rust_libext
203+
fi
204+
205+
echo "${RUST_TARGET:+$RUST_TARGET/}$ngx_cargo_profile/$ngx_rust_obj"
206+
}
207+
208+
209+
# Registers a module in the buildsystem.
210+
# Expects two variables to be set:
211+
#
212+
# ngx_rust_target_type=LIB|EXAMPLE
213+
# ngx_rust_target_name=<library or example name[^1]>
214+
#
215+
# [^1]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-name-field)
216+
217+
ngx_rust_module () {
218+
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
219+
ngx_rust_target_name=${ngx_rust_target_name:-ngx_module_name}
220+
ngx_rust_obj=$NGX_OBJS/$ngx_addon_id/$(ngx_rust_target_path)
221+
222+
ngx_module_deps="$ngx_rust_obj $ngx_module_deps"
223+
ngx_module_libs="$ngx_rust_obj $ngx_module_libs $RUST_LIBS"
224+
225+
# Module deps are usually added to the object file targets, but we don't have any
226+
LINK_DEPS="$LINK_DEPS $ngx_rust_obj"
227+
228+
eval ${ngx_addon_id}_MODULES=\"\$${ngx_addon_id}_MODULES \
229+
$ngx_rust_target_type:$ngx_rust_target_name\"
230+
231+
if [ -n "$ngx_rust_target_features" ]; then
232+
eval ${ngx_addon_id}_FEATURES=\"\$${ngx_addon_id}_FEATURES \
233+
$ngx_rust_target_features\"
234+
fi
235+
236+
. auto/module
237+
}
238+
239+
240+
# Writes a Makefile fragment for all the modules configured for "ngx_addon_name"
241+
242+
ngx_rust_make_modules () {
243+
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
244+
ngx_cargo_manifest=${ngx_cargo_manifest:-"$ngx_addon_dir/Cargo.toml"}
245+
246+
eval ngx_rust_features="\$${ngx_addon_id}_FEATURES"
247+
eval ngx_rust_modules="\$${ngx_addon_id}_MODULES"
248+
249+
for module in $ngx_rust_modules; do
250+
ngx_rust_target_type=${module%%:*}
251+
ngx_rust_target_name=${module#*:}
252+
253+
ngx_rust_make_module
254+
done
255+
}
256+
257+
258+
# Writes a Makefile fragment for a single module specified by
259+
# "ngx_addon_name", "ngx_rust_target_type" and "ngx_rust_target_name"
260+
261+
ngx_rust_make_module () {
262+
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
263+
ngx_rust_obj=$NGX_OBJS/$ngx_addon_id/$(ngx_rust_target_path)
264+
265+
ngx_rustc_module_opt=
266+
if [ "$ngx_rust_target_type" = EXAMPLE ]; then
267+
ngx_rustc_module_opt="--example $ngx_rust_target_name"
268+
fi
269+
270+
cat << END >> $NGX_MAKEFILE
271+
272+
# always run cargo instead of trying to track the source modifications
273+
.PHONY: $ngx_rust_obj
274+
275+
$ngx_rust_obj:
276+
$NGX_CARGO rustc \\
277+
--config $ngx_cargo_config \\
278+
--crate-type staticlib \\
279+
--manifest-path "$ngx_cargo_manifest" \\
280+
--no-default-features \\
281+
--profile $ngx_cargo_profile \\
282+
${RUST_TARGET:+--target $RUST_TARGET} \\
283+
--target-dir $NGX_OBJS/$ngx_addon_id \\
284+
--features "$ngx_rust_features" \\
285+
$ngx_rustc_module_opt $NGX_RUSTC_OPT
286+
287+
END
288+
}

0 commit comments

Comments
 (0)