Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
bpo-45949: Pure Python freeze module for cross builds (GH-29899)#29899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Use pure Python ``freeze_module`` for all but importlib bootstrap files. | ||
| ``--with-freeze-module`` :program:`configure` option is no longer needed for | ||
| cross builds. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| """Python implementation of Programs/_freeze_module.c | ||
| The pure Python implementation uses same functions and arguments as the C | ||
| implementation. | ||
| The generated byte code is slightly different because | ||
| compile() sets the PyCF_SOURCE_IS_UTF8 flag and objects have a | ||
| reference count > 1. Marshal adds the `FLAG_REF` flag and creates a | ||
| reference `hashtable`. | ||
ericsnowcurrently marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| """ | ||
| ||
| import marshal | ||
| import sys | ||
| header = "/* Auto-generated by Programs/_freeze_module.py */" | ||
| def read_text(inpath: str) -> bytes: | ||
| with open(inpath, "rb") as f: | ||
| return f.read() | ||
| def compile_and_marshal(name: str, text: bytes) -> bytes: | ||
| filename = f"<frozen{name}>" | ||
| # exec == Py_file_input | ||
| code = compile(text, filename, "exec", optimize=0, dont_inherit=True) | ||
| return marshal.dumps(code) | ||
| def get_varname(name: str, prefix: str) -> str: | ||
| return f"{prefix}{name.replace('.', '_')}" | ||
| def write_code(outfile, marshalled: bytes, varname: str) -> None: | ||
| data_size = len(marshalled) | ||
| outfile.write(f"const unsigned char{varname}[] ={{\n") | ||
| for n in range(0, data_size, 16): | ||
| outfile.write(" ") | ||
| outfile.write(",".join(str(i) for i in marshalled[n : n + 16])) | ||
| outfile.write(",\n") | ||
| outfile.write("};\n") | ||
| def write_frozen(outpath: str, inpath: str, name: str, marshalled: bytes) -> None: | ||
| with open(outpath, "w") as outfile: | ||
| outfile.write(header) | ||
| outfile.write("\n") | ||
| arrayname = get_varname(name, "_Py_M__") | ||
| write_code(outfile, marshalled, arrayname) | ||
| def main(): | ||
| if len(sys.argv) != 4: | ||
| sys.exit("need to specify the name, input and output paths\n") | ||
| name = sys.argv[1] | ||
| inpath = sys.argv[2] | ||
| outpath = sys.argv[3] | ||
| text = read_text(inpath) | ||
| marshalled = compile_and_marshal(name, text) | ||
| write_frozen(outpath, inpath, name, marshalled) | ||
| if __name__ == "__main__": | ||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -264,6 +264,10 @@ def ispkg(self): | ||
| else: | ||
| return os.path.basename(self.pyfile) == '__init__.py' | ||
| @property | ||
| def isbootstrap(self): | ||
| return self.id in BOOTSTRAP | ||
| def resolve_frozen_file(frozenid, destdir): | ||
| """Return the filename corresponding to the given frozen ID. | ||
| @@ -476,7 +480,7 @@ def regen_frozen(modules): | ||
| indent = ' ' | ||
| lastsection = None | ||
| for mod in modules: | ||
| if mod.frozenid in BOOTSTRAP: | ||
| if mod.isbootstrap: | ||
| lines = bootstraplines | ||
| elif mod.section == TESTS_SECTION: | ||
| lines = testlines | ||
| @@ -585,10 +589,17 @@ def regen_makefile(modules): | ||
| pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) | ||
| pyfiles.append(f'\t\t{pyfile} \\') | ||
| freeze = (f'$(FREEZE_MODULE){src.frozenid} ' | ||
| f'$(srcdir)/{pyfile}{frozen_header}') | ||
| if src.isbootstrap: | ||
| freezecmd = '$(FREEZE_MODULE_BOOTSTRAP)' | ||
ericsnowcurrently marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| freezedep = '$(FREEZE_MODULE_BOOTSTRAP_DEPS)' | ||
| else: | ||
| freezecmd = '$(FREEZE_MODULE)' | ||
| freezedep = '$(FREEZE_MODULE_DEPS)' | ||
| freeze = (f'{freezecmd}{src.frozenid} ' | ||
| f'$(srcdir)/{pyfile}{frozen_header}') | ||
| rules.extend([ | ||
| f'{frozen_header}: $(FREEZE_MODULE) {pyfile}', | ||
| f'{frozen_header}:{pyfile}{freezedep}', | ||
| f'\t{freeze}', | ||
| '', | ||
| ]) | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.