-
Notifications
You must be signed in to change notification settings - Fork 22
/
static_freeze.py
executable file
·110 lines (83 loc) · 3.42 KB
/
static_freeze.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env python
'''This script generates, runs, and then deletes a Makefile which will compile a
Python script into a standalone executable which is statically linked to the
Python runtime.
To use this script, first generate a static Python library (see the parent
directory's README.md).
Usage:
python static_freeze.py test_file.py /path/to/static/libpythonX.X.a
Any additional arguments will be passed to the generated Makefile,
e.g. PYTHON=python3
'''
import sys
import os
from subprocess import call
major_version = sys.version_info[0]
make_template = '''# Makefile for creating our standalone Cython program
PYTHON=./python
CYTHON=cython
PYVERSION=$(shell $(PYTHON) -c "import sys; print(sys.version[:3])")
#INCDIR=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())")
INCDIR=Include/
PLATINCDIR=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc(plat_specific=True))")
LIBDIR1=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
LIBDIR2=%library_dir%
PYLIB=%library_name%
CC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))")
LINKCC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))")
LIBS=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'))")
SYSLIBS= $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))")
INCLUDE=
%name%: %name%.o %library_dir%/lib%library_name%.a
$(LINKCC) -o $@ $^ -L$() -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) $(LIBS) $(SYSLIBS) $(INCLUDE)
%name%.o: %name%.c
$(CC) -c $^ -I$(INCDIR) -I$(PLATINCDIR) $(INCLUDE)
%name%.c: %filename%
@$(CYTHON) -%major% --embed %filename%
all: %name%
clean:
rm -f %name% %name%.c %name%.o
'''
def freeze(filename, library, make_args=None):
if make_args is None: make_args = []
name = '.'.join(filename.split('.')[:-1])
library_dir, library_name = os.path.split(os.path.abspath(library))
library_name = '.'.join((library.split('/')[-1][3:]).split('.')[:-1])
template = make_template
# generate makefile
for a, b in (
('%name%', name),
('%filename%', filename),
('%library_dir%', library_dir),
('%library_name%', library_name),
('%major%', str(major_version)),
):
template = template.replace(a, b)
with open(filename + '.make', 'wb') as make_file:
make_file.write(bytes(template, 'utf8'))
# call make
call(['make', '-f', '%s.make' % filename] + make_args)
# delete makefile
os.remove(filename + '.make')
if __name__ == '__main__':
def fail(message):
print(__doc__)
print(message)
sys.exit()
try:
script_file = sys.argv[1]
assert os.path.exists(script_file)
except IndexError:
fail('ERROR: No script specified')
except AssertionError:
fail('ERROR: Script not found')
try:
lib_path = sys.argv[2]
assert os.path.exists(lib_path)
except IndexError:
fail('ERROR: Path to Python runtime not specified')
except AssertionError:
fail('ERROR: Python runtime not found')
try: make_args = sys.argv[3:]
except IndexError: make_args = []
freeze(script_file, lib_path, make_args=make_args)