Skip to content

Fix Program/_freeze_module for cross compiling Python #90044

Closed

Description

@tiran
BPO 45886
Nosy @gvanrossum, @brettcannon, @tiran, @ericsnowcurrently, @iritkatriel
PRs
  • bpo-45886: Allow overriding freeze command for cross compiling (GH-29735) #29735
  • bpo-45886: Fix OOT build when srcdir has frozen module headers (GH-29793) #29793
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/tiran'
    closed_at = None
    created_at = <Date 2021-11-23.22:35:22.196>
    labels = ['type-feature', 'build', '3.11']
    title = 'Fix Program/_freeze_module for cross compiling Python'
    updated_at = <Date 2022-03-31.17:54:40.972>
    user = 'https://github.com/tiran'

    bugs.python.org fields:

    activity = <Date 2022-03-31.17:54:40.972>
    actor = 'brett.cannon'
    assignee = 'christian.heimes'
    closed = False
    closed_date = None
    closer = None
    components = ['Build']
    creation = <Date 2021-11-23.22:35:22.196>
    creator = 'christian.heimes'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 45886
    keywords = ['patch']
    message_count = 8.0
    messages = ['406893', '406898', '406904', '406988', '407006', '407062', '407267', '407272']
    nosy_count = 5.0
    nosy_names = ['gvanrossum', 'brett.cannon', 'christian.heimes', 'eric.snow', 'iritkatriel']
    pr_nums = ['29735', '29793']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue45886'
    versions = ['Python 3.11']

    Activity

    1. tiran commented on Nov 23, 2021

      @tiran
      MemberAuthor

      The build process creates the binary Program/_freeze_module, which is used to create frozen modules. The program takes a Python file, compiles it, and stores its marshalled output in a header file.

      The approach does not work when cross compiling Python. In cross building case Program/_freeze_module cannot be executed on the build host. For example a cross build with build host "x86_64" and target host "aarch64" would create a aarch64 Program/_freeze_module. The current x86_64 host cannot executed binary (unless you use qemu and binfmt, which I'm deliberately ignoring here).

      To unblock cross building and until we find a better solution, I propose that we allow developers to override the freeze module command on the command line. This allows developers to use a freeze_module program from a non-cross build:

      ../../configure -C --host=aarch64-linux-gnu-gcc --build=x86_64-pc-linux-gnu
      make FREEZE_MODULE=../x86_64/Program/_freeze_module

    2. self-assigned this
      on Nov 23, 2021
    3. added
      buildThe build process and cross-build
      type-featureA feature request or enhancement
      3.11only security fixes
      on Nov 23, 2021
    4. self-assigned this
      on Nov 23, 2021
    5. added
      buildThe build process and cross-build
      type-featureA feature request or enhancement
      on Nov 23, 2021
    6. gvanrossum commented on Nov 23, 2021

      @gvanrossum
      Member

      To the question "why does _freeze_module need to be a (C) binary" (IOW, why can't it be replaced by a Python script that is run with PYTHON_FOR_REGEN, which always runs on the build host), the reason is that it uses the bytecode compiler to generate correct output. The bytecode compiler is written in C and depends on many other parts of the runtime. Bytecode is not compatible between versions (and in 3.11 it is an especially moving target) so we absolutely must use the bytecode compiler from the current source tree.

      Fortunately bytecode *is* portable across OS and CPU versions, so there is no problem with taking a _freeze_module binary compiled for the build host and running it there (on the build host). It *is* complicated to build a binary for the build host in a tree configured for cross compilation though -- you'd have to do an out-of-tree build configured for the build host platform. Rather than solving *that* problem, Christian proposes to let the user solve that, and allowing the user to pass in the path to the host platform _freeze_module binary.

    7. tiran commented on Nov 24, 2021

      @tiran
      MemberAuthor

      New changeset dd8ce9e by Christian Heimes in branch 'main':
      bpo-45886: Allow overriding freeze command for cross compiling (GH-29735)
      dd8ce9e

    8. tiran commented on Nov 25, 2021

      @tiran
      MemberAuthor

      The FREEZE_MODULE trick fails with out-of-tree builds when SRCDIR contains the frozen_modules header files from a previous build. When doing OOT building, make includes the SRCDIR in the search path for dependencies (VPATH). It considers $(srcdir)/Python/frozen_modules/importlib._bootstrap_external.h as recent enough and therefore does not generate $(builddir)/Python/frozen_modules/importlib._bootstrap_external.h. The freeze_module program does not know about VPATH and looks up the file in the $(builddir) tree:

      $ make FREEZE_MODULE=/cpython/builddep/ubuntu-impish-x86_64/Programs/_freeze_module
      ...
      python3.9 ../../Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap_external.h -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c
      Traceback (most recent call last):
        File "/cpython/builddep/wasi/../../Tools/scripts/deepfreeze.py", line 463, in <module>
          main()
        File "/cpython/builddep/wasi/../../Tools/scripts/deepfreeze.py", line 451, in main
          with open(args.file, encoding="utf-8") as f:
      FileNotFoundError: [Errno 2] No such file or directory: 'Python/frozen_modules/importlib._bootstrap_external.h'
      make: *** [Makefile:1055: Python/deepfreeze/importlib._bootstrap_external.c] Error 1
      $ make FREEZE_MODULE=/cpython/builddep/ubuntu-impish-x86_64/Programs/_freeze_module Python/frozen_modules/importlib._bootstrap_external.h  
      make: '../../Python/frozen_modules/importlib._bootstrap_external.h' is up to date.

      I see two possible solutions for the problem:

      • extend make clean to also remove $(FROZEN_FILES_OUT). The make clean command is suppose to remove all files that interferes with OOT builds (see check-clean-src in Makefile.pre.in).
      • prefix $(FROZEN_FILES_OUT) and their targets with $(abs_builddir) to avoid VPATH lookups. abs_builddir is the absolute path to the build directory.
    9. gvanrossum commented on Nov 25, 2021

      @gvanrossum
      Member

      Imthink I prefer the ‘make clean’ extension.--
      --Guido (mobile)

    10. tiran commented on Nov 26, 2021

      @tiran
      MemberAuthor

      New changeset 765b2a3 by Christian Heimes in branch 'main':
      bpo-45886: Fix OOT build when srcdir has frozen module headers (GH-29793)
      765b2a3

    11. iritkatriel commented on Nov 29, 2021

      @iritkatriel
      Member

      Is this related to this issue or something else?

      https://buildbot.python.org/all/#/builders/310/builds/344

      gcc -pthread -c -Wsign-compare -g -Og -Wall -std=c99 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I. -I./Include -DPy_BUILD_CORE -o Programs/_freeze_module.o Programs/_freeze_module.c
      gcc -pthread -o Programs/_freeze_module Programs/_freeze_module.o Modules/getbuildinfo.o Parser/token.o Parser/pegen.o Parser/pegen_errors.o Parser/action_helpers.o Parser/parser.o Parser/string_parser.o Parser/peg_api.o Parser/myreadline.o Parser/tokenizer.o Objects/abstract.o Objects/accu.o Objects/boolobject.o Objects/bytes_methods.o Objects/bytearrayobject.o Objects/bytesobject.o Objects/call.o Objects/capsule.o Objects/cellobject.o Objects/classobject.o Objects/codeobject.o Objects/complexobject.o Objects/descrobject.o Objects/enumobject.o Objects/exceptions.o Objects/genericaliasobject.o Objects/genobject.o Objects/fileobject.o Objects/floatobject.o Objects/frameobject.o Objects/funcobject.o Objects/interpreteridobject.o Objects/iterobject.o Objects/listobject.o Objects/longobject.o Objects/dictobject.o Objects/odictobject.o Objects/memoryobject.o Objects/methodobject.o Objects/moduleobject.o Objects/namespaceobject.o Objects/object.o Objects/obmalloc.o Objects/picklebufobject.o Objects/rangeobject.o Objects/setobject.o Objects/sliceobject.o Objects/structseq.o Objects/tupleobject.o Objects/typeobject.o Objects/unicodeobject.o Objects/unicodectype.o Objects/unionobject.o Objects/weakrefobject.o Python/_warnings.o Python/Python-ast.o Python/Python-tokenize.o Python/asdl.o Python/ast.o Python/ast_opt.o Python/ast_unparse.o Python/bltinmodule.o Python/ceval.o Python/codecs.o Python/compile.o Python/context.o Python/dynamic_annotations.o Python/errors.o Python/frame.o Python/frozenmain.o Python/future.o Python/getargs.o Python/getcompiler.o Python/getcopyright.o Python/getplatform.o Python/getversion.o Python/hamt.o Python/hashtable.o Python/import.o Python/importdl.o Python/initconfig.o Python/marshal.o Python/modsupport.o Python/mysnprintf.o Python/mystrtoul.o Python/pathconfig.o Python/preconfig.o Python/pyarena.o Python/pyctype.o Python/pyfpe.o Python/pyhash.o Python/pylifecycle.o Python/pymath.o Python/pystate.o Python/pythonrun.o Python/pytime.o Python/bootstrap_hash.o Python/specialize.o Python/structmember.o Python/symtable.o Python/sysmodule.o Python/thread.o Python/traceback.o Python/getopt.o Python/pystrcmp.o Python/pystrtod.o Python/pystrhex.o Python/dtoa.o Python/formatter_unicode.o Python/fileutils.o Python/suggestions.o Python/dynload_shlib.o Modules/config.o Modules/getpath.o Modules/main.o Modules/gcmodule.o Modules/atexitmodule.o Modules/faulthandler.o Modules/posixmodule.o Modules/signalmodule.o Modules/_tracemalloc.o Modules/_codecsmodule.o Modules/_collectionsmodule.o Modules/errnomodule.o Modules/_io/_iomodule.o Modules/_io/iobase.o Modules/_io/fileio.o Modules/_io/bytesio.o Modules/_io/bufferedio.o Modules/_io/textio.o Modules/_io/stringio.o Modules/itertoolsmodule.o Modules/_sre.o Modules/_threadmodule.o Modules/timemodule.o Modules/_weakref.o Modules/_abc.o Modules/_functoolsmodule.o Modules/_localemodule.o Modules/_operator.o Modules/_stat.o Modules/symtablemodule.o Modules/pwdmodule.o Modules/xxsubtype.o -lpthread -ldl -lutil -lm
      Programs/_freeze_module importlib._bootstrap ./Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h
      python3 ./Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap.h -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c
      File "./Tools/scripts/deepfreeze.py", line 29
      res.append(f"\\x{i:02x}")
      ^
      SyntaxError: invalid syntax
      Makefile:1069: recipe for target 'Python/deepfreeze/importlib._bootstrap.c' failed
      make: *** [Python/deepfreeze/importlib._bootstrap.c] Error 1
      program finished with exit code 2
      elapsedTime=45.181814

    12. tiran commented on Nov 29, 2021

      @tiran
      MemberAuthor

      The issue is related to bpo-45873. The Debian buildbot has an ancient Python version that does not support f-strings.

    13. transferred this issue fromon Apr 10, 2022
    14. kumaraditya303 commented on May 9, 2022

      @kumaraditya303
      Contributor

      Can this be closed now ?

    15. gvanrossum commented on May 9, 2022

      @gvanrossum
      Member

      I guess so. (@tiran If there's still something to do here feel free to reopen.)

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    3.11only security fixesbuildThe build process and cross-buildtype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions