Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform support and auto scripts improvements #124

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ alloc = []
# Currently the only difference to `alloc` flag is `std::error::Error` implementation.
std = ["alloc"]
# Build our own copy of the NGINX by default.
# This could be disabled with `--no-default-features` to minimize the dependency tree
# when building against an existing copy of the NGINX with the NGX_OBJS variable.
# This could be disabled with `--no-default-features` to minimize the dependency
# tree when building against an existing copy of the NGINX with the
# NGINX_SOURCE_DIR/NGINX_BUILD_DIR variables.
vendored = ["nginx-sys/vendored"]

[badges]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ For example (all examples plus linux specific):
### Build with external NGINX source tree

If you require a customized NGINX configuration, you can build a module against an existing pre-configured source tree.
To do that, you need to set the `NGX_OBJS` variable to an _absolute_ path of the NGINX build directory (`--builddir`, defaults to the `objs` in the source directory).
To do that, you need to set the `NGINX_BUILD_DIR` variable to an _absolute_ path of the NGINX build directory (`--builddir`, defaults to the `objs` in the source directory).
Only the `./configure` step of the NGINX build is mandatory because bindings don't depend on any of the artifacts generated by `make`.


```
NGX_OBJS=$PWD/../nginx/objs cargo build --package=examples --examples
NGINX_BUILD_DIR=$PWD/../nginx/objs cargo build --package=examples --examples

```

Expand Down
313 changes: 313 additions & 0 deletions examples/auto/rust
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
#!/bin/sh
#
# Copyright 2025 Nginx, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Utility library for integration of ngx-rust modules into the NGINX build
# configuration.
#
# Usage:
#
# In "config",
#
# ```sh
# . $ngx_addon_dir/auto/rust
#
# # ngx_addon_name determines the build directory and should be set before
# # any modules are defined
#
# ngx_addon_name="example"
#
# if [ $HTTP = YES ]; then
# # Regular NGINX module options,
# # http://nginx.org/en/docs/dev/development_guide.html#adding_new_modules
#
# ngx_module_type=HTTP
# # Should match the "ngx_module_t" static name(s) exported from the Rust code
# ngx_module_name=ngx_http_example_module
# ngx_module_incs=
# ngx_module_deps=
# ngx_module_libs=
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about it a bit more, I agree that ngx_rust_ prefix for auto/module variables make the script more complicated.

Closing this remark.

#
# # Options for ngx-rust modules
#
# # Target type: LIB or EXAMPLE
# ngx_rust_target_type=LIB
#
# # Target name: crate name, lib.name or example.name
# ngx_rust_target_name=example
#
# # Whitespace-separated list of cargo features.
# # "default" should be specified explicitly if required.
# ngx_rust_target_features=
#
# ngx_rust_module
# fi
# ```
#
# In "config.make",
#
# ```sh
# ngx_addon_name="example"
# ngx_cargo_manifest=$ngx_addon_dir/Cargo.toml
#
# # generate Makefile section for all the modules configured earlier
#
# ngx_rust_make_modules
# ```

# Prevent duplicate invocation unless it is a newer library version
if [ "${NGX_RUST_AUTO_VER:-0}" -ge 1 ]; then
return
fi

NGX_RUST_AUTO_VER=1

echo $ngx_n "checking for Rust toolchain ...$ngx_c"

NGX_CARGO=${NGX_CARGO:-cargo}

NGX_RUST_VER=$($NGX_CARGO version 2>&1 \
| grep 'cargo 1\.[0-9][0-9]*\.[0-9]*' 2>&1 \
| sed -e 's/^.* \(1\.[0-9][0-9]*\.[0-9][0.9]*.*\)/\1/')

NGX_RUST_VERSION=${NGX_RUST_VER%% *}

if [ -z "$NGX_RUST_VERSION" ]; then
echo " not found"
echo
echo $0: error: cargo binary $NGX_CARGO is not found
echo
exit 1
fi

echo " found"
echo " + Rust version: $NGX_RUST_VER"

case "$NGX_MACHINE" in

amd64)
RUST_TARGET_ARCH=x86_64
;;

arm64)
RUST_TARGET_ARCH=aarch64
;;

i?86)
RUST_TARGET_ARCH=i686
;;

*)
RUST_TARGET_ARCH=$NGX_MACHINE
;;

esac

case "$NGX_PLATFORM" in

OpenBSD:*)
# ld: error: undefined symbol: _Unwind_...
RUST_LIBS="$RUST_LIBS -lutil"
RUST_LIBS="$RUST_LIBS -lexecinfo"
RUST_LIBS="$RUST_LIBS -lc++abi"
;;

win32)
case "$NGX_CC_NAME" in

msvc)
# as suggested by rustc --print native-static-libs,
# excluding entries already present in CORE_LIBS
RUST_LIBS="$RUST_LIBS bcrypt.lib" # ???
RUST_LIBS="$RUST_LIBS ntdll.lib" # std::io, std::sys::pal::windows
RUST_LIBS="$RUST_LIBS userenv.lib" # std::env::home_dir
RUST_LIBS="$RUST_LIBS dbghelp.lib" # backtrace symbolization

RUST_TARGET=$RUST_TARGET_ARCH-pc-windows-msvc
;;

gcc | clang)
RUST_LIBS="$RUST_LIBS -lbcrypt"
RUST_LIBS="$RUST_LIBS -lntdll"
RUST_LIBS="$RUST_LIBS -luserenv"
RUST_LIBS="$RUST_LIBS -ldbghelp"
# gnullvm on arm64?
RUST_TARGET=$RUST_TARGET_ARCH-pc-windows-gnu
;;

esac
;;

esac


# Prepare cargo configuration file

if [ "$NGX_DEBUG" = YES ]; then
ngx_cargo_default_profile=ngx-debug
else
ngx_cargo_default_profile=ngx-release
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When building without --with-debug I get

...
objs/ngx_modules.o \                                                                                                                              
-L/media/psf/workspace/nginx/nginScript/quickjs-ng/build -lpthread -lcrypt objs/ngx_rust_examples/ngx-release/examples/libawssig.a -lm objs/ngx_ru
st_examples/ngx-release/examples/libcurl.a objs/ngx_rust_examples/ngx-release/examples/libupstream.a objs/ngx_rust_examples/ngx-release/examples/l
ibhttporigdst.a -lpcre2-8 -lssl -lcrypto -lpthread -lz \                                                                                          
-Wl,-E                                                                                                                                            
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::num::from_str_radix_panic_rt':                                                                                        
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/num/mod.rs:1399: multiple definition of `core::num::from_str_radix_panic_rt'; obj
s/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.rcgu.o):/rus
tc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/num/mod.rs:1399: first defined here                                                  
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `...                                                                                                                         
u.0.rcgu.o.rcgu.o): in function `core::fmt::num::<impl core::fmt::LowerHex for i8>::fmt':                                                         
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::<impl core::fmt::UpperHex for i8>::fmt':                                                                    
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: multiple definition of `core::fmt::num::<impl core::fmt::UpperHex
 for u8>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.
rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: first defined here                                
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt':                                                               
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:313: multiple definition of `core::fmt::num::imp::<impl core::fmt::Dis
play for usize>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf
-cgu.0.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:313: first defined here                         
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::Formatter::write_str':                                                                                           
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/mod.rs:1625: multiple definition of `<core::fmt::Formatter as core::fmt::Writ
e>::write_str'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.
rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/mod.rs:1625: first defined here                               
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::<impl core::fmt::LowerHex for i64>::fmt':                                                                   
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: multiple definition of `core::fmt::num::<impl core::fmt::LowerHex
 for usize>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu
.0.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: first defined here                             
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::<impl core::fmt::UpperHex for i64>::fmt':                                                                   
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: multiple definition of `core::fmt::num::<impl core::fmt::UpperHex
 for usize>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu
.0.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: first defined here                             
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::<impl core::fmt::LowerHex for i64>::fmt':                                                                   
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: multiple definition of `core::fmt::num::<impl core::fmt::LowerHex
 for u64>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0
.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: first defined here                               
/usr/bin/ld: objs/ngx_rust_examples/ngx-release/examples/libcurl.a(curl-de3e6fe882b906f0.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.
rcgu.o): in function `core::fmt::num::<impl core::fmt::UpperHex for i64>::fmt':                                                                   
/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: multiple definition of `core::fmt::num::<impl core::fmt::UpperHex
 for u64>::fmt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0
.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/num.rs:155: first defined here                               
collect2: error: ld returned 1 exit status                                                                                                        
make[1]: *** [objs/Makefile:310: objs/nginx] Error 1                                                                                              
make[1]: Leaving directory '/media/psf/workspace/nginx/nginx'                                                                                     
make: *** [Makefile:10: build] Error 2                                                                                                            
(747 of 929): multiple definition of `core::num::from_str_radix_panic_rt'; objs/ngx_rust_examples/ngx-release/examples/libawssig.a(awssig-22b3aae1
e52dce40.core-f5a882967048065e.core.ecb3f420ec5f4bcf-cgu.0.rcgu.o.rcgu.o):/rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/num/mod
.rs:1399: first defined here   

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing lto = "thin" from profile.ngx-release solves the issue.

fi

ngx_cargo_config=$NGX_OBJS/.cargo/config.toml
ngx_cargo_profile=${ngx_cargo_profile:-$ngx_cargo_default_profile}

mkdir -p "$NGX_OBJS/.cargo"

cat << END > "$ngx_cargo_config"

[profile.ngx-debug]
inherits = "dev"

[profile.ngx-release]
inherits = "release"
lto = "thin"
strip = "none"

# compatibility with LIBC=-MT set in auto/cc/msvc
[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

[target.i686-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

[env]
NGINX_BUILD_DIR = { value = ".", force = true, relative = true }
END

if [ "$NGX_PLATFORM" = win32 ] && command -v cygpath >/dev/null; then
printf >> "$ngx_cargo_config" 'NGINX_SOURCE_DIR = "%s"\n' \
"$(cygpath -m "$PWD")"
else
printf >> "$ngx_cargo_config" 'NGINX_SOURCE_DIR = "%s"\n' "$PWD"
fi


# Reconstructs path to a static lib built with cargo rustc,
# relative to the --target-dir

ngx_rust_target_path () {
ngx_rust_obj=$(echo "$ngx_rust_target_name" | tr - _)

case "$NGX_CC_NAME" in

msvc)
ngx_rust_obj=${ngx_rust_obj}.lib
;;

*)
ngx_rust_obj=lib${ngx_rust_obj}.a
;;

esac

if [ "$ngx_rust_target_type" = EXAMPLE ]; then
ngx_rust_obj=examples/$ngx_rust_obj
fi

echo "${RUST_TARGET:+$RUST_TARGET/}$ngx_cargo_profile/$ngx_rust_obj"
}


# Registers a module in the buildsystem.
# Expects two variables to be set:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Expects two variables to be set:"
->
"In addition to auto/module variables expects two variables to be set:"?

#
# ngx_rust_target_type=LIB|EXAMPLE
# ngx_rust_target_name=<library or example name[^1]>
#
# [^1]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-name-field)

ngx_rust_module () {
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
ngx_rust_target_name=${ngx_rust_target_name:-ngx_module_name}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if $ngx_rust_target_name is not defined, $ngx_rust_target_name becomes "ngx_module_name"

ngx_rust_obj=$NGX_OBJS/$ngx_addon_id/$(ngx_rust_target_path)

ngx_module_deps_saved=$ngx_module_deps
ngx_module_deps="$ngx_rust_obj $ngx_module_deps"

ngx_module_libs_saved=$ngx_module_libs
ngx_module_libs="$ngx_rust_obj $ngx_module_libs $RUST_LIBS"

# Module deps are usually added to the object file targets, but we don't have any
LINK_DEPS="$LINK_DEPS $ngx_rust_obj"

eval ${ngx_addon_id}_MODULES=\"\$${ngx_addon_id}_MODULES \
$ngx_rust_target_type:$ngx_rust_target_name\"

if [ -n "$ngx_rust_target_features" ]; then
eval ${ngx_addon_id}_FEATURES=\"\$${ngx_addon_id}_FEATURES \
$ngx_rust_target_features\"
fi

. auto/module

ngx_module_deps=$ngx_module_deps_saved
ngx_module_libs=$ngx_module_libs_saved
}


# Writes a Makefile fragment for all the modules configured for "ngx_addon_name"

ngx_rust_make_modules () {
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
ngx_cargo_manifest=${ngx_cargo_manifest:-"$ngx_addon_dir/Cargo.toml"}

eval ngx_rust_features="\$${ngx_addon_id}_FEATURES"
eval ngx_rust_modules="\$${ngx_addon_id}_MODULES"

for module in $ngx_rust_modules; do
ngx_rust_target_type=${module%%:*}
ngx_rust_target_name=${module#*:}

ngx_rust_make_module
done
}


# Writes a Makefile fragment for a single module specified by
# "ngx_addon_name", "ngx_rust_target_type" and "ngx_rust_target_name"

ngx_rust_make_module () {
ngx_addon_id=$(echo "$ngx_addon_name" | sed -e 's/[^A-Za-z0-9_]/_/g')
ngx_rust_obj=$NGX_OBJS/$ngx_addon_id/$(ngx_rust_target_path)

ngx_rustc_module_opt=
if [ "$ngx_rust_target_type" = EXAMPLE ]; then
ngx_rustc_module_opt="--example $ngx_rust_target_name"
fi

cat << END >> $NGX_MAKEFILE

# always run cargo instead of trying to track the source modifications
.PHONY: $ngx_rust_obj

$ngx_rust_obj:
$NGX_CARGO rustc \\
--config $ngx_cargo_config \\
--crate-type staticlib \\
--manifest-path "$ngx_cargo_manifest" \\
--no-default-features \\
--profile $ngx_cargo_profile \\
${RUST_TARGET:+--target $RUST_TARGET} \\
--target-dir $NGX_OBJS/$ngx_addon_id \\
--features "$ngx_rust_features" \\
$ngx_rustc_module_opt $NGX_RUSTC_OPT

END
}
Loading
Loading