-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Codesigning vapor on Apple Silicon #3639
Changes from all commits
8e5b507
fea29ce
6059bcd
56e16c4
04d43bb
8b1fed9
7e6a00a
a946e48
c4139c5
6d1c381
4e03696
d1b2d1c
90d4736
65d1255
10effd9
46ed3b6
11999a9
e5d91aa
0173b8a
a61edc4
37b1ba3
1ae4ab7
b6e2604
c808979
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
set +e | ||
|
||
installDir="/Applications" | ||
dmgName="VAPOR3-3.9.3-AppleSilicon.dmg" | ||
dmgDir="tmp" | ||
|
||
#for file in ${installDir}/vapor.app/Contents/Frameworks/*; do | ||
# codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --timestamp --verbose $file | ||
#done | ||
|
||
# Deploy Qt with macdeployqt | ||
# N.B. Apple's notorization will give an "bundle format is ambiguous (could be app or framework)" if Qt's frameworks are missing symlinks | ||
# So, if copying the third party libraries use 'cp -a /old/libs /new/libs' and not 'cp -r /old/libs /new/libs' (-a and not -r) | ||
/usr/local/VAPOR-Deps/current/bin/macdeployqt ${installDir}/vapor.app -timestamp -sign-for-notarization="Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" | ||
|
||
# Codesign libraries and frameworks | ||
find ${installDir}/vapor.app/Contents/Frameworks -type f -exec file {} + | grep -E 'Mach-O .* shared library' | cut -d: -f1 | while read -r file; do | ||
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --timestamp --force --deep --verbose --options runtime "$file" | ||
done | ||
|
||
# Codesign plugins and python | ||
directories=( | ||
"${installDir}/vapor.app/Contents/share/plugins/" | ||
"${installDir}/vapor.app/Contents/Resources/" | ||
"${installDir}/vapor.app/Contents/Resources/python/lib/" | ||
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/numpy/.dylibs" | ||
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/PIL/.dylibs" | ||
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/scipy/.dylibs" | ||
) | ||
for dir in "${directories[@]}"; do | ||
find "$dir" -type f \( -name "*.so" -o -name "*.dylib" \) | while read -r file; do | ||
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --timestamp --force --deep --verbose $file | ||
done | ||
done | ||
|
||
# Codesign additional MacOS plugins | ||
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --verbose ${installDir}/vapor.app/Contents/MacOS/platforms/libqcocoa.dylib | ||
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --verbose ${installDir}/vapor.app/Contents/MacOS/styles/libqmacstyle.dylib | ||
|
||
# Codesign all vapor executables with timestamp and hardended runtime | ||
for file in ${installDir}/vapor.app/Contents/MacOS/*; do | ||
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --timestamp --verbose --options runtime $file | ||
done | ||
|
||
# Create .dmg that contains symlink to /Applications | ||
mkdir -p "${dmgDir}" | ||
cp -R "${installDir}/vapor.app" "${dmgDir}" | ||
ln -s /Applications "${dmgDir}/Applications" | ||
hdiutil create -volname "vapor" -srcfolder ${dmgDir} -ov -format UDZO "${installDir}/${dmgName}" | ||
rm -rf "${dmgDir}" | ||
|
||
# Sign and notarize the .dmg | ||
codesign --force --verify --verbose --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" ${installDir}/${dmgName} | ||
xcrun -v notarytool submit ${installDir}/${dmgName} --keychain-profile "testApp-password" --wait | ||
|
||
# Staple the notarized .dmg | ||
xcrun stapler staple ${installDir}/${dmgName} | ||
xcrun stapler validate ${installDir}/${dmgName} | ||
|
||
# Fetch the notorization log | ||
# xcrun notarytool log --keychain-profile "testApp-password" <hash> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,8 +97,10 @@ std::string Wasp::GetResourcePath(const std::string &name) | |
|
||
std::string Wasp::GetSharePath(const std::string &name) { return GetResourcePath("share/" + name); } | ||
|
||
#ifdef WIN32 | ||
#if defined(WIN32) | ||
#define PYTHON_INSTALLED_PATH ("python" + string(PYTHON_VERSION)) | ||
#elif defined(__aarch64__) | ||
#define PYTHON_INSTALLED_PATH ("Resources/python") | ||
#else | ||
#define PYTHON_INSTALLED_PATH ("lib/python" + string(PYTHON_VERSION)) | ||
#endif | ||
|
@@ -119,12 +121,16 @@ std::string Wasp::GetPythonDir() | |
#ifdef WIN32 | ||
return GetPythonPath(); | ||
#endif | ||
|
||
string path = GetResourcePath(""); | ||
|
||
string exists = FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH}); | ||
|
||
if (!FileUtils::Exists(FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH}))) path = string(PYTHON_DIR); | ||
string path = string(PYTHON_DIR); // Try our third-party-library directory first | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to use the installed python dir first, and only have the developer libs as a fallback. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a fairly obscure part of our codebase. I'd recommend revisiting it after 3.9.3 but we can postpone the release if it's that important. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean by obscure, this determines the version of python that is used by Vapor so it is rather critical. With this change it will be impossible for a developer to test an installed version of Vapor without first removing their third party library installation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand and totally see you point. IMO, I don't think it's critical to fix now, but it's critical to fix soon because installers are not often tested on dev computers. This is why we do platform tests on clean (non-dev) systems. If this solution didn't work as in this PR, I would agree to modify it as you've suggested. This file is obscure because:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use the installers to test on my dev machine frequently when I am unsure if an issue is related to new code or my dev environment. This invalidates such a test. It also creates the situation where if someone has a different incompatible version of the third part libs installed (older or newer) vapor may try to load that version and crash. A few months down the line we may forget about this behavior and have to figure out why vapor is crashing. Since this is only going to affect developers not end users I'm fine with not holding up the release over this. Also, read obscure as not important or well known. |
||
if (!FileUtils::Exists(path)) { | ||
path = GetResourcePath(""); | ||
string exists = FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH}); | ||
if (!exists.empty()) { | ||
#if defined(__aarch64__) | ||
path = exists; // If the third-party-library directory doesn't exist, use the python installed path. Otherwise, use the root. | ||
#endif | ||
} | ||
} | ||
return path; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RPATH is for finding libraries/frameworks which for an AppBundle should exist inside the Frameworks directory. Is there a reason we also need it to link to the Resources directory?
From the macOS docs:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's a codesigning requirement. Frameworks cannot contain non-binary files like .py modules, so Python needs to reside in Resources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a followup with a reference. This is also how Blender distributes Python.
https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG13
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the issue and I am fine keeping it this way.
To respond to your followup:
Blender's macOS app does not follow the specification at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks, but for the record:
Blender puts all of its libraries in the Resources directory. Could you elaborate if I'm mistaken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, which directly contradicts the specification.