Skip to content

Commit 567284f

Browse files
committed
Package SDL2 with ale-py
This commit introduces the necesarry changes to package SDL with ale-py. Most notably we no longer package the native shared library as the entire package, but now have a Python entry point so we can setup some infrastructure around search paths for dynamic libraries. We also introduce the necesarry changes for our CI infrastructure to build / test / bundle SDL with ale-py releases.
1 parent 4611970 commit 567284f

11 files changed

+103
-19
lines changed

.github/workflows/build-ale-py.yml

+11-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
strategy:
1515
matrix:
1616
config: [
17-
{"os": "ubuntu-latest", "deps": ["zlib"], "triplet": "x64-linux"},
18-
{"os": "windows-latest", "deps": ["zlib"], "triplet": "x64-windows"},
19-
{"os": "macos-latest", "deps": ["zlib"], "triplet": "x64-osx"}
17+
{"os": "ubuntu-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-linux-mixed"},
18+
{"os": "windows-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-windows"},
19+
{"os": "macos-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-osx-mixed"}
2020
]
2121
runs-on: ${{ matrix.config.os }}
2222
steps:
@@ -34,17 +34,19 @@ jobs:
3434
- name: Build wheels
3535
uses: pypa/[email protected]
3636
env:
37-
CIBW_MANYLINUX_X86_64_IMAGE: "ghcr.io/mgbellemare/manylinux2014-vcpkg"
38-
CIBW_SKIP: "*i686* *win32*"
37+
CIBW_MANYLINUX_X86_64_IMAGE: "ghcr.io/jessefarebro/manylinux2014-vcpkg"
38+
CIBW_SKIP: "*i686* *win32* pp*"
39+
CIBW_ARCHS_MACOS: "x86_64"
3940
CIBW_TEST_REQUIRES: "pytest"
4041
CIBW_TEST_COMMAND: "pytest {project}"
41-
CIBW_ENVIRONMENT: "ALE_BUILD_VERSION=${{ env.ALE_BUILD_VERSION }} VCPKG_DEFAULT_TRIPLET=${{ matrix.config.triplet }}"
42-
CIBW_BEFORE_ALL: "vcpkg install ${{ join(matrix.config.deps, ' ') }} --triplet ${{ matrix.config.triplet }}"
42+
CIBW_ENVIRONMENT: "ALE_BUILD_VERSION=${{ env.ALE_BUILD_VERSION }} MACOSX_DEPLOYMENT_TARGET='10.15' VCPKG_DEFAULT_TRIPLET=${{ matrix.config.triplet }}"
43+
CIBW_BEFORE_ALL: "vcpkg install ${{ join(matrix.config.deps, ' ') }} --triplet ${{ matrix.config.triplet }} --overlay-triplets cmake/custom-triplets --feature-flags=-compilertracking"
4344

44-
- uses: actions/upload-artifact@v1
45+
- name: Upload wheels
46+
uses: actions/upload-artifact@v2
4547
with:
4648
name: wheels
47-
path: wheelhouse/*.whl
49+
path: ./wheelhouse/*.whl
4850

4951

5052
pypi:

.github/workflows/build-ale.yml

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ jobs:
2727
strategy:
2828
matrix:
2929
config: [
30-
{"os": "ubuntu-latest", "deps": ["zlib"], "triplet": "x64-linux"},
31-
{"os": "windows-latest", "deps": ["zlib"], "triplet": "x64-windows"},
32-
{"os": "macos-latest", "deps": ["zlib"], "triplet": "x64-osx"}
30+
{"os": "ubuntu-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-linux-mixed"},
31+
{"os": "windows-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-windows"},
32+
{"os": "macos-latest", "deps": ["zlib", "sdl2"], "triplet": "x64-osx-mixed"}
3333
]
3434
env:
3535
VCPKG_DEFAULT_TRIPLET: ${{ matrix.config.triplet }}
@@ -61,7 +61,7 @@ jobs:
6161
- name: Install vcpkg dependencies
6262
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
6363
run: |
64-
vcpkg install ${{ join(matrix.config.deps, ' ') }} --triplet ${{ matrix.config.triplet }}
64+
vcpkg install ${{ join(matrix.config.deps, ' ') }} --overlay-triplets cmake/custom-triplets --triplet ${{ matrix.config.triplet }}
6565
6666
- name: Get pip cache info
6767
id: pip-cache-info
@@ -82,8 +82,9 @@ jobs:
8282
8383
- name: Configure ALE
8484
run: |
85+
cmake --version
8586
mkdir build; cd build
86-
cmake ../ -DUSE_SDL=OFF -DPython3_EXECUTABLE=$(which python)
87+
cmake ../ -DSDL_SUPPORT=ON -DPython3_EXECUTABLE=$(which python)
8788
8889
- name: Build ALE
8990
working-directory: ./build
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(VCPKG_TARGET_ARCHITECTURE x64)
2+
if(PORT MATCHES "sdl")
3+
set(VCPKG_LIBRARY_LINKAGE dynamic)
4+
set(VCPKG_CRT_LINKAGE dynamic)
5+
else()
6+
set(VCPKG_LIBRARY_LINKAGE static)
7+
set(VCPKG_CRT_LINKAGE static)
8+
endif()
9+
10+
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
set(VCPKG_TARGET_ARCHITECTURE x64)
2+
if(PORT MATCHES "sdl")
3+
set(VCPKG_LIBRARY_LINKAGE dynamic)
4+
set(VCPKG_CRT_LINKAGE dynamic)
5+
else()
6+
set(VCPKG_LIBRARY_LINKAGE static)
7+
set(VCPKG_CRT_LINKAGE static)
8+
endif()
9+
10+
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
11+
12+
if(DEFINED ENV{MACOSX_DEPLOYMENT_TARGET})
13+
set(VCPKG_OSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}")
14+
endif()

setup.cfg

+5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ project_urls =
2626
[options]
2727
python_requires = >=3.6
2828
zip_safe = False
29+
packages =
30+
ale_py
31+
package_dir =
32+
ale_py = src/python
2933
install_requires =
3034
numpy
35+
importlib_metadata;python_version<'3.8'
3136
tests_require =
3237
pytest

setup.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def build_extension(self, ext):
4949
f"-DCMAKE_BUILD_TYPE={config}",
5050
f"-DPython3_EXECUTABLE={sys.executable}",
5151
f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}",
52+
"-DSDL_SUPPORT=ON",
53+
"-DSDL_DYNLOAD=ON",
5254
"-DBUILD_CPP_LIB=OFF",
5355
"-DBUILD_PYTHON_LIB=ON"
5456
]
@@ -137,6 +139,6 @@ def parse_version(version_file):
137139
setup(
138140
version=parse_version('version.txt'),
139141
distclass=CMakeDistribution,
140-
ext_modules=[CMakeExtension("ale_py")],
142+
ext_modules=[CMakeExtension("ale_py._ale_py")],
141143
cmdclass={"build_ext": CMakeBuild}
142144
)

src/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ if (BUILD_PYTHON_LIB)
7878
add_library(ale-py MODULE ale_interface.cpp ale_python_interface.cpp)
7979
target_link_libraries(ale-py PUBLIC ale)
8080
target_link_libraries(ale-py PRIVATE pybind11::module)
81-
set_target_properties(ale-py PROPERTIES OUTPUT_NAME ale_py
81+
set_target_properties(ale-py PROPERTIES OUTPUT_NAME _ale_py
8282
PREFIX "${PYTHON_MODULE_PREFIX}"
8383
SUFFIX "${PYTHON_MODULE_EXTENSION}")
8484
# If we're dynamically loading SDL with Python we'll be building a wheel

src/ale_python_interface.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class ALEPythonInterface : public ALEInterface {
6868

6969
} // namespace ale
7070

71-
PYBIND11_MODULE(ale_py, m) {
71+
PYBIND11_MODULE(_ale_py, m) {
7272
m.attr("__version__") = py::str(ALE_VERSION);
7373
#ifdef ALE_SDL_SUPPORT
7474
m.attr("SDL_SUPPORT") = py::bool_(true);

src/python/__init__.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import platform
2+
import sys
3+
import os
4+
5+
packagedir = os.path.abspath(os.path.dirname(__file__))
6+
7+
if platform.system() == "Windows":
8+
try:
9+
import ctypes
10+
ctypes.CDLL('vcruntime140.dll')
11+
ctypes.CDLL('msvcp140.dll')
12+
except OSError:
13+
raise OSError("""Microsoft Visual C++ Redistribution Pack is not installed.
14+
It can be downloaded from https://aka.ms/vs/16/release/vc_redist.x64.exe.""")
15+
16+
# Loading DLLs on Windows is kind of a disaster
17+
# The best approach seems to be using LoadLibraryEx
18+
# with user defined search paths. This kind of acts like
19+
# $ORIGIN or @loader_path on Unix / macOS.
20+
# This way we guarantee we load OUR DLLs.
21+
if sys.version_info.major == 3 and sys.version_info.minor >= 8:
22+
os.add_dll_directory(packagedir)
23+
else:
24+
# TODO: Py38: Remove AddDllDirectory
25+
kernel32 = ctypes.WinDLL('kernel32.dll', use_last_error=True)
26+
if hasattr(kernel32, 'AddDllDirectory'):
27+
kernel32.AddDllDirectory(packagedir)
28+
29+
# TODO Py38: Once 3.7 is deprecated use importlib.metadata to parse
30+
# version string from package.
31+
try:
32+
import importlib.metadata as importlib_metadata
33+
except ImportError:
34+
import importlib_metadata
35+
try:
36+
__version__ = importlib_metadata.version(__package__)
37+
except importlib_metadata.PackageNotFoundError:
38+
__version__ = "unknown"
39+
40+
# Import native shared library
41+
from ._ale_py import *

tests/fixtures.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import pytest
22

3-
import ale_py
3+
# Try to import native library before attempting ale_py
4+
try:
5+
import _ale_py as ale_py
6+
except ImportError:
7+
import ale_py
48

59

610
@pytest.fixture

tests/test_python_interface.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import pickle
44
import tempfile
55
import numpy as np
6-
import ale_py
6+
7+
# Try to import native library before attempting ale_py
8+
try:
9+
import _ale_py as ale_py
10+
except ImportError:
11+
import ale_py
712

813

914
def test_ale_version():

0 commit comments

Comments
 (0)