conda-forge / pyinstaller-feedstock

A conda-smithy repository for pyinstaller.
BSD 3-Clause "New" or "Revised" License
5 stars 16 forks source link

Missing `objcopy` on Miniforge3 Docker #59

Open mfansler opened 3 years ago

mfansler commented 3 years ago

Issue

Running PyInstaller on condaforge/miniforge3:4.10.3-1 image fails to generate functional binaries. This is due to the assumption that linux-64 platform includes the objcopy command supplied by binutils. This could be remedied by adding binutils as a dependency.

Recreate Steps

## launch docker
docker run --rm -it condaforge/miniforge3:4.10.3-1

## within docker BASH session
conda create -yn pi python=3.9 pyinstaller

## activate 'pi' env
conda activate pi

## create dummy script
echo "import sys; print(sys.path)" > script.py

## test
pyinstaller -F script.py

Result

Throws error message:

FileNotFoundError: [Errno 2] No such file or directory: 'objcopy'

Full Output

```bash 172 INFO: PyInstaller: 4.3 172 INFO: Python: 3.9.6 (conda) 175 INFO: Platform: Linux-5.10.25-linuxkit-x86_64-with-glibc2.31 176 INFO: wrote /script.spec 178 INFO: UPX is not available. 180 INFO: Extending PYTHONPATH with paths ['/', '/'] 183 INFO: checking Analysis 183 INFO: Building Analysis because Analysis-00.toc is non existent 183 INFO: Initializing module dependency graph... 184 INFO: Caching module graph hooks... 190 INFO: Analyzing base_library.zip ... 2091 INFO: Processing pre-find module path hook distutils from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks/pre_find_module_path/hook-distutils.py'. 2092 INFO: distutils: retargeting to non-venv dir '/opt/conda/envs/pi/lib/python3.9' 4405 INFO: Caching module dependency graph... 4560 INFO: running Analysis Analysis-00.toc 4570 INFO: Analyzing /script.py 4571 INFO: Processing module hooks... 4572 INFO: Loading module hook 'hook-pickle.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4574 INFO: Loading module hook 'hook-multiprocessing.util.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4575 INFO: Loading module hook 'hook-difflib.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4577 INFO: Loading module hook 'hook-sysconfig.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4583 INFO: Loading module hook 'hook-lib2to3.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4599 INFO: Loading module hook 'hook-_tkinter.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... Traceback (most recent call last): File "", line 1, in File "/opt/conda/envs/pi/lib/python3.9/tkinter/__init__.py", line 37, in import _tkinter # If this fails your Python may not be configured for Tk ImportError: libX11.so.6: cannot open shared object file: No such file or directory Traceback (most recent call last): File "", line 1, in ImportError: libX11.so.6: cannot open shared object file: No such file or directory 4643 ERROR: Tcl/Tk improperly installed on this system. 4644 INFO: Loading module hook 'hook-distutils.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4644 INFO: Loading module hook 'hook-xml.etree.cElementTree.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4645 INFO: Loading module hook 'hook-xml.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4683 INFO: Loading module hook 'hook-heapq.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4685 INFO: Loading module hook 'hook-encodings.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4725 INFO: Loading module hook 'hook-distutils.util.py' from '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks'... 4739 INFO: Looking for ctypes DLLs 4770 INFO: Analyzing run-time hooks ... 4774 INFO: Including run-time hook '/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py' 4782 INFO: Looking for dynamic libraries 5205 INFO: Looking for eggs 5205 INFO: Python library not in binary dependencies. Doing additional searching... 5214 INFO: Using Python library /opt/conda/envs/pi/lib/libpython3.9.so.1.0 5219 INFO: Warnings written to /build/script/warn-script.txt 5244 INFO: Graph cross-reference written to /build/script/xref-script.html 5255 INFO: checking PYZ 5255 INFO: Building PYZ because PYZ-00.toc is non existent 5255 INFO: Building PYZ (ZlibArchive) /build/script/PYZ-00.pyz 5592 INFO: Building PYZ (ZlibArchive) /build/script/PYZ-00.pyz completed successfully. 5596 INFO: checking PKG 5597 INFO: Building PKG because PKG-00.toc is non existent 5597 INFO: Building PKG (CArchive) PKG-00.pkg 13615 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully. 13617 INFO: Bootloader /opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/bootloader/Linux-64bit/run 13618 INFO: checking EXE 13618 INFO: Building EXE because EXE-00.toc is non existent 13618 INFO: Building EXE from EXE-00.toc 13618 INFO: Appending archive to ELF section in EXE /dist/script Traceback (most recent call last): File "/opt/conda/envs/pi/bin/pyinstaller", line 11, in sys.exit(run()) File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/__main__.py", line 114, in run run_build(pyi_config, spec_file, **vars(args)) File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/__main__.py", line 65, in run_build PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs) File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 737, in main build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build')) File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 684, in build exec(code, spec_namespace) File "/script.spec", line 21, in exe = EXE(pyz, File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/building/api.py", line 450, in __init__ self.__postinit__() File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/building/datastruct.py", line 160, in __postinit__ self.assemble() File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/building/api.py", line 616, in assemble retcode, stdout, stderr = exec_command_all( File "/opt/conda/envs/pi/lib/python3.9/site-packages/PyInstaller/compat.py", line 461, in exec_command_all proc = subprocess.Popen(cmdargs, bufsize=-1, # Default OS buffer size. File "/opt/conda/envs/pi/lib/python3.9/subprocess.py", line 951, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "/opt/conda/envs/pi/lib/python3.9/subprocess.py", line 1821, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) FileNotFoundError: [Errno 2] No such file or directory: 'objcopy' ```

Expected Result

It should successfully build the binary.

Workaround

The error can be overcome by installing binutils. That is, running the above recreate steps, but with

conda create -yn pi python=3.9 pyinstaller binutils

enables error-free running of the last step.

Recommended Solution

The feedstock maintainers should consider including binutils as a runtime dependency, at least for linux-64 builds. The recipe should include a end-to-end test that would catch this failure in future builds.

jakirkham commented 3 years ago

I'm hesitant to do this as it would likely cause issues for packages building in conda-forge relying on pyinstaller. This is because they normally would be getting build utilities (like the compiler and binutils) from the build environment. Including this in pyinstaller would pull this in the host environment. This would then likely lead to clashes between these two environments.

Given this, is there a reason one can't install this themselves or grab it from the system?

mfansler commented 3 years ago

@jakirkham thanks for the reply. Yes, one can simply install the binutils to get things working. I created this issue partially to document that workaround for others, partially to spark a discussion as to adding it as an explicit dependency.

If there are non-trivial consequences to the latter, then it sounds better to leave it as is.

nehaljwani commented 3 years ago

Other ways to consider: either vendor a copy of objcopy and patch pyinstaller to use that or urge the developers of pyinstaller to switch to a solution that doesn't require dependency on objcopy (using some ELF library like py-lief or pyelftools). All objcopy is used for is this.

nehaljwani commented 3 years ago

Turns there is already a fallback in place, the path just doesn't get hit. Let's see what upstream devs have to say about https://github.com/pyinstaller/pyinstaller/pull/5991