Skip to content

Commit

Permalink
add graalpy recipe and required python_abi change
Browse files Browse the repository at this point in the history
  • Loading branch information
timfel authored and Tim Felgentreff committed Nov 4, 2022
1 parent 8ab02e0 commit 5a41b28
Show file tree
Hide file tree
Showing 14 changed files with 617 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .scripts/build_steps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# changes to this script, consider a proposal to conda-smithy so that other feedstocks can also
# benefit from the improvement.

git config --global --add safe.directory '*'

set -xeuo pipefail
export PYTHONUNBUFFERED=1

Expand Down
18 changes: 18 additions & 0 deletions recipes/graalpy/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Copyright (c) 2022, Oracle and/or its affiliates

The Universal Permissive License (UPL), Version 1.0

Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both

(a) the Software, and

(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a “Larger Work” to which the Software is contributed by such licensors),

without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms.

This license is subject to the following condition:

The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

83 changes: 83 additions & 0 deletions recipes/graalpy/build_standalone.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/bash

set -exo pipefail

# this needs to be updated when the target python version of graalpy changes
PY_VERSION=3.8

# set up paths for mx build
export MX_DIR=$SRC_DIR/mx
export PATH=$PATH:$MX_DIR
export MX_PRIMARY_SUITE_PATH=$SRC_DIR/graal/vm

# mx ninja build templates hardcode ar, gcc, g++; symlink these to the conda
# compilers
ln -s $AR $MX_DIR/ar
ln -s $CC $MX_DIR/gcc
ln -s $CXX $MX_DIR/g++

# sulong toolchain wrappers are not recognized and cmake is making trouble
# getting them to compile anything. Make sure to use the sysroot flag, and
# symlink build environment objects
export CFLAGS="$CFLAGS --sysroot $CONDA_BUILD_SYSROOT"
export CXXFLAGS="$CXXFLAGS --sysroot $CONDA_BUILD_SYSROOT"
export LDFLAGS="$LDFLAGS --sysroot $CONDA_BUILD_SYSROOT"
export CPATH="$BUILD_PREFIX/include"
export LIBRARY_PATH="$BUILD_PREFIX/lib"
for filename in $CONDA_BUILD_SYSROOT/../lib/libgcc_s.so*; do
ln -s $filename $CONDA_BUILD_SYSROOT/lib/
done
ln -s $CONDA_BUILD_SYSROOT/../../lib/gcc/x86_64-conda-linux-gnu/*/crtbegin.o $CONDA_BUILD_SYSROOT/lib/
ln -s $CONDA_BUILD_SYSROOT/../../lib/gcc/x86_64-conda-linux-gnu/*/crtbeginS.o $CONDA_BUILD_SYSROOT/lib/
ln -s $CONDA_BUILD_SYSROOT/../../lib/gcc/x86_64-conda-linux-gnu/*/crtend.o $CONDA_BUILD_SYSROOT/lib/
ln -s $CONDA_BUILD_SYSROOT/../../lib/gcc/x86_64-conda-linux-gnu/*/crtendS.o $CONDA_BUILD_SYSROOT/lib/
ln -s $CONDA_BUILD_SYSROOT/../../lib/gcc/x86_64-conda-linux-gnu/*/libgcc.a $CONDA_BUILD_SYSROOT/lib/

# git init an empty repo inside graal, to force mx to pick graal download as
# siblings dir
git init $SRC_DIR/graal
git -C $SRC_DIR/graal config --local user.name "none"
git -C $SRC_DIR/graal config --local user.email "none@example.org"
git -C $SRC_DIR/graal commit --allow-empty -m "dummy commit"

# set environment variables to build a graalpy distribution taken from the
# released graal/mx/mx.vm/ce env file
export MX_PYTHON=${BUILD_PREFIX}/bin/pypy3
export DYNAMIC_IMPORTS=/compiler,/regex,/sdk,/substratevm,/sulong,/tools,/truffle,graalpython
export COMPONENTS=cmp,cov,dap,dis,gu,gvm,icu4j,ins,insight,insightheap,lg,llp,llrc,llrl,llrn,lsp,nfi-libffi,pbm,pmh,poly,polynative,pro,pyn,pynl,rgx,sdk,tfl,tflm
export NATIVE_IMAGES=lib:pythonvm,lib:jvmcicompiler,graalvm-native-binutil,graalvm-native-clang,graalvm-native-clang-cl,graalvm-native-clang++,graalvm-native-ld
export DISABLE_INSTALLABLES=False

# set correct jdk paths
CONTINUOUS_INTEGRATION=true mx fetch-jdk --to $SRC_DIR --strip-contents-home --jdk-id labsjdk-ce-17
export JAVA_HOME=`echo $SRC_DIR/labsjdk-ce-17*`
export JAVA_OPTS="-Xmx4G"

# run the build
mx graalvm-show
mx build

# move the standalone build artifact into $PREFIX
STANDALONE=`$MX_DIR/mx standalone-home python`
cp -r $STANDALONE/* $PREFIX

# sulong ensures that the llvm toolchain uses libc++abi.so in the toolchain
# directory by dynamically making sure it's loaded in its toolchain wrappers,
# but the conda build cannot know this and complains
LIBCXX_RPATH=`patchelf --print-rpath $PREFIX/lib/llvm-toolchain/lib/*/libc++.so.1.0`
if [ -n "$LIBCXX_RPATH" ]; then
LIBCXX_RPATH="$LIBCXX_RPATH:\$ORIGIN"
else
LIBCXX_RPATH="\$ORIGIN"
fi
patchelf --set-rpath "$LIBCXX_RPATH" $PREFIX/lib/llvm-toolchain/lib/*/libc++.so.1.0

# create the site-packages folder to match cpython
mkdir -p $PREFIX/lib/python${PY_VERSION}/site-packages

# match cpython include folder structure
ln -sf $PREFIX/include $PREFIX/include/python${PY_VERSION}

# license is packaged by the build process
cat $PREFIX/LICENSE_GRAALPY.txt $PREFIX/THIRD_PARTY_LICENSE_GRAALPY.txt > $SRC_DIR/LICENSE_GRAALPY.txt
rm $PREFIX/LICENSE_GRAALPY.txt $PREFIX/THIRD_PARTY_LICENSE_GRAALPY.txt
14 changes: 14 additions & 0 deletions recipes/graalpy/conda_build_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
graalpy_distribution:
- standalone
# - graalvm

ignore_version:
- python

# Following are dummy keys to get a single version, as in python_abi
python:
- "2.7"
python_impl:
- '*'
numpy:
- '1.16'
129 changes: 129 additions & 0 deletions recipes/graalpy/meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# the graalpy version implies the gp_python_version and mx_version, so update these together
{% set version = "22.3.0" %}
{% set gp_python_version = "3.8.5" %}
{% set mx_version = "6.9.7" %}

{% if graalpy_distribution is not defined %}
{% set graalpy_distribution = "standalone" %}
{% endif %}

# Keep increasing the build_num until we get a new graalpy version. Do not reset
{% set build_num = "0" %}

{% set python_maj_min = ".".join(gp_python_version.split(".")[:2]) %}
{% set graalpy_abi = "".join(version.split(".")[:2]) %}

package:
name: graalpy
version: {{ version }}

build:
number: {{ build_num }}

# download graalpython and the mx build tool
source:
- url: https://github.com/graalvm/mx/archive/refs/tags/{{ mx_version }}.zip
sha256: 6719145418c9846fb75686190359c69018ac5e61af113aba35e8542fdf09e09c
folder: mx
patches:
- patches/mx-keep-rpath-origin-variable.patch
- patches/mx-pypy-support.patch
- url: https://github.com/oracle/graal/archive/refs/tags/vm-ce-{{ version }}.zip
sha256: 9b714747fbff0b9f477a102a22e6558f697322d8fa89b1ac9956938d3afb3b87
folder: graal
patches:
- patches/sulong-disable-tests.patch
- patches/sulong-relative-rpath.patch
- url: https://github.com/oracle/graalpython/archive/refs/tags/vm-ce-{{ version }}.zip
sha256: 72ad9a6e8d8283425768c2838d9f360a42eb1dc6096d0efe44464f4fd5c0982c
folder: graalpython
patches:
- patches/graalpy-honour-sysroot.patch
- patches/graalpy-reduce-image-build-xmx.patch

outputs:
- name: graalpy
version: {{ version }}
script: build_{{ graalpy_distribution }}.sh
build:
number: {{ build_num }}
string: {{ build_num }}_graalpy{{ python_maj_min.replace(".", "") }}_{{ graalpy_distribution }}
track_features: # [graalpy_distribution == "graalvm"]
- openjdk # [graalpy_distribution == "graalvm"]
skip: true # [win or osx]
run_exports:
weak:
- graalpy >={{ version }}
- python_abi {{ python_maj_min }} *_graalpy{{ graalpy_abi }}
noarch:
- {{ pin_subpackage("python", max_pin="x.x", min_pin="x.x") }}
requirements:
build:
- {{ compiler('c') }}
- {{ compiler('cxx') }}
- pypy3.9 >=7.3.9
- make
- patch
- zlib
- git
- curl
- cmake
- patchelf
host:
- zlib
run:
- libzlib
- patch
- curl
run_constrained:
- python {{ gp_python_version }} {{ build_num }}_{{ graalpy_abi }}_graalpy
test:
commands:
- python3 --help
- python3 -c "import platform; print(platform._sys_version())"
- graalpy -m venv --help
- graalpy -m venv testvenv
- testvenv/bin/graalpy -c "import _struct; print(_struct.pack('I', 15663050))"


- name: python
version: {{ gp_python_version }}
build:
number: {{ build_num }}
string: {{ build_num }}_{{ graalpy_abi }}_graalpy
track_features:
- graalpy
run_exports:
weak:
- graalpy >={{ version }}
- python_abi {{ python_maj_min }} *_graalpy{{ graalpy_abi }}
noarch:
- {{ pin_subpackage("python", max_pin="x.x", min_pin="x.x") }}
skip: true # [win or osx]
requirements:
host:
- graalpy {{ version }}
run:
- graalpy {{ version }}
run_constrained:
- python_abi {{ python_maj_min }} *_graalpy{{ graalpy_abi }}
test:
commands:
- python --version
- test $(python -c "import sys; print('.'.join(str(i) for i in sys.version_info[:3]))") == "{{ gp_python_version }}" # [unix]
- test $(python -c "import sys; print(sys.implementation.name)") == "graalpy" # [unix]

about:
home: http://graalvm.org/python
license: UPL-1.0
license_file: LICENSE_GRAALPY.txt
summary: >
GraalPy is a high-performance Python implementation on GraalVM. See
https://conda-forge.org/blog/posts/2020-03-10-pypy for more information
about using it in conda, replacing PyPy/pypy/pp with GraalPy/graalpy/gp
in commands.
extra:
recipe-maintainers:
- timfel
- msimacek
132 changes: 132 additions & 0 deletions recipes/graalpy/patches/graalpy-honour-sysroot.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
diff --git a/graalpython/com.oracle.graal.python.cext/lzma/Makefile b/graalpython/com.oracle.graal.python.cext/lzma/Makefile
index e0ddc86c76..1c3f230d83 100644
--- a/graalpython/com.oracle.graal.python.cext/lzma/Makefile
+++ b/graalpython/com.oracle.graal.python.cext/lzma/Makefile
@@ -57,7 +57,7 @@ INCLUDES=-I$(CONFIG_H_DIR) \
-I$(XZ_ROOT)/src/liblzma/simple \
-I$(XZ_ROOT)/src/common

-CFLAGS=-fPIC -DPIC -g -O2
+CFLAGS:=$(CFLAGS) -fPIC -DPIC -g -O2

ifeq ($(shell uname -s), Darwin)
LIB_NAME=liblzma.5.dylib
diff --git a/graalpython/com.oracle.graal.python.cext/setup.py b/graalpython/com.oracle.graal.python.cext/setup.py
index d29d53b914..8cb9733301 100644
--- a/graalpython/com.oracle.graal.python.cext/setup.py
+++ b/graalpython/com.oracle.graal.python.cext/setup.py
@@ -41,7 +41,7 @@ import logging
import os
import shutil
import sys
-from distutils.core import setup, Extension
+from distutils.core import setup as distutils_setup, Extension
from distutils.sysconfig import get_config_var, get_config_vars

import _sysconfig
@@ -73,6 +73,14 @@ logger = logging.getLogger(__name__)
logging.basicConfig(format='%(message)s', level=logging.DEBUG if sys.flags.verbose else logging.ERROR)


+def setup(*args, **kwargs):
+ # wrap the distutil setup. since we're running in the same process, running
+ # a full clean will fail the next build, since distutils thinks it already
+ # created the "build" directory
+ os.makedirs("build", exist_ok=False)
+ return distutils_setup(*args, **kwargs)
+
+
threaded = _sysconfig.get_config_var("WITH_THREAD")
if threaded:
logger.debug("building C API threaded")
@@ -262,14 +270,19 @@ class Bzip2Depedency(CAPIDependency):
logger.info("Building dependency %s in %s using Makefile %s" % (self.package_name, lib_src_folder, self.makefile))

# On Darwin, we need to use -install_name for the native linker
+ makefile_path = os.path.join(lib_src_folder, self.makefile)
if darwin_native:
- makefile_path = os.path.join(lib_src_folder, self.makefile)
with open(makefile_path, "r") as f:
content = f.read()
content = content.replace("-Wl,-soname -Wl,%s" % self.install_name, "-Wl,-install_name -Wl,@rpath/%s" % self.install_name)
with open(makefile_path, "w") as f:
f.write(content)

+ with open(makefile_path, "r") as f:
+ content = f.read()
+ with open(makefile_path, "w") as f:
+ f.write(content.replace("CFLAGS=", "CFLAGS:=${CFLAGS} ").replace("$(CC) -shared", "$(CC) -shared $(CFLAGS)"))
+
parallel_arg = "-j" + str(min(4, os.cpu_count())) if threaded else ""
system("make -C '%s' %s -f '%s' CC='%s'" % (lib_src_folder, parallel_arg, self.makefile, get_config_var("CC")), msg="Could not build libbz2")
return lib_src_folder
@@ -460,7 +473,7 @@ def build_libpython(capi_home):
sources=files,
extra_compile_args=cflags_warnings,
)
- args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean"]
+ args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean", "--all"]
setup(
script_name='setup' + libpython_name,
script_args=args,
@@ -479,7 +492,7 @@ def build_libhpy(capi_home):
define_macros=[("HPY_UNIVERSAL_ABI", 1)],
extra_compile_args=cflags_warnings,
)
- args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean"]
+ args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean", "--all"]
setup(
script_name='setup' + libhpy_name,
script_args=args,
@@ -510,7 +523,7 @@ def build_nativelibsupport(capi_home, subdir, libname, deps=[], **kwargs):
extra_link_args=extra_link_args,

)
- args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean"]
+ args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean", "--all"]
setup(
script_name='setup' + libname,
script_args=args,
@@ -530,7 +543,7 @@ def build_libposix(capi_home):
sources=files,
libraries=['crypt'] if not darwin_native else [],
extra_compile_args=cflags_warnings + ['-Wall', '-Werror'])
- args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean"]
+ args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s' % capi_home, "clean", "--all"]
setup(
script_name='setup' + libposix_name,
script_args=args,
@@ -544,7 +557,7 @@ def build_libposix(capi_home):


def build_builtin_exts(capi_home):
- args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s/modules' % capi_home, "clean"]
+ args = [verbosity, 'build', 'install_lib', '-f', '--install-dir=%s/modules' % capi_home, "clean", "--all"]
distutil_exts = [(ext, ext()) for ext in builtin_exts]
def build_builtin_ext(item):
ext, distutil_ext = item
diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py
index 17f98fea66..03b31dc64a 100644
--- a/mx.graalpython/mx_graalpython.py
+++ b/mx.graalpython/mx_graalpython.py
@@ -2086,9 +2086,18 @@ class GraalpythonCAPIBuildTask(GraalpythonBuildTask):
env.update(mx.dependency("com.oracle.graal.python.cext").getBuildEnv())
env.update(self.subject.getBuildEnv())

- # distutils will honor env variables CC, CFLAGS, LDFLAGS but we won't allow to change them
+ # distutils will honor env variables CC, CFLAGS, LDFLAGS but we won't allow to change them,
+ # besides keeping custom sysroot, since our toolchain forwards to the system headers
for var in ["CC", "CFLAGS", "LDFLAGS"]:
- env.pop(var, None)
+ value = env.pop(var, None)
+ if value and "--sysroot" in value:
+ seen_sysroot = False
+ for element in shlex.split(value):
+ if element == "--sysroot":
+ seen_sysroot = True
+ elif seen_sysroot:
+ env[var] = f"--sysroot {element}"
+ break
return super().run(args, env=env, cwd=cwd, **kwargs)

def _dev_headers_dir(self):
Loading

0 comments on commit 5a41b28

Please sign in to comment.