Skip to content

Commit af5981e

Browse files
committed
macos: initial support for macOS
Various features aren't yet implemented. But it should be "good enough" to facilitate experimentation.
1 parent 5abd974 commit af5981e

16 files changed

+589
-1
lines changed

.editorconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[Makefile]
2+
indent_style = tab
3+
4+
[Makefile.extra]
5+
indent_style = tab

README.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ common system libraries.
2727
Planned features include:
2828

2929
* Support for Windows
30-
* Support for macOS
3130
* Static/dynamic linking toggles for dependencies
3231

3332
Instructions
@@ -37,6 +36,10 @@ To build a Python distribution for Linux x64::
3736

3837
$ ./build-linux.py
3938

39+
To build a Python distribution for macOS::
40+
41+
$ ./build-macos.py
42+
4043
Requirements
4144
============
4245

@@ -48,6 +51,12 @@ available. The execution environment must have access to a Docker
4851
daemon (all build operations are performed in Docker containers for
4952
isolation from the host system).
5053

54+
macOS
55+
-----
56+
57+
The XCode command line tools must be installed. A Python 3 interpreter
58+
is required to execute the build. ``/usr/bin/clang`` must exist.
59+
5160
How It Works
5261
============
5362

build-macos.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env python3
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
import datetime
7+
import os
8+
import pathlib
9+
import subprocess
10+
import sys
11+
import venv
12+
13+
14+
ROOT = pathlib.Path(os.path.abspath(__file__)).parent
15+
BUILD = ROOT / 'build'
16+
DIST = ROOT / 'dist'
17+
VENV = BUILD / 'venv'
18+
PIP = VENV / 'bin' / 'pip'
19+
PYTHON = VENV / 'bin' / 'python'
20+
REQUIREMENTS = ROOT / 'requirements.txt'
21+
MAKE_DIR = ROOT / 'cpython-macos'
22+
23+
24+
def bootstrap():
25+
BUILD.mkdir(exist_ok=True)
26+
DIST.mkdir(exist_ok=True)
27+
28+
venv.create(VENV, with_pip=True)
29+
30+
subprocess.run([str(PIP), 'install', '-r', str(REQUIREMENTS)],
31+
check=True)
32+
33+
os.environ['PYBUILD_BOOTSTRAPPED'] = '1'
34+
os.environ['PATH'] = '%s:%s' % (str(VENV / 'bin'), os.environ['PATH'])
35+
os.environ['PYTHONPATH'] = str(ROOT)
36+
subprocess.run([str(PYTHON), __file__], check=True)
37+
38+
39+
def run():
40+
import zstandard
41+
from pythonbuild.downloads import DOWNLOADS
42+
43+
now = datetime.datetime.utcnow()
44+
45+
subprocess.run(['make'],
46+
cwd=str(MAKE_DIR), check=True)
47+
48+
source_path = BUILD / 'cpython-macos.tar'
49+
dest_path = DIST / ('cpython-%s-macos-%s.tar.zst' % (
50+
DOWNLOADS['cpython-3.7']['version'], now.strftime('%Y%m%dT%H%M')))
51+
52+
print('compressing Python archive to %s' % dest_path)
53+
with source_path.open('rb') as ifh, dest_path.open('wb') as ofh:
54+
cctx = zstandard.ZstdCompressor(level=15)
55+
cctx.copy_stream(ifh, ofh, source_path.stat().st_size)
56+
57+
58+
if __name__ == '__main__':
59+
try:
60+
if 'PYBUILD_BOOTSTRAPPED' not in os.environ:
61+
bootstrap()
62+
else:
63+
run()
64+
except subprocess.CalledProcessError as e:
65+
sys.exit(e.returncode)

cpython-macos/Makefile

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
ROOT := $(abspath $(CURDIR)/..)
2+
HERE := $(ROOT)/cpython-macos
3+
OUTDIR := $(ROOT)/build
4+
5+
BUILD := $(HERE)/build.py
6+
NULL :=
7+
8+
PLATFORM := macos
9+
10+
default: $(OUTDIR)/cpython-macos.tar
11+
12+
$(OUTDIR)/bzip2-macos.tar: $(HERE)/build-bzip2.sh
13+
$(BUILD) bzip2
14+
15+
$(OUTDIR)/libffi-macos.tar: $(HERE)/build-libffi.sh
16+
$(BUILD) libffi
17+
18+
$(OUTDIR)/openssl-macos.tar: $(HERE)/build-openssl.sh
19+
$(BUILD) openssl
20+
21+
$(OUTDIR)/ncurses-macos.tar: $(HERE)/build-ncurses.sh
22+
$(BUILD) ncurses
23+
24+
$(OUTDIR)/sqlite-macos.tar: $(HERE)/build-sqlite.sh
25+
$(BUILD) sqlite
26+
27+
$(OUTDIR)/uuid-macos.tar: $(HERE)/build-uuid.sh
28+
$(BUILD) uuid
29+
30+
$(OUTDIR)/xz-macos.tar: $(HERE)/build-xz.sh
31+
$(BUILD) xz
32+
33+
$(OUTDIR)/zlib-macos.tar: $(HERE)/build-zlib.sh
34+
$(BUILD) zlib
35+
36+
PYTHON_DEPENDS := \
37+
$(HERE)/static-modules \
38+
$(HERE)/build-cpython.sh \
39+
$(OUTDIR)/bzip2-macos.tar \
40+
$(OUTDIR)/libffi-macos.tar \
41+
$(OUTDIR)/ncurses-macos.tar \
42+
$(OUTDIR)/openssl-macos.tar \
43+
$(OUTDIR)/sqlite-macos.tar \
44+
$(OUTDIR)/uuid-macos.tar \
45+
$(OUTDIR)/xz-macos.tar \
46+
$(OUTDIR)/zlib-macos.tar \
47+
$(NULL)
48+
49+
$(OUTDIR)/cpython-macos.tar: $(PYTHON_DEPENDS)
50+
$(BUILD) cpython

cpython-macos/build-bzip2.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
tar -xf bzip2-${BZIP2_VERSION}.tar.gz
11+
12+
pushd bzip2-${BZIP2_VERSION}
13+
14+
make -j ${NUM_CPUS} install \
15+
CC=clang \
16+
CFLAGS="-fPIC" \
17+
PREFIX=${ROOT}/out

cpython-macos/build-cpython.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
DEPS_DIR="${ROOT}/deps"
10+
11+
export CC=clang
12+
export CXX=clang++
13+
14+
# We force linking of external static libraries by removing the shared
15+
# libraries. This is hacky. But we're building in a temporary directory
16+
# and it gets the job done.
17+
find ${DEPS_DIR} -name '*.so*' -exec rm {} \;
18+
find ${DEPS_DIR} -name '*.dylib' -exec rm {} \;
19+
20+
cat Python-${PYTHON_VERSION}/Modules/Setup.local
21+
22+
pushd Python-${PYTHON_VERSION}
23+
24+
# Most bits look at CFLAGS. But setup.py only looks at CPPFLAGS.
25+
# So we need to set both.
26+
CFLAGS="-I${DEPS_DIR}/include -I${DEPS_DIR}/lib/libffi-3.2.1/include -I/${DEPS_DIR}/include/ncurses -I${DEPS_DIR}/include/uuid"
27+
CPPFLAGS=$CFLAGS
28+
LDFLAGS="-L${DEPS_DIR}/lib"
29+
30+
CONFIGURE_FLAGS="--prefix=/install --with-openssl=${DEPS_DIR} --without-ensurepip"
31+
32+
if [ -n "${CPYTHON_OPTIMIZED}" ]; then
33+
CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-optimizations --enable-lto"
34+
fi
35+
36+
CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \
37+
./configure ${CONFIGURE_FLAGS}
38+
39+
# Supplement produced Makefile with our modifications.
40+
cat ../Makefile.extra >> Makefile
41+
42+
make -j ${NUM_CPUS}
43+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out/python
44+
45+
# Also copy object files so they can be linked in a custom manner by
46+
# downstream consumers.
47+
for d in Modules Objects Parser Programs Python; do
48+
mkdir -p ${ROOT}/out/python/build/$d
49+
cp -av $d/*.o ${ROOT}/out/python/build/$d/
50+
done
51+
52+
# config.c defines _PyImport_Inittab and extern references to modules, which
53+
# downstream consumers may want to strip. We bundle config.c and config.c.in so
54+
# a custom one can be produced downstream.
55+
# frozen.c is something similar for frozen modules.
56+
cp -av Modules/config.c ${ROOT}/out/python/build/Modules/
57+
cp -av Modules/config.c.in ${ROOT}/out/python/build/Modules/
58+
cp -av Python/frozen.c ${ROOT}/out/python/build/Python/
59+
cp ${ROOT}/python-licenses.rst ${ROOT}/out/python/LICENSE.rst

cpython-macos/build-libffi.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf libffi-${LIBFFI_VERSION}.tar.gz
14+
15+
pushd libffi-${LIBFFI_VERSION}
16+
17+
CFLAGS="-fPIC" CPPFLAGS="-fPIC" ./configure \
18+
--prefix=/
19+
20+
make -j ${NUM_CPUS}
21+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

cpython-macos/build-ncurses.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf ncurses-${NCURSES_VERSION}.tar.gz
14+
15+
pushd ncurses-${NCURSES_VERSION}
16+
17+
CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" ./configure \
18+
--prefix=/
19+
make -j ${NUM_CPUS}
20+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

cpython-macos/build-openssl.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf openssl-${OPENSSL_VERSION}.tar.gz
14+
15+
pushd openssl-${OPENSSL_VERSION}
16+
17+
/usr/bin/perl ./Configure --prefix=/ darwin64-x86_64-cc
18+
19+
make -j ${NUM_CPUS}
20+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

cpython-macos/build-sqlite.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf sqlite-autoconf-3250300.tar.gz
14+
pushd sqlite-autoconf-3250300
15+
16+
CFLAGS="-fPIC" CPPFLAGS="-fPIC" ./configure --prefix /
17+
18+
make -j ${NUM_CPUS}
19+
make -j ${NUM_CPUIS} install DESTDIR=${ROOT}/out

cpython-macos/build-uuid.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf libuuid-${UUID_VERSION}.tar.gz
14+
pushd libuuid-${UUID_VERSION}
15+
16+
CFLAGS="-fPIC" CPPFLAGS="-fPIC" ./configure --prefix=/
17+
18+
make -j ${NUM_CPUS}
19+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

cpython-macos/build-xz.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf xz-${XZ_VERSION}.tar.gz
14+
15+
pushd xz-${XZ_VERSION}
16+
17+
CFLAGS="-fPIC" CPPFLAGS="-fPIC" CCASFLAGS="-fPIC" ./configure \
18+
--prefix=/ \
19+
--disable-xz \
20+
--disable-xzdec \
21+
--disable-lzmadec \
22+
--disable-lzmainfo \
23+
--disable-lzma-links \
24+
--disable-scripts
25+
26+
make -j ${NUM_CPUS}
27+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

cpython-macos/build-zlib.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
ROOT=`pwd`
9+
10+
export CC=clang
11+
export CXX=clang++
12+
13+
tar -xf zlib-${ZLIB_VERSION}.tar.gz
14+
15+
pushd zlib-${ZLIB_VERSION}
16+
17+
CFLAGS="-fPIC" ./configure --prefix=/
18+
make -j ${NUM_CPUS}
19+
make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

0 commit comments

Comments
 (0)