diff --git a/Cargo.toml b/Cargo.toml index 5ea6c87..0fd9f26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,3 +31,9 @@ tracing = { version = "0.1.40", features = ["attributes"] } tracing-opentelemetry = "0.23.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } warp = "0.3.7" + +[profile.maxperf] +inherits = "release" +lto = "fat" +codegen-units = 1 +incremental = false diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 0000000..33659ee --- /dev/null +++ b/Cross.toml @@ -0,0 +1,5 @@ +[build] +pre-build = [ + # rust-bindgen dependencies: llvm-dev libclang-dev (>= 5.0) clang (>= 5.0) + "apt-get update && apt-get install --assume-yes --no-install-recommends llvm-dev libclang-6.0-dev clang-6.0 libssl-dev" +] diff --git a/Dockerfile b/Dockerfile index 7e69a30..6085c67 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ ARG FEATURES="" ENV FEATURES $FEATURES # Install system dependencies -RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config +RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev libssl-dev pkg-config # Builds dependencies RUN cargo chef cook --profile $BUILD_PROFILE --features "$FEATURES" --recipe-path recipe.json @@ -48,5 +48,5 @@ COPY --from=builder /app/eth-node-monitor /usr/local/bin # Copy licenses COPY LICENSE-* ./ -EXPOSE 3000 +EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/eth-node-monitor"] \ No newline at end of file diff --git a/Dockerfile.cross b/Dockerfile.cross new file mode 100644 index 0000000..2db8b7d --- /dev/null +++ b/Dockerfile.cross @@ -0,0 +1,15 @@ +# This image is meant to enable cross-architecture builds. +# It assumes the eth-node-monitor binary has already been compiled for `$TARGETPLATFORM` and is +# locatable in `./dist/bin/$TARGETARCH` +FROM --platform=$TARGETPLATFORM ubuntu:22.04 + +LABEL org.opencontainers.image.source=https://github.com/cowprotocol/eth-node-monitor +LABEL org.opencontainers.image.licenses="GPL-3.0" + +# Filled by docker buildx +ARG TARGETARCH + +COPY ./dist/bin/$TARGETARCH/eth-node-monitor /usr/local/bin/eth-node-monitor + +EXPOSE 8080 +ENTRYPOINT ["/usr/local/bin/eth-node-monitor"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..35dd591 --- /dev/null +++ b/Makefile @@ -0,0 +1,155 @@ +# Heavily inspired by Lighthouse: https://github.com/sigp/lighthouse/blob/693886b94176faa4cb450f024696cb69cda2fe58/Makefile +.DEFAULT_GOAL := help + +GIT_TAG ?= $(shell git describe --tags --abbrev=0) +BIN_DIR = "dist/bin" + +BUILD_PATH = "target" + +# Cargo profile for builds. Default is for local builds, CI uses an override. +PROFILE ?= release + +# Extra flags for Cargo +CARGO_INSTALL_EXTRA_FLAGS ?= + +# The docker image name +DOCKER_IMAGE_NAME ?= ghcr.io/cowprotocol/eth-node-monitor + +##@ Build + +.PHONY: install +install: ## Build and install the eth-node-monitor binary under `~/.cargo/bin`. + cargo install --bin eth-node-monitor --force --locked \ + --profile "$(PROFILE)" \ + $(CARGO_INSTALL_EXTRA_FLAGS) + +.PHONY: build +build: ## Build the eth-node-monitor binary into `target` directory. + $(MAKE) build-native-$(shell rustc -Vv | grep host | cut -d ' ' -f2) + +# Builds the eth-node-monitor binary natively. +build-native-%: + cargo build --target $* --profile "$(PROFILE)" + +# The following commands use `cross` to build a cross-compile. +# +# These commands require that: +# +# - `cross` is installed (`cargo install cross`). +# - Docker is running. +# - The current user is in the `docker` group. +# +# The resulting binaries will be created in the `target/` directory. + +# For aarch64, disable asm-keccak optimizations and set the page size for +# jemalloc. When cross compiling, we must compile jemalloc with a large page +# size, otherwise it will use the current system's page size which may not work +# on other systems. JEMALLOC_SYS_WITH_LG_PAGE=16 tells jemalloc to use 64-KiB +# pages. See: https://github.com/paradigmxyz/reth/issues/6742 +build-aarch64-unknown-linux-gnu: FEATURES := $(filter-out asm-keccak,$(FEATURES)) +build-aarch64-unknown-linux-gnu: export JEMALLOC_SYS_WITH_LG_PAGE=16 + +# No jemalloc on Windows +build-x86_64-pc-windows-gnu: FEATURES := $(filter-out jemalloc jemalloc-prof,$(FEATURES)) + +# Note: The additional rustc compiler flags are for intrinsics needed by MDBX. +# See: https://github.com/cross-rs/cross/wiki/FAQ#undefined-reference-with-build-std +build-%: + RUSTFLAGS="-C link-arg=-lgcc -Clink-arg=-static-libgcc" \ + cross build --target $* --features "$(FEATURES)" --profile "$(PROFILE)" + +# Unfortunately we can't easily use cross to build for Darwin because of licensing issues. +# If we wanted to, we would need to build a custom Docker image with the SDK available. +# +# Note: You must set `SDKROOT` and `MACOSX_DEPLOYMENT_TARGET`. These can be found using `xcrun`. +# +# `SDKROOT=$(xcrun -sdk macosx --show-sdk-path) MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)` +build-x86_64-apple-darwin: + $(MAKE) build-native-x86_64-apple-darwin +build-aarch64-apple-darwin: + $(MAKE) build-native-aarch64-apple-darwin + +# Create a `.tar.gz` containing a binary for a specific target. +define tarball_release_binary + cp $(BUILD_PATH)/$(1)/$(PROFILE)/$(2) $(BIN_DIR)/$(2) + cd $(BIN_DIR) && \ + tar -czf eth-node-monitor-$(GIT_TAG)-$(1)$(3).tar.gz $(2) && \ + rm $(2) +endef + +# The current git tag will be used as the version in the output file names. You +# will likely need to use `git tag` and create a semver tag (e.g., `v0.2.3`). +# +# Note: This excludes macOS tarballs because of SDK licensing issues. +.PHONY: build-release-tarballs +build-release-tarballs: ## Create a series of `.tar.gz` files in the BIN_DIR directory, each containing a `eth-node-monitor` binary for a different target. + [ -d $(BIN_DIR) ] || mkdir -p $(BIN_DIR) + $(MAKE) build-x86_64-unknown-linux-gnu + $(call tarball_release_binary,"x86_64-unknown-linux-gnu","eth-node-monitor","") + $(MAKE) build-x86_64-pc-windows-gnu + $(call tarball_release_binary,"x86_64-pc-windows-gnu","eth-node-monitor.exe","") + +##@ Test + +UNIT_TEST_ARGS := --locked --workspace --features 'jemalloc-prof' -E 'kind(lib)' -E 'kind(bin)' -E 'kind(proc-macro)' +UNIT_TEST_ARGS_OP := --locked --workspace --features 'jemalloc-prof,optimism' -E 'kind(lib)' -E 'kind(bin)' -E 'kind(proc-macro)' +COV_FILE := lcov.info + +.PHONY: test-unit +test-unit: ## Run unit tests. + cargo install cargo-nextest --locked + cargo nextest run $(UNIT_TEST_ARGS) + +##@ Docker + +# Note: This requires a buildx builder with emulation support. For example: +# +# `docker run --privileged --rm tonistiigi/binfmt --install amd64,arm64` +# `docker buildx create --use --driver docker-container --name cross-builder` +.PHONY: docker-build-push +docker-build-push: ## Build and push a cross-arch Docker image tagged with the latest git tag. + $(call docker_build_push,$(GIT_TAG),$(GIT_TAG)) + +# Note: This requires a buildx builder with emulation support. For example: +# +# `docker run --privileged --rm tonistiigi/binfmt --install amd64,arm64` +# `docker buildx create --use --driver docker-container --name cross-builder` +.PHONY: docker-build-push-latest +docker-build-push-latest: ## Build and push a cross-arch Docker image tagged with the latest git tag and `latest`. + $(call docker_build_push,$(GIT_TAG),latest) + +# Note: This requires a buildx builder with emulation support. For example: +# +# `docker run --privileged --rm tonistiigi/binfmt --install amd64,arm64` +# `docker buildx create --use --name cross-builder` +.PHONY: docker-build-push-nightly +docker-build-push-nightly: ## Build and push cross-arch Docker image tagged with the latest git tag with a `-nightly` suffix, and `latest-nightly`. + $(call docker_build_push,$(GIT_TAG)-nightly,latest-nightly) + +# Create a cross-arch Docker image with the given tags and push it +define docker_build_push + $(MAKE) build-x86_64-unknown-linux-gnu + mkdir -p $(BIN_DIR)/amd64 + cp $(BUILD_PATH)/x86_64-unknown-linux-gnu/$(PROFILE)/eth-node-monitor $(BIN_DIR)/amd64/eth-node-monitor + + docker buildx build --file ./Dockerfile.cross . \ + --platform linux/amd64 \ + --tag $(DOCKER_IMAGE_NAME):$(1) \ + --tag $(DOCKER_IMAGE_NAME):$(2) \ + --provenance=false \ + --push +endef + +##@ Other + +.PHONY: clean +clean: ## Perform a `cargo` clean and remove the binary and test vectors directories. + cargo clean + rm -rf $(BIN_DIR) + +.PHONY: maxperf +maxperf: ## Builds `eth-node-monitor` with the most aggressive optimisations. + RUSTFLAGS="-C target-cpu=native" cargo build --profile maxperf + +fmt: + cargo +nightly fmt