Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
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
Uh oh!There was an error while loading. Please reload this page. | ||
| """ | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you mind adding a short note here (or even a TODO) about the relationship with Tools/freeze/freeze.py? MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea! | ||
| 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
Uh 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.