This repo contains the source code of Python 2.7.18 customized to compile with Cosmopolitan libc. Meant for experimental purposes only.
The header_stubs
folder contains dummy headers corresponding to the C
stdlib. The libcosmo
folder should contain the required files for
compiling an executable using Cosmopolitan on Linux.
The compiled APE runs on Linux and Windows -- the Python standard library,
platform dependent files, pip
, and setuptools
are all contained within the
executable, (APEs are also valid ZIP files!!!). Note: environment variables
PYTHONPATH
and PYTHONHOME
are NOT read during interpreter startup.
The following modules of the Python stdlib are currently not compiled:
_ctypes _ctypes_test _curses
_curses_panel _hashlib _locale
_socket _ssl audioop
bz2 crypt linuxaudiodev
nis ossaudiodev readline
resource termios
_bsddb _multiprocessing _sqlite3
_tkinter bsddb185 dbm
dl gdbm imageop
spwd sunaudiodev
Modules/Setup.local
contains recipes to compile the _ctypes
and _sqlite3
modules.
Compiled on:
# Debian Buster (Linux 4.19.0-12-amd64)
$ gcc --version
gcc (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ clang --version
Debian clang version 11.0.1-++20201103062553+ef4ffcafbb2-1~exp1~20201103053214.125
Target: x86_64-pc-linux-gnu
Thread model: posix
Also needs sh
, make
, objcopy
, find
, zip
, and xargs
.
- Obtain
cosmopolitan.zip
amalgamation or compile any version of Cosmopolitan after (8c4cce0
July 11 2021), preferably the latest stable version. - Copy
cosmopolitan.h
(andcrt.o
,ape.o
,ape.lds
,cosmopolitan.a
) to thelibcosmo/
folder. - Run
superconfigure
with the appropriate$CC
(callsconfigure
with a bunch of parameters, followed bymake
and thenobjcopy
to producepython.com
) - Copy
python.com
to wherever and run it
cd libcosmo/
# use the latest version
wget https://justine.lol/cosmopolitan/cosmopolitan.zip
unzip cosmopolitan.zip
cd ../
CC=gcc ./superconfigure # or clang
./python.com
As of right now python.com -m pip download/install
from the web doesn't work
nicely because the APE does not currently have SSL support. So find some other
way to get the wheels. Create a folder called Lib
in the same location as
python.com
and unzip all necessary packages there.
./python.com -V
mkdir -p Lib/site-packages # Lib is also okay
# need to download packages from pip first, so using system python
/usr/bin/python2 -m pip download pytz
# dataclasses are not included in Python3.6 by default
./python.com -m pip --help
./python.com -m pip install ./pytz.whl -t ./Lib/site-packages
# or if pip complains for whatever reason
unzip ./pytz.whl -d ./Lib/site-packages
# check if importing works
./python.com -c 'import pytz'
Of course, only packages with the py2-none-any.whl
(ie no C extensions) will
import properly.
APEs are statically compiled, so no dlopen
, which means you currently can't
have shared objects as part of your setup. However, it is still possible to
use some C extensions by compiling them like stdlib modules:
- Obtain the source for a given package
my_package
with an extensionmy_package.ext
- Move all C source files to a subfolder of
Modules
calledmy_package_ext
- Move all Python source files to a subfolder
Lib
(ensure directory structure is valid for the Python files). - Change the name of C extensions and replace dots
with underscores. For example, if the extension name is
my_package.ext
, it should now bemy_package_ext
. Also, there must be a function calledinit_my_package_ext
which initializes the extension. - Change the necessary imports in the Python source files to use
my_package_ext
correctly. For example,import func from .ext
inmy_package.__init__
would becomeimport func from my_package_ext
(no dot). - Add the compilation recipe for the package into
Modules/Setup.local
.- The recipe format is described in
Modules/Setup
, and it is used to compile the C extensions for the standard library. It's basically[<extension_name> <source-files> <includes> <links>]
(imagine it withgcc -o
added at the start), but a little finicky, especially if you're passing stuff like-DMY_FLAG=1
(checkpyexpat
inModules/Setup
to see how to do it right).
- The recipe format is described in
- If you didn't add the recipe correctly, the Makefile will complain. Delete the
makefile and run
superconfigure
again. - If you added the recipe correctly, run
make
to check successful compilation, and then try importing the package with the./python -c 'import my_package'
.
For example, the APE includes greenlet 1.1.0 alongside the
stdlib, because I wanted to try Flask 1.1.4. Modules/Setup.local
contains
the recipe to compile the _greenlet
component of the greenlet package.