Repository: pyinstaller/pyinstaller

Issue:
universal2 builds codesign failure
when creating builds for x86-x64 the codesign is working fine , but when using universal the codesign shows the below error . Any idea on how to fix it?



32924 WARNING: codesign command (['codesign', '-s', '-', '--force', '--all-architectures', '--timestamp', '--entitlements', 'entitlements.plist', '****]) failed with error code 1!
stdout: ''
stderr: '/****: main executable failed strict validation\n'
Traceback (most recent call last):
  File "/usr/local/bin/pyinstaller", line 8, in <module>
    sys.exit(run())
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/__main__.py", line 124, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/__main__.py", line 58, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 782, in main
    build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 714, in build
    exec(code, spec_namespace)
  File "HRAPP-Mac.spec", line 23, in <module>
    exe = EXE(pyz,
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/api.py", line 507, in __init__
    self.__postinit__()
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/datastruct.py", line 155, in __postinit__
    self.assemble()
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/api.py", line 750, in assemble
    osxutils.sign_binary(self.name, self.codesign_identity, self.entitlements_file)
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/utils/osx.py", line 348, in sign_binary
    raise SystemError("codesign failure!")
SystemError: codesign failure!


Discussion:
is there anyway to skip the pyinstaller codesign and I can sign it manually 
> is there anyway to skip the pyinstaller codesign and I can sign it manually

You can edit PyInstaller code and comment out the calls to `sign_binary` (e.g., line 750 in `/usr/local/lib/python3.9/site-packages/PyInstaller/building/api.py`, as indicated in the traceback).
Other than that, can you provide a minimal example that triggers the issue?
thanks for the info , what part of the code do you require? is the spec file enough? 
Everything to reproduce the issue locally, so code and spec. If your program is not open-source, try reproducing the problem with a minimal program/code that you can share (e.g., if a simple hello-world program does not trigger the issue per-se, try adding imports of all 3rd party packages you use, etc.).
Hi @rokm 
System Info :
63 INFO: PyInstaller: 4.7
363 INFO: Python: 3.9.8
405 INFO: Platform: macOS-12.0.1-x86_64-i386-64bit
420 INFO: UPX is not available.

after commenting out the sign_binary I get this error 
  File "/usr/local/bin/pyinstaller", line 8, in <module>
    sys.exit(run())
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/__main__.py", line 124, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/__main__.py", line 58, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 782, in main
    build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/build_main.py", line 714, in build
    exec(code, spec_namespace)
  File "HRAPP-Mac.spec", line 37, in <module>
    coll = COLLECT(exe,
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/api.py", line 818, in __init__
    self.__postinit__()
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/datastruct.py", line 155, in __postinit__
    self.assemble()
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/api.py", line 850, in assemble
    fnm = checkCache(
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/building/utils.py", line 360, in checkCache
    osxutils.binary_to_target_arch(cachedfile, target_arch, display_name=fnm)
  File "/usr/local/lib/python3.9/site-packages/PyInstaller/utils/osx.py", line 302, in binary_to_target_arch
    assert target_arch != 'universal2', f"{display_name} is not a fat binary!"
AssertionError: /usr/local/Cellar/python@3.9/3.9.8/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload/_struct.cpython-39-darwin.so is not a fat binary!
let me get you a sample 
> AssertionError: /usr/local/Cellar/python@3.9/3.9.8/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload/_struct.cpython-39-darwin.so is not a fat binary!

You cannot build `universal2` frozen applications using homebrew python, because the latter is single arch.

But I'd still be interested in an example that generates executable that fails `codesign` validation.

Resolving patch:
diff --git a/PyInstaller/utils/osx.py b/PyInstaller/utils/osx.py
--- a/PyInstaller/utils/osx.py
+++ b/PyInstaller/utils/osx.py
@@ -198,9 +198,11 @@ def fix_exe_for_code_signing(filename):
     # We can compensate for that by not using the declared sizes anywhere, and simply recompute them. In the final
     # binary, the __LINKEDIT segment and the SYMTAB section MUST end at the end of the file (otherwise, we have bigger
     # issues...). So simply recompute the declared sizes as difference between the final file length and the
-    # corresponding start offset.
-    symtab_sec.strsize = file_size - symtab_sec.stroff
-    linkedit_seg.filesize = file_size - linkedit_seg.fileoff
+    # corresponding start offset (NOTE: the offset is relative to start of the slice, which is stored in header.offset.
+    # In thin binaries, header.offset is zero and start offset is relative to the start of file, but with fat binaries,
+    # header.offset is non-zero)
+    symtab_sec.strsize = file_size - (header.offset + symtab_sec.stroff)
+    linkedit_seg.filesize = file_size - (header.offset + linkedit_seg.fileoff)
 
     # Compute new vmsize by rounding filesize up to full page size.
     page_size = (0x4000 if _get_arch_string(header.header).startswith('arm64') else 0x1000)


Test patch: