Issues with Codesigning pyinstaller generated MACOS .app bundle - unsealed contents present in the root directory of an embedded framework

68 views
Skip to first unread message

NachoDog

unread,
Nov 13, 2019, 5:37:30 PM11/13/19
to PyInstaller
I am attempting to codesign and notarize a MacOS .app bundle generated by Pyinstaller.  The application is developed using Python3, PyQt bindings, and the Qt toolkit.  Here are the versions:

PyInstaller 3.5

Python version: 3.7.4 (v3.7.4:e09359112e, Jul  8 2019, 14:54:52)

[Clang 6.0 (clang-600.0.57)]

Qt version: 5.13.0

PyQt version: 5.13.1

sip version: 4.19.19


The app itself runs great on the MAC, the problems start when attempting to code sign the app so it can be notarized.  The issue I'm illustrating here has to do with the Qt Frameworks.  If anyone can provide a set of steps that will successfully sign one of the Qt Frameworks in the pyinstaller generated .app bundle I'd really appreciate it.

Here is my process...  
The .app bundle is created by Pyinstaller and runs fine.
The first step is to fix the folder structure created by Pyinstaller.  It doesn't conform exactly to what Apple expects, but to be fair, what Qt installs doesn't either.  Run this script to fix the QtCore framework in the .app bundle

Echo Fix the QtCore framework folders

qtfolder="/Users/xxx/Qt/5.13.1/clang_64/lib"

basefolder="/Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework"

cp -R $qtfolder/QtCore.framework/Versions/5/Resources $basefolder/Versions/5

ln -s $basefolder/Versions/5 $basefolder

mv $basefolder/5 $basefolder/Versions/Current

ln -s $basefolder/Versions/Current/Resources $basefolder

ln -s $basefolder/Versions/Current/QtCore $basefolder

This produces the following folder structure and files which I believe conform to what Apple expects.  this is based on numerous blog posts etc.

QtCore@ -> /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/Versions/Current/QtCore

Resources@ -> /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/Versions/Current/Resources

Versions/

 

./Versions:


5/

Current@ -> /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/Versions/5


./Versions/5:

QtCore*

Resources/

 

./Versions/5/Resources:

Info.plist


Now I start signing the files.  There are many posts on what to sign and how to sign all of which seem outdated and contradictory.  The best current advice I think is to sign everything.  I've tried many combinations and they've all ended up with the same error.


sudo codesign --verbose --force --sign "Developer ID Application:  (xxx)" /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/versions/5/resources/Info.plist

sudo codesign --verbose --force --sign "Developer ID Application:  (xxx)" /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/versions/5/QtCore

sudo codesign --verbose --force --sign "Developer ID Application:  (xxx)" /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/versions/5/_CodeSignature/CodeResources

sudo codesign --verbose --force --sign "Developer ID Application:  (xxx)" /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework/versions/5


At this point every file and folder in the framework that can be signed has been signed successfully.  I don't sign the symlinks as I think that just resigns the underlying files.  The final step is to sign the framework itself.


sudo codesign  --verbose --force --sign "Developer ID Application: (xxx)" /Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework


this produces the following error message:

/Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework: replacing existing signature

/Users/xxx/Documents/PYINSTALLERTEST/dist/MyApp.app/Contents/MacOS/PyQt5/Qt/lib/QtCore.framework: unsealed contents present in the root directory of an embedded framework


Any ideas on what I'm doing wrong?



  

Raoul Snyman

unread,
Nov 13, 2019, 11:26:48 PM11/13/19
to PyInstaller
I've actually just been working on the Mac build for my open source
project, using the same stack as you.

In my case, however, I install Python, Qt and PyQt5 from MacPorts, and
then I used the script on the PyInstaller wiki[0] to sort out Qt's
stuff for codesigning. This seems to work. Except for QtWebEngine, but
that's not related to the code signing.

[0] https://github.com/pyinstaller/pyinstaller/wiki/Recipe-OSX-Code-Signing-Qt
> --
> You received this message because you are subscribed to the Google Groups "PyInstaller" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to pyinstaller...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/pyinstaller/b3219614-2df3-44a5-ad2a-e57e822f0813%40googlegroups.com.



--
Raoul Snyman

NachoDog

unread,
Nov 14, 2019, 10:31:10 AM11/14/19
to PyInstaller
Raoul - thanks for the response.  I'm using the python script you mentioned to cleanup the QML folders but it doesn't really do anything for the QT Frameworks.  Would you mind posting the steps you use to code sign the frameworks using QtCore as an example?  
> To unsubscribe from this group and stop receiving emails from it, send an email to pyins...@googlegroups.com.

Raoul Snyman

unread,
Nov 15, 2019, 12:10:05 AM11/15/19
to PyInstaller
Sure!

So, we use a script to do the building, but the following steps are
essentially what the script does, minus some of the stuff that's more
specific to the app:

1. Run PyInstaller
$ pyinstaller --clean --noconfirm --windowed --noupx
--additional-hooks-dir <hooks_path> --runtime-hook <runtime_hook> -i
<icon_path> -n MyAppName myapp.py
2. Run script to fix QML files
3. Do other stuff needed by our app (unrelated to PyInstaller and codesign)
4. Check the certificate:
$ security find-certificate -c <certificate>
5. Sign:
$ codesign --deep -s <certificate> <path/to/MyAppName.app>

And that's about it.
> To unsubscribe from this group and stop receiving emails from it, send an email to pyinstaller...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/pyinstaller/c852bab4-8940-4dad-bef0-6cda737f150f%40googlegroups.com.



--
Raoul Snyman

John Singer

unread,
Nov 15, 2019, 8:34:26 AM11/15/19
to pyins...@googlegroups.com
What version of PyInstaller?  How did you install Qt on your Mac?  I’m starting to think that might be my problem.  I’m out of town until next week so I’ll do more then.  
Also, do you notarize your app?  


From: pyins...@googlegroups.com <pyins...@googlegroups.com> on behalf of Raoul Snyman <raoul....@gmail.com>
Sent: Thursday, November 14, 2019 11:09:51 PM
To: PyInstaller <pyins...@googlegroups.com>
Subject: Re: [PyInstaller] Issues with Codesigning pyinstaller generated MACOS .app bundle - unsealed contents present in the root directory of an embedded framework
 
You received this message because you are subscribed to a topic in the Google Groups "PyInstaller" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyinstaller/cksYjmLObjQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyinstaller...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyinstaller/CAJvrXnJdqXnvxaNdZjihTC5SuX6o_GRRpWaMb-UUM2DR_04QbQ%40mail.gmail.com.

Raoul Snyman

unread,
Nov 17, 2019, 10:43:30 AM11/17/19
to PyInstaller
> What version of PyInstaller?

Python 3.7.5
PyInstaller 3.5

> How did you install Qt on your Mac?

Via MacPorts

> Also, do you notarize your app?

I'm not sure what you mean by that, so I'm going to say no :-)


--
Raoul Snyman
Reply all
Reply to author
Forward
0 new messages