Skip to content

Commit

Permalink
Add patchelf to the list of binaries provided (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
haampie authored Aug 19, 2022
1 parent 111ee5c commit b4dd7b7
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 0 deletions.
97 changes: 97 additions & 0 deletions .github/workflows/patchelf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: "Patchelf"

on:
push:
branches:
- main
tags:
- v0.**
pull_request:
branches:
- main
workflow_dispatch:

concurrency:
group: patchelf-${{ github.ref }}
cancel-in-progress: true

jobs:

manylinux2014:
runs-on: ubuntu-20.04
outputs:
spack_manylinux_tag: ${{ fromJSON(steps.docker_meta.outputs.json).tags[0] }}

steps:
- uses: actions/checkout@v3

# Setup tags to be used for docker images
- uses: docker/metadata-action@v4
id: docker_meta
with:
images: ghcr.io/${{ github.repository_owner }}/patchelf_manylinux2014

# Login to Github Packages
- uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/setup-qemu-action@v2
id: qemu
with:
platforms: linux/ppc64le,linux/arm64,linux/amd64

- uses: docker/setup-buildx-action@v2

# Build and eventually push to registry
- uses: docker/build-push-action@v3
with:
file: ./patchelf/Dockerfile.manylinux2014
platforms: linux/arm64,linux/ppc64le,linux/amd64
pull: ${{ github.event_name == 'pull_request' }}
# Self-hosted runners use the local cache
# cache-from: type=gha
# cache-to: type=gha,mode=max
cache-from: type=local,src=/tmp/.buildx-cache-patchelf-manylinux2014
cache-to: type=local,dest=/tmp/.buildx-cache-patchelf-manylinux2014,mode=max
push: true
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}

upload-manylinux2014:
runs-on: ubuntu-latest
needs: [ manylinux2014 ]
env:
SPACK_MANYLINUX2014_TAG: ${{ needs.manylinux2014.outputs.spack_manylinux_tag }}

steps:
- uses: actions/checkout@v3
- run: |
. ./patchelf/scripts/copy_mirror_manylinux2014.sh
- uses: actions/upload-artifact@v3
with:
name: patchelf_binary_mirror
path: |
binary-mirror
patchelf_json:
runs-on: ubuntu-latest
needs: [ upload-manylinux2014 ]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: 3.9
- uses: actions/download-artifact@v3
with:
name: patchelf_binary_mirror
- run: |
pip install ruamel.yaml
python patchelf/scripts/patchelf_json.py
- uses: actions/upload-artifact@v3
with:
name: patchelf_manifest
path: |
patchelf.json
21 changes: 21 additions & 0 deletions patchelf/Dockerfile.manylinux2014
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM ghcr.io/spack/manylinux2014:latest

RUN adduser -m spack

# Switch to a non-root user
USER spack
ENV SPACK_CMD="/opt/python/cp39-cp39/bin/python /home/spack/spack/bin/spack"
WORKDIR /home/spack

# Clone the repo and install Spack
RUN git clone https://www.github.com/spack/spack.git

# Set externals, locate compilers
RUN ${SPACK_CMD} external find --not-buildable cmake
RUN ${SPACK_CMD} compiler find

RUN ${SPACK_CMD} python -c "import archspec.cpu;print(archspec.cpu.host().family)" > target.txt
RUN ${SPACK_CMD} install patchelf 'ldflags="-static-libstdc++ -static-libgcc"' target=$(cat target.txt)

RUN mkdir -p /home/spack/binary-mirror && \
${SPACK_CMD} buildcache create -d /home/spack/binary-mirror -a -u -f patchelf
24 changes: 24 additions & 0 deletions patchelf/scripts/copy_mirror_manylinux2014.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env sh

id=$(docker create --platform linux/amd64 ${SPACK_MANYLINUX2014_TAG})
mkdir amd64
docker cp $id:/home/spack/binary-mirror amd64/binary-mirror
docker rm -v $id

id=$(docker create --platform linux/arm64 ${SPACK_MANYLINUX2014_TAG})
mkdir arm64
docker cp $id:/home/spack/binary-mirror arm64/binary-mirror
docker rm -v $id

id=$(docker create --platform linux/ppc64le ${SPACK_MANYLINUX2014_TAG})
mkdir ppc64le
docker cp $id:/home/spack/binary-mirror ppc64le/binary-mirror
docker rm -v $id

# Unify the two mirrors. This is required since the upload-artifacts action
# computes the common ancestore among different paths and starts from there
# instead of "merging" the copies
mkdir binary-mirror
rsync -a ./amd64/binary-mirror/ ./binary-mirror
rsync -a ./arm64/binary-mirror/ ./binary-mirror
rsync -a ./ppc64le/binary-mirror/ ./binary-mirror
94 changes: 94 additions & 0 deletions patchelf/scripts/patchelf_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""Produce the clingo.json file associated with the mirror"""
import json
import glob
import hashlib
import json
import os.path


# Each entry in patchelf.json has the following keys:
#
# "spec": root spec to be matched
# "binaries": list of objects, to be installed in order (each one has a "hash", "sha256" and "name" attribute)
# "python": constraints on the python interpreter
# "compiler": compiler entry used to build the spec
#

# Dictionary that maps (OS, TARGET) to info for the spec
SPEC_INFO = {
('centos7', 'x86_64'): {
'spec': '[email protected]: %gcc platform=linux target=x86_64',
},
('centos7', 'aarch64'): {
'spec': '[email protected]: %gcc platform=linux target=aarch64',
},
('centos7', 'ppc64le'): {
'spec': '[email protected]: %gcc platform=linux target=ppc64le',
}
}

def compiler_entry(name, version, os, target):
return {
"spec": "{0}@{1}".format(name, version),
"paths": {
"cc": "/dev/null",
"cxx": "/dev/null",
"f77": "/dev/null",
"fc": "/dev/null"
},
"operating_system": "{0}".format(os),
"target": "{0}".format(target),
"modules": []
}

def sha256(path):
fn = hashlib.sha256()
with open(path, "rb") as f:
fn.update(f.read())
return fn.hexdigest()

def tarball_hash(path):
filename = os.path.basename(path)
filename = filename.replace('.spack', '')
return filename.split('-')[-1]

tarballs = glob.glob( './build_cache/**/*.spack', recursive=True)
shas = {tarball_hash(tarball): sha256(tarball) for tarball in tarballs}
spec_yaml_files = glob.glob('./build_cache/*.json')

mirror_info = []
spec_yaml_dict = {}
for spec_yaml in spec_yaml_files:
if 'patchelf' not in spec_yaml:
continue
print(spec_yaml)
# Get the raw data from spec.yaml
with open(spec_yaml) as f:
spec_yaml_data = json.load(f)['spec']['nodes']

# Find the patchelf entry and store it somewhere
binary_data = {}
for entry in spec_yaml_data:
if 'patchelf' == entry['name']:
binary_data['patchelf'] = entry
assert 'patchelf' in binary_data

current_os = binary_data['patchelf']['arch']['platform_os']
current_target = binary_data['patchelf']['arch']['target']

compiler_name = binary_data['patchelf']['compiler']['name']
compiler_version = str(binary_data['patchelf']['compiler']['version'])

current_hash = binary_data['patchelf']['hash']
binaries = [
('patchelf', current_hash, shas[current_hash])
]
mirror_entry = {
"spec": SPEC_INFO[(current_os, current_target)]['spec'],
"binaries": binaries,
}
mirror_info.append(mirror_entry)

mirror_info = sorted(mirror_info, key=lambda x: x['spec'])
with open('./patchelf.json', 'w') as f:
json.dump({'verified': mirror_info}, f, sort_keys=True, indent=2)

0 comments on commit b4dd7b7

Please sign in to comment.