Skip to content

Commit

Permalink
Merge pull request #2952 from boegel/20230621164436_new_pr_rust
Browse files Browse the repository at this point in the history
add custom easyblock for Rust
  • Loading branch information
casparvl authored Jun 23, 2023
2 parents 38919ff + 6c34f05 commit 8a7ffba
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 additions & 0 deletions easybuild/easyblocks/r/rust.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
##
# Copyright 2023-2023 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
EasyBuild support for building and installing Rust, implemented as an easyblock
@author: Kenneth Hoste (Ghent University)
"""
import glob
import os
import re

from easybuild.easyblocks.generic.configuremake import ConfigureMake

from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext


class EB_Rust(ConfigureMake):
"""Support for building/installing Rust."""

def __init__(self, *args, **kwargs):
"""Custom easyblock constructor for Rust."""
super(EB_Rust, self).__init__(*args, **kwargs)

# see https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy
# note: ConfigureMake.build_step automatically adds '-j <parallel>'
self.cfg['build_cmd'] = "./x.py build"
self.cfg['install_cmd'] = "./x.py install -j %(parallel)s"

def configure_step(self):
"""Custom configure step for Rust"""

# perform extended build, which includes cargo, rustfmt, Rust Language Server (RLS), etc.
self.cfg.update('configopts', "--enable-extended")

self.cfg.update('configopts', "--sysconfdir=%s" % os.path.join(self.installdir, 'etc'))

# don't use Ninja if it is not listed as a build dependency;
# may be because Ninja requires Python, and Rust is a build dependency for cryptography
# which may be included as an extension with Python
build_dep_names = set(dep['name'] for dep in self.cfg.dependencies(build_only=True))
if 'Ninja' not in build_dep_names:
self.cfg.update('configopts', "--set=llvm.ninja=false")

super(EB_Rust, self).configure_step()

# avoid failure when home directory is an NFS mount,
# see https://github.com/rust-lang/cargo/issues/6652
cargo_home = "export CARGO_HOME=%s && " % os.path.join(self.builddir, 'cargo')
self.cfg.update('prebuildopts', cargo_home)
self.cfg.update('preinstallopts', cargo_home)

def install_step(self):
"""Custom install step for Rust"""

super(EB_Rust, self).install_step()

if build_option('rpath'):
# make sure that all shared libraries use RPATH, not RUNPATH;
# cfr. https://github.com/easybuilders/easybuild-easyconfigs/issues/18079
shlib_ext = get_shared_lib_ext()
shared_libs = glob.glob(os.path.join(self.installdir, 'lib', 'lib*.%s' % shlib_ext))

runpath_regex = re.compile(r"\(RUNPATH\)\s+Library runpath")

for shared_lib in shared_libs:
out, ec = run_cmd("readelf -d %s" % shared_lib, simple=False, trace=False)
if ec:
raise EasyBuildError("Failed to check RPATH section in %s: %s", shared_lib, out)
elif runpath_regex.search(out):
self.log.info("RUNPATH section found in %s - need to change to RPATH", shared_lib)

# first determine current RUNPATH value
out, ec = run_cmd("patchelf --print-rpath %s" % shared_lib)
if ec:
raise EasyBuildError("Failed to determine current RUNPATH value for %s: %s", shared_lib, out)
else:
runpath = out.strip()
# use RUNPATH value to RPATH value
out, ec = run_cmd("patchelf --set-rpath '%s' --force-rpath %s" % (runpath, shared_lib))
if ec:
raise EasyBuildError("Failed to set RPATH for %s: %s", shared_lib, out)
else:
self.log.info("RPATH set for %s", shared_lib)
else:
self.log.info("No RUNPATH section found in %s", shared_lib)

def sanity_check_step(self):
"""Custom sanity check for Rust"""

custom_paths = {
'files': ['bin/cargo', 'bin/rustc', 'bin/rustdoc'],
'dirs': ['lib/rustlib', 'share/doc', 'share/man'],
}

custom_commands = [
"cargo --version",
"rustc --version",
]
return super(EB_Rust, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)

0 comments on commit 8a7ffba

Please sign in to comment.