Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions package/generate_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env python3
Copy link
Contributor

@yerzhan7 yerzhan7 Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we commit the generated spec file to this git repo? Otherwise, it's hard for me as a reviewer to review the final spec file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, i'll add it in the next revision

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make this file as executable?

chmod +x package/generate_spec.py


"""
This RPM spec generator creates distribution-specific .spec files using template inheritance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this accurate?

It extracts versions from Cargo.toml/rust-toolchain.toml, scans git submodules for bundled library declarations,
and uses a base template with distribution-specific overrides.

The script takes a target distribution (like amzn2023), loads the corresponding template,
and outputs a complete RPM spec file ready for rpmbuild.
"""

import argparse
import subprocess
from pathlib import Path
import sys
from datetime import datetime
from jinja2 import Environment, FileSystemLoader
import tomllib

script_dir = Path(__file__).parent
project_root = script_dir.parent
templates_dir = script_dir / "templates"


def get_version():
cargo_path = project_root / "mountpoint-s3" / "Cargo.toml"
with open(cargo_path, "rb") as f:
data = tomllib.load(f)
return data["package"]["version"]


def get_rust_version():
rust_path = project_root / "rust-toolchain.toml"
with open(rust_path, "rb") as f:
data = tomllib.load(f)
return data["toolchain"]["channel"]


def get_submodule_versions():
result = subprocess.run(
'git submodule foreach -q \'echo $name `git describe --tags`\'', capture_output=True, text=True, shell=True
)
versions = {}
for line in result.stdout.strip().split('\n'):
if line.strip():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this if statement need to be here?

match line.strip().split(' ', 1):
case [name, version]:
versions[name] = version.lstrip('v')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: use removeprefix

return versions


def generate_bundled_provides(submodule_versions):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not actually using this function

return "\n".join(
[f"Provides: bundled({lib_name}) = {lib_version}" for lib_name, lib_version in submodule_versions.items()]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a generator comprehension suffices

)


def main():
parser = argparse.ArgumentParser(description="Generate RPM spec files for different distributions")
parser.add_argument("build_target", help="Target distribution (e.g., amzn2023)")

args = parser.parse_args()
build_target = args.build_target
template_file = f"{build_target}.spec.template"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be another argument?


# Checking if template exists
template_path = templates_dir / template_file
if not template_path.exists():
print(f"Error: Template file {template_path} not found")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raise an exception

sys.exit(1)

version = get_version()
rust_version = get_rust_version()
submodule_versions = get_submodule_versions()
current_date = datetime.now().strftime("%a %b %d %Y")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've traditionally used this April 9, 2025 as our date format - why change it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its RPM changelog format, they include the day, you can double check by running dnf changelog x .


template_data = {
'version': version,
'rust_version': rust_version,
'build_target': build_target,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is always constant for a given spec file. Why do we need to pass this in as an argument?

'current_date': current_date,
'submodule_versions': submodule_versions,
}

# Setting up template env
env = Environment(loader=FileSystemLoader(templates_dir), trim_blocks=True, lstrip_blocks=True)

template = env.get_template(template_file)

spec_content = template.render(**template_data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use kwarg splatting here when you can just pass in arguments normally?


output_file = f"{build_target}.spec"
with open(output_file, "w") as f:
f.write(spec_content)

print(f"Generated {output_file}")


if __name__ == "__main__":
main()
103 changes: 103 additions & 0 deletions package/templates/amzn2023.spec.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{# Amazon Linux 2023 Complete RPM Spec Template #}
%bcond_without check

Copy link
Contributor Author

@tadiwa-aizen tadiwa-aizen Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the spec file created:

%bcond_without check

Name:           mount-s3
Version:        1.21.0
Release:        amzn2023
Summary:        Mountpoint for Amazon S3

License:        Apache-2.0
URL:            https://github.com/awslabs/mountpoint-s3 
Source0:        mountpoint-s3-1.21.0.tar.gz
Source1:        LICENSE
Source2:        NOTICE
Source3:        THIRD_PARTY_LICENSES

BuildRequires:  clang
BuildRequires:  clang-devel
BuildRequires:  rust >= 1.88      
BuildRequires:  cargo >= 1.88    
BuildRequires:  cmake
BuildRequires:  gcc
BuildRequires:  gcc-c++
BuildRequires:  git
BuildRequires:  pkgconfig
BuildRequires:  fuse-devel
BuildRequires:  glibc-devel
BuildRequires:  glibc-headers
BuildRequires:  glibc-static
BuildRequires:  libstdc++-devel
BuildRequires:  nasm
BuildRequires:  make
BuildRequires:  which
BuildRequires:  rust-packaging
BuildRequires:  rust-toolset

ExclusiveArch: x86_64 aarch64

Provides: bundled(aws-c-auth) = 0.9.0
Provides: bundled(aws-c-cal) = 0.9.2
Provides: bundled(aws-c-common) = 0.12.4
Provides: bundled(aws-c-compression) = 0.3.1
Provides: bundled(aws-c-http) = 0.10.3
Provides: bundled(aws-c-io) = 0.21.1
Provides: bundled(aws-c-s3) = 0.8.5
Provides: bundled(aws-c-sdkutils) = 0.2.4
Provides: bundled(aws-checksums) = 0.2.6
Provides: bundled(aws-lc) = 1.53.1
Provides: bundled(s2n-tls) = 1.5.18

Requires:       ca-certificates
Requires:       fuse >= 2.9.0
Requires:       fuse-libs >= 2.9.0

%description
Mountpoint for Amazon S3 is a simple, high-throughput file client for
mounting an Amazon S3 bucket as a local file system. With Mountpoint for Amazon
S3, your applications can access objects stored in Amazon S3 through file
operations like open and read. Mountpoint for Amazon S3 automatically
translates these operations into S3 object API calls, giving your applications
access to the elastic storage and throughput of Amazon S3 through a file
interface.

%build
export CFLAGS="${CFLAGS:-%{optflags}} -O2 -Wno-error=cpp"
export CMAKE_C_FLAGS="$CFLAGS"

export MOUNTPOINT_S3_AWS_RELEASE="amzn2023"

cargo build --release

%cargo_vendor_manifest

%prep
%autosetup -n mountpoint-s3
%cargo_prep -v vendor

%install
mkdir -p %{buildroot}/opt/aws/mountpoint-s3/bin
mkdir -p %{buildroot}/%{_prefix}/sbin
mkdir -p %{buildroot}/%{_bindir}
install -m 755 target/release/mount-s3 %{buildroot}/opt/aws/mountpoint-s3/bin/mount-s3
install -m 644 NOTICE %{buildroot}/opt/aws/mountpoint-s3/
install -m 644 LICENSE %{buildroot}/opt/aws/mountpoint-s3/
install -m 644 THIRD_PARTY_LICENSES %{buildroot}/opt/aws/mountpoint-s3/
install -m 644 cargo-vendor.txt %{buildroot}/opt/aws/mountpoint-s3/
echo "1.21.0" > %{buildroot}/opt/aws/mountpoint-s3/VERSION
ln -sf /opt/aws/mountpoint-s3/bin/mount-s3 %{buildroot}/%{_bindir}/mount-s3
ln -sf /opt/aws/mountpoint-s3/bin/mount-s3 %{buildroot}/%{_prefix}/sbin/mount.mount-s3

%files
%defattr(-,root,root,-)
%dir %attr(755,root,root) /opt/aws/mountpoint-s3
%dir %attr(755,root,root) /opt/aws/mountpoint-s3/bin
%attr(755,root,root) /opt/aws/mountpoint-s3/bin/mount-s3
%doc %attr(644,root,root) /opt/aws/mountpoint-s3/NOTICE
%license %attr(644,root,root) /opt/aws/mountpoint-s3/LICENSE
%license %attr(644,root,root) /opt/aws/mountpoint-s3/cargo-vendor.txt
%attr(644,root,root) /opt/aws/mountpoint-s3/THIRD_PARTY_LICENSES
%attr(644,root,root) /opt/aws/mountpoint-s3/VERSION
%attr(755,root,root) %{_bindir}/mount-s3
%attr(755,root,root) %{_prefix}/sbin/mount.mount-s3

%changelog
* Thu Oct 09 2025 Mountpoint-S3 Team <s3-opensource@amazon.com> - 1.21.0+amzn2023
- Mountpoint-S3 1.21.0 amzn2023 release
- Refer to https://github.com/awslabs/mountpoint-s3/blob/main/mountpoint-s3/CHANGELOG.md

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see rust >= 1.88. I thought we agreed to change it to exact version, no? rust = 1.88

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, Source0: mountpoint-s3-%{version}.tar.gz still didn't to resolve to exact version? mountpoint-s3-1.21.0.tar.gz

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see rust >= 1.88. I thought we agreed to change it to exact version, no? rust = 1.88

Discussed offline.

Name: mount-s3
Version: {{ version }}
Release: {{ build_target }}
Summary: Mountpoint for Amazon S3

License: Apache-2.0
URL: https://github.com/awslabs/mountpoint-s3
Source0: mountpoint-s3-{{ version }}.tar.gz
Source1: LICENSE
Source2: NOTICE
Source3: THIRD_PARTY_LICENSES

{# Build dependencies #}
BuildRequires: clang
BuildRequires: clang-devel
BuildRequires: rust >= {{ rust_version }}
BuildRequires: cargo >= {{ rust_version }}
BuildRequires: cmake
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: git
BuildRequires: pkgconfig
BuildRequires: fuse-devel
BuildRequires: glibc-devel
BuildRequires: glibc-headers
BuildRequires: glibc-static
BuildRequires: libstdc++-devel
BuildRequires: nasm
BuildRequires: make
BuildRequires: which
BuildRequires: rust-packaging
BuildRequires: rust-toolset

{# Supported architectures #}
ExclusiveArch: x86_64 aarch64

{# Bundled C/C++ libraries for security tracking #}
{% for lib_name, lib_version in submodule_versions.items() %}
Provides: bundled({{ lib_name }}) = {{ lib_version }}
{% endfor %}

{# Runtime dependencies #}
Requires: ca-certificates
Requires: fuse >= 2.9.0
Requires: fuse-libs >= 2.9.0

%description
Mountpoint for Amazon S3 is a simple, high-throughput file client for
mounting an Amazon S3 bucket as a local file system. With Mountpoint for Amazon
S3, your applications can access objects stored in Amazon S3 through file
operations like open and read. Mountpoint for Amazon S3 automatically
translates these operations into S3 object API calls, giving your applications
access to the elastic storage and throughput of Amazon S3 through a file
interface.

{# Build commands #}
%build
export CFLAGS="${CFLAGS:-%{optflags}} -O2 -Wno-error=cpp"
export CMAKE_C_FLAGS="$CFLAGS"

export MOUNTPOINT_S3_AWS_RELEASE="{{ build_target }}"

cargo build --release

%cargo_vendor_manifest

%prep
%autosetup -n mountpoint-s3
%cargo_prep -v vendor

%install
mkdir -p %{{buildroot}}/opt/aws/mountpoint-s3/bin
mkdir -p %{{buildroot}}/%{{_prefix}}/sbin
mkdir -p %{{buildroot}}/%{{_bindir}}
install -m 755 target/release/mount-s3 %{{buildroot}}/opt/aws/mountpoint-s3/bin/mount-s3
install -m 644 NOTICE %{{buildroot}}/opt/aws/mountpoint-s3/
install -m 644 LICENSE %{{buildroot}}/opt/aws/mountpoint-s3/
install -m 644 THIRD_PARTY_LICENSES %{{buildroot}}/opt/aws/mountpoint-s3/
install -m 644 cargo-vendor.txt %{{buildroot}}/opt/aws/mountpoint-s3/
echo "%{{version}}" > %{{buildroot}}/opt/aws/mountpoint-s3/VERSION
ln -sf /opt/aws/mountpoint-s3/bin/mount-s3 %{{buildroot}}/%{{_bindir}}/mount-s3
ln -sf /opt/aws/mountpoint-s3/bin/mount-s3 %{{buildroot}}/%{{_prefix}}/sbin/mount.mount-s3

%files
%defattr(-,root,root,-)
%dir %attr(755,root,root) /opt/aws/mountpoint-s3
%dir %attr(755,root,root) /opt/aws/mountpoint-s3/bin
%attr(755,root,root) /opt/aws/mountpoint-s3/bin/mount-s3
%doc %attr(644,root,root) /opt/aws/mountpoint-s3/NOTICE
%license %attr(644,root,root) /opt/aws/mountpoint-s3/LICENSE
%license %attr(644,root,root) /opt/aws/mountpoint-s3/cargo-vendor.txt
%attr(644,root,root) /opt/aws/mountpoint-s3/THIRD_PARTY_LICENSES
%attr(644,root,root) /opt/aws/mountpoint-s3/VERSION
%attr(755,root,root) %{_bindir}/mount-s3
%attr(755,root,root) %{_prefix}/sbin/mount.mount-s3

%changelog
* {{ current_date }} Mountpoint-S3 Team <s3-opensource@amazon.com> - {{ version }}+{{ build_target }}
- Mountpoint-S3 {{ version }} {{ build_target }} release
- Refer to https://github.com/awslabs/mountpoint-s3/blob/main/mountpoint-s3/CHANGELOG.md
Loading