1
0
mirror of https://github.com/strawberrymusicplayer/strawberry synced 2025-01-31 01:29:41 +01:00

Fix macOS deployment

This commit is contained in:
Jonas Kvinge 2021-03-18 00:52:04 +01:00
parent 8193be36e5
commit 6fb48af598
7 changed files with 127 additions and 18 deletions

View File

@ -1055,8 +1055,7 @@ jobs:
- name: Link Sparkle
shell: bash
run: |
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
- name: Create Build Environment
shell: bash
@ -1082,9 +1081,6 @@ jobs:
working-directory: build
shell: bash
run: make install
- name: Hack to make macdeployqt find plugins
shell: bash
run: sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
- name: Create DMG
working-directory: build
shell: bash
@ -1131,8 +1127,7 @@ jobs:
- name: Link Sparkle
shell: bash
run: |
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
- name: Create Build Environment
shell: bash
@ -1158,9 +1153,6 @@ jobs:
working-directory: build
shell: bash
run: make install
- name: Hack to make macdeployqt find plugins
shell: bash
run: sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
- name: Create DMG
working-directory: build
shell: bash

View File

@ -19,8 +19,7 @@ before_install:
- brew install libcdio libmtp
- brew install create-dmg
- brew install --cask sparkle
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
- export Qt6_DIR=/usr/local/opt/qt6/lib/cmake
- export Qt6LinguistTools_DIR=/usr/local/opt/qt6/lib/cmake/Qt6LinguistTools
- ls /usr/local/lib/gstreamer-1.0
@ -31,7 +30,6 @@ before_script:
script:
- make -j8
- make install
- sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
- make dmg2
after_success:
- ls -lh strawberry*.dmg

View File

@ -278,6 +278,10 @@ int main(int argc, char **argv)
if (runStripEnabled)
stripAppBinary(appBundlePath);
if (!FinalCheck(appBundlePath)) {
return 1;
}
if (runCodesign)
codesign(codesignIdentiy, appBundlePath);
@ -288,4 +292,3 @@ int main(int argc, char **argv)
return 0;
}

View File

@ -856,6 +856,11 @@ void changeInstallName(const QString &bundlePath, const FrameworkInfo &framework
if (!canonicalInstallName.isEmpty() && canonicalInstallName != framework.installName) {
changeInstallName(canonicalInstallName, deployedInstallName, binary);
}
// Homebrew workaround, resolve symlink /usr/local/opt/library to /usr/local/Cellar/library
if (framework.installName.startsWith("/usr/local/opt/") && framework.installName.count('/') >= 5) {
canonicalInstallName = QFileInfo(framework.installName.section('/', 0, 4)).canonicalFilePath() + "/" + framework.installName.section('/', 5);
changeInstallName(canonicalInstallName, deployedInstallName, binary);
}
}
}
@ -1679,3 +1684,110 @@ void fixupFramework(const QString &frameworkName)
changeIdentification("@rpath/" + frameworkBinary, frameworkBinary);
addRPath("@loader_path/../../Contents/Frameworks/", frameworkBinary);
}
bool FinalCheck(const QString &appBundlePath) {
bool success = true;
QDirIterator iter(appBundlePath, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories);
while (iter.hasNext()) {
iter.next();
QString filepath = iter.fileInfo().filePath();
if (filepath.endsWith(".plist") ||
filepath.endsWith(".icns") ||
filepath.endsWith(".prl") ||
filepath.endsWith(".conf") ||
filepath.endsWith(".h") ||
filepath.endsWith(".nib") ||
filepath.endsWith(".strings") ||
filepath.endsWith(".css") ||
filepath.endsWith("CodeResources") ||
filepath.endsWith("PkgInfo") ||
filepath.endsWith(".modulemap")) {
continue;
}
//qDebug() << "Final check on" << filepath;
QProcess otool;
otool.start("otool", QStringList() << "-L" << filepath);
otool.waitForFinished();
if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) {
LogError() << otool.readAllStandardError();
success = false;
continue;
}
QString output = otool.readAllStandardOutput();
QStringList output_lines = output.split("\n", Qt::SkipEmptyParts);
if (output_lines.size() < 2) {
LogError() << "Could not parse otool output:" << output;
success = false;
continue;
}
QString first_line = output_lines.first();
if (first_line.endsWith(':')) first_line.chop(1);
if (first_line == filepath) {
output_lines.removeFirst();
}
else {
LogError() << "First line" << first_line << "does not match" << filepath;
success = false;
}
static const QRegularExpression regexp(QStringLiteral("^\\t(.+) \\(compatibility version (\\d+\\.\\d+\\.\\d+), current version (\\d+\\.\\d+\\.\\d+)(, weak)?\\)$"));
for (const QString &output_line : output_lines) {
//qDebug() << "Final check on" << filepath << output_line;
const auto match = regexp.match(output_line);
if (match.hasMatch()) {
QString library = match.captured(1);
if (QFileInfo(library).fileName() == QFileInfo(filepath).fileName()) { // It's this.
continue;
}
else if (library.startsWith("@executable_path")) {
QString real_path = library;
real_path = real_path.replace("@executable_path", appBundlePath + "/Contents/MacOS");
if (!QFile(real_path).exists()) {
LogError() << real_path << "does not exist for" << filepath;
success = false;
}
}
else if (library.startsWith("@rpath")) {
QString real_path = library;
real_path = real_path.replace("@rpath", appBundlePath + "/Contents/Frameworks");
if (!QFile(real_path).exists() && !real_path.endsWith("QtSvg")) { // FIXME: Ignore broken svg image plugin.
LogError() << real_path << "does not exist for" << filepath;
success = false;
}
}
else if (library.startsWith("@loader_path")) {
QString loader_path = QFileInfo(filepath).path();
QString real_path = library;
real_path = real_path.replace("@loader_path", loader_path);
if (!QFile(real_path).exists()) {
LogError() << real_path << "does not exist for" << filepath;
success = false;
}
}
else if (library.startsWith("/System/Library/") || library.startsWith("/usr/lib/")) { // System library
continue;
}
else if (library.endsWith("libgcc_s.1.dylib")) { // fftw points to it for some reason.
continue;
}
else {
LogError() << "File" << filepath << "points to" << library;
success = false;
}
}
else {
LogError() << "Could not parse otool output line:" << output_line;
success = false;
}
}
}
return success;
}

View File

@ -136,6 +136,6 @@ QSet<QString> codesignBundle(const QString &identity,
void codesign(const QString &identity, const QString &appBundlePath);
void createDiskImage(const QString &appBundlePath, const QString &filesystemType);
void fixupFramework(const QString &appBundlePath);
bool FinalCheck(const QString &appBundlePath);
#endif

View File

@ -251,7 +251,7 @@ set(SINGLEAPPLICATION_LIBRARIES singleapplication)
set(SINGLECOREAPPLICATION_LIBRARIES singlecoreapplication)
if(APPLE)
find_library(SPARKLE Sparkle)
find_library(SPARKLE Sparkle PATHS "/usr/local/opt/sparkle")
add_subdirectory(3rdparty/macdeployqt)
add_subdirectory(3rdparty/SPMediaKeyTap)
set(SPMEDIAKEYTAP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/SPMediaKeyTap)

View File

@ -21,12 +21,16 @@ endif()
if(MACDEPLOYQT_EXECUTABLE AND CREATEDMG_EXECUTABLE AND MACOS_VERSION_PACKAGE)
add_custom_target(dmg
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader -verbose=3
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
COMMAND cp -r /usr/local/opt/sparkle/Sparkle.framework ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3 -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
COMMAND ${CREATEDMG_EXECUTABLE} --volname strawberry --background "${CMAKE_SOURCE_DIR}/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon strawberry.app 150 218 --window-size 600 450 strawberry-${STRAWBERRY_VERSION_PACKAGE}-${MACOS_VERSION_PACKAGE}-${CMAKE_HOST_SYSTEM_PROCESSOR}.dmg strawberry.app
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_target(dmg2
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader -verbose=3
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
COMMAND cp -r /usr/local/opt/sparkle/Sparkle.framework ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3 -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
COMMAND ${CREATEDMG_EXECUTABLE} --skip-jenkins --volname strawberry --background "${CMAKE_SOURCE_DIR}/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon strawberry.app 150 218 --window-size 600 450 strawberry-${STRAWBERRY_VERSION_PACKAGE}-${MACOS_VERSION_PACKAGE}-${CMAKE_HOST_SYSTEM_PROCESSOR}.dmg strawberry.app
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)