Skip to content

Add support for building cpython embed exe's. #826

@AraHaan

Description

@AraHaan

I am using meson.build to hopefully bundle in a wheel of my package that not only builds C extensions, but also packages in:

  • 1 embed exe file that gets built my meson (I really wish py.executable was a think like py.extension_module is today which automatically passes in the following for me:
  • the python include folder(s)
  • the python lib folder(s) for the link step

Also the package expects a stub exe to be built as well which does NOT need the python include folder nor the python lib folder as it is meant to be act like a "SFX EXE" like file for the embedded python to get packed down to a single file.

The resulting expected files that are to be packed in the resulting wheels (after building everything)

  • py2exestub/ (temp package name for now)
    • __init__.py
    • __main__.py
    • DistBuilder.py
    • _resourceediting.pyd (built with the limited api)
    • data/
      • memimport.py (gets copied by the code in DistBuilder.py to a specific dist/site-packages folder for zipping up into a site-packages.zip file)
      • zipextimporter.py (gets copied by the code in DistBuilder.py to a specific dist/site-packages folder for zipping up into a site-packages.zip file)
      • embed.exe (gets copied by the code in DistBuilder.py to a specific dist/build_tmp folder for zipping up into a files.zip file)
      • stub.exe (gets copied by the code in DistBuilder.py to a specific dist folder and where then the icon, string, and zip file resources in the exe gets replaced using the _resourceediting extension, also the icon resource in the embed.exe gets replaced before it gets zipped into the zip file that is used to replace the initial empty one in the stub exe)

My meson.build file currently:

project('py2exestub', 'c')

py = import('python').find_installation(pure: false)

# Optional: enable Py_LIMITED_API for the embed exe
limited_api_args = ['-DPy_LIMITED_API=0x030C0000', '-D_UNICODE', '-DUNICODE']

# ----------------------------------------------------
# 1. Build _memimport from externals/py2exe sources
# ----------------------------------------------------

memimport_sources = files(
    '../py2exe/source/_memimport.c',
    '../py2exe/source/actctx.c',
    '../py2exe/source/import_mini.c',
    '../py2exe/source/MemoryModule.c',
    '../py2exe/source/MyLoadLibrary.c'
)

_memimport = py.extension_module(
    '_memimport',
    memimport_sources,
    install: true,
    include_directories: [include_directories('../py2exe/source')],
    c_args: ['-DSTANDALONE', '-DPy_LIMITED_API=0x030C0000', '-D_UNICODE', '-DUNICODE'],   # ← required define
)

_resourceediting = py.extension_module(
    '_resourceediting',
    'src/py2exestub/_resourceediting.c',
    install: true,
    include_directories: [include_directories('src/py2exestub')],
    c_args: limited_api_args,
)

# ----------------------------------------------------
# 2. Build embed (uses Python)
# ----------------------------------------------------

embed_sources = files(
    'src/py2exestub/embed.c',
    'src/py2exestub/embed.rc'
)

# Need the Python include + library dirs here
embed = executable(
    'embed',
    embed_sources,
    install: true,
    include_directories: [py_inc, py_plat_inc, include_directories('src/py2exestub')],
    link_with: py_lib,
    c_args: limited_api_args,
)

# ----------------------------------------------------
# 3. Build stub (no Python)
# ----------------------------------------------------

stub_sources = files(
    'src/py2exestub/stub.c',
    '../miniz-3.0.2/miniz.c',
    'src/py2exestub/stub.rc'
)

stub = executable(
    'stub_launcher',
    stub_sources,
    install: true,
    include_directories: [include_directories('../miniz-3.0.2'), include_directories('src/py2exestub')],
    c_args: ['-D_CRT_SECURE_NO_WARNINGS', '-D_UNICODE', '-DUNICODE'],
)

# Install the two executables, the C extension, and the contents of the data folder in src into py2exestub/data/
py.install_sources(
    [embed, stub, _memimport] + files('src/py2exestub/data'),
    subdir: 'py2exestub/data'
)

# Install the _resourceediting c extension required for the package to work.
py.install_sources(
    [_resourceediting],
    subdir: 'py2exestub'
)

Basically having support for building the embed exe itself would be great in meson-python. Also it would have been nice if one could also configure meson-python to pass in the following defines (_UNICODE, UNICODE, and _CRT_SECURE_NO_WARNINGS) as well from within pyproject.toml to avoid some duplication in the meson.build file.

My goal with this:
I been working hard on a project with the hopes of someday pull requesting the files to the py2exe repository to bring back single file exe support using my idea of having a SFX EXE type thing as a stub to do such.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions