From e6add997ebbcd967734391da8a8987c7926e168f Mon Sep 17 00:00:00 2001 From: Steffen Eiden Date: Thu, 4 May 2023 13:58:07 +0200 Subject: [PATCH] Integrate rust into s390-tools build system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rust integration into the s390-tools build system consists of the following steps: - Add a subdirectory for the rust code. - Add a Makefile that forwards rust builds to `cargo`. - Add a `utils` crate for rust code in s390-tools. - Add rust stuff for dotfiles: - gitignore - editorconfig - codespellrc (while at it, add an ignore file) With cargo the rust ecosystem has its own build system which also is responsible to resolve rust dependencies via downloading the dependencies from (default) crates.io and discover the source files. Therefore, the Makefile just calls `cargo build` to forward the build to cargo. If a rust crate does not require external dependencies, users might call rustc directly. A simple `make` will build all the rust targets as well (with --release specified). Also `make install` will work as usual. A few Makefile configuration variables are introduced for rust/Cargo: - HAVE_CARGO (default 1) to toggle the build of rust code using cargo - CARGOFLAGS to add custom cargo flags, e.g. --offline - CARGO Cargo binary location defaults to $(where cargo) A new global make target is defined to get the current s390-tools version: $ make version 2.28.0 rust/Makefile also has the `print-rust-targets` target to print all rust directories/crates that should be shipped/installed. Signed-off-by: Steffen Eiden Reviewed-by: Jan Höppner Acked-by: Marc Hartmayer Signed-off-by: Jan Höppner --- .codespell.ignore | 5 +++ .codespellrc | 3 +- .editorconfig | 6 ++++ .rustfmt.toml | 12 +++++++ CHANGELOG.md | 2 ++ Makefile | 5 +-- README.md | 6 ++++ common.mak | 49 ++++++++++++++++---------- rust/.gitignore | 14 ++++++++ rust/Makefile | 81 +++++++++++++++++++++++++++++++++++++++++++ rust/utils/Cargo.toml | 5 +++ rust/utils/src/lib.rs | 29 ++++++++++++++++ zfcpdump/Makefile | 2 +- 13 files changed, 196 insertions(+), 23 deletions(-) create mode 100644 .codespell.ignore create mode 100644 .rustfmt.toml create mode 100644 rust/.gitignore create mode 100644 rust/Makefile create mode 100644 rust/utils/Cargo.toml create mode 100644 rust/utils/src/lib.rs diff --git a/.codespell.ignore b/.codespell.ignore new file mode 100644 index 00000000..94c0c59d --- /dev/null +++ b/.codespell.ignore @@ -0,0 +1,5 @@ +parm +parms +crate +ser +deriver diff --git a/.codespellrc b/.codespellrc index 388a7c2d..e9f3ff68 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,5 +1,4 @@ [codespell] -ignore-words-list = parm,parms -skip = '' +ignore-words = .codespell.ignore count = '' quiet-level = 3 diff --git a/.editorconfig b/.editorconfig index 18d9ee17..201a3d8a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,12 @@ insert_final_newline = true charset = utf-8 indent_style = tab tab_width = 8 +trim_trailing_whitespace = true + +[*.rs] +indent_style = space +indent_size = 4 +tab_width = 4 [*.sh] shell_variant = bash # used by `shfmt` diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..3de5cc49 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,12 @@ +edition = "2021" +newline_style = "Unix" + +# Unstable options that help catching some mistakes in formatting and that we may want to enable +# when they become stable. +# +# They are kept here since they are useful to run from time to time. +#format_code_in_doc_comments = true +#reorder_impl_items = true +#comment_width = 100 +#wrap_comments = true +#normalize_comments = true diff --git a/CHANGELOG.md b/CHANGELOG.md index 22c4421a..9b69f615 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Release history for s390-tools (MIT version) For Linux kernel version: 6.x + s390-tools now supports tools written in rust! + Add new tools / libraries: Changes of existing tools: diff --git a/Makefile b/Makefile index b3212d98..a485af5a 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,12 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \ vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \ ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \ systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \ - genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools pvattest + genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools pvattest \ + rust else BASELIB_DIRS = LIB_DIRS = libpv -TOOL_DIRS = genprotimg pvattest +TOOL_DIRS = genprotimg pvattest rust endif SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS) diff --git a/README.md b/README.md index f558dfdd..5d5ee973 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@ The package also contains the following files: Package contents ---------------- + * rust: + all s390-tools that are written in rust and require external crates. + Disable the compilation of all tools in `rust/` using HAVE_CARGO=0 + See the `rust/README.md` for Details + * dasdfmt: Low-level format ECKD DASDs with the classical Linux disk layout or the new z/OS compatible disk layout. @@ -324,6 +329,7 @@ This table lists additional build or install options: | | | zipl | | initramfs-tools | `HAVE_INITRAMFS` | zdev, zipl | | | `ZDEV_ALWAYS_UPDATE_INITRD` | zdev | +| rust | `HAVE_CARGO` | rust/* | The s390-tools build process uses "pkg-config" and therefore it must be available. diff --git a/common.mak b/common.mak index e1b1814d..424f952b 100644 --- a/common.mak +++ b/common.mak @@ -8,6 +8,8 @@ ASAN ?= 0 ENABLE_WERROR ?= 0 OPT_FLAGS ?= MAKECMDGOALS ?= +CARGO ?= cargo +CARGOFLAGS ?= ifeq ($(COMMON_INCLUDED),false) COMMON_INCLUDED := true @@ -89,17 +91,17 @@ define cmd_define_and_export endef define define_toolchain_variables - $(eval $(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as)) - $(eval $(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc)) - $(eval $(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1)))) - $(eval $(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++)) - $(eval $(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1)))) - $(eval $(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E)) - $(eval $(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar)) - $(eval $(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm)) - $(eval $(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip)) - $(eval $(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy)) - $(eval $(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump)) + $(eval $(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as)) + $(eval $(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc)) + $(eval $(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1)))) + $(eval $(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++)) + $(eval $(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1)))) + $(eval $(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E)) + $(eval $(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar)) + $(eval $(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm)) + $(eval $(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip)) + $(eval $(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy)) + $(eval $(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump)) $(eval PKG_CONFIG$(1) = pkg-config) $(eval export PKG_CONFIG$(1)) endef @@ -118,12 +120,16 @@ endif $(call define_toolchain_variables,_FOR_BUILD,) $(call define_toolchain_variables,,$(CROSS_COMPILE)) -$(eval $(call cmd_define,RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest)) -$(eval $(call cmd_define, CAT," CAT ",cat)) -$(eval $(call cmd_define, SED," SED ",sed)) -$(eval $(call cmd_define, GZIP," GZIP ",gzip)) -$(eval $(call cmd_define, MV," MV ",mv)) -$(eval $(call cmd_define, PERLC," PERLC ",perl -c)) + +$(eval $(call cmd_define, RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest)) +$(eval $(call cmd_define, CAT," CAT ",cat)) +$(eval $(call cmd_define, SED," SED ",sed)) +$(eval $(call cmd_define, GZIP," GZIP ",gzip)) +$(eval $(call cmd_define, MV," MV ",mv)) +$(eval $(call cmd_define, PERLC," PERLC ",perl -c)) +$(eval $(call cmd_define,CARGO_BUILD," CARGO BUILD ",$(CARGO) build)) +$(eval $(call cmd_define,CARGO_TEST, " CARGO TEST ",$(CARGO) test)) +$(eval $(call cmd_define,CARGO_CLEAN," CARGO CLEAN ",$(CARGO) clean)) CHECK = sparse CHECK_SILENT := $(CHECK) @@ -133,8 +139,10 @@ SKIP = echo " SKIP $(call reldir) due to" INSTALL = install CP = cp +ALL_CARGOFLAGS := $(CARGOFLAGS) ifneq ("${V}","1") MAKEFLAGS += --quiet + ALL_CARGOFLAGS += --quiet echocmd=echo $1$(call reldir)$2; RUNTEST += > /dev/null 2>&1 else @@ -397,6 +405,11 @@ else $(error Please install either 'compiledb' or 'bear') endif +# Prints the s390-tools release string +version: + $(info $(S390_TOOLS_RELEASE)) +.PHONY: version + # Automatic dependency generation # # Create ".o.d" dependency files with the -MM compile option for all ".c" and @@ -507,7 +520,7 @@ install_echo: install: install_echo install_dirs clean_echo: - $(call echocmd," CLEAN ") + $(call echocmd," CLEAN ") clean_gcov: rm -f -- *.gcda *.gcno *.gcov clean_dep: diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 00000000..4760f821 --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +*.rs.bk + +# Generated during make build can be removed at any point +.check-dep-pvtools +.check-cargo + +# Ignore lock files by default +Cargo.lock diff --git a/rust/Makefile b/rust/Makefile new file mode 100644 index 00000000..60e7e4d8 --- /dev/null +++ b/rust/Makefile @@ -0,0 +1,81 @@ +include ../common.mak +SHELL := /bin/bash +HAVE_CARGO ?= 1 + +INSTALL_TARGETS := skip-build +BUILD_TARGETS := skip-build +CARGO_TARGETS := +CARGO_TEST_TARGETS := + +ifneq (${HAVE_CARGO},0) + CARGO_TARGETS := + + BUILD_TARGETS = $(CARGO_TARGETS) + INSTALL_TARGETS := install-rust-tools install-man + CARGO_TEST_TARGETS = $(addsuffix, _test, $(CARGO_TARGETS)) + +endif + +# build release targets by default +ifeq ("${D}","0") + ALL_CARGOFLAGS += --release +endif + +# the cc crate uses these variables to compile c code. It does not open a shell +# to call the compiler, so no echo etc. allowed here, just a path to a program +$(BUILD_TARGETS) rust-test: CC = $(CC_SILENT) +$(BUILD_TARGETS) rust-test: AR = $(AR_SILENT) + +$(CARGO_TARGETS): .check-cargo .no-cross-compile + $(CARGO_BUILD) --manifest-path=$@/Cargo.toml $(ALL_CARGOFLAGS) +.PHONY: $(CARGO_TARGETS) + + +$(CARGO_TEST_TARGETS): .check-cargo .no-cross-compile + $(CARGO_TEST) --manifest-path=$@/Cargo.toml --all-features $(CARGOFLAGS) +.PHONY: $(CARGO_TEST_TARGETS) + +skip-build: + echo " SKIP rust-tools due to unresolved dependencies" + +all: $(BUILD_TARGETS) +install: $(INSTALL_TARGETS) + +print-rust-targets: + echo $(BUILD_TARGETS) + +clean: + $(foreach target,$(CARGO_TARGETS),\ + $(CARGO_CLEAN) --manifest-path=$(target)/Cargo.toml ${ALL_CARGOFLAGS} ;) + $(RM) -- .check-dep-pvtools .detect-openssl.dep.c .check-cargo + +rust-test: .check-cargo .no-cross-compile + $(foreach target,$(CARGO_TEST_TARGETS),\ + $(CARGO_TEST) --manifest-path=$(target)/Cargo.toml --all-features ${ALL_CARGOFLAGS} ;) + +install-rust-tools: $(BUILD_TARGETS) + $(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR) + $(foreach target,$(CARGO_TARGETS),\ + $(INSTALL) $(target)/target/release/$(target) $(DESTDIR)$(USRBINDIR);) + +install-man: + $(foreach target,$(CARGO_TARGETS),\ + $(INSTALL) -m 644 $(target)/man/*.1 -t $(DESTDIR)$(MANDIR)/man1;) + +.PHONY: all install clean skip-build install-rust-tools print-rust-targets install-man rust-test + +.check-cargo: +ifeq ($(shell command -v $(CARGO)),) + $(call check_dep, \ + "rust/cargo", \ + "invalid-incl", \ + "cargo", \ + "HAVE_CARGO=0") +endif + touch $@ + +.no-cross-compile: +ifneq ($(HOST_ARCH), $(BUILD_ARCH)) + $(error Cross compiling is not supported for rust code. Specify HAVE_CARGO=0 to disable rust compilation) +endif +.PHONY: .no-cross-compile diff --git a/rust/utils/Cargo.toml b/rust/utils/Cargo.toml new file mode 100644 index 00000000..30bbbc83 --- /dev/null +++ b/rust/utils/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2021" +license = "MIT" diff --git a/rust/utils/src/lib.rs b/rust/utils/src/lib.rs new file mode 100644 index 00000000..e519f6c1 --- /dev/null +++ b/rust/utils/src/lib.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +//! Utils for s390-tools written in rust. +//! Not intened to be used outside of s390-tools. +//! +//! Copyright IBM Corp. 2023 + +/// Get the s390-tools release string +/// +/// Provides the s390-tools release string. +/// For release builds this reqquires the environment variable +/// `S390_TOOLS_RELEASE` to be present at compile time. +/// For debug builds this value defaults to `DEBUG_BUILD` +/// if that variable is not present. +/// Should only be used by binary targets!! +/// +/// Collapses to a compile time constant, that is likely to be inlined +/// by the compiler in release builds. +#[macro_export] +macro_rules! release_string { + () => {{ + #[cfg(debug_assertions)] + match option_env!("S390_TOOLS_RELEASE") { + Some(ver) => ver, + None => "DEBUG BUILD", + } + #[cfg(not(debug_assertions))] + env!("S390_TOOLS_RELEASE", "env 'S390_TOOLS_RELEASE' must be set for release builds. Trigger build using the s390-tools build system or export the variable yourself") + }}; +} diff --git a/zfcpdump/Makefile b/zfcpdump/Makefile index 34df1bff..309ea8f6 100644 --- a/zfcpdump/Makefile +++ b/zfcpdump/Makefile @@ -1,6 +1,6 @@ include ../common.mak -CPIOINIT = $(call echocmd," CPIOINI ",/$@)./cpioinit +CPIOINIT = $(call echocmd," CPIOINI ",/$@)./cpioinit INSTALL_SCRIPTS = 10-zfcpdump.install ALL_CFLAGS += -fno-sanitize=all