commit df82b50333bc178afe8fc5221c4e0a6ac5036c1f
parent 672fa4cef6382c7686c0270c9d78f3fccc5ddf3e
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 4 Aug 2026 09:47:54 +0200
avoid need for rustup
Diffstat:
9 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,6 +1,7 @@
.rustc_info.json
Cargo.lock
debian/.debhelper/
+debian/cargo/
debian/debhelper-build-stamp
debian/files
debian/robocop/
@@ -8,5 +9,6 @@ debian/robocop.substvars
debian/tmp/
release/
target
-*.mk__pycache__/
+*.mk
+__pycache__/
*.pyc
diff --git a/Cargo.toml b/Cargo.toml
@@ -2,6 +2,11 @@
name = "robocop"
version = "1.0.0"
edition = "2024"
+# Edition 2024 needs 1.85, and nothing here needs more: keep it that way so the
+# build works with a distribution's stock cargo/rustc (Debian trixie: 1.85)
+# rather than requiring a rustup-managed toolchain. In particular, avoid
+# let-chains (`if let ... && let ...`), which are 1.88+.
+rust-version = "1.85"
[dependencies]
serde_json = "1.0"
diff --git a/Makefile b/Makefile
@@ -1,6 +1,16 @@
# This Makefile has been placed under the public domain
+
+# Written by ./configure; sets 'prefix' and 'cargo'. The leading '-' keeps it
+# optional and it is included BEFORE the '?=' defaults below, so a configured
+# tree wins while a plain 'make' in an unconfigured tree still builds.
-include build-system/config.mk
+# The Rust toolchain to build with. Any cargo on $PATH works -- the
+# distribution's cargo package, a rustup-managed one, or an explicit override:
+# make build cargo=/opt/rust/bin/cargo
+cargo ?= cargo
+prefix ?= /usr/local
+
# Absolute DESTDIR or empty string if DESTDIR unset/empty
abs_destdir=$(abspath $(DESTDIR))
@@ -11,11 +21,11 @@ all: build
.PHONY: check
check:
- cargo test
+ $(cargo) test
.PHONY: build
build:
- cargo build --release
+ $(cargo) build --release
.PHONY: install
install: build
@@ -30,7 +40,7 @@ install: build
.PHONY: doc
doc:
- cargo doc
+ $(cargo) doc
.PHONY: deb
deb:
diff --git a/build-system/configure.py b/build-system/configure.py
@@ -5,6 +5,9 @@ from talerbuildconfig import *
b = BuildConfig()
b.enable_prefix()
b.enable_configmk()
-b.add_tool(PosixTool("rustup"))
+# cargo is the whole build, so it is the only tool we insist on. Deliberately
+# NOT rustup: robocop builds with whatever Rust toolchain is already installed
+# (the distribution's cargo/rustc packages do fine), so a rustup-managed
+# toolchain is one supported option rather than a prerequisite.
b.add_tool(PosixTool("cargo"))
b.run()
diff --git a/contrib/ci/Containerfile b/contrib/ci/Containerfile
@@ -2,16 +2,21 @@ FROM docker.io/library/debian:trixie
ENV DEBIAN_FRONTEND=noninteractive
+# cargo/rustc are the distribution's own packages (trixie: 1.85), not a
+# rustup-managed toolchain -- the same toolchain the .deb's Build-Depends ask
+# for, so CI builds what a distributor builds.
RUN apt-get update -yqq && \
apt-get install -yqq \
- rustup \
+ cargo \
+ rustc \
python3 \
python3-lxml \
jq \
+ git \
+ git-buildpackage \
po-debconf \
build-essential \
- debhelper && \
- rustup default stable
+ debhelper
WORKDIR /workdir
diff --git a/contrib/ci/jobs/2-deb-package/job.sh b/contrib/ci/jobs/2-deb-package/job.sh
@@ -1,13 +1,25 @@
#!/bin/bash
set -exuo pipefail
+job_dir=$(dirname "${BASH_SOURCE[0]}")
+
# Update system
apt-get update -yq
apt-get upgrade -yq
-# Build package
-export VERSION="$(./contrib/ci/jobs/4-deb-package/version.sh)"
+# Stamp the package with a version derived from the most recent v*.*.* tag plus
+# the distance to HEAD, so every CI build is uniquely versioned and the packages
+# the deploy job pushes actually supersede one another. Without this the
+# version would be whatever debian/changelog says (1.0.0) for every commit.
+export VERSION="$("${job_dir}"/version.sh)"
echo "Building package version ${VERSION}"
+EMAIL=none gbp dch --ignore-branch --debian-tag="%(version)s" --git-author --new-version="${VERSION}"
+
+# Fetch the submodules: the package ships doc/prebuilt/man/robocop.1, and
+# dh_install fails the build outright when that man page is not checked out.
+./bootstrap
+
+# Build package
make deb
# Move to artifact
diff --git a/debian/control b/debian/control
@@ -5,7 +5,8 @@ Maintainer: Christian Grothoff <grothoff@gnu.org>
Rules-Requires-Root: no
Build-Depends:
debhelper-compat (= 13),
- rustup
+ cargo,
+ rustc (>= 1.85)
Standards-Version: 4.7.2
Homepage: https://taler.net/
#Vcs-Browser: https://salsa.debian.org/debian/robocop
diff --git a/debian/rules b/debian/rules
@@ -1,10 +1,21 @@
#!/usr/bin/make -f
+# Keep cargo's registry/cache inside the build tree. cargo fetches crates from
+# the network at build time (this is not an archive-policy-clean offline build),
+# and without this it would write to $HOME, which is not ours to touch under
+# Rules-Requires-Root: no.
+export CARGO_HOME = $(CURDIR)/debian/cargo
+
%:
dh $@ --no-parallel
+# Nothing to configure: the build needs no toolchain setup (it uses the cargo
+# from the cargo Build-Depends), and upstream's ./configure only records the
+# install prefix in build-system/config.mk -- which this package does not use,
+# as debian/robocop.install names explicit paths. The override is still
+# required: ./configure exists, so dh would otherwise select the autoconf build
+# system and call it with autoconf-style options it does not accept.
override_dh_auto_configure:
- rustup default stable
override_dh_auto_build:
make build
@@ -14,3 +25,6 @@ override_dh_auto_test:
override_dh_auto_install:
true
+
+override_dh_auto_clean:
+ rm -rf $(CARGO_HOME) target
diff --git a/src/main.rs b/src/main.rs
@@ -221,13 +221,17 @@ impl MatchingEngine {
let mut matching_fields = 0;
let total_fields = record.fields.len();
+ // Nested rather than a let-chain (`if let ... && let ...`): those
+ // only parse on rustc 1.88+, and we build with the toolchain the
+ // distribution ships (Debian trixie: 1.85).
for (key, input_value) in input {
- if let Some(input_str) = input_value.as_str()
- && let Some(fsm) = record.fields.get(key)
- && let Some((_, score)) = fsm.find_best_match(input_str)
- {
- total_score += score;
- matching_fields += 1;
+ if let Some(input_str) = input_value.as_str() {
+ if let Some(fsm) = record.fields.get(key) {
+ if let Some((_, score)) = fsm.find_best_match(input_str) {
+ total_score += score;
+ matching_fields += 1;
+ }
+ }
}
}
max_fields = max_fields.max(total_fields);