Skip to content

Commit

Permalink
Merge pull request #170 from felddy/improvement/rust-binary
Browse files Browse the repository at this point in the history
Replace test binary with a Rust implementation
  • Loading branch information
felddy authored Jan 22, 2024
2 parents 665fbb2 + 9fbc6af commit 285e4f2
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 52 deletions.
3 changes: 3 additions & 0 deletions .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
- name: "regression :boom:"
color: "cd8703"
description: ""
- name: "rust :crab:"
color: "dea584"
description: ""
- name: "sponsor :sparkling_heart:"
color: "fedbf0"
description: ""
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
inputs:
platforms:
description: "The platforms to build (CSV)"
default: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
default: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
required: false
type: string
outputs:
Expand Down
23 changes: 23 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
authors = ["Mark Feldhousen <markf@geekpad.com>"]
categories = ["command-line-utilities"]
description = "A tool to determine the architecture of a system."
documentation = "https://github.com/felddy/reusable-workflows/blob/develop/README.md"
edition = "2021"
homepage = "https://github.com/felddy/reusable-workflows"
keywords = ["architecture", "system", "cross-platform"]
license = "CC0-1.0"
name = "arch-info"
repository = "https://github.com/felddy/reusable-workflows"
version = "0.0.1"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[dev-dependencies]

[profile.release]
codegen-units = 1
lto = true
opt-level = 'z' # Optimize for size.
32 changes: 21 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,41 @@
FROM --platform=$BUILDPLATFORM tonistiigi/xx:latest AS xx

# Base image for the build
FROM --platform=$BUILDPLATFORM debian:bookworm AS build
FROM --platform=$BUILDPLATFORM rust:bookworm AS build

# Copy the xx scripts for setting up the cross-compilation environment
COPY --from=xx / /

# Install build dependencies
RUN apt-get update && apt-get install -y \
clang

# Set up the working directory
WORKDIR /workspace

# Copy the C source file into the image
COPY src/arch_info.c .
# Set RUSTFLAGS for static linking with the GNU toolchain
ENV RUSTFLAGS='-C target-feature=+crt-static'

# Install clang and other necessary tools
RUN apt-get update && \
apt-get install -y clang lld

# Copy the Cargo.toml (and Cargo.lock if available) and source file into the image
COPY Cargo.toml Cargo.lock* ./

# Copy the Rust source file into the image
COPY src/main.rs ./src/

# Compile the program for the target platform
ARG TARGETPLATFORM
RUN xx-apt install -y libc6-dev gcc
RUN xx-clang --static -o arch_info arch_info.c
RUN xx-apt install -y gcc libc6-dev
RUN xx-cargo build --release --target-dir ./build
RUN xx-verify ./build/$(xx-cargo --print-target-triple)/release/arch-info

# Link the compiled binary into the workspace root
RUN ln -v ./build/$(xx-cargo --print-target-triple)/release/arch-info .

# Stage 2: Create the final minimal output image
FROM scratch

# Copy the compiled binary from the build stage
COPY --from=build /workspace/arch_info /
COPY --from=build /workspace/arch-info /

# Set the entry point to the compiled binary
ENTRYPOINT ["/arch_info"]
ENTRYPOINT ["/arch-info"]
22 changes: 14 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

# Standard Python Libraries
from glob import glob
from os.path import basename, splitext
from os.path import basename, dirname, join, splitext
import re

# Third-Party Libraries
from setuptools import find_packages, setup
Expand All @@ -22,18 +23,23 @@ def readme():
return f.read()


def package_vars(version_file):
"""Read in and return the variables defined by the version_file."""
pkg_vars = {}
with open(version_file) as f:
exec(f.read(), pkg_vars) # nosec
return pkg_vars
def cargo_version():
"""Manually extract version from Cargo.toml."""
cargo_toml_path = join(dirname(__file__), "Cargo.toml")
version_pattern = r'^version\s*=\s*"(.*?)"$'
with open(cargo_toml_path, encoding="utf-8") as f:
for line in f:
match = re.match(version_pattern, line.strip())
if match:
return match.group(1)
# Raise an exception if version is not found
raise RuntimeError("Version not found in Cargo.toml")


setup(
name="reusable-workflows",
# Versions should comply with PEP440
version=package_vars("src/_version.py")["__version__"],
version=cargo_version(),
description="reusable workflows for GitHub Actions",
long_description=readme(),
long_description_content_type="text/markdown",
Expand Down
3 changes: 0 additions & 3 deletions src/_version.py

This file was deleted.

29 changes: 0 additions & 29 deletions src/arch_info.c

This file was deleted.

53 changes: 53 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/// Prints the architecture string based on the current compilation target.
/// - If the architecture is known, prints the architecture string and exits with code 0 (success).
/// - If the architecture is unknown, prints a message and exits with code 1 (error).
use std::process;

/// Entry point of the application.
fn main() {
match get_architecture() {
// If an architecture is identified, print it and exit with code 0 (success).
Some(arch) => {
println!("{}", arch);
process::exit(0);
}
// If the architecture is unknown, print a message and exit with code 1 (error).
None => {
println!("Architecture: Unknown");
process::exit(1);
}
}
}

/// Returns the architecture string based on the current compilation target.
///
/// Uses Rust's conditional compilation features to determine the architecture.
/// Returns `Some(arch_string)` if known, or `None` if the architecture is unknown.
fn get_architecture() -> Option<&'static str> {
match std::env::consts::ARCH {
// ARM 64-bit architecture
"aarch64" => Some("linux/arm64"),
// ARM architecture with further checks for specific versions
"arm" => Some(if cfg!(target_feature = "v7") {
"linux/arm/v7"
} else if cfg!(target_feature = "v6") {
"linux/arm/v6"
} else {
"linux/arm"
}),
// MIPS architecture with endian check
"mips64" => Some(if cfg!(target_endian = "little") {
"linux/mips64le"
} else {
"linux/mips64"
}),
// Other architectures without specific version checks
"powerpc64" => Some("linux/ppc64le"),
"riscv64" => Some("linux/riscv64"),
"s390x" => Some("linux/s390x"),
"x86_64" => Some("linux/amd64"),
"x86" => Some("linux/386"),
// Fallback case for unknown architectures
_ => None,
}
}

0 comments on commit 285e4f2

Please sign in to comment.