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:
Matteo Bigoi 2022-08-02 00:27:51 +01:00 committed by GitHub
parent 430f4bf8b4
commit 000e8b0db7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 9 deletions

View File

@ -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",
]

View File

@ -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

View File

@ -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

View File

@ -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)?;