From 12ab631072e6076f9dbcd905c62a42795ea9dbfa Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Fri, 7 Nov 2025 10:37:47 -0700 Subject: [PATCH 01/13] make: undo Patrick's changes concerning Rust Signed-off-by: Ezekiel Newren --- Makefile | 49 ------------------------------------------------- shared.mak | 1 - 2 files changed, 50 deletions(-) diff --git a/Makefile b/Makefile index 7e0f77e2988e3b..28bc00e64865ad 100644 --- a/Makefile +++ b/Makefile @@ -483,14 +483,6 @@ include shared.mak # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are # in /foo/bar/include and /foo/bar/lib directories. # -# == Optional Rust support == -# -# Define WITH_RUST if you want to include features and subsystems written in -# Rust into Git. For now, Rust is still an optional feature of the build -# process. With Git 3.0 though, Rust will always be enabled. -# -# Building Rust code requires Cargo. -# # == SHA-1 and SHA-256 defines == # # === SHA-1 backend === @@ -691,7 +683,6 @@ OBJECTS = OTHER_PROGRAMS = PROGRAM_OBJS = PROGRAMS = -RUST_SOURCES = EXCLUDED_PROGRAMS = SCRIPT_PERL = SCRIPT_PYTHON = @@ -928,18 +919,6 @@ TEST_SHELL_PATH = $(SHELL_PATH) LIB_FILE = libgit.a -ifdef DEBUG -RUST_TARGET_DIR = target/debug -else -RUST_TARGET_DIR = target/release -endif - -ifeq ($(uname_S),Windows) -RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib -else -RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a -endif - GITLIBS = common-main.o $(LIB_FILE) EXTLIBS = @@ -963,15 +942,6 @@ BASIC_LDFLAGS = ARFLAGS = rcs PTHREAD_CFLAGS = -# Rust flags -CARGO_ARGS = -ifndef V -CARGO_ARGS += --quiet -endif -ifndef DEBUG -CARGO_ARGS += --release -endif - # For the 'sparse' target SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__ SP_EXTRA_FLAGS = @@ -1333,9 +1303,7 @@ LIB_OBJS += urlmatch.o LIB_OBJS += usage.o LIB_OBJS += userdiff.o LIB_OBJS += utf8.o -ifndef WITH_RUST LIB_OBJS += varint.o -endif LIB_OBJS += version.o LIB_OBJS += versioncmp.o LIB_OBJS += walker.o @@ -1534,9 +1502,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o -RUST_SOURCES += src/lib.rs -RUST_SOURCES += src/varint.rs - GIT-VERSION-FILE: FORCE @OLD=$$(cat $@ 2>/dev/null || :) && \ $(call version_gen,"$(shell pwd)",GIT-VERSION-FILE.in,$@) && \ @@ -1566,14 +1531,6 @@ endif ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND) ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND) -ifdef WITH_RUST -BASIC_CFLAGS += -DWITH_RUST -GITLIBS += $(RUST_LIB) -ifeq ($(uname_S),Windows) -EXTLIBS += -luserenv -endif -endif - ifdef SANITIZE SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag)) BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE) @@ -2963,12 +2920,6 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS) $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ -$(RUST_LIB): Cargo.toml $(RUST_SOURCES) - $(QUIET_CARGO)cargo build $(CARGO_ARGS) - -.PHONY: rust -rust: $(RUST_LIB) - export DEFAULT_EDITOR DEFAULT_PAGER Documentation/GIT-EXCLUDED-PROGRAMS: FORCE diff --git a/shared.mak b/shared.mak index 0e7492076ebc4f..5c7bc9478544c8 100644 --- a/shared.mak +++ b/shared.mak @@ -56,7 +56,6 @@ ifndef V QUIET_MKDIR_P_PARENT = @echo ' ' MKDIR -p $(@D); ## Used in "Makefile" - QUIET_CARGO = @echo ' ' CARGO $@; QUIET_CC = @echo ' ' CC $@; QUIET_AR = @echo ' ' AR $@; QUIET_LINK = @echo ' ' LINK $@; From dd8787e3e07a567acf56c23c69599aaefd87b3b0 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Fri, 7 Nov 2025 10:49:11 -0700 Subject: [PATCH 02/13] meson: undo Patrick's changes concerning Rust Signed-off-by: Ezekiel Newren --- meson.build | 19 ++----------------- meson_options.txt | 4 ++-- src/cargo-meson.sh | 39 --------------------------------------- src/meson.build | 41 ----------------------------------------- 4 files changed, 4 insertions(+), 99 deletions(-) delete mode 100755 src/cargo-meson.sh delete mode 100644 src/meson.build diff --git a/meson.build b/meson.build index 2b763f7c53493c..8966596ee8b42f 100644 --- a/meson.build +++ b/meson.build @@ -220,7 +220,7 @@ project('git', 'c', # learned to define __STDC_VERSION__ with C11 and later. We thus require # GNU C99 and fall back to C11. Meson only learned to handle the fallback # with version 1.3.0, so on older versions we use GNU C99 unconditionally. - default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'], + default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'], ) fs = import('fs') @@ -1709,21 +1709,6 @@ version_def_h = custom_target( ) libgit_sources += version_def_h -cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust')) -rust_option = get_option('rust').disable_auto_if(not cargo.found()) -if rust_option.allowed() - subdir('src') - libgit_c_args += '-DWITH_RUST' - - if host_machine.system() == 'windows' - libgit_dependencies += compiler.find_library('userenv') - endif -else - libgit_sources += [ - 'varint.c', - ] -endif - libgit = declare_dependency( link_with: static_library('git', sources: libgit_sources, @@ -2270,7 +2255,7 @@ summary({ 'pcre2': pcre2, 'perl': perl_features_enabled, 'python': target_python.found(), - 'rust': rust_option.allowed(), + 'rust': get_option('with_rust'), }, section: 'Auto-detected features', bool_yn: true) summary({ diff --git a/meson_options.txt b/meson_options.txt index 143dee9237cb41..0059b7c7df1e78 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -71,8 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu # Build tweaks. option('breaking_changes', type: 'boolean', value: false, description: 'Enable upcoming breaking changes.') -option('rust', type: 'feature', value: 'auto', - description: 'Enable building with Rust.') +option('with_rust', type: 'boolean', value: true, + description: 'Enable building with Rust, true by default.') option('macos_use_homebrew_gettext', type: 'boolean', value: true, description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.') diff --git a/src/cargo-meson.sh b/src/cargo-meson.sh deleted file mode 100755 index 3998db04354864..00000000000000 --- a/src/cargo-meson.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -if test "$#" -lt 2 -then - exit 1 -fi - -SOURCE_DIR="$1" -BUILD_DIR="$2" -BUILD_TYPE=debug - -shift 2 - -for arg -do - case "$arg" in - --release) - BUILD_TYPE=release;; - esac -done - -cargo build --lib --quiet --manifest-path="$SOURCE_DIR/Cargo.toml" --target-dir="$BUILD_DIR" "$@" -RET=$? -if test $RET -ne 0 -then - exit $RET -fi - -case "$(cargo -vV | sed -s 's/^host: \(.*\)$/\1/')" in - *-windows-*) - LIBNAME=gitcore.lib;; - *) - LIBNAME=libgitcore.a;; -esac - -if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 -then - cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" -fi diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 25b9ad5a1479c0..00000000000000 --- a/src/meson.build +++ /dev/null @@ -1,41 +0,0 @@ -libgit_rs_sources = [ - 'lib.rs', - 'varint.rs', -] - -# Unfortunately we must use a wrapper command to move the output file into the -# current build directory. This can fixed once `cargo build --artifact-dir` -# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that -# effort. -cargo_command = [ - shell, - meson.current_source_dir() / 'cargo-meson.sh', - meson.project_source_root(), - meson.current_build_dir(), -] -if get_option('buildtype') == 'release' - cargo_command += '--release' -endif - -libgit_rs = custom_target('git_rs', - input: libgit_rs_sources + [ - meson.project_source_root() / 'Cargo.toml', - ], - output: 'libgitcore.a', - command: cargo_command, -) -libgit_dependencies += declare_dependency(link_with: libgit_rs) - -if get_option('tests') - test('rust', cargo, - args: [ - 'test', - '--manifest-path', - meson.project_source_root() / 'Cargo.toml', - '--target-dir', - meson.current_build_dir() / 'target', - ], - timeout: 0, - protocol: 'rust', - ) -endif From e49ffba5c99ce40b67500bac52a36ae83d10647b Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Fri, 7 Nov 2025 10:54:39 -0700 Subject: [PATCH 03/13] cargo: convert from a crate to a workspace Signed-off-by: Ezekiel Newren --- Cargo.toml | 15 +++++---------- rust/gitcore/Cargo.toml | 10 ++++++++++ {src => rust/gitcore/src}/lib.rs | 0 {src => rust/gitcore/src}/varint.rs | 0 4 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 rust/gitcore/Cargo.toml rename {src => rust/gitcore/src}/lib.rs (100%) rename {src => rust/gitcore/src}/varint.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 2f51bf5d5ff5f8..02273f514258cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,5 @@ -[package] -name = "gitcore" -version = "0.1.0" -edition = "2018" -rust-version = "1.49.0" - -[lib] -crate-type = ["staticlib"] - -[dependencies] +[workspace] +members = [ + "rust/gitcore", +] +resolver = "2" diff --git a/rust/gitcore/Cargo.toml b/rust/gitcore/Cargo.toml new file mode 100644 index 00000000000000..2f51bf5d5ff5f8 --- /dev/null +++ b/rust/gitcore/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "gitcore" +version = "0.1.0" +edition = "2018" +rust-version = "1.49.0" + +[lib] +crate-type = ["staticlib"] + +[dependencies] diff --git a/src/lib.rs b/rust/gitcore/src/lib.rs similarity index 100% rename from src/lib.rs rename to rust/gitcore/src/lib.rs diff --git a/src/varint.rs b/rust/gitcore/src/varint.rs similarity index 100% rename from src/varint.rs rename to rust/gitcore/src/varint.rs From a4b79e70c152a8774b59822763045456a8c6b828 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Fri, 7 Nov 2025 12:11:20 -0700 Subject: [PATCH 04/13] build: build Rust with Makefile and Meson Signed-off-by: Ezekiel Newren --- Makefile | 91 ++++++++++++++++++++++++++++++++++++++------- meson.build | 63 ++++++++++++++++++++++++++++++- rust/build-crate.sh | 58 +++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 15 deletions(-) create mode 100755 rust/build-crate.sh diff --git a/Makefile b/Makefile index 28bc00e64865ad..0aa6b3ae734803 100644 --- a/Makefile +++ b/Makefile @@ -483,6 +483,14 @@ include shared.mak # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are # in /foo/bar/include and /foo/bar/lib directories. # +# == Optional Rust support == +# +# Define WITH_RUST=false if you don't want to include features and subsystems +# written in Rust into Git. For now, Rust is still an optional feature of the +# build process. With Git 3.0 though, Rust will be mandatory. +# +# Building Rust code requires Cargo. +# # == SHA-1 and SHA-256 defines == # # === SHA-1 backend === @@ -919,9 +927,55 @@ TEST_SHELL_PATH = $(SHELL_PATH) LIB_FILE = libgit.a -GITLIBS = common-main.o $(LIB_FILE) EXTLIBS = +GIT_BUILD_DIR := $(CURDIR) +export GIT_BUILD_DIR + +RUST_CRATES := gitcore +.PHONY: rust-compile rust-clean + +WITH_RUST ?= true +ifeq ($(WITH_RUST),true) + +ifeq ($(DEBUG), 1) + RUST_BUILD_MODE := debug +else + RUST_BUILD_MODE := release +endif + +RUST_LIBS := $(foreach c,$(RUST_CRATES),$(GIT_BUILD_DIR)/lib$(c).a) + +rust-compile: + @for c in $(RUST_CRATES); do \ + echo "Building $$c..."; \ + ./rust/build-crate.sh $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $$c || exit $$?; \ + done + +rust-clean: + $(RM) $(RUST_LIBS) Cargo.lock + cargo clean + +$(GIT_BUILD_DIR)/lib%.a: + echo $(RUST_LIBS) + ./rust/build-crate.sh $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $* + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + EXTLIBS += -ldl +endif + +else ifeq ($(WITH_RUST),false) +rust-compile: + : +rust-clean: + : +else +$(error 'WITH_RUST' must be true or false) +endif + +GITLIBS = common-main.o $(LIB_FILE) + GIT_USER_AGENT = git/$(GIT_VERSION) ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h) @@ -938,6 +992,11 @@ CC_LD_DYNPATH = -Wl,-rpath, BASIC_CFLAGS = -I. BASIC_LDFLAGS = +ifeq ($(WITH_RUST),true) + BASIC_CFLAGS += -DWITH_RUST + BASIC_CFLAGS += -fPIE +endif + # library flags ARFLAGS = rcs PTHREAD_CFLAGS = @@ -1303,7 +1362,9 @@ LIB_OBJS += urlmatch.o LIB_OBJS += usage.o LIB_OBJS += userdiff.o LIB_OBJS += utf8.o +ifeq ($(WITH_RUST),false) LIB_OBJS += varint.o +endif LIB_OBJS += version.o LIB_OBJS += versioncmp.o LIB_OBJS += walker.o @@ -2409,6 +2470,10 @@ endif # from the dependency list, that would make each entry appear twice. LIBS = $(filter-out %.o, $(GITLIBS)) $(EXTLIBS) +ifeq ($(WITH_RUST),true) +LIBS += $(RUST_LIBS) +endif + BASIC_CFLAGS += $(COMPAT_CFLAGS) LIB_OBJS += $(COMPAT_OBJS) @@ -2564,7 +2629,7 @@ git.sp git.s git.o: EXTRA_CPPFLAGS = \ '-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \ '-DGIT_INFO_PATH="$(infodir_relative_SQ)"' -git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS) +git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ $(filter %.o,$^) $(LIBS) @@ -2889,17 +2954,17 @@ headless-git.o: compat/win32/headless.c GIT-CFLAGS headless-git$X: headless-git.o git.res GIT-LDFLAGS $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -mwindows -o $@ $< git.res -git-%$X: %.o GIT-LDFLAGS $(GITLIBS) +git-%$X: %.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) -git-imap-send$X: imap-send.o $(IMAP_SEND_BUILDDEPS) GIT-LDFLAGS $(GITLIBS) +git-imap-send$X: imap-send.o $(IMAP_SEND_BUILDDEPS) GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(IMAP_SEND_LDFLAGS) $(LIBS) -git-http-fetch$X: http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS) +git-http-fetch$X: http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CURL_LIBCURL) $(LIBS) -git-http-push$X: http.o http-push.o GIT-LDFLAGS $(GITLIBS) +git-http-push$X: http.o http-push.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) @@ -2909,11 +2974,11 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY) ln -s $< $@ 2>/dev/null || \ cp $< $@ -$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS) +$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) -scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS) +scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ $(filter %.o,$^) $(LIBS) @@ -3286,7 +3351,7 @@ perf: all t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) $(UNIT_TEST_DIR)/test-lib.o -t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) +t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) rust-compile $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS) check-sha1:: t/helper/test-tool$X @@ -3751,7 +3816,7 @@ cocciclean: $(RM) -r .build/contrib/coccinelle $(RM) contrib/coccinelle/*.cocci.patch -clean: profile-clean coverage-clean cocciclean +clean: profile-clean coverage-clean cocciclean rust-clean $(RM) -r .build $(UNIT_TEST_BIN) $(RM) GIT-TEST-SUITES $(RM) po/git.pot po/git-core.pot @@ -3907,13 +3972,13 @@ FUZZ_CXXFLAGS ?= $(ALL_CFLAGS) .PHONY: fuzz-all fuzz-all: $(FUZZ_PROGRAMS) -$(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS +$(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS rust-compile $(QUIET_LINK)$(FUZZ_CXX) $(FUZZ_CXXFLAGS) -o $@ $(ALL_LDFLAGS) \ -Wl,--allow-multiple-definition \ $(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE) $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_OBJS) \ - $(GITLIBS) GIT-LDFLAGS + $(GITLIBS) GIT-LDFLAGS rust-compile $(call mkdir_p_parent_template) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ $(filter %.o,$^) $(filter %.a,$^) $(LIBS) @@ -3932,7 +3997,7 @@ $(UNIT_TEST_DIR)/clar.suite: $(UNIT_TEST_DIR)/clar-decls.h $(UNIT_TEST_DIR)/gene $(UNIT_TEST_DIR)/clar/clar.o: $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS): $(UNIT_TEST_DIR)/clar-decls.h $(CLAR_TEST_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR) -$(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT-LDFLAGS +$(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT-LDFLAGS rust-compile $(call mkdir_p_parent_template) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) diff --git a/meson.build b/meson.build index 8966596ee8b42f..94ec5e4ac0b0ff 100644 --- a/meson.build +++ b/meson.build @@ -267,6 +267,55 @@ version_gen_environment.set('GIT_DATE', get_option('build_date')) version_gen_environment.set('GIT_USER_AGENT', get_option('user_agent')) version_gen_environment.set('GIT_VERSION', get_option('version')) +rust_crates = ['gitcore'] + +rust_builds = [] +with_rust = get_option('with_rust') +if with_rust + rustc = find_program('rustc', required : false) + cargo = find_program('cargo', required : false) + + if not rustc.found() or not cargo.found() + error('Rust toolchain not found. Reconfigure with -Dwith_rust=false') + endif + + if get_option('optimization') in ['2', '3', 's', 'z'] + rust_build_profile = 'release' + else + rust_build_profile = 'debug' + endif + + # Run `rustup show active-toolchain` and capture output + rustup_out = run_command('rustup', 'show', 'active-toolchain', + check: true).stdout().strip() + + rust_environment = script_environment + + foreach crate : rust_crates + if rustup_out.contains('windows-msvc') + libfile = crate + '.lib' + else + libfile = 'lib' + crate + '.a' + endif + + rust_builds += custom_target( + 'rust_build_'+crate, + output: libfile, + build_by_default: true, + build_always_stale: true, + command: [ + meson.project_source_root() / 'rust' / 'build-crate.sh', + meson.current_build_dir(), rust_build_profile, crate, + ], + install: false, + env: rust_environment, + ) + endforeach +else + message('Rust components disabled (-Dwith_rust=false)') +endif + + compiler = meson.get_compiler('c') libgit_sources = [ @@ -548,6 +597,10 @@ libgit_sources = [ 'xdiff/xutils.c', ] +if not with_rust + libgit_sources += 'varint.c' +endif + libgit_sources += custom_target( input: 'command-list.txt', output: 'command-list.h', @@ -782,6 +835,10 @@ libgit_c_args = [ '-DSHELL_PATH="' + fs.as_posix(target_shell.full_path()) + '"', ] +if with_rust + libgit_c_args += '-DWITH_RUST' +endif + system_attributes = get_option('gitattributes') if system_attributes != '' libgit_c_args += '-DETC_GITATTRIBUTES="' + system_attributes + '"' @@ -1274,6 +1331,7 @@ elif host_machine.system() == 'windows' ] libgit_dependencies += compiler.find_library('ntdll') + libgit_dependencies += compiler.find_library('userenv') libgit_include_directories += 'compat/win32' if compiler.get_id() == 'msvc' libgit_include_directories += 'compat/vcbuild/include' @@ -1710,14 +1768,15 @@ version_def_h = custom_target( libgit_sources += version_def_h libgit = declare_dependency( - link_with: static_library('git', + link_with: [ + static_library('git', sources: libgit_sources, c_args: libgit_c_args + [ '-DGIT_VERSION_H="' + version_def_h.full_path() + '"', ], dependencies: libgit_dependencies, include_directories: libgit_include_directories, - ), + )] + rust_builds, compile_args: libgit_c_args, dependencies: libgit_dependencies, include_directories: libgit_include_directories, diff --git a/rust/build-crate.sh b/rust/build-crate.sh new file mode 100755 index 00000000000000..b3debf70e5f69b --- /dev/null +++ b/rust/build-crate.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +rustc -vV || exit $? +cargo --version || exit $? + +dir_git_root=${0%/*} +dir_build=$1 +rust_build_profile=$2 +crate=$3 + +if [ "$dir_git_root" = "" ]; then + echo "did not specify the directory for the root of git" + exit 1 +fi + +if [ "$dir_build" = "" ]; then + echo "did not specify the build directory" + exit 1 +fi + +if [ "$rust_build_profile" = "" ]; then + echo "did not specify the rust_build_profile" + exit 1 +fi + +if [ "$rust_build_profile" = "release" ]; then + rust_args="--release" + export RUSTFLAGS='' +elif [ "$rust_build_profile" = "debug" ]; then + rust_args="" + export RUSTFLAGS='-C debuginfo=2 -C opt-level=1 -C force-frame-pointers=yes' +else + echo "illegal rust_build_profile value $rust_build_profile" + exit 1 +fi + +libfile="lib${crate}.a" +if rustc -vV | grep windows-msvc; then + libfile="${crate}.lib" + PATH="$(echo $PATH | tr ':' '\n' | grep -Ev "^(/mingw64/bin|/usr/bin)$" | paste -sd: -):/mingw64/bin:/usr/bin" +fi + +CARGO_TARGET_DIR=$dir_git_root/.build/rust/$crate +export CARGO_TARGET_DIR + +cargo clean && pwd && USE_LINKING="false" cargo build -p $crate $rust_args + +src=$CARGO_TARGET_DIR/$rust_build_profile/$libfile +dst=$dir_build/$libfile + +if [ ! -f $src ]; then + echo >&2 "::error:: cannot find path of static library $src is not a file or does not exist" + exit 5 +fi + +rm $dst 2>/dev/null +echo mv $src $dst +mv $src $dst From 66648e01e486f2c74202cb15618b95e87e6aea18 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Tue, 11 Nov 2025 16:33:08 -0700 Subject: [PATCH 05/13] .gitignore: ignore /generated/ Signed-off-by: Ezekiel Newren --- .gitignore | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 78a45cb5bec991..5df42eee5adf3c 100644 --- a/.gitignore +++ b/.gitignore @@ -258,3 +258,4 @@ Release/ /contrib/buildsystems/out /contrib/libgit-rs/target /contrib/libgit-sys/target +/generated/ diff --git a/Makefile b/Makefile index 0aa6b3ae734803..8a73afca1686f9 100644 --- a/Makefile +++ b/Makefile @@ -953,7 +953,7 @@ rust-compile: done rust-clean: - $(RM) $(RUST_LIBS) Cargo.lock + $(RM) $(RUST_LIBS) Cargo.lock generated/ cargo clean $(GIT_BUILD_DIR)/lib%.a: From 4a17edade9aa18eaa7a173bf2bd5eecda74508c3 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 13 Nov 2025 15:38:10 -0700 Subject: [PATCH 06/13] cargo: create crate generate-headers Signed-off-by: Ezekiel Newren --- Cargo.toml | 1 + rust/cbindgen-template.toml | 13 +++++++++ rust/generate-headers/Cargo.toml | 12 +++++++++ rust/generate-headers/src/main.rs | 44 +++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 rust/cbindgen-template.toml create mode 100644 rust/generate-headers/Cargo.toml create mode 100644 rust/generate-headers/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 02273f514258cc..b7b5890934389e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "rust/generate-headers", "rust/gitcore", ] resolver = "2" diff --git a/rust/cbindgen-template.toml b/rust/cbindgen-template.toml new file mode 100644 index 00000000000000..13c192d60e0b3f --- /dev/null +++ b/rust/cbindgen-template.toml @@ -0,0 +1,13 @@ +## don't include any system files, not even git-compat-util.h +# sys_includes = [] + +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" + +language = "C" +no_includes = true +usize_is_size_t = true +style = "tag" +tab_width = 8 + +[parse] +parse_deps = false diff --git a/rust/generate-headers/Cargo.toml b/rust/generate-headers/Cargo.toml new file mode 100644 index 00000000000000..9216d83d75fb50 --- /dev/null +++ b/rust/generate-headers/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "generate-headers" +version = "0.1.0" +edition = "2018" + +[dependencies] +cbindgen = "0.24.0" +textwrap = "=0.16.1" +once_cell = "=1.20.3" +unicode-width = "=0.1.13" +quote = "=1.0.41" +syn = "=2.0.106" diff --git a/rust/generate-headers/src/main.rs b/rust/generate-headers/src/main.rs new file mode 100644 index 00000000000000..da68c8ae3d89fa --- /dev/null +++ b/rust/generate-headers/src/main.rs @@ -0,0 +1,44 @@ +use cbindgen; + +use std::io::Write; +use std::path::PathBuf; +use cbindgen::Config; + +fn generate_header(crate_name: String, editor: F) +where + F: Fn(&mut Config) +{ + let dir_workspace = PathBuf::default(); + let dir_rust = dir_workspace.join("rust"); + let dir_crate = dir_rust.join(crate_name.clone()); + let dir_generated = dir_workspace.join("generated"); + if !dir_generated.exists() { + std::fs::create_dir(dir_generated.clone()).unwrap(); + } + + let file_cbindgen = dir_rust.join("cbindgen-template.toml"); + let file_out = dir_generated.join(format!("{}.h", crate_name.clone())); + + let mut config = Config::from_file(file_cbindgen.display().to_string().as_str()).unwrap(); + config.include_guard = Some(format!("{}_H", crate_name.to_uppercase())); + + editor(&mut config); + + let mut buffer = Vec::::new(); + cbindgen::Builder::new() + .with_crate(dir_crate.clone()) + .with_config(config) + .with_std_types(true) + .generate() + .expect("Unable to generate bindings") + .write(&mut buffer); + + let mut fd = std::fs::File::create(file_out).unwrap(); + fd.write(buffer.as_slice()).unwrap(); +} + +fn main() { + // cargo run -p generate-headers + + generate_header(String::from("gitcore"), |_|{}); +} From e51a78cfb5dd6d34948dc26d21513450469c6790 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 13 Nov 2025 15:40:11 -0700 Subject: [PATCH 07/13] cargo: create crate link-with-c Signed-off-by: Ezekiel Newren --- rust/link-with-c/Cargo.toml | 9 +++++ rust/link-with-c/src/lib.rs | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 rust/link-with-c/Cargo.toml create mode 100644 rust/link-with-c/src/lib.rs diff --git a/rust/link-with-c/Cargo.toml b/rust/link-with-c/Cargo.toml new file mode 100644 index 00000000000000..adb38fdc9c3999 --- /dev/null +++ b/rust/link-with-c/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "link-with-c" +version = "0.1.0" +edition = "2018" + +[lib] +crate-type = ["staticlib", "rlib"] + +[dependencies] diff --git a/rust/link-with-c/src/lib.rs b/rust/link-with-c/src/lib.rs new file mode 100644 index 00000000000000..f6faaf774dea84 --- /dev/null +++ b/rust/link-with-c/src/lib.rs @@ -0,0 +1,77 @@ +use std::collections::HashMap; +use std::path::PathBuf; + + +fn parse_bool_from_str(value: &str) -> bool { + match value { + "1" | "true" | "yes" | "on" => true, + "0" | "false" | "no" | "off" => false, + _ => false + } +} + +fn parse_bool_from_option(value: Option<&String>, default: bool) -> bool { + match value { + Some(v) => { + parse_bool_from_str(v.as_str()) + }, + None => default, + } +} + +/// To build without linking against C libraries run `USE_LINKING=false cargo build` +/// To run tests set GIT_BUILD_DIR and run `USE_LINKING=true cargo test` +pub struct BuildHelper { + crate_env: HashMap, +} + + +impl BuildHelper { + pub fn new(crate_env: HashMap) -> Self { + Self { + crate_env, + } + } + + pub fn crate_name(&self) -> String { + self.crate_env["CARGO_PKG_NAME"].clone() + } + + pub fn dir_crate(&self) -> PathBuf { + PathBuf::from(self.crate_env["CARGO_MANIFEST_DIR"].clone()) + } + + pub fn build(self) { + let use_linking = parse_bool_from_option(self.crate_env.get("USE_LINKING"), self.crate_env.get("CARGO_TARGET_DIR").is_none()); + let dir_crate = self.dir_crate(); + let dir_git = dir_crate.parent().unwrap().parent().unwrap(); + + println!("cargo:rerun-if-changed={}", dir_git.display()); + + if use_linking { + if let Some(git_build_dir) = self.crate_env.get("GIT_BUILD_DIR") { + let path_git_build_dir = PathBuf::from(git_build_dir); + let is_abs = path_git_build_dir.is_absolute(); + if !is_abs { + panic!("GIT_BUILD_DIR must be an absolute path: {}'", path_git_build_dir.display()); + } + if !path_git_build_dir.is_dir() { + panic!("'GIT_BUILD_DIR' is not a directory: {}", path_git_build_dir.display()); + } + println!("cargo:rustc-link-search=native={}", git_build_dir); + } else { + panic!("environment variable 'GIT_BUILD_DIR' is not set"); + } + + println!("cargo:rustc-link-lib=static=git"); + println!("cargo:rustc-link-lib=pcre2-8"); + if self.crate_env.get("ZLIB_NG").is_some() { + println!("cargo:rustc-link-lib=z-ng"); + } else { + println!("cargo:rustc-link-lib=z"); + } + } else { + println!("cargo:warning={} is not linking against C objects, `USE_LINKING=true cargo test`", self.crate_env["CARGO_PKG_NAME"]); + } + } +} From 288bdb39d23a0130876cad8d52ab54cbc4463a1d Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 13 Nov 2025 15:41:43 -0700 Subject: [PATCH 08/13] rust/gitcore: link with c Signed-off-by: Ezekiel Newren --- Cargo.toml | 1 + rust/gitcore/Cargo.toml | 6 ++++-- rust/gitcore/build.rs | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 rust/gitcore/build.rs diff --git a/Cargo.toml b/Cargo.toml index b7b5890934389e..4585fda0fc0eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,6 @@ members = [ "rust/generate-headers", "rust/gitcore", + "rust/link-with-c", ] resolver = "2" diff --git a/rust/gitcore/Cargo.toml b/rust/gitcore/Cargo.toml index 2f51bf5d5ff5f8..fadac77d4278fa 100644 --- a/rust/gitcore/Cargo.toml +++ b/rust/gitcore/Cargo.toml @@ -2,9 +2,11 @@ name = "gitcore" version = "0.1.0" edition = "2018" -rust-version = "1.49.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib", "rlib"] [dependencies] + +[build-dependencies] +link-with-c = { path = "../link-with-c" } diff --git a/rust/gitcore/build.rs b/rust/gitcore/build.rs new file mode 100644 index 00000000000000..7427a5e45ddd58 --- /dev/null +++ b/rust/gitcore/build.rs @@ -0,0 +1,7 @@ +use link_with_c::BuildHelper; + +fn main() { + BuildHelper::new(std::env::vars().collect()) + // .generate_header(|_|{}) + .build(); +} From 8649a6c0f6633c13fa1c0ae2ff05889043d1d8b7 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 20 Nov 2025 11:58:39 -0700 Subject: [PATCH 09/13] varint.h: unsigned char -> uint8_t Signed-off-by: Ezekiel Newren --- varint.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/varint.h b/varint.h index eb401935bd24c9..a618a4b1ce362d 100644 --- a/varint.h +++ b/varint.h @@ -1,7 +1,7 @@ #ifndef VARINT_H #define VARINT_H -uint8_t encode_varint(uint64_t, unsigned char *); -uint64_t decode_varint(const unsigned char **); +uint8_t encode_varint(uint64_t, uint8_t *); +uint64_t decode_varint(const uint8_t **); #endif /* VARINT_H */ From 72429e04843a90e3cf9a1d697c1ca7f57de8950f Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 20 Nov 2025 12:00:25 -0700 Subject: [PATCH 10/13] make: delete files in generated/ Signed-off-by: Ezekiel Newren --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8a73afca1686f9..6da9db7d8322b7 100644 --- a/Makefile +++ b/Makefile @@ -953,7 +953,7 @@ rust-compile: done rust-clean: - $(RM) $(RUST_LIBS) Cargo.lock generated/ + $(RM) $(RUST_LIBS) Cargo.lock generated/*.h cargo clean $(GIT_BUILD_DIR)/lib%.a: From 218f995c384ad7e97589d56a8ae09b6782666836 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 20 Nov 2025 13:31:05 -0700 Subject: [PATCH 11/13] github-workflows: unify with rust parameters in make and meson -Drust=enabled -> -Dwith_rust=enabled WITH_RUST=YesPlease -> WITH_RUST=true Signed-off-by: Ezekiel Newren --- ci/run-build-and-tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 8bda62b921920f..d4f7cbd15f4078 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -8,9 +8,9 @@ case "$jobname" in fedora-breaking-changes-musl|linux-breaking-changes) export WITH_BREAKING_CHANGES=YesPlease - export WITH_RUST=YesPlease + export WITH_RUST=true MESONFLAGS="$MESONFLAGS -Dbreaking_changes=true" - MESONFLAGS="$MESONFLAGS -Drust=enabled" + MESONFLAGS="$MESONFLAGS -Dwith_rust=enabled" ;; linux-TEST-vars) export OPENSSL_SHA1_UNSAFE=YesPlease From 20558a8e1e037227b194e9a04c0a9c461e214fb7 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Thu, 20 Nov 2025 15:26:43 -0700 Subject: [PATCH 12/13] github workflows: install Rust Signed-off-by: Ezekiel Newren --- .github/workflows/main.yml | 62 +++++++++++++++++++++++++++++++++++- ci/install-dependencies.sh | 14 ++++---- ci/install-rust-toolchain.sh | 30 +++++++++++++++++ ci/install-rustup.sh | 25 +++++++++++++++ ci/make-test-artifacts.sh | 9 ++++++ ci/run-build-and-tests.sh | 13 ++++++++ 6 files changed, 145 insertions(+), 8 deletions(-) create mode 100755 ci/install-rust-toolchain.sh create mode 100755 ci/install-rustup.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cc54824c388371..396b0108a0c86b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,6 +26,13 @@ jobs: outputs: enabled: ${{ steps.check-ref.outputs.enabled }}${{ steps.skip-if-redundant.outputs.enabled }} skip_concurrent: ${{ steps.check-ref.outputs.skip_concurrent }} + rust_version_minimum: 1.63.0 + rust_version_windows: 1.78.0 + rust_version_musl: 1.72.0 + ## the rust target is inferred by rustup unless specified + rust_target_windows_make: x86_64-pc-windows-gnu + rust_target_windows_meson: x86_64-pc-windows-msvc + rust_target_32bit_linux: i686-unknown-linux-gnu steps: - name: try to clone ci-config branch run: | @@ -108,12 +115,28 @@ jobs: needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' runs-on: windows-latest + env: + CARGO_HOME: "/c/Users/runneradmin/.cargo" concurrency: group: windows-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v5 - uses: git-for-windows/setup-git-for-windows-sdk@v1 + with: + flavor: full + - name: Install rustup via github actions + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: false + - name: Install Rust toolchain + shell: bash + env: + RUST_VERSION: ${{ needs.ci-config.outputs.rust_version_windows }} + RUST_TARGET: ${{ needs.ci-config.outputs.rust_target_windows_make }} + run: ci/install-rust-toolchain.sh - name: build shell: bash env: @@ -254,12 +277,26 @@ jobs: needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' runs-on: windows-latest + env: + CARGO_HOME: "/c/Users/runneradmin/.cargo" concurrency: group: windows-meson-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 + - name: Install rustup via github actions + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: false + - name: Install Rust toolchain + shell: bash + env: + RUST_VERSION: ${{ needs.ci-config.outputs.rust_version_windows }} + RUST_TARGET: ${{ needs.ci-config.outputs.rust_target_windows_meson }} + run: ci/install-rust-toolchain.sh - name: Set up dependencies shell: pwsh run: pip install meson ninja @@ -329,11 +366,24 @@ jobs: jobname: ${{matrix.vector.jobname}} CI_JOB_IMAGE: ${{matrix.vector.pool}} TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t + CARGO_HOME: "/Users/runner/.cargo" runs-on: ${{matrix.vector.pool}} steps: - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - - run: ci/run-build-and-tests.sh + - name: Install rustup via github actions + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: false + - name: Install Rust toolchain + shell: bash + env: + RUST_VERSION: ${{ needs.ci-config.outputs.rust_version_minimum }} + run: ci/install-rust-toolchain.sh + - name: Run build and tests + run: ci/run-build-and-tests.sh - name: print test failures if: failure() && env.FAILED_TEST_ARTIFACTS != '' run: ci/print-test-failures.sh @@ -395,9 +445,11 @@ jobs: cc: gcc - jobname: linux-musl-meson image: alpine:latest + rust_version_override: ${{ needs.ci-config.outputs.rust_version_musl }} # Supported until 2025-04-02. - jobname: linux32 image: i386/ubuntu:focal + rust_target_override: ${{ needs.ci-config.outputs.rust_target_32bit_linux }} # A RHEL 8 compatible distro. Supported until 2029-05-31. - jobname: almalinux-8 image: almalinux:8 @@ -409,6 +461,7 @@ jobs: CC: ${{matrix.vector.cc}} CI_JOB_IMAGE: ${{matrix.vector.image}} CUSTOM_PATH: /custom + CARGO_HOME: /home/builder/.cargo runs-on: ubuntu-latest container: ${{matrix.vector.image}} steps: @@ -433,6 +486,13 @@ jobs: - run: ci/install-dependencies.sh - run: useradd builder --create-home - run: chown -R builder . + - name: Install rustup via script + run: sudo --preserve-env --set-home --user=builder ci/install-rustup.sh + - name: Install Rust toolchain + env: + RUST_VERSION: ${{ matrix.vector.rust_version_override || needs.ci-config.outputs.rust_version_minimum }} + RUST_TARGET: ${{ matrix.vector.rust_target_override || '' }} + run: sudo --preserve-env --set-home --user=builder ci/install-rust-toolchain.sh - run: sudo --preserve-env --set-home --user=builder ci/run-build-and-tests.sh - name: print test failures if: failure() && env.FAILED_TEST_ARTIFACTS != '' diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh index 50628ee2dd6ac7..f1b3ee2dd9bb20 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -26,7 +26,7 @@ fi case "$distro" in alpine-*) - apk add --update shadow sudo meson ninja-build gcc libc-dev curl-dev openssl-dev expat-dev gettext \ + apk add --update shadow sudo meson ninja-build gcc libc-dev curl curl-dev openssl-dev expat-dev gettext \ zlib-ng-dev pcre2-dev python3 musl-libintl perl-utils ncurses \ apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \ bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null @@ -37,7 +37,7 @@ fedora-*|almalinux-*) MESON_DEPS="meson ninja";; esac dnf -yq update >/dev/null && - dnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null + dnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null ;; ubuntu-*|i386/ubuntu-*|debian-*) # Required so that apt doesn't wait for user input on certain packages. @@ -61,8 +61,8 @@ ubuntu-*|i386/ubuntu-*|debian-*) sudo apt-get -q update sudo apt-get -q -y install \ $LANGUAGES apache2 cvs cvsps git gnupg $SVN \ - make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \ - tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \ + make libssl-dev curl libcurl4-openssl-dev libexpat-dev wget sudo default-jre \ + tcl tk gettext zlib1g zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \ libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \ libsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \ ${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE @@ -134,7 +134,7 @@ ClangFormat) sudo apt-get -q -y install clang-format ;; StaticAnalysis) - sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \ + sudo apt-get -q -y install coccinelle curl libcurl4-openssl-dev libssl-dev \ libexpat-dev gettext make ;; RustAnalysis) @@ -149,8 +149,8 @@ RustAnalysis) sudo chmod a+x "$CUSTOM_PATH/cargo-msrv" ;; sparse) - sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \ - libexpat-dev gettext zlib1g-dev sparse + sudo apt-get -q -y install libssl-dev curl libcurl4-openssl-dev \ + libexpat-dev gettext zlib1g zlib1g-dev sparse ;; Documentation) sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make diff --git a/ci/install-rust-toolchain.sh b/ci/install-rust-toolchain.sh new file mode 100755 index 00000000000000..06a29c4cfa17f8 --- /dev/null +++ b/ci/install-rust-toolchain.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ "$CARGO_HOME" = "" ]; then + echo >&2 "::error:: CARGO_HOME is not set" + exit 2 +fi +export PATH="$CARGO_HOME/bin:$PATH" +rustup -vV || exit $? + +## Enforce the correct Rust toolchain +rustup override unset || true + +## install a specific version of rust +if [ "$RUST_TARGET" != "" ]; then + rustup default --force-non-host "$RUST_VERSION-$RUST_TARGET" || exit $? +else + rustup default "$RUST_VERSION" || exit $? +fi + +rustc -vV || exit $? + +RE_RUST_TARGET="$RUST_TARGET" +if [ "$RUST_TARGET" = "" ]; then + RE_RUST_TARGET="[^ ]+" +fi + +if ! rustup show active-toolchain | grep -E "^$RUST_VERSION-$RE_RUST_TARGET \(default\)$"; then + echo >&2 "::error:: wrong Rust toolchain, active-toolchain: $(rustup show active-toolchain)" + exit 3 +fi diff --git a/ci/install-rustup.sh b/ci/install-rustup.sh new file mode 100755 index 00000000000000..0036231aeea7f2 --- /dev/null +++ b/ci/install-rustup.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +## github workflows actions-rs/toolchain@v1 doesn't work for docker +## targets. This script should only be used if the ci pipeline +## doesn't support installing rust on a particular target. + +if [ "$(id -u)" -eq 0 ]; then + echo >&2 "::warning:: installing rust as root" +fi + +if [ "$CARGO_HOME" = "" ]; then + echo >&2 "::error:: CARGO_HOME is not set" + exit 2 +fi + +export RUSTUP_HOME=$CARGO_HOME + +## install rustup +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain none -y +if [ ! -f $CARGO_HOME/env ]; then + echo "PATH=$CARGO_HOME/bin:\$PATH" > $CARGO_HOME/env +fi +. $CARGO_HOME/env + +rustup -vV diff --git a/ci/make-test-artifacts.sh b/ci/make-test-artifacts.sh index 74141af0cc7462..e37ed7030cdf07 100755 --- a/ci/make-test-artifacts.sh +++ b/ci/make-test-artifacts.sh @@ -7,6 +7,15 @@ mkdir -p "$1" # in case ci/lib.sh decides to quit early . ${0%/*}/lib.sh +## ensure rustup is in the PATH variable +if [ "$CARGO_HOME" = "" ]; then + echo >&2 "::error:: CARGO_HOME is not set" + exit 2 +fi +export PATH="$CARGO_HOME/bin:$PATH" + +rustc -vV + group Build make artifacts-tar ARTIFACTS_DIRECTORY="$1" check_unignored_build_artifacts diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index d4f7cbd15f4078..e87c5174c41775 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -5,6 +5,15 @@ . ${0%/*}/lib.sh +## ensure rustup is in the PATH variable +if [ "$CARGO_HOME" = "" ]; then + echo >&2 "::error:: CARGO_HOME is not set" + exit 2 +fi +. $CARGO_HOME/env + +rustc -vV || exit $? + case "$jobname" in fedora-breaking-changes-musl|linux-breaking-changes) export WITH_BREAKING_CHANGES=YesPlease @@ -60,5 +69,9 @@ case "$jobname" in ;; esac +if [ -d "$CARGO_HOME" ]; then + rm -rf $CARGO_HOME +fi + check_unignored_build_artifacts save_good_tree From 0f797a238c3c102814a3402caca2539a518ecb74 Mon Sep 17 00:00:00 2001 From: Ezekiel Newren Date: Fri, 21 Nov 2025 17:51:45 -0700 Subject: [PATCH 13/13] rust/build-rust.sh: update dir_git_root variable instantiation Signed-off-by: Ezekiel Newren --- Makefile | 6 ++++-- meson.build | 1 + rust/build-crate.sh | 15 ++++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 6da9db7d8322b7..848db0322767d4 100644 --- a/Makefile +++ b/Makefile @@ -931,6 +931,8 @@ EXTLIBS = GIT_BUILD_DIR := $(CURDIR) export GIT_BUILD_DIR +MAKEFILE_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +export MAKEFILE_DIR RUST_CRATES := gitcore .PHONY: rust-compile rust-clean @@ -949,7 +951,7 @@ RUST_LIBS := $(foreach c,$(RUST_CRATES),$(GIT_BUILD_DIR)/lib$(c).a) rust-compile: @for c in $(RUST_CRATES); do \ echo "Building $$c..."; \ - ./rust/build-crate.sh $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $$c || exit $$?; \ + ./rust/build-crate.sh $(MAKEFILE_DIR) $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $$c || exit $$?; \ done rust-clean: @@ -958,7 +960,7 @@ rust-clean: $(GIT_BUILD_DIR)/lib%.a: echo $(RUST_LIBS) - ./rust/build-crate.sh $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $* + ./rust/build-crate.sh $(MAKEFILE_DIR) $(GIT_BUILD_DIR) $(RUST_BUILD_MODE) $* UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) diff --git a/meson.build b/meson.build index 94ec5e4ac0b0ff..3154cd684afea3 100644 --- a/meson.build +++ b/meson.build @@ -305,6 +305,7 @@ if with_rust build_always_stale: true, command: [ meson.project_source_root() / 'rust' / 'build-crate.sh', + meson.project_source_root(), meson.current_build_dir(), rust_build_profile, crate, ], install: false, diff --git a/rust/build-crate.sh b/rust/build-crate.sh index b3debf70e5f69b..50f5b0058c6f5f 100755 --- a/rust/build-crate.sh +++ b/rust/build-crate.sh @@ -3,10 +3,12 @@ rustc -vV || exit $? cargo --version || exit $? -dir_git_root=${0%/*} -dir_build=$1 -rust_build_profile=$2 -crate=$3 +dir_git_root=$1 +cd $dir_git_root || exit $? +dir_git_root=$PWD +dir_build=$2 +rust_build_profile=$3 +crate=$4 if [ "$dir_git_root" = "" ]; then echo "did not specify the directory for the root of git" @@ -38,9 +40,12 @@ libfile="lib${crate}.a" if rustc -vV | grep windows-msvc; then libfile="${crate}.lib" PATH="$(echo $PATH | tr ':' '\n' | grep -Ev "^(/mingw64/bin|/usr/bin)$" | paste -sd: -):/mingw64/bin:/usr/bin" + echo "PATH=$PATH" fi -CARGO_TARGET_DIR=$dir_git_root/.build/rust/$crate +echo "libfile=$libfile" + +CARGO_TARGET_DIR=$dir_build/.build/rust/$crate export CARGO_TARGET_DIR cargo clean && pwd && USE_LINKING="false" cargo build -p $crate $rust_args