diff --git a/Makefile b/Makefile index 186b40c..c5773db 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PLATFORMS := ubuntu-1804 ubuntu-2004 ubuntu-2204 debian-10 debian-11 centos-7 centos-8 opensuse-153 +PLATFORMS := ubuntu-1804 ubuntu-2004 ubuntu-2204 debian-10 debian-11 centos-7 centos-8 rhel-9 opensuse-153 SLS_BINARY ?= ./node_modules/serverless/bin/serverless deps: diff --git a/README.md b/README.md index ba42a2f..fecf59e 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ R binaries are built for the following Linux operating systems: - Ubuntu 18.04, 20.04, 22.04 - Debian 10, 11 - CentOS 7 -- Red Hat Enterprise Linux 7, 8 +- Red Hat Enterprise Linux 7, 8, 9 - openSUSE 15.3 - SUSE Linux Enterprise 15 SP3 @@ -81,30 +81,51 @@ sudo gdebi r-${R_VERSION}_1_amd64.deb #### RHEL/CentOS Linux Enable the [Extra Packages for Enterprise Linux](https://fedoraproject.org/wiki/EPEL) -repository (RHEL/CentOS 7 only): +repository (RHEL/CentOS 7 and RHEL 9 only): ```bash # CentOS / RHEL 7 sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + +# Rocky Linux 9 / AlmaLinux 9 +sudo dnf install dnf-plugins-core +sudo dnf config-manager --set-enabled crb +sudo dnf install epel-release + +# RHEL 9 +sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm ``` -> Note that on RHEL 7, you may also need to enable the Optional repository: +> On RHEL 7, you may also need to enable the Optional repository: > ```bash -> # For RHEL 7 users with certificate subscriptions: > sudo subscription-manager repos --enable "rhel-*-optional-rpms" > -> # Or alternatively, using yum: +> # If running RHEL 7 in a public cloud, such as Amazon EC2, enable the +> # Optional repository from Red Hat Update Infrastructure (RHUI) instead > sudo yum install yum-utils > sudo yum-config-manager --enable "rhel-*-optional-rpms" > ``` +> On RHEL 9, you may also need to enable the CodeReady Linux Builder repository: +> ```bash +> sudo subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms +> +> # If running RHEL 9 in a public cloud, such as Amazon EC2, enable the CodeReady +> # Linux Builder repository from Red Hat Update Infrastructure (RHUI) instead +> sudo dnf install dnf-plugins-core +> sudo dnf config-manager --enable codeready-builder-for-rhel-9-*-rpms +> ``` + Download the rpm package: ```bash # CentOS / RHEL 7 wget https://cdn.rstudio.com/r/centos-7/pkgs/R-${R_VERSION}-1-1.x86_64.rpm -# RHEL 8 +# RHEL 8 / Rocky Linux 8 / AlmaLinux 8 wget https://cdn.rstudio.com/r/centos-8/pkgs/R-${R_VERSION}-1-1.x86_64.rpm + +# RHEL 9 / Rocky Linux 9 / AlmaLinux 9 +wget https://cdn.rstudio.com/r/rhel-9/pkgs/R-${R_VERSION}-1-1.x86_64.rpm ``` Then install the package: diff --git a/builder/Dockerfile.rhel-9 b/builder/Dockerfile.rhel-9 new file mode 100644 index 0000000..9d7f37f --- /dev/null +++ b/builder/Dockerfile.rhel-9 @@ -0,0 +1,90 @@ +FROM rockylinux:9 + +ENV OS_IDENTIFIER rhel-9 + +RUN dnf -y upgrade \ + && dnf -y install dnf-plugins-core \ + && dnf config-manager --set-enabled crb \ + && dnf install -y epel-release \ + && dnf -y install \ + autoconf \ + automake \ + bzip2-devel \ + cairo-devel \ + gcc-c++ \ + gcc-gfortran \ + java-11-openjdk-devel \ + libICE-devel \ + libSM-devel \ + libX11-devel \ + libXmu-devel \ + libXt-devel \ + libcurl-devel \ + libicu-devel \ + libjpeg-devel \ + libpng-devel \ + libtiff-devel \ + libtool \ + make \ + ncurses-devel \ + pango-devel \ + pcre-devel \ + pcre2-devel \ + readline-devel \ + rpm-build \ + ruby \ + ruby-devel \ + tcl-devel \ + tex \ + texinfo-tex \ + texlive-collection-latexrecommended \ + tk-devel \ + unzip \ + valgrind-devel \ + which \ + wget \ + xz-devel \ + zlib-devel \ + && dnf clean all + +# Install AWS CLI +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ + unzip awscliv2.zip && \ + ./aws/install && \ + rm -rf aws awscliv2.zip + +RUN gem install fpm + +RUN chmod 0777 /opt + +# Configure flags for RHEL 9 that don't use the defaults in build.sh +ENV CONFIGURE_OPTIONS="\ + --enable-R-shlib \ + --with-tcltk \ + --enable-memory-profiling \ + --with-x \ + --with-system-valgrind-headers \ + --with-tcl-config=/usr/lib64/tclConfig.sh \ + --with-tk-config=/usr/lib64/tkConfig.sh \ + --enable-prebuilt-html" + +# RHEL 9 doesn't have the inconsolata font, so override the defaults. +# This may be removed if RHEL ever adds the texlive-inconsolata package from Fedora. +# Or check `dnf provides '*/inconsolata.sty'` for a package that provides it. +# https://cran.r-project.org/doc/manuals/r-release/R-admin.html#Making-the-manuals +ENV R_RD4PDF="times,hyper" + +# Make sure that patching Java does not break R. +# R's default JAVA_HOME path includes the exact Java version on CentOS/RHEL, which +# requires users to run `R CMD javareconf` even on minor/patch upgrades. Use the +# major version symlink to avoid this. +# https://cran.r-project.org/doc/manuals/r-release/R-admin.html#Java-support +# https://solutions.rstudio.com/r/using-rjava/ +ENV JAVA_HOME=/usr/lib/jvm/jre-11-openjdk + +# R 3.x requires PCRE2 for Pango support on RHEL 9 +ENV INCLUDE_PCRE2_IN_R_3 yes + +COPY package.rhel-9 /package.sh +COPY build.sh . +ENTRYPOINT ./build.sh diff --git a/builder/docker-compose.yml b/builder/docker-compose.yml index 0ab026c..fe3a031 100644 --- a/builder/docker-compose.yml +++ b/builder/docker-compose.yml @@ -76,6 +76,17 @@ services: image: r-builds:centos-8 volumes: - ./integration/tmp:/tmp/output + rhel-9: + command: ./build.sh + environment: + - R_VERSION=${R_VERSION} + - LOCAL_STORE=/tmp/output + build: + context: . + dockerfile: Dockerfile.rhel-9 + image: r-builds:rhel-9 + volumes: + - ./integration/tmp:/tmp/output opensuse-153: command: ./build.sh environment: diff --git a/builder/package.rhel-9 b/builder/package.rhel-9 new file mode 100644 index 0000000..9338288 --- /dev/null +++ b/builder/package.rhel-9 @@ -0,0 +1,76 @@ +if [[ ! -d /tmp/output/rhel-9 ]]; then + mkdir -p /tmp/output/rhel-9 +fi + +# R 3.x requires PCRE1 +pcre_lib='pcre2-devel' +if [[ "${R_VERSION}" =~ ^3 ]]; then + pcre_lib='pcre-devel' +fi + +# Create post-install script required for OpenBLAS. +# +# On RHEL and SUSE, we link R against the internal shared BLAS to make the +# R binaries more portable and allow users to switch BLAS implementations without +# having to recompile R. We default to OpenBLAS, but users may prefer other implementations. +# +# Binary packages built against the shared BLAS are also more portable and may be used +# with the default R distributed by RHEL/SUSE, or other R installations using +# shared BLAS and configured with a different BLAS (such as Microsoft R Open with MKL). +# This is especially important for RSPM's binary packages. +# +# On Ubuntu/Debian, we link R against the external BLAS instead (--with-blas/--with-lapack), +# as those distributions use the alternatives system to swap BLAS libraries at runtime. +# The default R distributions on Ubuntu/Debian use the external BLAS, so we do as well +# for portability. +# +# https://cran.r-project.org/doc/manuals/r-release/R-admin.html#Shared-BLAS +cat <> /post-install.sh +mv /opt/R/${R_VERSION}/lib/R/lib/libRblas.so /opt/R/${R_VERSION}/lib/R/lib/libRblas.so.keep +ln -s /usr/lib64/libopenblasp.so /opt/R/${R_VERSION}/lib/R/lib/libRblas.so +EOF + +# Create after-remove script to remove internal BLAS, which won't be cleaned up automatically. +cat <> /after-remove.sh +if [ -d /opt/R/${R_VERSION} ]; then + rm -r /opt/R/${R_VERSION} +fi +EOF + +fpm \ + -s dir \ + -t rpm \ + -v 1 \ + -n "R-${R_VERSION}" \ + --vendor "RStudio, PBC" \ + --url "https://www.r-project.org" \ + --description "GNU R statistical computation and graphics system" \ + --maintainer "RStudio, PBC " \ + --license "GPLv2+" \ + --after-install /post-install.sh \ + --after-remove /after-remove.sh \ + -p /tmp/output/rhel-9/ \ + -d bzip2-devel \ + -d gcc \ + -d gcc-c++ \ + -d gcc-gfortran \ + -d libcurl-devel \ + -d libicu-devel \ + -d libSM \ + -d libtiff \ + -d libXmu \ + -d libXt \ + -d make \ + -d openblas-devel \ + -d pango \ + -d ${pcre_lib} \ + -d tcl \ + -d tk \ + -d unzip \ + -d which \ + -d xz-devel \ + -d zip \ + -d zlib-devel \ + "/opt/R/${R_VERSION}" + +export PKG_FILE=$(ls /tmp/output/rhel-9/R-${R_VERSION}*.rpm | head -1) diff --git a/handler.py b/handler.py index 3d22e3c..ada133c 100644 --- a/handler.py +++ b/handler.py @@ -128,16 +128,9 @@ def queue_builds(event, context): for platform in event['supported_platforms']: # In R 3.3.0, 3.3.1, and 3.3.2, the configure script check for the # zlib version fails to handle versions longer than 5 characters. - # Skip builds affected by this bug. - if platform in [ - 'ubuntu-2204', - 'ubuntu-2004', - 'ubuntu-1804', - 'opensuse-153', - 'centos-8', - 'debian-10', - 'debian-11', - ] and version in ['3.3.0', '3.3.1', '3.3.2']: + # Skip builds affected by this bug. Most newer distros will be affected. + # https://github.com/rstudio/r-builds/issues/76 + if version in ['3.3.0', '3.3.1', '3.3.2'] and platform not in ['centos-7']: continue job_ids.append(_submit_job(version, platform)) event['jobIds'] = job_ids diff --git a/install.sh b/install.sh index 43321dc..1c0ec0f 100755 --- a/install.sh +++ b/install.sh @@ -79,11 +79,11 @@ detect_os () { then distro="Amazon" fi - if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') =~ cpe:/o:almalinux:almalinux:8::baseos ]] + if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') =~ cpe:/o:almalinux:almalinux: ]] then distro="Alma" fi - if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') =~ cpe:/o:rocky:rocky:8.5:GA ]] + if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') =~ cpe:/o:rocky:rocky: ]] then distro="Rocky" fi @@ -97,17 +97,13 @@ detect_os () { # Returns the OS version detect_os_version () { os=$1 - if [[ "${os}" == "RedHat" ]]; then - if [[ $(cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=') =~ ^(\"8.|28) ]]; then - echo "8" - elif [[ $(cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=') =~ ^(\"7.) ]]; then - echo "7" + if [[ "${os}" =~ ^(RedHat|Alma|Rocky)$ ]]; then + # Get the major version. /etc/redhat-release is used if /etc/os-release isn't available, + # e.g., on CentOS/RHEL 6. + if [[ -f /etc/os-release ]]; then + cat /etc/os-release | grep VERSION_ID= | sed -E 's/VERSION_ID="([0-9.]*)"/\1/' | cut -d '.' -f 1 elif [[ -f /etc/redhat-release ]]; then - if [[ $(cat /etc/redhat-release | grep "6.") ]]; then - echo 6 - fi - elif [[ -f /etc/os-release ]]; then - cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=' | sed -e 's/"//g' + cat /etc/redhat-release | sed -E 's/[^0-9]+([0-9.]+)[^0-9]*/\1/' | cut -d '.' -f 1 fi fi if [[ "${os}" == "Ubuntu" ]] || [[ "${os}" == "Debian" ]]; then @@ -120,10 +116,6 @@ detect_os_version () { if [[ "${os}" == "Amazon" ]]; then echo "7" fi - # reuse rhel8 binaries for alma and rocky - if [[ "${os}" =~ ^(Alma|Rocky) ]]; then - echo "8" - fi } # Returns the installer type @@ -186,7 +178,11 @@ download_url () { case $os in "RedHat" | "CentOS" | "Amazon" | "Alma" | "Rocky") - echo "${CDN_URL}/centos-${ver}/pkgs/${name}" + if [ "${ver}" -ge 9 ]; then + echo "${CDN_URL}/rhel-${ver}/pkgs/${name}" + else + echo "${CDN_URL}/centos-${ver}/pkgs/${name}" + fi ;; "Ubuntu") echo "${CDN_URL}/ubuntu-${ver}/pkgs/${name}" @@ -328,7 +324,7 @@ install_pre () { case $os in "RedHat" | "CentOS" | "Alma" | "Rocky") - install_epel "${ver}" + install_epel "${os}" "${ver}" ;; "Amazon") install_epel_amzn @@ -352,7 +348,8 @@ install_epel_amzn () { # Installs EPEL for RHEL/CentOS/Alma/Rocky install_epel () { - ver=$1 + os=$1 + ver=$2 yes= if [[ "${RUN_UNATTENDED}" -ne "0" ]]; then yes="-y" @@ -366,6 +363,16 @@ install_epel () { ;; "8") ;; + "9") + if [[ "${os}" == "RedHat" ]]; then + ${SUDO} subscription-manager repos --enable "codeready-builder-for-rhel-9-$(arch)-rpms" + ${SUDO} dnf install ${yes} https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + else + ${SUDO} dnf install ${yes} dnf-plugins-core + ${SUDO} dnf config-manager --set-enabled crb + ${SUDO} dnf install ${yes} epel-release + fi + ;; esac } diff --git a/serverless-resources.yml b/serverless-resources.yml index 4318ed0..8e6492b 100644 --- a/serverless-resources.yml +++ b/serverless-resources.yml @@ -228,6 +228,20 @@ rBuildsBatchJobDefinitionCentos8: Image: "#{AWS::AccountId}.dkr.ecr.#{AWS::Region}.amazonaws.com/r-builds:centos-8" Timeout: AttemptDurationSeconds: 7200 +rBuildsBatchJobDefinitionRhel9: + Type: AWS::Batch::JobDefinition + Properties: + Type: container + ContainerProperties: + Command: + - ./build.sh + Vcpus: 4 + Memory: 4096 + JobRoleArn: + "Fn::GetAtt": [ rBuildsEcsTaskIamRole, Arn ] + Image: "#{AWS::AccountId}.dkr.ecr.#{AWS::Region}.amazonaws.com/r-builds:rhel-9" + Timeout: + AttemptDurationSeconds: 7200 rBuildsBatchJobDefinitionOpensuse153: Type: AWS::Batch::JobDefinition Properties: diff --git a/serverless.yml b/serverless.yml index 8e618f8..0020176 100644 --- a/serverless.yml +++ b/serverless.yml @@ -49,9 +49,11 @@ provider: Ref: rBuildsBatchJobDefinitionCentos7 JOB_DEFINITION_ARN_centos_8: Ref: rBuildsBatchJobDefinitionCentos8 + JOB_DEFINITION_ARN_rhel_9: + Ref: rBuildsBatchJobDefinitionRhel9 JOB_DEFINITION_ARN_opensuse_153: Ref: rBuildsBatchJobDefinitionOpensuse153 - SUPPORTED_PLATFORMS: ubuntu-1804,ubuntu-2004,ubuntu-2204,debian-10,debian-11,centos-7,centos-8,opensuse-153 + SUPPORTED_PLATFORMS: ubuntu-1804,ubuntu-2004,ubuntu-2204,debian-10,debian-11,centos-7,centos-8,rhel-9,opensuse-153 functions: queueBuilds: diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 2bb5760..ca304be 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -55,6 +55,14 @@ services: - R_VERSION=${R_VERSION} volumes: - ../:/r-builds + rhel-9: + image: rockylinux:9 + command: /r-builds/test/test-yum.sh + environment: + - OS_IDENTIFIER=rhel-9 + - R_VERSION=${R_VERSION} + volumes: + - ../:/r-builds opensuse-153: image: opensuse/leap:15.3 command: /r-builds/test/test-zypper.sh