mirror of https://github.com/smithy-lang/smithy-rs
Allow to build and test on MacOX M1/x86 chips (#1609)
* Allow to build and test on MacOX M1 chips * Add MacOS linker config * Fall back to standard event loop if uvloop is not available
This commit is contained in:
parent
430f4bf8b4
commit
000e8b0db7
|
@ -0,0 +1,12 @@
|
|||
# See: https://pyo3.rs/latest/building_and_distribution.html?highlight=rustflags#macos
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
||||
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
|
@ -1,3 +1,4 @@
|
|||
OS := $(shell uname -s)
|
||||
SRC_DIR := $(shell git rev-parse --show-toplevel)
|
||||
CUR_DIR := $(shell pwd)
|
||||
GRADLE := $(SRC_DIR)/gradlew
|
||||
|
@ -5,8 +6,15 @@ SERVER_SDK_DST := $(CUR_DIR)/pokemon-service-server-sdk
|
|||
CLIENT_SDK_DST := $(CUR_DIR)/pokemon-service-client
|
||||
SERVER_SDK_SRC := $(SRC_DIR)/codegen-server-test/python/build/smithyprojections/codegen-server-test-python/pokemon-service-server-sdk/rust-server-codegen-python
|
||||
CLIENT_SDK_SRC := $(SRC_DIR)/codegen-test/build/smithyprojections/codegen-test/pokemon-service-client/rust-codegen
|
||||
DEBUG_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/debug/libpokemon_service_server_sdk.so
|
||||
RELEASE_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/release/libpokemon_service_server_sdk.so
|
||||
|
||||
SHARED_LIBRARY_DST := $(CUR_DIR)/libpokemon_service_server_sdk.so
|
||||
ifeq ($(OS), Darwin)
|
||||
DEBUG_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/debug/libpokemon_service_server_sdk.dylib
|
||||
RELEASE_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/release/libpokemon_service_server_sdk.dylib
|
||||
else
|
||||
DEBUG_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/debug/libpokemon_service_server_sdk.so
|
||||
RELEASE_SHARED_LIBRARY_SRC := $(SRC_DIR)/target/release/libpokemon_service_server_sdk.so
|
||||
endif
|
||||
|
||||
all: codegen
|
||||
|
||||
|
@ -18,11 +26,11 @@ codegen:
|
|||
|
||||
build: codegen
|
||||
cargo build
|
||||
ln -sf $(DEBUG_SHARED_LIBRARY_SRC) $(CUR_DIR)/libpokemon_service_server_sdk.so
|
||||
ln -sf $(DEBUG_SHARED_LIBRARY_SRC) $(SHARED_LIBRARY_DST)
|
||||
|
||||
release: codegen
|
||||
cargo build --release
|
||||
ln -sf $(RELEASE_SHARED_LIBRARY_SRC) $(CUR_DIR)/libpokemon_service_server_sdk.so
|
||||
ln -sf $(RELEASE_SHARED_LIBRARY_SRC) $(SHARED_LIBRARY_DST)
|
||||
|
||||
run: build
|
||||
python $(CUR_DIR)/pokemon_service.py
|
||||
|
@ -37,6 +45,6 @@ clean:
|
|||
cargo clean || echo "Unable to run cargo clean"
|
||||
|
||||
distclean: clean
|
||||
rm -rf $(SERVER_SDK_DST) $(CLIENT_SDK_DST) $(CUR_DIR)/Cargo.lock $(CUR_DIR)/libpokemon_service_server_sdk.so
|
||||
rm -rf $(SERVER_SDK_DST) $(CLIENT_SDK_DST) $(CUR_DIR)/Cargo.lock $(SHARED_LIBRARY_DST)
|
||||
|
||||
.PHONY: all
|
||||
|
|
|
@ -18,6 +18,27 @@ can be used directly.
|
|||
|
||||
`make distclean` can be used for a complete cleanup of all artefacts.
|
||||
|
||||
### Uvloop
|
||||
|
||||
The server can depend on [uvloop](https://pypi.org/project/uvloop/) for a
|
||||
faster event loop implementation. Uvloop can be installed with your favourite
|
||||
package manager or by using pip:
|
||||
|
||||
```sh
|
||||
pip instal uvloop
|
||||
```
|
||||
|
||||
and it will be automatically used instead of the standard library event loop if
|
||||
it is found in the dependencies' closure.
|
||||
|
||||
### MacOs
|
||||
|
||||
To compile and test on MacOs, please follow the official PyO3 guidelines on how
|
||||
to [configure your linker](https://pyo3.rs/latest/building_and_distribution.html?highlight=rustflags#macos).
|
||||
|
||||
Please note that the `.cargo/config.toml` with linkers override can be local to
|
||||
your project.
|
||||
|
||||
## Run
|
||||
|
||||
`cargo run` can be used to start the Pokémon service on
|
||||
|
|
|
@ -178,7 +178,9 @@ impl PyApp {
|
|||
/// Python asynchronous loop needs to be started and handled during the lifetime of the process.
|
||||
/// First of all we install [uvloop] as the main Python event loop. Thanks to libuv, uvloop
|
||||
/// performs ~20% better than Python standard event loop in most benchmarks, while being 100%
|
||||
/// compatible.
|
||||
/// compatible. If [uvloop] is not available as a dependency, we just fall back to the standard
|
||||
/// Python event loop.
|
||||
///
|
||||
/// We retrieve the Python context object, if setup by the user calling [PyApp::context] method,
|
||||
/// generate the [PyState] structure and build the [aws_smithy_http_server::Router], filling
|
||||
/// it with the functions generated by `PythonServerOperationHandlerGenerator.kt`.
|
||||
|
@ -198,10 +200,18 @@ impl PyApp {
|
|||
worker_number: isize,
|
||||
) -> PyResult<()> {
|
||||
// Setup the Python asyncio loop to use `uvloop`.
|
||||
// If uvloop is not available as a dependency, the standard Python
|
||||
// event loop will be used instead.
|
||||
let asyncio = py.import("asyncio")?;
|
||||
let uvloop = py.import("uvloop")?;
|
||||
uvloop.call_method0("install")?;
|
||||
tracing::debug!("Setting up uvloop for current process");
|
||||
match py.import("uvloop") {
|
||||
Ok(uvloop) => {
|
||||
uvloop.call_method0("install")?;
|
||||
tracing::debug!("Setting up uvloop for current process");
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::warn!("Uvloop not found, using Python standard event loop, which could have worse performance than uvloop");
|
||||
}
|
||||
}
|
||||
let event_loop = asyncio.call_method0("new_event_loop")?;
|
||||
asyncio.call_method1("set_event_loop", (event_loop,))?;
|
||||
// Create the `PyState` object from the Python context object.
|
||||
|
@ -309,6 +319,16 @@ impl PyApp {
|
|||
let mp = py.import("multiprocessing")?;
|
||||
// https://github.com/python/cpython/blob/f4c03484da59049eb62a9bf7777b963e2267d187/Lib/multiprocessing/context.py#L164
|
||||
mp.call_method0("allow_connection_pickling")?;
|
||||
|
||||
// Starting from Python 3.8, on macOS, the spawn start method is now the default. See bpo-33725.
|
||||
// This forces the `PyApp` class to be pickled when it is shared between different process,
|
||||
// which is currently not supported by PyO3 classes.
|
||||
//
|
||||
// Forcing the multiprocessing start method to fork is a workaround for it.
|
||||
// https://github.com/pytest-dev/pytest-flask/issues/104#issuecomment-577908228
|
||||
#[cfg(target_os = "macos")]
|
||||
mp.call_method1("set_start_method", ("fork",))?;
|
||||
|
||||
let address = address.unwrap_or_else(|| String::from("127.0.0.1"));
|
||||
let port = port.unwrap_or(13734);
|
||||
let socket = PySocket::new(address, port, backlog)?;
|
||||
|
|
Loading…
Reference in New Issue