Repository navigation
Add support for building cpython embed exe's. #826
Description
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.executablewas a think likepy.extension_moduleis 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__.pyDistBuilder.py_resourceediting.pyd(built with the limited api)- data/
memimport.py(gets copied by the code inDistBuilder.pyto a specificdist/site-packagesfolder for zipping up into asite-packages.zipfile)zipextimporter.py(gets copied by the code inDistBuilder.pyto a specificdist/site-packagesfolder for zipping up into asite-packages.zipfile)embed.exe(gets copied by the code inDistBuilder.pyto a specificdist/build_tmpfolder for zipping up into afiles.zipfile)stub.exe(gets copied by the code inDistBuilder.pyto a specificdistfolder and where then the icon, string, and zip file resources in the exe gets replaced using the_resourceeditingextension, also the icon resource in theembed.exegets 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.
Activity
dnicolodi commentedon Dec 28, 2025
This is spelled like this:
I doubt this works. To install the executables in the right path you should set the
install_dirparameter to something likepy.get_install_dir() / 'py2exestub/data'. Alsoinstall_sources()does not work for installing directories, thus addingfiles('src/py2exestub/data')to the list of files to install does not work. You should list all files individually.This does not work either. You should just use the
subdirargument toextension_module()call.This is already supported by meson. See above.
Why do you want to have these defines specified in
pyproject.toml? If you want to have these passed to all compiler invocations you can usein
meson.build.AraHaan commentedon Dec 28, 2025
Now that I done this, I realized the
executablecalls don't have this argument supported though, it would be nice if it was supported in there though so I could then place the 2 python scripts in the data folder in thepy.install_sourcesas the only call to it.In other news, it seems it cannot figure out how to compile the resource scripts for the 2 exes.
dnicolodi commentedon Dec 28, 2025
Please read my previous comment again. The solution is spelled out clearly there.
I don't know what you mean by resources scripts, but in the case you are referring to MSVC resources, please refer to the Meson manual: https://mesonbuild.com/Windows-module.html#windows-module