mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2026-07-01 19:06:58 +03:00
Compare commits
106 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdfdf2eef1 | ||
|
|
bbfa5a5ed1 | ||
|
|
43dc330e55 | ||
|
|
0c962dff59 | ||
|
|
ca0dd583ba | ||
|
|
7bb686c85b | ||
|
|
f8d3d8399d | ||
|
|
9cb2a3ab2d | ||
|
|
072c495ec6 | ||
|
|
335941fb46 | ||
|
|
ebeff36da5 | ||
|
|
1d29f63bec | ||
|
|
87dc1bb6a6 | ||
|
|
a85720b8d6 | ||
|
|
4c28a94de1 | ||
|
|
344ae87f25 | ||
|
|
577999bd35 | ||
|
|
887db29f35 | ||
|
|
7865b8128e | ||
|
|
a58f125535 | ||
|
|
d1a05d312d | ||
|
|
bbf21e5824 | ||
|
|
73b4223b61 | ||
|
|
686e0b7b18 | ||
|
|
189878e7e3 | ||
|
|
af74d5f410 | ||
|
|
cdfd0b1002 | ||
|
|
9791c306dc | ||
|
|
e7e9265c40 | ||
|
|
e0c323a190 | ||
|
|
a914747416 | ||
|
|
d453240a94 | ||
|
|
4c4017d7ca | ||
|
|
2a4c4ed8ea | ||
|
|
947fbf7d64 | ||
|
|
1c94a3e3e5 | ||
|
|
eefeb5799d | ||
|
|
6c6a4625ab | ||
|
|
6d2a96f6a7 | ||
|
|
ea9029d7b6 | ||
|
|
76602391f4 | ||
|
|
509f8c7307 | ||
|
|
984daa450b | ||
|
|
04e1a97d59 | ||
|
|
1dce1360bd | ||
|
|
87d5b96760 | ||
|
|
7f074ca7b9 | ||
|
|
c0394c52b7 | ||
|
|
53bc20f13f | ||
|
|
40af3cf3d2 | ||
|
|
3977918c5b | ||
|
|
484d90899f | ||
|
|
0f5eb03839 | ||
|
|
d21cda1880 | ||
|
|
52a321b93b | ||
|
|
dd8dec8be8 | ||
|
|
23d6f8aaed | ||
|
|
d105d76f2a | ||
|
|
698a838b56 | ||
|
|
1129b4160c | ||
|
|
63a6f823fd | ||
|
|
db32b2ad99 | ||
|
|
c3cf5d31da | ||
|
|
1e696328bb | ||
|
|
1d9c97803a | ||
|
|
3d55236fdf | ||
|
|
42190819ae | ||
|
|
130714a9ab | ||
|
|
bf57d77075 | ||
|
|
98fe035442 | ||
|
|
8e4994590b | ||
|
|
0722dba820 | ||
|
|
9560447c92 | ||
|
|
4d89512ca1 | ||
|
|
42a6bd1151 | ||
|
|
f06505b138 | ||
|
|
d854087089 | ||
|
|
31031ec923 | ||
|
|
5f06517b62 | ||
|
|
dde5fc47d3 | ||
|
|
76d5f632dc | ||
|
|
27c6596bcb | ||
|
|
e2f5fb27a6 | ||
|
|
98819a0d02 | ||
|
|
2dde2c4bec | ||
|
|
008d69e5e5 | ||
|
|
a839258c07 | ||
|
|
89041531e1 | ||
|
|
729cec5f45 | ||
|
|
80d675d2e6 | ||
|
|
fb7d19941f | ||
|
|
877ab62c2f | ||
|
|
b983ae0fb0 | ||
|
|
85422427b9 | ||
|
|
51a71d0471 | ||
|
|
25eaa4eba6 | ||
|
|
6da14d66bb | ||
|
|
199c5497d3 | ||
|
|
740db2db02 | ||
|
|
577f8074e1 | ||
|
|
c5e7bb90c5 | ||
|
|
1cf91fa5d9 | ||
|
|
3bf4fbf8f4 | ||
|
|
ff97affa72 | ||
|
|
e8c9722a53 | ||
|
|
9a810dfa6e |
1151 changed files with 26954 additions and 52303 deletions
|
|
@ -5,7 +5,6 @@ AllowShortIfStatementsOnASingleLine: false
|
|||
ColumnLimit: 140
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -1
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
BraceWrapping:
|
||||
|
|
@ -16,4 +15,3 @@ BraceWrapping:
|
|||
BreakBeforeBraces: Custom
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
Cpp11BracedListStyle: false
|
||||
QualifierAlignment: Left
|
||||
|
|
|
|||
33
.clang-tidy
33
.clang-tidy
|
|
@ -1,32 +1,5 @@
|
|||
FormatStyle: file
|
||||
|
||||
Checks:
|
||||
"bugprone-*,clang-analyzer-*,cppcoreguidelines-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*,
|
||||
-*-magic-numbers,
|
||||
-*-non-private-member-variables-in-classes,
|
||||
-*-special-member-functions,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
-modernize-use-nodiscard,
|
||||
-modernize-use-trailing-return-type,
|
||||
-portability-avoid-pragma-once,
|
||||
-readability-avoid-unconditional-preprocessor-if,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-length,
|
||||
-readability-redundant-access-specifiers"
|
||||
- modernize-use-using
|
||||
- readability-avoid-const-params-in-decls
|
||||
|
||||
CheckOptions:
|
||||
misc-include-cleaner.MissingIncludes: false
|
||||
readability-identifier-naming.DefaultCase: "camelBack"
|
||||
readability-identifier-naming.NamespaceCase: "CamelCase"
|
||||
readability-identifier-naming.ClassCase: "CamelCase"
|
||||
readability-identifier-naming.ClassConstantCase: "CamelCase"
|
||||
readability-identifier-naming.EnumCase: "CamelCase"
|
||||
readability-identifier-naming.EnumConstantCase: "CamelCase"
|
||||
readability-identifier-naming.MacroDefinitionCase: "UPPER_CASE"
|
||||
readability-identifier-naming.ClassMemberPrefix: "m_"
|
||||
readability-identifier-naming.StaticConstantPrefix: "s_"
|
||||
readability-identifier-naming.StaticVariablePrefix: "s_"
|
||||
readability-identifier-naming.GlobalConstantPrefix: "g_"
|
||||
readability-implicit-bool-conversion.AllowPointerConditions: true
|
||||
SystemHeaders: false
|
||||
|
|
|
|||
|
|
@ -1,22 +1,8 @@
|
|||
# EditorConfig specs and documentation: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{yml,nix}]
|
||||
indent_size = 2
|
||||
|
||||
# C++ Code Style settings
|
||||
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||
cpp_generate_documentation_comments = doxygen_slash_star
|
||||
|
||||
[CMakeLists.txt]
|
||||
ij_continuation_indent_size = 4
|
||||
# EditorConfig specs and documentation: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# C++ Code Style settings
|
||||
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||
cpp_generate_documentation_comments = doxygen_slash_star
|
||||
|
|
|
|||
2
.envrc
2
.envrc
|
|
@ -1,2 +1,2 @@
|
|||
use nix
|
||||
use flake
|
||||
watch_file nix/*.nix
|
||||
|
|
|
|||
|
|
@ -5,9 +5,3 @@ bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9
|
|||
|
||||
# (nix) alejandra -> nixfmt
|
||||
4c81d8c53d09196426568c4a31a4e752ed05397a
|
||||
|
||||
# reformat codebase
|
||||
1d468ac35ad88d8c77cc83f25e3704d9bd7df01b
|
||||
|
||||
# format a part of codebase
|
||||
5c8481a118c8fefbfe901001d7828eaf6866eac4
|
||||
|
|
|
|||
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
name: Bug Report
|
||||
description: File a bug report
|
||||
labels: ["bug: unconfirmed", "status: needs triage"]
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
|
@ -23,14 +23,14 @@ body:
|
|||
- macOS
|
||||
- Linux
|
||||
- Other
|
||||
- type: input
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Version of Prism Launcher
|
||||
description: The version of Prism Launcher used in the bug report.
|
||||
placeholder: Prism Launcher 5.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Version of Qt
|
||||
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.
|
||||
|
|
|
|||
6
.github/ISSUE_TEMPLATE/rfc.yml
vendored
6
.github/ISSUE_TEMPLATE/rfc.yml
vendored
|
|
@ -1,7 +1,7 @@
|
|||
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
|
||||
name: Request for Comment (RFC)
|
||||
description: Propose a larger change and start a discussion.
|
||||
labels: ["type: enhancement", "status: needs discussion", "status: needs triage"]
|
||||
labels: [rfc]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
|
@ -44,8 +44,8 @@ body:
|
|||
attributes:
|
||||
label: Unresolved Questions
|
||||
description: |
|
||||
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
|
||||
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
|
||||
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
|
||||
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
|
||||
If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
|
||||
placeholder: Do a lot of users care about the cat?
|
||||
validations:
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
2
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
name: Suggestion
|
||||
description: Make a suggestion
|
||||
labels: ["type: enhancement", "status: needs triage"]
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
|
|
|||
153
.github/actions/package/linux/action.yml
vendored
153
.github/actions/package/linux/action.yml
vendored
|
|
@ -1,153 +0,0 @@
|
|||
name: Package for Linux
|
||||
description: Create Linux packages for Prism Launcher
|
||||
|
||||
inputs:
|
||||
version:
|
||||
description: Launcher version
|
||||
required: true
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
artifact-name:
|
||||
description: Name of the uploaded artifact
|
||||
required: true
|
||||
default: Linux
|
||||
qt-version:
|
||||
description: Version of Qt to use
|
||||
required: true
|
||||
gpg-private-key:
|
||||
description: Private key for AppImage signing
|
||||
required: false
|
||||
gpg-private-key-id:
|
||||
description: ID for the gpg-private-key, to select the signing key
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Cleanup Qt installation on Linux
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf "$QT_PLUGIN_PATH"/printsupport
|
||||
rm -rf "$QT_PLUGIN_PATH"/sqldrivers
|
||||
rm -rf "$QT_PLUGIN_PATH"/help
|
||||
rm -rf "$QT_PLUGIN_PATH"/designer
|
||||
rm -rf "$QT_PLUGIN_PATH"/qmltooling
|
||||
rm -rf "$QT_PLUGIN_PATH"/qmlls
|
||||
rm -rf "$QT_PLUGIN_PATH"/qmllint
|
||||
rm -rf "$QT_PLUGIN_PATH"/platformthemes/libqgtk3.so
|
||||
|
||||
- name: Setup build variables
|
||||
shell: bash
|
||||
run: |
|
||||
# Fixup architecture naming for AppImages
|
||||
dpkg_arch="$(dpkg-architecture -q DEB_HOST_ARCH_CPU)"
|
||||
case "$dpkg_arch" in
|
||||
"amd64")
|
||||
APPIMAGE_ARCH="x86_64"
|
||||
;;
|
||||
"arm64")
|
||||
APPIMAGE_ARCH="aarch64"
|
||||
;;
|
||||
*)
|
||||
echo "# 🚨 The Debian architecture \"$deb_arch\" is not recognized!" >> "$GITHUB_STEP_SUMMARY"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo "APPIMAGE_ARCH=$APPIMAGE_ARCH" >> "$GITHUB_ENV"
|
||||
|
||||
# Used for the file paths of libraries
|
||||
echo "DEB_HOST_MULTIARCH=$(dpkg-architecture -q DEB_HOST_MULTIARCH)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Package AppImage
|
||||
shell: bash
|
||||
env:
|
||||
VERSION: ${{ github.ref_type == 'tag' && github.ref_name || inputs.version }}
|
||||
BUILD_DIR: build
|
||||
INSTALL_APPIMAGE_DIR: install-appdir
|
||||
|
||||
GPG_PRIVATE_KEY: ${{ inputs.gpg-private-key }}
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}
|
||||
|
||||
if [ '${{ inputs.gpg-private-key-id }}' != '' ]; then
|
||||
echo "$GPG_PRIVATE_KEY" > privkey.asc
|
||||
gpg --import privkey.asc
|
||||
gpg --export --armor ${{ inputs.gpg-private-key-id }} > pubkey.asc
|
||||
else
|
||||
echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
sharun lib4bin \
|
||||
--hard-links \
|
||||
--with-hooks \
|
||||
--dst-dir "$INSTALL_APPIMAGE_DIR" \
|
||||
"$INSTALL_APPIMAGE_DIR"/bin/* "$QT_PLUGIN_PATH"/*/*.so
|
||||
|
||||
cp ~/bin/AppImageUpdate.AppImage "$INSTALL_APPIMAGE_DIR"/bin/
|
||||
# FIXME(@getchoo): gamemode doesn't seem to be very portable with DBus. Find a way to make it work!
|
||||
find "$INSTALL_APPIMAGE_DIR" -name '*gamemode*' -exec rm {} +
|
||||
|
||||
#disable OpenGL and Vulkan launcher features until https://github.com/VHSgunzo/sharun/issues/35
|
||||
echo "PRISMLAUNCHER_DISABLE_GLVULKAN=1" >> "$INSTALL_APPIMAGE_DIR"/.env
|
||||
#makes the launcher use portals for file picking
|
||||
echo "QT_QPA_PLATFORMTHEME=xdgdesktopportal" >> "$INSTALL_APPIMAGE_DIR"/.env
|
||||
ln -s org.prismlauncher.PrismLauncher.metainfo.xml "$INSTALL_APPIMAGE_DIR"/share/metainfo/org.prismlauncher.PrismLauncher.appdata.xml
|
||||
ln -s share/applications/org.prismlauncher.PrismLauncher.desktop "$INSTALL_APPIMAGE_DIR"
|
||||
ln -s share/icons/hicolor/256x256/apps/org.prismlauncher.PrismLauncher.png "$INSTALL_APPIMAGE_DIR"
|
||||
mv "$INSTALL_APPIMAGE_DIR"/{sharun,AppRun}
|
||||
ls -la "$INSTALL_APPIMAGE_DIR"
|
||||
|
||||
if [[ "${{ github.ref_type }}" == "tag" ]]; then
|
||||
APPIMAGE_DEST="PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage"
|
||||
else
|
||||
APPIMAGE_DEST="PrismLauncher-Linux-$VERSION-${{ inputs.build-type }}-$APPIMAGE_ARCH.AppImage"
|
||||
fi
|
||||
|
||||
mkappimage \
|
||||
--updateinformation "gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-$APPIMAGE_ARCH.AppImage.zsync" \
|
||||
"$INSTALL_APPIMAGE_DIR" \
|
||||
"$APPIMAGE_DEST"
|
||||
|
||||
- name: Package portable tarball
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
|
||||
INSTALL_PORTABLE_DIR: install-portable
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
|
||||
sharun lib4bin \
|
||||
--with-hooks \
|
||||
--hard-links \
|
||||
--dst-dir "$INSTALL_PORTABLE_DIR" \
|
||||
"$INSTALL_PORTABLE_DIR"/bin/* "$QT_PLUGIN_PATH"/*/*.so
|
||||
|
||||
# FIXME(@getchoo): gamemode doesn't seem to be very portable with DBus. Find a way to make it work!
|
||||
find "$INSTALL_PORTABLE_DIR" -name '*gamemode*' -exec rm {} +
|
||||
|
||||
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f -o -type l); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
tar -czf ../PrismLauncher-portable.tar.gz *
|
||||
|
||||
- name: Upload binary tarball
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-Qt6-Portable-${{ inputs.version }}-${{ inputs.build-type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
|
||||
- name: Upload AppImage
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage
|
||||
path: PrismLauncher-${{ runner.os }}-*${{ env.APPIMAGE_ARCH }}.AppImage
|
||||
|
||||
- name: Upload AppImage Zsync
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ inputs.version }}-${{ inputs.build-type }}-${{ env.APPIMAGE_ARCH }}.AppImage.zsync
|
||||
path: PrismLauncher-${{ runner.os }}-*${{ env.APPIMAGE_ARCH }}.AppImage.zsync
|
||||
147
.github/actions/package/macos/action.yml
vendored
147
.github/actions/package/macos/action.yml
vendored
|
|
@ -1,147 +0,0 @@
|
|||
name: Package for macOS
|
||||
description: Create a macOS package for Prism Launcher
|
||||
|
||||
inputs:
|
||||
version:
|
||||
description: Launcher version
|
||||
required: true
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
artifact-name:
|
||||
description: Name of the uploaded artifact
|
||||
required: true
|
||||
default: macOS
|
||||
apple-codesign-cert:
|
||||
description: Certificate for signing macOS builds
|
||||
required: false
|
||||
apple-codesign-password:
|
||||
description: Password for signing macOS builds
|
||||
required: false
|
||||
apple-codesign-id:
|
||||
description: Certificate ID for signing macOS builds
|
||||
required: false
|
||||
apple-notarize-apple-id:
|
||||
description: Apple ID used for notarizing macOS builds
|
||||
required: false
|
||||
apple-notarize-team-id:
|
||||
description: Team ID used for notarizing macOS builds
|
||||
required: false
|
||||
apple-notarize-password:
|
||||
description: Password used for notarizing macOS builds
|
||||
required: false
|
||||
sparkle-ed25519-key:
|
||||
description: Private key for signing Sparkle updates
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Fetch codesign certificate
|
||||
shell: bash
|
||||
run: |
|
||||
echo '${{ inputs.apple-codesign-cert }}' | base64 --decode > codesign.p12
|
||||
if [ -n '${{ inputs.apple-codesign-id }}' ]; then
|
||||
security create-keychain -p '${{ inputs.apple-codesign-password }}' build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p '${{ inputs.apple-codesign-password }}' build.keychain
|
||||
security import codesign.p12 -k build.keychain -P '${{ inputs.apple-codesign-password }}' -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k '${{ inputs.apple-codesign-password }}' build.keychain
|
||||
else
|
||||
echo ":warning: Using ad-hoc code signing for macOS, as certificate was not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }}
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
|
||||
if [ -n '${{ inputs.apple-codesign-id }}' ]; then
|
||||
APPLE_CODESIGN_ID='${{ inputs.apple-codesign-id }}'
|
||||
ENTITLEMENTS_FILE='../program_info/App.entitlements'
|
||||
else
|
||||
APPLE_CODESIGN_ID='-'
|
||||
ENTITLEMENTS_FILE='../program_info/AdhocSignedApp.entitlements'
|
||||
fi
|
||||
|
||||
sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "$ENTITLEMENTS_FILE" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
mv "PrismLauncher.app" "Prism Launcher.app"
|
||||
|
||||
- name: Notarize
|
||||
shell: bash
|
||||
env:
|
||||
INSTALL_DIR: install
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
|
||||
if [ -n '${{ inputs.apple-notarize-password }}' ]; then
|
||||
ditto -c -k --sequesterRsrc --keepParent "Prism Launcher.app" ../PrismLauncher.zip
|
||||
xcrun notarytool submit ../PrismLauncher.zip \
|
||||
--wait --progress \
|
||||
--apple-id '${{ inputs.apple-notarize-apple-id }}' \
|
||||
--team-id '${{ inputs.apple-notarize-team-id }}' \
|
||||
--password '${{ inputs.apple-notarize-password }}'
|
||||
|
||||
xcrun stapler staple "Prism Launcher.app"
|
||||
else
|
||||
echo ":warning: Skipping notarization as credentials are not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
ditto -c -k --sequesterRsrc --keepParent "Prism Launcher.app" ../PrismLauncher.zip
|
||||
|
||||
- name: Create DMG
|
||||
shell: bash
|
||||
env:
|
||||
INSTALL_DIR: install
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
|
||||
mkdir -p src
|
||||
cp -R "Prism Launcher.app" src/
|
||||
|
||||
ln -s /Applications src/
|
||||
|
||||
hdiutil create \
|
||||
-volname "Prism Launcher ${{ inputs.version }}" \
|
||||
-srcfolder src \
|
||||
-ov -format ULMO \
|
||||
"../PrismLauncher.dmg"
|
||||
|
||||
- name: Make Sparkle signature
|
||||
shell: bash
|
||||
run: |
|
||||
if [ '${{ inputs.sparkle-ed25519-key }}' != '' ]; then
|
||||
echo '${{ inputs.sparkle-ed25519-key }}' > ed25519-priv.pem
|
||||
signature_zip=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.zip -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||
signature_dmg=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.dmg -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||
rm ed25519-priv.pem
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
### Artifact Information :information_source:
|
||||
- :memo: Sparkle Signature (ed25519): \`$signature_zip\` (ZIP)
|
||||
- :memo: Sparkle Signature (ed25519): \`$signature_dmg\` (DMG)
|
||||
EOF
|
||||
else
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
### Artifact Information :information_source:
|
||||
- :warning: Sparkle Signature (ed25519): No private key available (likely a pull request or fork)
|
||||
EOF
|
||||
fi
|
||||
|
||||
- name: Upload binary tarball
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}
|
||||
path: PrismLauncher.zip
|
||||
|
||||
- name: Upload disk image
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}.dmg
|
||||
path: PrismLauncher.dmg
|
||||
186
.github/actions/package/windows/action.yml
vendored
186
.github/actions/package/windows/action.yml
vendored
|
|
@ -1,186 +0,0 @@
|
|||
name: Package for Windows
|
||||
description: Create a Windows package for Prism Launcher
|
||||
|
||||
inputs:
|
||||
version:
|
||||
description: Launcher version
|
||||
required: true
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
artifact-name:
|
||||
description: Name of the uploaded artifact
|
||||
required: true
|
||||
msystem:
|
||||
description: MSYS2 subsystem to use
|
||||
required: false
|
||||
azure-client-id:
|
||||
description: Client ID for the Azure Signer Application
|
||||
required: true
|
||||
azure-tenant-id:
|
||||
description: Tenant ID for the Azure Signer Application
|
||||
required: true
|
||||
azure-subscription-id:
|
||||
description: Subscription ID for the Azure Signer Application
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Package (MinGW)
|
||||
if: ${{ inputs.msystem != '' }}
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }}
|
||||
touch ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (MSVC)
|
||||
if: ${{ inputs.msystem == '' }}
|
||||
shell: pwsh
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }}
|
||||
|
||||
cd ${{ github.workspace }}
|
||||
|
||||
Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Emit warning for unsigned builds
|
||||
if: ${{ env.CI_HAS_ACCESS_TO_AZURE == '' || inputs.azure-client-id == '' }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Login to Azure
|
||||
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
|
||||
uses: azure/login@v3
|
||||
with:
|
||||
client-id: ${{ inputs.azure-client-id }}
|
||||
tenant-id: ${{ inputs.azure-tenant-id }}
|
||||
subscription-id: ${{ inputs.azure-subscription-id }}
|
||||
|
||||
- name: Sign executables
|
||||
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
|
||||
uses: azure/artifact-signing-action@v2
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: PrismLauncher
|
||||
certificate-profile-name: PrismLauncher
|
||||
files-folder: ${{ github.workspace }}\install\
|
||||
files-folder-filter: dll,exe
|
||||
files-folder-recurse: true
|
||||
files-folder-depth: 2
|
||||
# recommended in https://github.com/Azure/artifact-signing-action#timestamping-1
|
||||
timestamp-rfc3161: 'http://timestamp.acs.microsoft.com'
|
||||
timestamp-digest: 'SHA256'
|
||||
# TODO(@getchoo): Is this all really needed???
|
||||
# https://github.com/Azure/trusted-signing-action/blob/fc390cf8ed0f14e248a542af1d838388a47c7a7c/docs/OIDC.md
|
||||
exclude-environment-credential: true
|
||||
exclude-workload-identity-credential: true
|
||||
exclude-managed-identity-credential: true
|
||||
exclude-shared-token-cache-credential: true
|
||||
exclude-visual-studio-credential: true
|
||||
exclude-visual-studio-code-credential: true
|
||||
exclude-azure-cli-credential: false
|
||||
exclude-azure-powershell-credential: true
|
||||
exclude-azure-developer-cli-credential: true
|
||||
exclude-interactive-browser-credential: true
|
||||
|
||||
- name: Package (MinGW, portable)
|
||||
if: ${{ inputs.msystem != '' }}
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
INSTALL_PORTABLE_DIR: install-portable
|
||||
run: |
|
||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (MSVC, portable)
|
||||
if: ${{ inputs.msystem == '' }}
|
||||
shell: pwsh
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
INSTALL_PORTABLE_DIR: install-portable
|
||||
run: |
|
||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build-type }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
|
||||
Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (installer)
|
||||
shell: pwsh
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
INSTALL_DIR: install
|
||||
|
||||
NSCURL_VERSION: "v24.9.26.122"
|
||||
NSCURL_SHA256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0"
|
||||
run: |
|
||||
New-Item -Name NSISPlugins -ItemType Directory
|
||||
Invoke-Webrequest https://github.com/negrutiu/nsis-nscurl/releases/download/"${{ env.NSCURL_VERSION }}"/NScurl.zip -OutFile NSISPlugins\NScurl.zip
|
||||
$nscurl_hash = Get-FileHash NSISPlugins\NScurl.zip -Algorithm Sha256 | Select-Object -ExpandProperty Hash
|
||||
if ( $nscurl_hash -ne "${{ env.nscurl_sha256 }}") {
|
||||
echo "::error:: NSCurl.zip sha256 mismatch"
|
||||
exit 1
|
||||
}
|
||||
Expand-Archive -Path NSISPlugins\NScurl.zip -DestinationPath NSISPlugins\NScurl
|
||||
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi"
|
||||
|
||||
- name: Sign installer
|
||||
if: ${{ env.CI_HAS_ACCESS_TO_AZURE != '' && inputs.azure-client-id != '' }}
|
||||
uses: azure/artifact-signing-action@v2
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: PrismLauncher
|
||||
certificate-profile-name: PrismLauncher
|
||||
|
||||
files: |
|
||||
${{ github.workspace }}\PrismLauncher-Setup.exe
|
||||
|
||||
# recommended in https://github.com/Azure/artifact-signing-action#timestamping-1
|
||||
timestamp-rfc3161: 'http://timestamp.acs.microsoft.com'
|
||||
timestamp-digest: 'SHA256'
|
||||
# TODO(@getchoo): Is this all really needed???
|
||||
# https://github.com/Azure/trusted-signing-action/blob/fc390cf8ed0f14e248a542af1d838388a47c7a7c/docs/OIDC.md
|
||||
exclude-environment-credential: true
|
||||
exclude-workload-identity-credential: true
|
||||
exclude-managed-identity-credential: true
|
||||
exclude-shared-token-cache-credential: true
|
||||
exclude-visual-studio-credential: true
|
||||
exclude-visual-studio-code-credential: true
|
||||
exclude-azure-cli-credential: false
|
||||
exclude-azure-powershell-credential: true
|
||||
exclude-azure-developer-cli-credential: true
|
||||
exclude-interactive-browser-credential: true
|
||||
|
||||
- name: Upload binary zip
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-${{ inputs.version }}-${{ inputs.build-type }}
|
||||
path: install/**
|
||||
|
||||
- name: Upload portable zip
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-Portable-${{ inputs.version }}-${{ inputs.build-type }}
|
||||
path: install-portable/**
|
||||
|
||||
- name: Upload installer
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: PrismLauncher-${{ inputs.artifact-name }}-Setup-${{ inputs.version }}-${{ inputs.build-type }}
|
||||
path: PrismLauncher-Setup.exe
|
||||
81
.github/actions/setup-dependencies/action.yml
vendored
81
.github/actions/setup-dependencies/action.yml
vendored
|
|
@ -1,81 +0,0 @@
|
|||
name: Setup Dependencies
|
||||
description: Install and setup dependencies for building Prism Launcher
|
||||
|
||||
inputs:
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
artifact-name:
|
||||
description: Name of the uploaded artifact
|
||||
required: true
|
||||
msystem:
|
||||
description: MSYS2 subsystem to use
|
||||
required: false
|
||||
vcvars-arch:
|
||||
description: Visual Studio architecture to use
|
||||
required: false
|
||||
qt-architecture:
|
||||
description: Qt architecture
|
||||
required: false
|
||||
qt-version:
|
||||
description: Version of Qt to use
|
||||
required: true
|
||||
|
||||
outputs:
|
||||
build-type:
|
||||
description: Type of build used
|
||||
value: ${{ inputs.build-type }}
|
||||
qt-version:
|
||||
description: Version of Qt used
|
||||
value: ${{ inputs.qt-version }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Setup Linux dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: ./.github/actions/setup-dependencies/linux
|
||||
|
||||
- name: Setup macOS dependencies
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: ./.github/actions/setup-dependencies/macos
|
||||
with:
|
||||
build-type: ${{ inputs.build-type }}
|
||||
|
||||
- name: Setup Windows dependencies
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
uses: ./.github/actions/setup-dependencies/windows
|
||||
with:
|
||||
build-type: ${{ inputs.build-type }}
|
||||
msystem: ${{ inputs.msystem }}
|
||||
vcvars-arch: ${{ inputs.vcvars-arch }}
|
||||
|
||||
# TODO(@getchoo): Get this working on MSYS2!
|
||||
- name: Setup ccache
|
||||
if: ${{ (runner.os != 'Windows' || inputs.msystem == '') && inputs.build-type == 'Debug' }}
|
||||
uses: hendrikmuhs/ccache-action@v1.2.23
|
||||
with:
|
||||
variant: sccache
|
||||
create-symlink: ${{ runner.os != 'Windows' }}
|
||||
key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.artifact-name }}-sccache
|
||||
|
||||
- name: Use ccache on debug builds
|
||||
if: ${{ inputs.build-type == 'Debug' }}
|
||||
shell: bash
|
||||
env:
|
||||
# Only use ccache on MSYS2
|
||||
CCACHE_VARIANT: ${{ (runner.os == 'Windows' && inputs.msystem != '') && 'ccache' || 'sccache' }}
|
||||
run: |
|
||||
echo "CMAKE_C_COMPILER_LAUNCHER=$CCACHE_VARIANT" >> "$GITHUB_ENV"
|
||||
echo "CMAKE_CXX_COMPILER_LAUNCHER=$CCACHE_VARIANT" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Install Qt
|
||||
if: ${{ inputs.msystem == '' }}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
aqtversion: "==3.1.*"
|
||||
version: ${{ inputs.qt-version }}
|
||||
modules: qtimageformats qtnetworkauth
|
||||
cache: ${{ inputs.build-type == 'Debug' }}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
name: Setup Linux dependencies
|
||||
description: Install and setup dependencies for building Prism Launcher
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Install host dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install \
|
||||
dpkg-dev \
|
||||
ninja-build extra-cmake-modules pkg-config scdoc \
|
||||
cmark gamemode-dev libarchive-dev libcmark-dev libqrencode-dev zlib1g-dev \
|
||||
libxcb-cursor-dev libtomlplusplus-dev
|
||||
|
||||
- name: Setup AppImage tooling
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
# Determinate AppImage architecture to use
|
||||
dpkg_arch="$(dpkg-architecture -q DEB_HOST_ARCH_CPU)"
|
||||
case "$dpkg_arch" in
|
||||
"amd64")
|
||||
APPIMAGE_ARCH="x86_64"
|
||||
;;
|
||||
"arm64")
|
||||
APPIMAGE_ARCH="aarch64"
|
||||
;;
|
||||
*)
|
||||
echo "# 🚨 The Debian architecture \"$deb_arch\" is not recognized!" >> "$GITHUB_STEP_SUMMARY"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
gh release download \
|
||||
--repo VHSgunzo/sharun \
|
||||
--pattern "sharun-$APPIMAGE_ARCH-aio" \
|
||||
--output ~/bin/sharun
|
||||
|
||||
# FIXME!: revert this to probonopd/go-appimage once https://github.com/probonopd/go-appimage/pull/377 is merged!
|
||||
gh release download continuous \
|
||||
--repo DioEgizio/go-appimage \
|
||||
--pattern "mkappimage-*-$APPIMAGE_ARCH.AppImage" \
|
||||
--output ~/bin/mkappimage
|
||||
|
||||
gh release download \
|
||||
--repo AppImageCommunity/AppImageUpdate \
|
||||
--pattern "AppImageUpdate-$APPIMAGE_ARCH.AppImage" \
|
||||
--output ~/bin/AppImageUpdate.AppImage
|
||||
chmod +x ~/bin/*
|
||||
echo "$HOME/bin" >> "$GITHUB_PATH"
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
name: Setup macOS dependencies
|
||||
|
||||
inputs:
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
brew update
|
||||
brew install ninja extra-cmake-modules temurin@17 mono
|
||||
|
||||
- name: Set JAVA_HOME
|
||||
shell: bash
|
||||
run: |
|
||||
echo "JAVA_HOME=$(/usr/libexec/java_home -v 17)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Setup vcpkg cache
|
||||
if: ${{ inputs.build-type == 'Debug' }}
|
||||
shell: bash
|
||||
env:
|
||||
USERNAME: ${{ github.repository_owner }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
FEED_URL: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
|
||||
run: |
|
||||
mono `vcpkg fetch nuget | tail -n 1` \
|
||||
sources add \
|
||||
-Source "$FEED_URL" \
|
||||
-StorePasswordInClearText \
|
||||
-Name GitHubPackages \
|
||||
-UserName "$USERNAME" \
|
||||
-Password "$GITHUB_TOKEN"
|
||||
mono `vcpkg fetch nuget | tail -n 1` \
|
||||
setapikey "$GITHUB_TOKEN" \
|
||||
-Source "$FEED_URL"
|
||||
echo "VCPKG_BINARY_SOURCES=clear;nuget,$FEED_URL,readwrite" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Setup vcpkg environment
|
||||
shell: bash
|
||||
run: |
|
||||
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
name: Setup Windows Dependencies
|
||||
description: Install and setup dependencies for building Prism Launcher
|
||||
|
||||
inputs:
|
||||
build-type:
|
||||
description: Type for the build
|
||||
required: true
|
||||
default: Debug
|
||||
msystem:
|
||||
description: MSYS2 subsystem to use
|
||||
required: false
|
||||
vcvars-arch:
|
||||
description: Visual Studio architecture to use
|
||||
required: true
|
||||
default: amd64
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
# NOTE: Installed on MinGW as well for SignTool
|
||||
- name: Enter VS Developer shell
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ inputs.vcvars-arch }}
|
||||
vsversion: 2022
|
||||
|
||||
- name: Setup Java (MSVC)
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
# NOTE(@getchoo): We should probably stay on Zulu.
|
||||
# Temurin doesn't have Java 17 builds for WoA
|
||||
distribution: zulu
|
||||
java-version: 17
|
||||
|
||||
- name: Setup vcpkg cache (MSVC)
|
||||
if: ${{ inputs.msystem == '' && inputs.build-type == 'Debug' }}
|
||||
shell: pwsh
|
||||
env:
|
||||
USERNAME: ${{ github.repository_owner }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
FEED_URL: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
|
||||
run: |
|
||||
.$(vcpkg fetch nuget) `
|
||||
sources add `
|
||||
-Source "$env:FEED_URL" `
|
||||
-StorePasswordInClearText `
|
||||
-Name GitHubPackages `
|
||||
-UserName "$env:USERNAME" `
|
||||
-Password "$env:GITHUB_TOKEN"
|
||||
.$(vcpkg fetch nuget) `
|
||||
setapikey "$env:GITHUB_TOKEN" `
|
||||
-Source "$env:FEED_URL"
|
||||
"VCPKG_BINARY_SOURCES=clear;nuget,$env:FEED_URL,readwrite" | Out-File -Append $env:GITHUB_ENV
|
||||
|
||||
- name: Setup vcpkg environment (MSVC)
|
||||
if: ${{ inputs.msystem == '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Setup MSYS2 (MinGW)
|
||||
if: ${{ inputs.msystem != '' }}
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ inputs.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
pacboy: >-
|
||||
toolchain:p
|
||||
ccache:p
|
||||
cmake:p
|
||||
extra-cmake-modules:p
|
||||
ninja:p
|
||||
qt6-base:p
|
||||
qt6-svg:p
|
||||
qt6-imageformats:p
|
||||
qt6-networkauth:p
|
||||
cmark:p
|
||||
qrencode:p
|
||||
tomlplusplus:p
|
||||
libarchive:p
|
||||
|
||||
- name: List pacman packages (MinGW)
|
||||
if: ${{ inputs.msystem != '' }}
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
pacman -Qe
|
||||
|
||||
- name: Retrieve ccache cache (MinGW)
|
||||
if: ${{ inputs.msystem != '' && inputs.build-type == 'Debug' }}
|
||||
uses: actions/cache@v5.0.5
|
||||
with:
|
||||
path: '${{ github.workspace }}\.ccache'
|
||||
key: ${{ runner.os }}-mingw-w64-ccache-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-mingw-w64-ccache
|
||||
|
||||
- name: Setup ccache (MinGW)
|
||||
if: ${{ inputs.msystem != '' && inputs.build-type == 'Debug' }}
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
|
||||
ccache --set-config=max_size='500M'
|
||||
ccache --set-config=compression=true
|
||||
ccache -p # Show config
|
||||
9
.github/workflows/backport.yml
vendored
9
.github/workflows/backport.yml
vendored
|
|
@ -8,7 +8,8 @@ on:
|
|||
# the GitHub repository. This means that it should not evaluate user input in a
|
||||
# way that allows code injection.
|
||||
|
||||
permissions: {}
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
|
|
@ -18,13 +19,13 @@ jobs:
|
|||
actions: write # for korthout/backport-action to create PR with workflow changes
|
||||
name: Backport Pull Request
|
||||
if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@v4.5
|
||||
uses: korthout/backport-action@v3.1.0
|
||||
with:
|
||||
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||
pull_description: |-
|
||||
|
|
|
|||
257
.github/workflows/blocked-prs.yml
vendored
257
.github/workflows/blocked-prs.yml
vendored
|
|
@ -1,257 +0,0 @@
|
|||
name: Blocked/Stacked Pull Requests Automation
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_id:
|
||||
description: Local Pull Request number to work on
|
||||
required: true
|
||||
type: number
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
blocked_status:
|
||||
name: Check Blocked Status
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
steps:
|
||||
- name: Generate token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
|
||||
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Setup From Dispatch Event
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
id: dispatch_event_setup
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
PR_NUMBER: ${{ inputs.pr_id }}
|
||||
run: |
|
||||
# setup env for the rest of the workflow
|
||||
OWNER=$(dirname "${{ github.repository }}")
|
||||
REPO=$(basename "${{ github.repository }}")
|
||||
PR_JSON=$(
|
||||
gh api \
|
||||
-H "Accept: application/vnd.github.raw+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$OWNER/$REPO/pulls/$PR_NUMBER"
|
||||
)
|
||||
echo "PR_JSON=$PR_JSON" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Setup Environment
|
||||
id: env_setup
|
||||
env:
|
||||
EVENT_PR_JSON: ${{ toJSON(github.event.pull_request) }}
|
||||
run: |
|
||||
# setup env for the rest of the workflow
|
||||
PR_JSON=${PR_JSON:-"$EVENT_PR_JSON"}
|
||||
{
|
||||
echo "REPO=$(jq -r '.base.repo.name' <<< "$PR_JSON")"
|
||||
echo "OWNER=$(jq -r '.base.repo.owner.login' <<< "$PR_JSON")"
|
||||
echo "PR_NUMBER=$(jq -r '.number' <<< "$PR_JSON")"
|
||||
echo "JOB_DATA=$(jq -c '
|
||||
{
|
||||
"repo": .base.repo.name,
|
||||
"owner": .base.repo.owner.login,
|
||||
"repoUrl": .base.repo.html_url,
|
||||
"prNumber": .number,
|
||||
"prHeadSha": .head.sha,
|
||||
"prHeadLabel": .head.label,
|
||||
"prBody": (.body // ""),
|
||||
"prLabels": (reduce .labels[].name as $l ([]; . + [$l]))
|
||||
}
|
||||
' <<< "$PR_JSON")"
|
||||
} >> "$GITHUB_ENV"
|
||||
|
||||
|
||||
- name: Find Blocked/Stacked PRs in body
|
||||
id: pr_ids
|
||||
run: |
|
||||
prs=$(
|
||||
jq -c '
|
||||
.prBody as $body
|
||||
| (
|
||||
$body |
|
||||
reduce (
|
||||
. | scan("[Bb]locked (?:[Bb]y|[Oo]n):? #([0-9]+)")
|
||||
| map({
|
||||
"type": "Blocked on",
|
||||
"number": ( . | tonumber )
|
||||
})
|
||||
) as $i ([]; . + [$i[]])
|
||||
) as $bprs
|
||||
| (
|
||||
$body |
|
||||
reduce (
|
||||
. | scan("[Ss]tacked [Oo]n:? #([0-9]+)")
|
||||
| map({
|
||||
"type": "Stacked on",
|
||||
"number": ( . | tonumber )
|
||||
})
|
||||
) as $i ([]; . + [$i[]])
|
||||
) as $sprs
|
||||
| ($bprs + $sprs) as $prs
|
||||
| {
|
||||
"blocking": $prs,
|
||||
"numBlocking": ( $prs | length),
|
||||
}
|
||||
' <<< "$JOB_DATA"
|
||||
)
|
||||
echo "prs=$prs" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Collect Blocked PR Data
|
||||
id: blocking_data
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
BLOCKING_PRS: ${{ steps.pr_ids.outputs.prs }}
|
||||
run: |
|
||||
blocked_pr_data=$(
|
||||
while read -r pr_data ; do
|
||||
gh api \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$OWNER/$REPO/pulls/$(jq -r '.number' <<< "$pr_data")" \
|
||||
| jq -c --arg type "$(jq -r '.type' <<< "$pr_data")" \
|
||||
'
|
||||
. | {
|
||||
"type": $type,
|
||||
"number": .number,
|
||||
"merged": .merged,
|
||||
"state": (if .state == "open" then "Open" elif .merged then "Merged" else "Closed" end),
|
||||
"labels": (reduce .labels[].name as $l ([]; . + [$l])),
|
||||
"basePrUrl": .html_url,
|
||||
"baseRepoName": .head.repo.name,
|
||||
"baseRepoOwner": .head.repo.owner.login,
|
||||
"baseRepoUrl": .head.repo.html_url,
|
||||
"baseSha": .head.sha,
|
||||
"baseRefName": .head.ref,
|
||||
}
|
||||
'
|
||||
done < <(jq -c '.blocking[]' <<< "$BLOCKING_PRS") | jq -c -s
|
||||
)
|
||||
{
|
||||
echo "data=$blocked_pr_data";
|
||||
echo "all_merged=$(jq -r 'all(.[] | (.type == "Stacked on" and .merged) or (.type == "Blocked on" and (.state != "Open")); .)' <<< "$blocked_pr_data")";
|
||||
echo "current_blocking=$(jq -c 'map(
|
||||
select(
|
||||
(.type == "Stacked on" and (.merged | not)) or
|
||||
(.type == "Blocked on" and (.state == "Open"))
|
||||
) | .number
|
||||
)' <<< "$blocked_pr_data" )";
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Add 'blocked' Label if Missing
|
||||
id: label_blocked
|
||||
if: "(fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0) && !contains(fromJSON(env.JOB_DATA).prLabels, 'status: blocked') && !fromJSON(steps.blocking_data.outputs.all_merged)"
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
run: |
|
||||
gh -R ${{ github.repository }} issue edit --add-label 'status: blocked' "$PR_NUMBER"
|
||||
|
||||
- name: Remove 'blocked' Label if All Dependencies Are Merged
|
||||
id: unlabel_blocked
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 && fromJSON(steps.blocking_data.outputs.all_merged)
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
run: |
|
||||
gh -R ${{ github.repository }} issue edit --remove-label 'status: blocked' "$PR_NUMBER"
|
||||
|
||||
- name: Apply 'blocking' Label to Unmerged Dependencies
|
||||
id: label_blocking
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
BLOCKING_ISSUES: ${{ steps.blocking_data.outputs.current_blocking }}
|
||||
run: |
|
||||
while read -r pr ; do
|
||||
gh -R ${{ github.repository }} issue edit --add-label 'status: blocking' "$pr" || true
|
||||
done < <(jq -c '.[]' <<< "$BLOCKING_ISSUES")
|
||||
|
||||
- name: Apply Blocking PR Status Check
|
||||
id: blocked_check
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }}
|
||||
run: |
|
||||
pr_head_sha=$(jq -r '.prHeadSha' <<< "$JOB_DATA")
|
||||
# create commit Status, overwrites previous identical context
|
||||
while read -r pr_data ; do
|
||||
DESC=$(
|
||||
jq -r 'if .type == "Stacked on" then
|
||||
"Stacked PR #" + (.number | tostring) + " is " + (if .merged then "" else "not yet " end) + "merged"
|
||||
else
|
||||
"Blocking PR #" + (.number | tostring) + " is " + (if .state == "Open" then "" else "not yet " end) + "merged or closed"
|
||||
end ' <<< "$pr_data"
|
||||
)
|
||||
gh api \
|
||||
--method POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/${OWNER}/${REPO}/statuses/${pr_head_sha}" \
|
||||
-f "state=$(jq -r 'if (.type == "Stacked on" and .merged) or (.type == "Blocked on" and (.state != "Open")) then "success" else "failure" end' <<< "$pr_data")" \
|
||||
-f "target_url=$(jq -r '.basePrUrl' <<< "$pr_data" )" \
|
||||
-f "description=$DESC" \
|
||||
-f "context=ci/blocking-pr-check:$(jq '.number' <<< "$pr_data")"
|
||||
done < <(jq -c '.[]' <<< "$BLOCKING_DATA")
|
||||
|
||||
- name: Context Comment
|
||||
id: generate-comment
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
|
||||
continue-on-error: true
|
||||
env:
|
||||
BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }}
|
||||
run: |
|
||||
COMMENT_PATH="$(pwd)/temp_comment_file.txt"
|
||||
echo '<h3>PR Dependencies :pushpin:</h3>' > "$COMMENT_PATH"
|
||||
echo >> "$COMMENT_PATH"
|
||||
pr_head_label=$(jq -r '.prHeadLabel' <<< "$JOB_DATA")
|
||||
while read -r pr_data ; do
|
||||
base_pr=$(jq -r '.number' <<< "$pr_data")
|
||||
base_ref_name=$(jq -r '.baseRefName' <<< "$pr_data")
|
||||
base_repo_owner=$(jq -r '.baseRepoOwner' <<< "$pr_data")
|
||||
base_repo_name=$(jq -r '.baseRepoName' <<< "$pr_data")
|
||||
compare_url="https://github.com/$base_repo_owner/$base_repo_name/compare/$base_ref_name...$pr_head_label"
|
||||
status=$(jq -r '
|
||||
if .type == "Stacked on" then
|
||||
if .merged then ":heavy_check_mark: Merged" else ":x: Not Merged (" + .state + ")" end
|
||||
else
|
||||
if .state != "Open" then ":white_check_mark: " + .state else ":x: Open" end
|
||||
end
|
||||
' <<< "$pr_data")
|
||||
type=$(jq -r '.type' <<< "$pr_data")
|
||||
echo " - $type #$base_pr $status [(compare)]($compare_url)" >> "$COMMENT_PATH"
|
||||
done < <(jq -c '.[]' <<< "$BLOCKING_DATA")
|
||||
|
||||
{
|
||||
echo 'body<<EOF';
|
||||
cat "${COMMENT_PATH}";
|
||||
echo 'EOF';
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 💬 PR Comment
|
||||
if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
COMMENT_BODY: ${{ steps.generate-comment.outputs.body }}
|
||||
run: |
|
||||
gh -R ${{ github.repository }} issue comment "$PR_NUMBER" \
|
||||
--body "$COMMENT_BODY" \
|
||||
--create-if-none \
|
||||
--edit-last
|
||||
|
||||
782
.github/workflows/build.yml
vendored
782
.github/workflows/build.yml
vendored
|
|
@ -1,188 +1,704 @@
|
|||
name: Build
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
pull_request:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-type:
|
||||
description: Type of build (Debug or Release)
|
||||
build_type:
|
||||
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
|
||||
type: string
|
||||
default: Debug
|
||||
environment:
|
||||
description: Deployment environment to run under
|
||||
is_qt_cached:
|
||||
description: Enable Qt caching or not
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-type:
|
||||
description: Type of build (Debug or Release)
|
||||
type: string
|
||||
default: Debug
|
||||
|
||||
permissions: {}
|
||||
default: true
|
||||
secrets:
|
||||
SPARKLE_ED25519_KEY:
|
||||
description: Private key for signing Sparkle updates
|
||||
required: false
|
||||
WINDOWS_CODESIGN_CERT:
|
||||
description: Certificate for signing Windows builds
|
||||
required: false
|
||||
WINDOWS_CODESIGN_PASSWORD:
|
||||
description: Password for signing Windows builds
|
||||
required: false
|
||||
APPLE_CODESIGN_CERT:
|
||||
description: Certificate for signing macOS builds
|
||||
required: false
|
||||
APPLE_CODESIGN_PASSWORD:
|
||||
description: Password for signing macOS builds
|
||||
required: false
|
||||
APPLE_CODESIGN_ID:
|
||||
description: Certificate ID for signing macOS builds
|
||||
required: false
|
||||
APPLE_NOTARIZE_APPLE_ID:
|
||||
description: Apple ID used for notarizing macOS builds
|
||||
required: false
|
||||
APPLE_NOTARIZE_TEAM_ID:
|
||||
description: Team ID used for notarizing macOS builds
|
||||
required: false
|
||||
APPLE_NOTARIZE_PASSWORD:
|
||||
description: Password used for notarizing macOS builds
|
||||
required: false
|
||||
CACHIX_AUTH_TOKEN:
|
||||
description: Private token for authenticating against Cachix cache
|
||||
required: false
|
||||
GPG_PRIVATE_KEY:
|
||||
description: Private key for AppImage signing
|
||||
required: false
|
||||
GPG_PRIVATE_KEY_ID:
|
||||
description: ID for the GPG_PRIVATE_KEY, to select the signing key
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (${{ matrix.artifact-name }})
|
||||
|
||||
environment: ${{ inputs.environment || '' }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
# Required for Azure Trusted Signing
|
||||
id-token: write
|
||||
# Required for vcpkg binary cache
|
||||
packages: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
artifact-name: Linux
|
||||
cmake-preset: linux
|
||||
qt-version: 6.10.2
|
||||
- os: ubuntu-20.04
|
||||
qt_ver: 5
|
||||
qt_host: linux
|
||||
qt_arch: ""
|
||||
qt_version: "5.15.2"
|
||||
qt_modules: "qtnetworkauth"
|
||||
|
||||
- os: ubuntu-24.04-arm
|
||||
artifact-name: Linux-aarch64
|
||||
cmake-preset: linux
|
||||
qt-version: 6.10.2
|
||||
- os: ubuntu-20.04
|
||||
qt_ver: 6
|
||||
qt_host: linux
|
||||
qt_arch: ""
|
||||
qt_version: "6.5.3"
|
||||
qt_modules: "qt5compat qtimageformats qtnetworkauth"
|
||||
|
||||
- os: windows-2022
|
||||
artifact-name: Windows-MinGW-w64
|
||||
cmake-preset: windows_mingw
|
||||
msystem: CLANG64
|
||||
vcvars-arch: amd64_x86
|
||||
|
||||
- os: windows-11-arm
|
||||
artifact-name: Windows-MinGW-arm64
|
||||
cmake-preset: windows_mingw
|
||||
msystem: CLANGARM64
|
||||
vcvars-arch: arm64
|
||||
name: "Windows-MinGW-w64"
|
||||
msystem: clang64
|
||||
vcvars_arch: "amd64_x86"
|
||||
|
||||
- os: windows-2022
|
||||
artifact-name: Windows-MSVC
|
||||
cmake-preset: windows_msvc
|
||||
# TODO(@getchoo): This is the default in setup-dependencies/windows. Why isn't it working?!?!
|
||||
vcvars-arch: amd64
|
||||
qt-version: 6.10.2
|
||||
name: "Windows-MSVC"
|
||||
msystem: ""
|
||||
architecture: "x64"
|
||||
vcvars_arch: "amd64"
|
||||
qt_ver: 6
|
||||
qt_host: windows
|
||||
qt_arch: ""
|
||||
qt_version: "6.7.3"
|
||||
qt_modules: "qt5compat qtimageformats qtnetworkauth"
|
||||
nscurl_tag: "v24.9.26.122"
|
||||
nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0"
|
||||
|
||||
- os: windows-11-arm
|
||||
artifact-name: Windows-MSVC-arm64
|
||||
cmake-preset: windows_msvc
|
||||
vcvars-arch: arm64
|
||||
qt-version: 6.10.2
|
||||
- os: windows-2022
|
||||
name: "Windows-MSVC-arm64"
|
||||
msystem: ""
|
||||
architecture: "arm64"
|
||||
vcvars_arch: "amd64_arm64"
|
||||
qt_ver: 6
|
||||
qt_host: windows
|
||||
qt_arch: "win64_msvc2019_arm64"
|
||||
qt_version: "6.7.3"
|
||||
qt_modules: "qt5compat qtimageformats qtnetworkauth"
|
||||
nscurl_tag: "v24.9.26.122"
|
||||
nscurl_sha256: "AEE6C4BE3CB6455858E9C1EE4B3AFE0DB9960FA03FE99CCDEDC28390D57CCBB0"
|
||||
|
||||
- os: macos-26
|
||||
artifact-name: macOS
|
||||
cmake-preset: macos_universal
|
||||
macosx-deployment-target: 12.0
|
||||
qt-version: 6.9.3
|
||||
- os: macos-14
|
||||
name: macOS
|
||||
macosx_deployment_target: 11.0
|
||||
qt_ver: 6
|
||||
qt_host: mac
|
||||
qt_arch: ""
|
||||
qt_version: "6.7.3"
|
||||
qt_modules: "qt5compat qtimageformats qtnetworkauth"
|
||||
|
||||
- os: macos-14
|
||||
name: macOS-Legacy
|
||||
macosx_deployment_target: 10.13
|
||||
qt_ver: 5
|
||||
qt_host: mac
|
||||
qt_version: "5.15.2"
|
||||
qt_modules: "qtnetworkauth"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.msystem != '' && 'msys2 {0}' || 'bash' }}
|
||||
|
||||
env:
|
||||
ARTIFACT_NAME: ${{ matrix.artifact-name }}-Qt6
|
||||
BUILD_PLATFORM: official
|
||||
BUILD_TYPE: ${{ inputs.build-type || 'Debug' }}
|
||||
CMAKE_PRESET: ${{ matrix.cmake-preset }}
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx-deployment-target }}
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||
INSTALL_DIR: "install"
|
||||
INSTALL_PORTABLE_DIR: "install-portable"
|
||||
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||
BUILD_DIR: "build"
|
||||
CCACHE_VAR: ""
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||
|
||||
steps:
|
||||
##
|
||||
# SETUP
|
||||
# PREPARE
|
||||
##
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "true"
|
||||
|
||||
- name: "Setup MSYS2"
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
mingw-w64-x86_64-binutils
|
||||
pacboy: >-
|
||||
toolchain:p
|
||||
cmake:p
|
||||
extra-cmake-modules:p
|
||||
ninja:p
|
||||
qt6-base:p
|
||||
qt6-svg:p
|
||||
qt6-imageformats:p
|
||||
quazip-qt6:p
|
||||
ccache:p
|
||||
qt6-5compat:p
|
||||
qt6-networkauth:p
|
||||
cmark:p
|
||||
|
||||
- name: Force newer ccache
|
||||
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
|
||||
run: |
|
||||
choco install ccache --version 4.7.1
|
||||
|
||||
- name: Setup ccache
|
||||
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
with:
|
||||
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
|
||||
|
||||
- name: Retrieve ccache cache (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
||||
uses: actions/cache@v4.2.0
|
||||
with:
|
||||
path: '${{ github.workspace }}\.ccache'
|
||||
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ matrix.os }}-mingw-w64-ccache
|
||||
|
||||
- name: Setup ccache (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
|
||||
ccache --set-config=max_size='500M'
|
||||
ccache --set-config=compression=true
|
||||
ccache -p # Show config
|
||||
ccache -z # Zero stats
|
||||
|
||||
- name: Use ccache on Debug builds only
|
||||
if: inputs.build_type == 'Debug'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
|
||||
|
||||
- name: Set short version
|
||||
shell: bash
|
||||
run: |
|
||||
ver_short=`git rev-parse --short HEAD`
|
||||
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream libxcb-cursor-dev
|
||||
|
||||
- name: Install Dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update
|
||||
brew install ninja extra-cmake-modules
|
||||
|
||||
- name: Install host Qt (Windows MSVC arm64)
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
aqtversion: "==3.1.*"
|
||||
py7zrversion: ">=0.20.2"
|
||||
version: ${{ matrix.qt_version }}
|
||||
host: "windows"
|
||||
target: "desktop"
|
||||
arch: ""
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
cache-key-prefix: host-qt-arm64-windows
|
||||
dir: ${{ github.workspace }}\HostQt
|
||||
set-env: false
|
||||
|
||||
- name: Install Qt (macOS, Linux & Windows MSVC)
|
||||
if: matrix.msystem == ''
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
aqtversion: "==3.1.*"
|
||||
py7zrversion: ">=0.20.2"
|
||||
version: ${{ matrix.qt_version }}
|
||||
target: "desktop"
|
||||
arch: ${{ matrix.qt_arch }}
|
||||
modules: ${{ matrix.qt_modules }}
|
||||
tools: ${{ matrix.qt_tools }}
|
||||
cache: ${{ inputs.is_qt_cached }}
|
||||
|
||||
- name: Install MSVC (Windows MSVC)
|
||||
if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
vsversion: 2022
|
||||
arch: ${{ matrix.vcvars_arch }}
|
||||
|
||||
- name: Prepare AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
run: |
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
|
||||
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||
|
||||
wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage"
|
||||
|
||||
sudo apt install libopengl0
|
||||
|
||||
- name: Add QT_HOST_PATH var (Windows MSVC arm64)
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
||||
run: |
|
||||
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Setup java (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
##
|
||||
# CONFIGURE
|
||||
##
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: Configure CMake (macOS)
|
||||
if: runner.os == 'macOS' && matrix.qt_ver == 6
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja
|
||||
|
||||
- name: Setup dependencies
|
||||
id: setup-dependencies
|
||||
uses: ./.github/actions/setup-dependencies
|
||||
with:
|
||||
build-type: ${{ env.BUILD_TYPE }}
|
||||
artifact-name: ${{ matrix.artifact-name }}
|
||||
msystem: ${{ matrix.msystem }}
|
||||
vcvars-arch: ${{ matrix.vcvars-arch }}
|
||||
qt-version: ${{ matrix.qt-version }}
|
||||
- name: Configure CMake (macOS-Legacy)
|
||||
if: runner.os == 'macOS' && matrix.qt_ver == 5
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -DCMAKE_OSX_ARCHITECTURES="x86_64" -G Ninja
|
||||
|
||||
- name: Configure CMake (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
|
||||
|
||||
- name: Configure CMake (Windows MSVC)
|
||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
|
||||
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
||||
if ("${{ env.CCACHE_VAR }}")
|
||||
{
|
||||
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
|
||||
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
|
||||
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
|
||||
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
|
||||
}
|
||||
# Needed for ccache, but also speeds up compile
|
||||
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Configure CMake (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_ENABLE_JAVA_DOWNLOADER=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja
|
||||
|
||||
##
|
||||
# BUILD
|
||||
##
|
||||
|
||||
- name: Configure project
|
||||
- name: Build
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
cmake --preset "$CMAKE_PRESET"
|
||||
cmake --build ${{ env.BUILD_DIR }}
|
||||
|
||||
- name: Run build
|
||||
- name: Build (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cmake --build --preset "$CMAKE_PRESET" --config "$BUILD_TYPE"
|
||||
cmake --build ${{ env.BUILD_DIR }}
|
||||
|
||||
- name: Run tests
|
||||
- name: Build (Windows MSVC)
|
||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||
run: |
|
||||
ctest --preset "$CMAKE_PRESET" --build-config "$BUILD_TYPE"
|
||||
cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
||||
|
||||
##
|
||||
# PACKAGE
|
||||
# TEST
|
||||
##
|
||||
|
||||
- name: Get short version
|
||||
id: short-version
|
||||
shell: bash
|
||||
- name: Test
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
echo "version=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
||||
|
||||
- name: Package (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: ./.github/actions/package/linux
|
||||
with:
|
||||
version: ${{ steps.short-version.outputs.version }}
|
||||
build-type: ${{ steps.setup-dependencies.outputs.build-type }}
|
||||
artifact-name: ${{ matrix.artifact-name }}
|
||||
qt-version: ${{ steps.setup-dependencies.outputs.qt-version }}
|
||||
- name: Test (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
||||
|
||||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
gpg-private-key-id: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
- name: Test (Windows MSVC)
|
||||
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
|
||||
run: |
|
||||
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
|
||||
|
||||
##
|
||||
# PACKAGE BUILDS
|
||||
##
|
||||
|
||||
- name: Fetch codesign certificate (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
echo '${{ secrets.APPLE_CODESIGN_CERT }}' | base64 --decode > codesign.p12
|
||||
if [ -n '${{ secrets.APPLE_CODESIGN_ID }}' ]; then
|
||||
security create-keychain -p '${{ secrets.APPLE_CODESIGN_PASSWORD }}' build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p '${{ secrets.APPLE_CODESIGN_PASSWORD }}' build.keychain
|
||||
security import codesign.p12 -k build.keychain -P '${{ secrets.APPLE_CODESIGN_PASSWORD }}' -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k '${{ secrets.APPLE_CODESIGN_PASSWORD }}' build.keychain
|
||||
else
|
||||
echo ":warning: Using ad-hoc code signing for macOS, as certificate was not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Package (macOS)
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: ./.github/actions/package/macos
|
||||
with:
|
||||
version: ${{ steps.short-version.outputs.version }}
|
||||
build-type: ${{ steps.setup-dependencies.outputs.build-type }}
|
||||
artifact-name: ${{ matrix.artifact-name }}
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
|
||||
apple-codesign-cert: ${{ secrets.APPLE_CODESIGN_CERT }}
|
||||
apple-codesign-password: ${{ secrets.APPLE_CODESIGN_PASSWORD }}
|
||||
apple-codesign-id: ${{ secrets.APPLE_CODESIGN_ID }}
|
||||
apple-notarize-apple-id: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }}
|
||||
apple-notarize-team-id: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }}
|
||||
apple-notarize-password: ${{ secrets.APPLE_NOTARIZE_PASSWORD }}
|
||||
sparkle-ed25519-key: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
|
||||
- name: Package (Windows)
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
uses: ./.github/actions/package/windows
|
||||
if [ -n '${{ secrets.APPLE_CODESIGN_ID }}' ]; then
|
||||
APPLE_CODESIGN_ID='${{ secrets.APPLE_CODESIGN_ID }}'
|
||||
else
|
||||
APPLE_CODESIGN_ID='-'
|
||||
fi
|
||||
|
||||
sudo codesign --sign "$APPLE_CODESIGN_ID" --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||
mv "PrismLauncher.app" "Prism Launcher.app"
|
||||
|
||||
- name: Notarize (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
|
||||
if [ -n '${{ secrets.APPLE_NOTARIZE_PASSWORD }}' ]; then
|
||||
ditto -c -k --sequesterRsrc --keepParent "Prism Launcher.app" ../PrismLauncher.zip
|
||||
xcrun notarytool submit ../PrismLauncher.zip \
|
||||
--wait --progress \
|
||||
--apple-id '${{ secrets.APPLE_NOTARIZE_APPLE_ID }}' \
|
||||
--team-id '${{ secrets.APPLE_NOTARIZE_TEAM_ID }}' \
|
||||
--password '${{ secrets.APPLE_NOTARIZE_PASSWORD }}'
|
||||
|
||||
xcrun stapler staple "Prism Launcher.app"
|
||||
else
|
||||
echo ":warning: Skipping notarization as credentials are not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
ditto -c -k --sequesterRsrc --keepParent "Prism Launcher.app" ../PrismLauncher.zip
|
||||
|
||||
- name: Make Sparkle signature (macOS)
|
||||
if: matrix.name == 'macOS'
|
||||
run: |
|
||||
if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then
|
||||
echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem
|
||||
signature=$(/opt/homebrew/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.zip -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||
rm ed25519-priv.pem
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
### Artifact Information :information_source:
|
||||
- :memo: Sparkle Signature (ed25519): \`$signature\`
|
||||
EOF
|
||||
else
|
||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||
### Artifact Information :information_source:
|
||||
- :warning: Sparkle Signature (ed25519): No private key available (likely a pull request or fork)
|
||||
EOF
|
||||
fi
|
||||
|
||||
- name: Package (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
touch ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (Windows MSVC)
|
||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
||||
|
||||
cd ${{ github.workspace }}
|
||||
|
||||
Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Fetch codesign certificate (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash # yes, we are not using MSYS2 or PowerShell here
|
||||
run: |
|
||||
echo '${{ secrets.WINDOWS_CODESIGN_CERT }}' | base64 --decode > codesign.pfx
|
||||
|
||||
- name: Sign executable (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
if (Get-Content ./codesign.pfx){
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
# We ship the exact same executable for portable and non-portable editions, so signing just once is fine
|
||||
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_updater.exe prismlauncher_filelink.exe
|
||||
} else {
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
}
|
||||
|
||||
- name: Package (Windows MinGW-w64, portable)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (Windows MSVC, portable)
|
||||
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||
run: |
|
||||
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||
|
||||
Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||
|
||||
- name: Package (Windows, installer)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
if ('${{ matrix.nscurl_tag }}') {
|
||||
New-Item -Name NSISPlugins -ItemType Directory
|
||||
Invoke-Webrequest https://github.com/negrutiu/nsis-nscurl/releases/download/${{ matrix.nscurl_tag }}/NScurl.zip -OutFile NSISPlugins\NScurl.zip
|
||||
$nscurl_hash = Get-FileHash NSISPlugins\NScurl.zip -Algorithm Sha256 | Select-Object -ExpandProperty Hash
|
||||
if ( $nscurl_hash -ne "${{ matrix.nscurl_sha256 }}") {
|
||||
echo "::error:: NSCurl.zip sha256 mismatch"
|
||||
exit 1
|
||||
}
|
||||
Expand-Archive -Path NSISPlugins\NScurl.zip -DestinationPath NSISPlugins\NScurl
|
||||
}
|
||||
cd ${{ env.INSTALL_DIR }}
|
||||
makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi"
|
||||
|
||||
- name: Sign installer (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
if (Get-Content ./codesign.pfx){
|
||||
SignTool sign /fd sha256 /td sha256 /f codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com PrismLauncher-Setup.exe
|
||||
} else {
|
||||
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||
}
|
||||
|
||||
- name: Package AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
shell: bash
|
||||
env:
|
||||
CI_HAS_ACCESS_TO_AZURE: ${{ vars.CI_HAS_ACCESS_TO_AZURE || '' }}
|
||||
with:
|
||||
version: ${{ steps.short-version.outputs.version }}
|
||||
build-type: ${{ steps.setup-dependencies.outputs.build-type }}
|
||||
artifact-name: ${{ matrix.artifact-name }}
|
||||
msystem: ${{ matrix.msystem }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
run: |
|
||||
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
|
||||
|
||||
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
azure-subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
mv ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.metainfo.xml ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.appdata.xml
|
||||
export "NO_APPSTREAM=1" # we have to skip appstream checking because appstream on ubuntu 20.04 is outdated
|
||||
|
||||
export OUTPUT="PrismLauncher-Linux-x86_64.AppImage"
|
||||
|
||||
chmod +x linuxdeploy-*.AppImage
|
||||
|
||||
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib
|
||||
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||
|
||||
cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||
|
||||
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||
cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||
|
||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
chmod +x AppImageUpdate-x86_64.AppImage
|
||||
cp AppImageUpdate-x86_64.AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin
|
||||
|
||||
export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync"
|
||||
|
||||
if [ '${{ secrets.GPG_PRIVATE_KEY_ID }}' != '' ]; then
|
||||
export SIGN=1
|
||||
export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
mkdir -p ~/.gnupg/
|
||||
echo "$GPG_PRIVATE_KEY" > ~/.gnupg/private.key
|
||||
gpg --import ~/.gnupg/private.key
|
||||
else
|
||||
echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg
|
||||
|
||||
mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||
|
||||
- name: Package (Linux, portable)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PORTABLE_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -DINSTALL_BUNDLE=full -G Ninja
|
||||
cmake --install ${{ env.BUILD_DIR }}
|
||||
cmake --install ${{ env.BUILD_DIR }} --component portable
|
||||
|
||||
mkdir ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
cp /lib/x86_64-linux-gnu/libbz2.so.1.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
cp /usr/lib/x86_64-linux-gnu/libffi.so.7 ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
mv ${{ env.INSTALL_PORTABLE_DIR }}/bin/*.so* ${{ env.INSTALL_PORTABLE_DIR }}/lib
|
||||
|
||||
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||
tar -czf ../PrismLauncher-portable.tar.gz *
|
||||
|
||||
##
|
||||
# UPLOAD BUILDS
|
||||
##
|
||||
|
||||
- name: Upload binary tarball (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher.zip
|
||||
|
||||
- name: Upload binary zip (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: ${{ env.INSTALL_DIR }}/**
|
||||
|
||||
- name: Upload binary zip (Windows, portable)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||
|
||||
- name: Upload installer (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-Setup.exe
|
||||
|
||||
- name: Upload binary tarball (Linux, portable, Qt 5)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
|
||||
- name: Upload binary tarball (Linux, portable, Qt 6)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||
path: PrismLauncher-portable.tar.gz
|
||||
|
||||
- name: Upload AppImage (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||
|
||||
- name: Upload AppImage Zsync (Linux)
|
||||
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync
|
||||
path: PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
|
||||
- name: ccache stats (Windows MinGW-w64)
|
||||
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
ccache -s
|
||||
|
||||
flatpak:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
if: inputs.build_type == 'Debug'
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set short version
|
||||
shell: bash
|
||||
run: echo "VERSION=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build Flatpak (Linux)
|
||||
if: inputs.build_type == 'Debug'
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
with:
|
||||
bundle: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-Flatpak.flatpak
|
||||
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
||||
|
||||
nix:
|
||||
name: Nix (${{ matrix.system }})
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
system: x86_64-linux
|
||||
|
||||
- os: macos-13
|
||||
system: x86_64-darwin
|
||||
|
||||
- os: macos-14
|
||||
system: aarch64-darwin
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
|
||||
# For PRs
|
||||
- name: Setup Nix Magic Cache
|
||||
uses: DeterminateSystems/magic-nix-cache-action@v8
|
||||
|
||||
# For in-tree builds
|
||||
- name: Setup Cachix
|
||||
uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: prismlauncher
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
|
||||
- name: Run flake checks
|
||||
run: |
|
||||
nix flake check --print-build-logs --show-trace
|
||||
|
||||
- name: Build debug package
|
||||
if: ${{ inputs.build_type == 'Debug' }}
|
||||
run: |
|
||||
nix build --print-build-logs .#prismlauncher-debug
|
||||
|
||||
- name: Build release package
|
||||
if: ${{ inputs.build_type != 'Debug' }}
|
||||
run: |
|
||||
nix build --print-build-logs .#prismlauncher
|
||||
|
|
|
|||
48
.github/workflows/clang-tidy.yml
vendored
48
.github/workflows/clang-tidy.yml
vendored
|
|
@ -1,48 +0,0 @@
|
|||
name: Clang-Tidy Code Scanning
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
clang-tidy:
|
||||
name: Run Clang-Tidy
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0 # Required for diffing later on
|
||||
submodules: "true"
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v31
|
||||
|
||||
- name: Run source generators
|
||||
# TODO(@getchoo): Figure out how to make this work with PCH
|
||||
run: |
|
||||
nix develop --command bash -c '
|
||||
cmake -B build -D Launcher_USE_PCH=OFF && cmake --build build --target autogen autorcc
|
||||
'
|
||||
|
||||
# TODO: Use SARIF after https://github.com/psastras/sarif-rs/issues/638 is fixed
|
||||
- name: Run clang-tidy-diff
|
||||
env:
|
||||
BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }}
|
||||
run: |
|
||||
nix develop --command bash -c '
|
||||
clang-tidy -verify-config && git diff -U0 --no-color "$BASE_REF" | clang-tidy-diff.py -p1 -quiet -only-check-in-db
|
||||
'
|
||||
43
.github/workflows/codeql.yml
vendored
43
.github/workflows/codeql.yml
vendored
|
|
@ -1,52 +1,35 @@
|
|||
name: "CodeQL Code Scanning"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
on: [ push, pull_request, workflow_dispatch ]
|
||||
|
||||
jobs:
|
||||
CodeQL:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "true"
|
||||
submodules: 'true'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
queries: security-and-quality
|
||||
languages: cpp, java
|
||||
|
||||
- name: Setup dependencies
|
||||
uses: ./.github/actions/setup-dependencies
|
||||
with:
|
||||
build-type: Debug
|
||||
qt-version: 6.4.3
|
||||
- name: Install Dependencies
|
||||
run:
|
||||
sudo apt-get -y update
|
||||
|
||||
sudo apt-get -y install ninja-build extra-cmake-modules scdoc qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 libqt5networkauth5 libqt5networkauth5-dev
|
||||
|
||||
- name: Configure and Build
|
||||
run: |
|
||||
cmake --preset linux -DLauncher_USE_PCH=OFF
|
||||
cmake --build --preset linux --config Debug
|
||||
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
ctest --preset linux --build-config Debug --extra-verbose --output-on-failure
|
||||
cmake --build build
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
|
|
|||
174
.github/workflows/container.yml
vendored
174
.github/workflows/container.yml
vendored
|
|
@ -1,174 +0,0 @@
|
|||
name: Development Container
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (${{ matrix.arch }})
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
outputs:
|
||||
image-name: ${{ steps.image-name.outputs.image-name }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: arm64
|
||||
os: ubuntu-24.04-arm
|
||||
- arch: amd64
|
||||
os: ubuntu-24.04
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Set image name
|
||||
id: image-name
|
||||
run: |
|
||||
echo "image-name=${REGISTRY}/${GITHUB_REPOSITORY_OWNER,,}/devcontainer" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install Podman
|
||||
uses: redhat-actions/podman-install@main
|
||||
# TODO(@getchoo): Always use this when the action properly supports ARM
|
||||
if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }}
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Determine metadata for image
|
||||
id: image-metadata
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
${{ steps.image-name.outputs.image-name }}
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }}
|
||||
|
||||
type=sha
|
||||
type=sha,format=long
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build image
|
||||
id: build-image
|
||||
uses: redhat-actions/buildah-build@v2
|
||||
with:
|
||||
containerfiles: |
|
||||
./Containerfile
|
||||
tags: ${{ steps.image-metadata.outputs.tags }}
|
||||
labels: ${{ steps.image-metadata.outputs.labels }}
|
||||
|
||||
- name: Push image
|
||||
id: push-image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: redhat-actions/push-to-registry@v2
|
||||
with:
|
||||
tags: ${{ steps.build-image.outputs.tags }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ github.token }}
|
||||
tls-verify: true
|
||||
|
||||
- name: Export image digest
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
DIGEST: ${{ steps.push-image.outputs.digest }}
|
||||
run: |
|
||||
mkdir -p "$RUNNER_TEMP"/digests
|
||||
touch "$RUNNER_TEMP"/digests/"${DIGEST#sha256:}"
|
||||
|
||||
- name: Upload digest artifact
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: digests-${{ matrix.arch }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
manifest:
|
||||
name: Create manifest
|
||||
|
||||
needs: [ build ]
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Install Podman
|
||||
# TODO(@getchoo): Always use this when the action properly supports ARM
|
||||
if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }}
|
||||
uses: redhat-actions/podman-install@main
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
- name: Login to registry
|
||||
uses: redhat-actions/podman-login@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ github.token }}
|
||||
|
||||
- name: Determine metadata for manifest
|
||||
id: manifest-metadata
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
${{ needs.build.outputs.image-name }}
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }}
|
||||
|
||||
type=sha
|
||||
type=sha,format=long
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Create manifest list
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
env:
|
||||
IMAGE_NAME: ${{ needs.build.outputs.image-name }}
|
||||
run: |
|
||||
while read -r tag; do
|
||||
podman manifest create "$tag" \
|
||||
$(printf "$IMAGE_NAME@sha256:%s " *)
|
||||
done <<< "$DOCKER_METADATA_OUTPUT_TAGS"
|
||||
|
||||
- name: Push manifest
|
||||
uses: redhat-actions/push-to-registry@v2
|
||||
with:
|
||||
tags: ${{ steps.manifest-metadata.outputs.tags }}
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ github.token }}
|
||||
tls-verify: true
|
||||
64
.github/workflows/merge-blocking-pr.yml
vendored
64
.github/workflows/merge-blocking-pr.yml
vendored
|
|
@ -1,64 +0,0 @@
|
|||
name: Merged Blocking Pull Request Automation
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_id:
|
||||
description: Local Pull Request number to work on
|
||||
required: true
|
||||
type: number
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
update-blocked-status:
|
||||
name: Update Blocked Status
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
# a pr that was a `blocking:<id>` label was merged.
|
||||
# find the open pr's it was blocked by and trigger a refresh of their state
|
||||
if: "${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'status: blocking') }}"
|
||||
|
||||
steps:
|
||||
- name: Generate token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
app-id: ${{ vars.PULL_REQUEST_APP_ID }}
|
||||
private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Gather Dependent PRs
|
||||
id: gather_deps
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
PR_NUMBER: ${{ inputs.pr_id || github.event.pull_request.number }}
|
||||
run: |
|
||||
blocked_prs=$(
|
||||
gh -R ${{ github.repository }} pr list --label 'status: blocked' --json 'number,body' \
|
||||
| jq -c --argjson pr "$PR_NUMBER" '
|
||||
reduce ( .[] | select(
|
||||
.body |
|
||||
scan("(?:blocked (?:by|on)|stacked on):? #([0-9]+)") |
|
||||
map(tonumber) |
|
||||
any(.[]; . == $pr)
|
||||
)) as $i ([]; . + [$i])
|
||||
'
|
||||
)
|
||||
{
|
||||
echo "deps=$blocked_prs"
|
||||
echo "numdeps=$(jq -r '. | length' <<< "$blocked_prs")"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Trigger Blocked PR Workflows for Dependants
|
||||
if: fromJSON(steps.gather_deps.outputs.numdeps) > 0
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
DEPS: ${{ steps.gather_deps.outputs.deps }}
|
||||
run: |
|
||||
while read -r pr ; do
|
||||
gh -R ${{ github.repository }} workflow run 'blocked-prs.yml' -r "${{ github.ref_name }}" -f pr_id="$pr"
|
||||
done < <(jq -c '.[].number' <<< "$DEPS")
|
||||
|
||||
138
.github/workflows/nix.yml
vendored
138
.github/workflows/nix.yml
vendored
|
|
@ -1,138 +0,0 @@
|
|||
name: Nix
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "develop"
|
||||
- "release-*"
|
||||
tags:
|
||||
- "*"
|
||||
paths:
|
||||
# File types
|
||||
- "**.cpp"
|
||||
- "**.h"
|
||||
- "**.java"
|
||||
- "**.ui"
|
||||
- "**.md"
|
||||
|
||||
# Build files
|
||||
- "**.nix"
|
||||
- "nix/**"
|
||||
- "flake.lock"
|
||||
|
||||
# Directories
|
||||
- "buildconfig/**"
|
||||
- "cmake/**"
|
||||
- "launcher/**"
|
||||
- "libraries/**"
|
||||
- "program_info/**"
|
||||
- "tests/**"
|
||||
|
||||
# Files
|
||||
- "CMakeLists.txt"
|
||||
|
||||
# Workflows
|
||||
- ".github/workflows/nix.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
# File types
|
||||
- "**.cpp"
|
||||
- "**.h"
|
||||
- "**.java"
|
||||
- "**.ui"
|
||||
- "**.md"
|
||||
|
||||
# Build files
|
||||
- "**.nix"
|
||||
- "nix/**"
|
||||
- "flake.lock"
|
||||
|
||||
# Directories
|
||||
- "buildconfig/**"
|
||||
- "cmake/**"
|
||||
- "launcher/**"
|
||||
- "libraries/**"
|
||||
- "program_info/**"
|
||||
- "tests/**"
|
||||
|
||||
# Files
|
||||
- "CMakeLists.txt"
|
||||
|
||||
# Workflows
|
||||
- ".github/workflows/nix.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
DEBUG: ${{ github.ref_type != 'tag' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (${{ matrix.system }})
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
system: x86_64-linux
|
||||
|
||||
- os: ubuntu-22.04-arm
|
||||
system: aarch64-linux
|
||||
|
||||
- os: macos-26
|
||||
system: aarch64-darwin
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v31
|
||||
|
||||
# For PRs
|
||||
- name: Setup Nix Magic Cache
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: DeterminateSystems/magic-nix-cache-action@v14
|
||||
with:
|
||||
diagnostic-endpoint: ""
|
||||
use-flakehub: false
|
||||
|
||||
# For in-tree builds
|
||||
- name: Setup Cachix
|
||||
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
|
||||
uses: cachix/cachix-action@v17
|
||||
with:
|
||||
name: prismlauncher
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
|
||||
- name: Run Flake checks
|
||||
run: |
|
||||
nix flake check --print-build-logs --show-trace
|
||||
|
||||
- name: Build debug package
|
||||
if: ${{ env.DEBUG == 'true' }}
|
||||
run: |
|
||||
nix build \
|
||||
--no-link --print-build-logs --print-out-paths \
|
||||
.#prismlauncher-debug >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Build release package
|
||||
if: ${{ env.DEBUG == 'false' }}
|
||||
env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
SYSTEM: ${{ matrix.system }}
|
||||
run: |
|
||||
nix build --no-link --print-out-paths .#prismlauncher \
|
||||
| tee -a "$GITHUB_STEP_SUMMARY" \
|
||||
| xargs cachix pin prismlauncher "$TAG"-"$SYSTEM"
|
||||
43
.github/workflows/trigger_builds.yml
vendored
Normal file
43
.github/workflows/trigger_builds.yml
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
name: Build Application
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- "renovate/**"
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "**/LICENSE"
|
||||
- "flake.lock"
|
||||
- "packages/**"
|
||||
- ".github/ISSUE_TEMPLATE/**"
|
||||
- ".markdownlint**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "**/LICENSE"
|
||||
- "flake.lock"
|
||||
- "packages/**"
|
||||
- ".github/ISSUE_TEMPLATE/**"
|
||||
- ".markdownlint**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_debug:
|
||||
name: Build Debug
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
build_type: Debug
|
||||
is_qt_cached: true
|
||||
secrets:
|
||||
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||
APPLE_CODESIGN_CERT: ${{ secrets.APPLE_CODESIGN_CERT }}
|
||||
APPLE_CODESIGN_PASSWORD: ${{ secrets.APPLE_CODESIGN_PASSWORD }}
|
||||
APPLE_CODESIGN_ID: ${{ secrets.APPLE_CODESIGN_ID }}
|
||||
APPLE_NOTARIZE_APPLE_ID: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }}
|
||||
APPLE_NOTARIZE_TEAM_ID: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }}
|
||||
APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }}
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
|
|
@ -5,38 +5,40 @@ on:
|
|||
tags:
|
||||
- "*"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build_release:
|
||||
name: Build Release
|
||||
uses: ./.github/workflows/build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
# Required for Azure Trusted Signing
|
||||
id-token: write
|
||||
# Required for vcpkg binary cache
|
||||
packages: write
|
||||
with:
|
||||
build-type: Release
|
||||
environment: Release
|
||||
secrets: inherit
|
||||
build_type: Release
|
||||
is_qt_cached: false
|
||||
secrets:
|
||||
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||
APPLE_CODESIGN_CERT: ${{ secrets.APPLE_CODESIGN_CERT }}
|
||||
APPLE_CODESIGN_PASSWORD: ${{ secrets.APPLE_CODESIGN_PASSWORD }}
|
||||
APPLE_CODESIGN_ID: ${{ secrets.APPLE_CODESIGN_ID }}
|
||||
APPLE_NOTARIZE_APPLE_ID: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }}
|
||||
APPLE_NOTARIZE_TEAM_ID: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }}
|
||||
APPLE_NOTARIZE_PASSWORD: ${{ secrets.APPLE_NOTARIZE_PASSWORD }}
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||
|
||||
create_release:
|
||||
needs: build_release
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "true"
|
||||
path: "PrismLauncher-source"
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Grab and store version
|
||||
run: |
|
||||
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||
|
|
@ -45,13 +47,11 @@ jobs:
|
|||
run: |
|
||||
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
|
||||
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-Linux-aarch64-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-*.AppImage/PrismLauncher-*-x86_64.AppImage PrismLauncher-Linux-x86_64.AppImage
|
||||
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-x86_64.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
mv PrismLauncher-*.AppImage/PrismLauncher-*-aarch64.AppImage PrismLauncher-Linux-aarch64.AppImage
|
||||
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*-aarch64.AppImage.zsync PrismLauncher-Linux-aarch64.AppImage.zsync
|
||||
mv PrismLauncher-Linux-Qt5-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||
mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage
|
||||
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
mv PrismLauncher-macOS-Legacy*/PrismLauncher.zip PrismLauncher-macOS-Legacy-${{ env.VERSION }}.zip
|
||||
mv PrismLauncher-macOS*/PrismLauncher.zip PrismLauncher-macOS-${{ env.VERSION }}.zip
|
||||
mv PrismLauncher-macOS*/PrismLauncher.dmg PrismLauncher-macOS-${{ env.VERSION }}.dmg
|
||||
|
||||
tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
|
||||
|
||||
|
|
@ -81,40 +81,23 @@ jobs:
|
|||
cd ..
|
||||
done
|
||||
|
||||
for d in PrismLauncher-Windows-MinGW-arm64*; do
|
||||
cd "${d}" || continue
|
||||
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||
NAME="PrismLauncher-Windows-MinGW-arm64"
|
||||
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||
cd ..
|
||||
done
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v3
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag_name: ${{ github.ref }}
|
||||
name: Prism Launcher ${{ env.VERSION }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-x86_64.AppImage
|
||||
PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||
PrismLauncher-Linux-aarch64.AppImage
|
||||
PrismLauncher-Linux-aarch64.AppImage.zsync
|
||||
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||
PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-Windows-MinGW-arm64-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-arm64-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MinGW-arm64-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
|
||||
|
|
@ -122,5 +105,5 @@ jobs:
|
|||
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
|
||||
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
|
||||
PrismLauncher-macOS-${{ env.VERSION }}.zip
|
||||
PrismLauncher-macOS-${{ env.VERSION }}.dmg
|
||||
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.zip
|
||||
PrismLauncher-${{ env.VERSION }}.tar.gz
|
||||
25
.github/workflows/update-flake.yml
vendored
25
.github/workflows/update-flake.yml
vendored
|
|
@ -6,30 +6,25 @@ on:
|
|||
- cron: "0 0 * * 0"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-flake:
|
||||
if: github.repository == 'PrismLauncher/PrismLauncher'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31
|
||||
- uses: actions/checkout@v4
|
||||
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
|
||||
|
||||
- uses: DeterminateSystems/update-flake-lock@v28
|
||||
- uses: DeterminateSystems/update-flake-lock@v24
|
||||
with:
|
||||
commit-msg: "chore(nix): update lockfile"
|
||||
pr-title: "chore(nix): update lockfile"
|
||||
pr-labels: |
|
||||
platform: Linux
|
||||
area: packaging
|
||||
complexity: low
|
||||
priority: low
|
||||
type: robot
|
||||
Linux
|
||||
packaging
|
||||
simple change
|
||||
changelog:omit
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
name: Publish
|
||||
|
||||
name: Publish to WinGet
|
||||
on:
|
||||
release:
|
||||
types: [ released ]
|
||||
|
||||
permissions: {}
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
winget:
|
||||
name: Winget
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
runs-on: ubuntu-slim
|
||||
|
||||
publish:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Publish on Winget
|
||||
uses: vedantmgoyal2009/winget-releaser@v2
|
||||
- uses: vedantmgoyal2009/winget-releaser@v2
|
||||
with:
|
||||
identifier: PrismLauncher.PrismLauncher
|
||||
version: ${{ github.event.release.tag_name }}
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -14,7 +14,6 @@ CMakeLists.txt.user.*
|
|||
CMakeSettings.json
|
||||
/CMakeFiles
|
||||
CMakeCache.txt
|
||||
CMakeUserPresets.json
|
||||
/.project
|
||||
/.settings
|
||||
/.idea
|
||||
|
|
@ -22,7 +21,6 @@ CMakeUserPresets.json
|
|||
/.vs
|
||||
cmake-build-*/
|
||||
Debug
|
||||
compile_commands.json
|
||||
|
||||
# Build dirs
|
||||
build
|
||||
|
|
@ -49,12 +47,8 @@ run/
|
|||
|
||||
# Nix/NixOS
|
||||
.direnv/
|
||||
## Used when manually invoking stdenv phases
|
||||
outputs/
|
||||
## Regular artifacts
|
||||
.pre-commit-config.yaml
|
||||
result
|
||||
result-*
|
||||
repl-result-*
|
||||
|
||||
# Flatpak
|
||||
.flatpak-builder
|
||||
|
|
|
|||
21
.gitmodules
vendored
21
.gitmodules
vendored
|
|
@ -1,3 +1,24 @@
|
|||
[submodule "libraries/quazip"]
|
||||
path = libraries/quazip
|
||||
url = https://github.com/stachenov/quazip.git
|
||||
[submodule "libraries/tomlplusplus"]
|
||||
path = libraries/tomlplusplus
|
||||
url = https://github.com/marzer/tomlplusplus.git
|
||||
[submodule "libraries/filesystem"]
|
||||
path = libraries/filesystem
|
||||
url = https://github.com/gulrak/filesystem
|
||||
[submodule "libraries/libnbtplusplus"]
|
||||
path = libraries/libnbtplusplus
|
||||
url = https://github.com/PrismLauncher/libnbtplusplus.git
|
||||
[submodule "libraries/zlib"]
|
||||
path = libraries/zlib
|
||||
url = https://github.com/madler/zlib.git
|
||||
[submodule "libraries/extra-cmake-modules"]
|
||||
path = libraries/extra-cmake-modules
|
||||
url = https://github.com/KDE/extra-cmake-modules
|
||||
[submodule "libraries/cmark"]
|
||||
path = libraries/cmark
|
||||
url = https://github.com/commonmark/cmark.git
|
||||
[submodule "flatpak/shared-modules"]
|
||||
path = flatpak/shared-modules
|
||||
url = https://github.com/flathub/shared-modules.git
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
libraries/nbtplusplus
|
||||
libraries/quazip
|
||||
|
|
|
|||
437
CMakeLists.txt
437
CMakeLists.txt
|
|
@ -1,9 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.25) # Required for features like `CMAKE_MSVC_DEBUG_INFORMATION_FORMAT`
|
||||
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
|
||||
|
||||
project(Launcher LANGUAGES C CXX)
|
||||
if(APPLE)
|
||||
enable_language(OBJC OBJCXX)
|
||||
endif()
|
||||
project(Launcher)
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
||||
if(IS_IN_SOURCE_BUILD)
|
||||
|
|
@ -13,10 +10,6 @@ endif()
|
|||
##################################### Set CMake options #####################################
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOGEN_ORIGIN_DEPENDS OFF)
|
||||
set(CMAKE_GLOBAL_AUTOGEN_TARGET ON)
|
||||
set(CMAKE_GLOBAL_AUTORCC_TARGET ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
|
@ -31,106 +24,101 @@ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
|
|||
######## Set compiler flags ########
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||
set(CMAKE_C_STANDARD_REQUIRED true)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
include(GenerateExportHeader)
|
||||
if(MSVC)
|
||||
# /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
|
||||
# /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
|
||||
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
|
||||
set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
add_compile_definitions($<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>)
|
||||
add_compile_definitions(QT_WARN_DEPRECATED_UP_TO=0x060400)
|
||||
add_compile_definitions(QT_DISABLE_DEPRECATED_UP_TO=0x060400)
|
||||
# /EHs Enables stack unwind semantics for standard C++ exceptions to ensure stackframes are unwound
|
||||
# and object deconstructors are called when an exception is caught.
|
||||
# without it memory leaks and a warning is printed
|
||||
# /EHc tells the compiler to assume that functions declared as extern "C" never throw a C++ exception
|
||||
# This appears to not always be a defualt compiler option in CMAKE
|
||||
set(CMAKE_CXX_FLAGS "/EHsc ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||
add_compile_options(
|
||||
# /GS Adds buffer security checks, default on but included anyway to mirror gcc's fstack-protector flag
|
||||
"$<$<COMPILE_LANGUAGE:C,CXX>:/GS>"
|
||||
|
||||
# /Gw helps reduce binary size
|
||||
# /Gy allows the compiler to package individual functions
|
||||
# /guard:cf enables control flow guard
|
||||
"$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:/Gw;/Gy;/guard:cf>"
|
||||
)
|
||||
|
||||
add_link_options(
|
||||
# /LTCG allows for linking wholy optimizated programs
|
||||
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
|
||||
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
|
||||
"$<$<COMPILE_LANGUAGE:C,CXX>:/LTCG;/MANIFEST:NO;/STACK:8388608>"
|
||||
)
|
||||
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
|
||||
# This implicitly selects an entrypoint specific to the subsystem selected
|
||||
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
|
||||
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
|
||||
# This allows tests to still use have console without using seperate linker flags
|
||||
# /LTCG allows for linking wholy optimizated programs
|
||||
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
|
||||
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
|
||||
set(CMAKE_EXE_LINKER_FLAGS "/LTCG /MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
||||
# /GL enables whole program optimizations
|
||||
# NOTE: With Clang, this is implemented as regular LTO and only used during linking
|
||||
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_compile_options("$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:/GL>")
|
||||
endif()
|
||||
# /Gw helps reduce binary size
|
||||
# /Gy allows the compiler to package individual functions
|
||||
# /guard:cf enables control flow guard
|
||||
foreach(lang C CXX)
|
||||
set("CMAKE_${lang}_FLAGS_RELEASE" "/GL /Gw /Gy /guard:cf")
|
||||
endforeach()
|
||||
|
||||
# See https://github.com/ccache/ccache/issues/1040
|
||||
# TODO(@getchoo): Is sccache affected by this? Would be nice to use `ProgramDatabase`....
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>")
|
||||
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
||||
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
|
||||
foreach(config DEBUG RELWITHDEBINFO)
|
||||
foreach(lang C CXX)
|
||||
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
|
||||
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
|
||||
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
|
||||
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
|
||||
endif()
|
||||
else()
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:-fstack-protector-strong;--param=ssp-buffer-size=4>")
|
||||
|
||||
# Avoid re-defining _FORTIFY_SOURCE, as it can cause redefinition errors in setups that use it by default (i.e., package builds)
|
||||
if(NOT (CMAKE_C_FLAGS MATCHES "-D_FORTIFY_SOURCE" OR CMAKE_CXX_FLAGS MATCHES "-D_FORTIFY_SOURCE"))
|
||||
# NOTE: _FORTIFY_SOURCE requires optimizations in most newer versions of glibc
|
||||
add_compile_options("$<$<AND:$<COMPILE_LANGUAGE:C,CXX>,$<CONFIG:Release,RelWithDebInfo>>:-D_FORTIFY_SOURCE=2>")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# ATL's pack list needs more than the default 1 Mib stack on windows
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
add_link_options("$<$<COMPILE_LANGUAGE:C,CXX>:-Wl,--stack,8388608>")
|
||||
|
||||
# -ffunction-sections and -fdata-sections help reduce binary size
|
||||
# -mguard=cf enables Control Flow Guard
|
||||
# TODO: Look into -gc-sections to further reduce binary size
|
||||
add_compile_options("$<$<AND:$<CONFIG:Release,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>:-ffunction-sections;-fdata-sections;-mguard=cf>")
|
||||
if(WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Export compile commands for debug builds if we can (useful in LSPs like clangd)
|
||||
# https://cmake.org/cmake/help/v3.31/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html
|
||||
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR MATCHES "^Ninja")
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
endif()
|
||||
# Fix build with Qt 5.13
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
||||
|
||||
option(USE_CLANG_TIDY "Enable the use of clang-tidy during compilation" OFF)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_BEFORE=0x050C00")
|
||||
|
||||
if(USE_CLANG_TIDY)
|
||||
find_program(CLANG_TIDY clang-tidy OPTIONAL)
|
||||
if(CLANG_TIDY)
|
||||
message(STATUS "Using clang-tidy during compilation")
|
||||
set(CLANG_TIDY_COMMAND "${CLANG_TIDY}" "--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy")
|
||||
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_COMMAND})
|
||||
else()
|
||||
message(WARNING "Unable to find `clang-tidy`. Not using during compilation")
|
||||
endif()
|
||||
endif()
|
||||
# Fix aarch64 build for toml++
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
|
||||
|
||||
# set CXXFLAGS for build targets
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF)
|
||||
|
||||
# If this is a Debug build turn on address sanitiser
|
||||
if (DEBUG_ADDRESS_SANITIZER)
|
||||
if ((CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND DEBUG_ADDRESS_SANITIZER)
|
||||
message(STATUS "Address Sanitizer enabled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off")
|
||||
|
||||
set(USE_ASAN_COMPILE_OPTIONS $<AND:$<CONFIG:Debug,RelWithDebInfo>,$<COMPILE_LANGUAGE:C,CXX>>)
|
||||
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||
message(STATUS "Using Address Sanitizer compile options for MSVC frontend")
|
||||
add_compile_options(
|
||||
$<${USE_ASAN_COMPILE_OPTIONS}:/fsanitize=address>
|
||||
$<${USE_ASAN_COMPILE_OPTIONS}:/Oy->
|
||||
)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
message(STATUS "Using Address Sanitizer compile options for GCC/Clang")
|
||||
add_compile_options(
|
||||
$<${USE_ASAN_COMPILE_OPTIONS}:-fsanitize=address,undefined>
|
||||
$<${USE_ASAN_COMPILE_OPTIONS}:-fno-omit-frame-pointer>
|
||||
$<${USE_ASAN_COMPILE_OPTIONS}:-fno-sanitize-recover=null>
|
||||
)
|
||||
link_libraries("asan" "ubsan")
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||
# using clang with clang-cl front end
|
||||
message(STATUS "Address Sanitizer available on Clang MSVC frontend")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
|
||||
else()
|
||||
# AppleClang and Clang
|
||||
message(STATUS "Address Sanitizer available on Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
endif()
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# GCC
|
||||
message(STATUS "Address Sanitizer available on GCC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
link_libraries("asan")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "Address Sanitizer available on MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
|
||||
else()
|
||||
message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
|
|
@ -146,9 +134,8 @@ if(ENABLE_LTO)
|
|||
if(ipo_supported)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
else()
|
||||
message(STATUS "Not enabling IPO / LTO on debug builds")
|
||||
|
|
@ -163,9 +150,20 @@ endif()
|
|||
|
||||
option(BUILD_TESTING "Build the testing tree." ON)
|
||||
|
||||
find_package(ECM NO_MODULE REQUIRED)
|
||||
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
||||
|
||||
find_package(ECM QUIET NO_MODULE)
|
||||
if(NOT ECM_FOUND)
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt")
|
||||
message(STATUS "Using bundled ECM")
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}")
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
" Could not find ECM\n \n"
|
||||
" Either install ECM using the system package manager or clone submodules\n"
|
||||
" Submodules can be cloned with 'git submodule update --init --recursive'")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
||||
endif()
|
||||
include(CTest)
|
||||
include(ECMAddTests)
|
||||
if(BUILD_TESTING)
|
||||
|
|
@ -177,19 +175,17 @@ endif()
|
|||
######## Set URLs ########
|
||||
set(Launcher_NEWS_RSS_URL "https://prismlauncher.org/feed/feed.xml" CACHE STRING "URL to fetch Prism Launcher's news RSS feed from.")
|
||||
set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
|
||||
set(Launcher_WIKI_URL "https://prismlauncher.org/wiki/" CACHE STRING "URL that gets opened when the user clicks 'Launcher Help'")
|
||||
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help in a dialog window")
|
||||
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
||||
set(Launcher_LOGIN_CALLBACK_URL "https://prismlauncher.org/successful-login" CACHE STRING "URL that gets opened when the user successfully logins.")
|
||||
set(Launcher_LEGACY_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for legacy (<=1.5.2) FML Libraries.")
|
||||
set(Launcher_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for FML Libraries.")
|
||||
|
||||
######## Set version numbers ########
|
||||
set(Launcher_VERSION_MAJOR 12)
|
||||
set(Launcher_VERSION_MINOR 0)
|
||||
set(Launcher_VERSION_PATCH 0)
|
||||
set(Launcher_VERSION_MAJOR 9)
|
||||
set(Launcher_VERSION_MINOR 2)
|
||||
|
||||
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}")
|
||||
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_PATCH}.0")
|
||||
set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},${Launcher_VERSION_PATCH},0")
|
||||
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
|
||||
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
|
||||
set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0")
|
||||
|
||||
# Build platform.
|
||||
set(Launcher_BUILD_PLATFORM "unknown" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
||||
|
|
@ -223,10 +219,9 @@ set(Launcher_DISCORD_URL "https://prismlauncher.org/discord" CACHE STRING "URL f
|
|||
set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL for the subreddit.")
|
||||
|
||||
# Builds
|
||||
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||
set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
|
||||
|
||||
option(Launcher_USE_PCH "Use precompiled headers where possible" ON)
|
||||
|
||||
# Java downloader
|
||||
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT ON)
|
||||
|
||||
|
|
@ -234,7 +229,7 @@ set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT ON)
|
|||
# differing Linux/BSD/etc distributions. Downstream packagers should be explicitly opt-ing into this
|
||||
# feature if they know it will work with their distribution.
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT OFF)
|
||||
set(Launcher_ENABLE_JAVA_DOWNLOADER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
# Java downloader
|
||||
|
|
@ -289,59 +284,75 @@ set(Launcher_BUILD_TIMESTAMP "${TODAY}")
|
|||
|
||||
################################ 3rd Party Libs ################################
|
||||
|
||||
# Successive configurations of cmake without cleaning the build dir will cause zlib fallback to fail due to cached values
|
||||
# Record when fallback triggered and skip this find_package
|
||||
if(NOT Launcher_FORCE_BUNDLED_LIBS AND NOT FORCE_BUNDLED_ZLIB)
|
||||
find_package(ZLIB QUIET)
|
||||
endif()
|
||||
if(NOT ZLIB_FOUND)
|
||||
set(FORCE_BUNDLED_ZLIB TRUE CACHE BOOL "")
|
||||
mark_as_advanced(FORCE_BUNDLED_ZLIB)
|
||||
endif()
|
||||
|
||||
# Find the required Qt parts
|
||||
if(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
||||
include(QtVersionlessBackport)
|
||||
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||
set(QT_VERSION_MAJOR 5)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml NetworkAuth)
|
||||
|
||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||
find_package(QuaZip-Qt5 1.3 QUIET)
|
||||
endif()
|
||||
if (NOT QuaZip-Qt5_FOUND)
|
||||
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||
set(FORCE_BUNDLED_QUAZIP 1)
|
||||
endif()
|
||||
|
||||
# Qt 6 sets these by default. Notably causes Windows APIs to use UNICODE strings.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
|
||||
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
||||
set(QT_VERSION_MAJOR 6)
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml NetworkAuth OpenGL)
|
||||
find_package(Qt6 COMPONENTS DBus)
|
||||
list(APPEND Launcher_QT_DBUS Qt6::DBus)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat NetworkAuth)
|
||||
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
|
||||
|
||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||
find_package(QuaZip-Qt6 1.3 QUIET)
|
||||
endif()
|
||||
if (NOT QuaZip-Qt6_FOUND)
|
||||
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||
set(FORCE_BUNDLED_QUAZIP 1)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
|
||||
endif()
|
||||
|
||||
if(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
||||
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||
include(ECMQueryQt)
|
||||
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
|
||||
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
|
||||
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
|
||||
else()
|
||||
set(QT_PLUGINS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_PLUGINS})
|
||||
set(QT_LIBS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBS})
|
||||
set(QT_LIBEXECS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBEXECS})
|
||||
endif()
|
||||
|
||||
find_package(cmark REQUIRED)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(gamemode REQUIRED IMPORTED_TARGET gamemode)
|
||||
# NOTE: Qt 6 already sets this by default
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# Find libqrencode
|
||||
## NOTE(@getchoo): Never use pkg-config with MSVC since the vcpkg port makes our install bundle fail to find the dll
|
||||
if(MSVC)
|
||||
find_path(LIBQRENCODE_INCLUDE_DIR qrencode.h REQUIRED)
|
||||
find_library(LIBQRENCODE_LIBRARY_RELEASE qrencode REQUIRED)
|
||||
find_library(LIBQRENCODE_LIBRARY_DEBUG qrencoded)
|
||||
set(LIBQRENCODE_LIBRARIES optimized ${LIBQRENCODE_LIBRARY_RELEASE} debug ${LIBQRENCODE_LIBRARY_DEBUG})
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(libqrencode REQUIRED IMPORTED_TARGET libqrencode)
|
||||
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||
# Find toml++
|
||||
find_package(tomlplusplus 3.2.0 QUIET)
|
||||
|
||||
# Find ghc_filesystem
|
||||
find_package(ghc_filesystem QUIET)
|
||||
|
||||
# Find cmark
|
||||
find_package(cmark QUIET)
|
||||
endif()
|
||||
|
||||
# Find libarchive through CMake packages, mainly for vcpkg
|
||||
find_package(LibArchive)
|
||||
# CMake packages aren't available in most distributions of libarchive, so fallback to pkg-config
|
||||
if(NOT LibArchive_FOUND)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(libarchive REQUIRED IMPORTED_TARGET libarchive)
|
||||
endif()
|
||||
|
||||
find_package(tomlplusplus 3.2.0)
|
||||
# fallback to pkgconfig, important especially as many distros package toml++ built with meson
|
||||
if(NOT tomlplusplus_FOUND)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus>=3.2.0)
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
|
||||
####################################### Program Info #######################################
|
||||
|
|
@ -355,7 +366,7 @@ set(Launcher_ENABLE_UPDATER NO)
|
|||
set(Launcher_BUILD_UPDATER NO)
|
||||
|
||||
if (NOT APPLE AND (NOT Launcher_UPDATER_GITHUB_REPO STREQUAL "" AND NOT Launcher_BUILD_ARTIFACT STREQUAL ""))
|
||||
set(Launcher_BUILD_UPDATER YES)
|
||||
set(Launcher_BUILD_UPDATER YES)
|
||||
endif()
|
||||
|
||||
if(NOT (UNIX AND APPLE))
|
||||
|
|
@ -371,10 +382,13 @@ if(UNIX AND APPLE)
|
|||
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
||||
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
||||
|
||||
# Apps to bundle
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
||||
|
||||
# Mac bundle settings
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}")
|
||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "${Launcher_AppID}")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.prismlauncher.${Launcher_Name}")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_NAME}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||
|
|
@ -383,63 +397,23 @@ if(UNIX AND APPLE)
|
|||
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed")
|
||||
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed")
|
||||
|
||||
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.8.0/Sparkle-2.8.0.tar.xz" CACHE STRING "URL to Sparkle release archive")
|
||||
set(MACOSX_SPARKLE_SHA256 "fd5681ee92bf238aaac2d08214ceaf0cc8976e452d7f882d80bac1e61581f3b1" CACHE STRING "SHA256 checksum for Sparkle release archive")
|
||||
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" CACHE STRING "URL to Sparkle release archive")
|
||||
set(MACOSX_SPARKLE_SHA256 "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b" CACHE STRING "SHA256 checksum for Sparkle release archive")
|
||||
set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MACOSX_SPARKLE_DIR})
|
||||
|
||||
if(NOT MACOSX_SPARKLE_UPDATE_PUBLIC_KEY STREQUAL "" AND NOT MACOSX_SPARKLE_UPDATE_FEED_URL STREQUAL "")
|
||||
set(Launcher_ENABLE_UPDATER YES)
|
||||
endif()
|
||||
|
||||
# install as bundle
|
||||
set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||
|
||||
# Add the icon
|
||||
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
||||
|
||||
find_program(ACTOOL_EXE actool DOC "Path to the apple asset catalog compiler")
|
||||
if(ACTOOL_EXE)
|
||||
execute_process(
|
||||
COMMAND xcodebuild -version
|
||||
OUTPUT_VARIABLE XCODE_VERSION_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
string(REGEX MATCH "Xcode ([0-9]+\.[0-9]+)" XCODE_VERSION_MATCH "${XCODE_VERSION_OUTPUT}")
|
||||
if(XCODE_VERSION_MATCH)
|
||||
set(XCODE_VERSION ${CMAKE_MATCH_1})
|
||||
else()
|
||||
set(XCODE_VERSION 0.0)
|
||||
endif()
|
||||
|
||||
if(XCODE_VERSION VERSION_GREATER_EQUAL 26.0)
|
||||
set(ASSETS_OUT_DIR "${CMAKE_BINARY_DIR}/program_info")
|
||||
set(GENERATED_ASSETS_CAR "${ASSETS_OUT_DIR}/Assets.car")
|
||||
set(ICON_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Branding_MAC_ICON}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${GENERATED_ASSETS_CAR}"
|
||||
COMMAND ${ACTOOL_EXE} "${ICON_SOURCE}"
|
||||
--compile "${ASSETS_OUT_DIR}"
|
||||
--output-partial-info-plist /dev/null
|
||||
--app-icon ${Launcher_Name}
|
||||
--enable-on-demand-resources NO
|
||||
--target-device mac
|
||||
--minimum-deployment-target ${CMAKE_OSX_DEPLOYMENT_TARGET}
|
||||
--platform macosx
|
||||
DEPENDS "${ICON_SOURCE}"
|
||||
COMMENT "Compiling asset catalog (${ICON_SOURCE})"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(compile_assets ALL DEPENDS "${GENERATED_ASSETS_CAR}")
|
||||
install(FILES "${GENERATED_ASSETS_CAR}" DESTINATION "${RESOURCES_DEST_DIR}")
|
||||
else()
|
||||
message(WARNING "Xcode ${XCODE_VERSION} is too old. Minimum required version is 26.0. Not compiling liquid glass icons.")
|
||||
endif()
|
||||
|
||||
else()
|
||||
message(WARNING "actool not found. Cannot compile macOS app icons.\n"
|
||||
"Install Xcode command line tools: 'xcode-select --install'")
|
||||
endif()
|
||||
|
||||
|
||||
elseif(UNIX)
|
||||
include(KDEInstallDirs)
|
||||
|
||||
|
|
@ -447,20 +421,30 @@ elseif(UNIX)
|
|||
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
||||
set(JARS_DEST_DIR "share/${Launcher_Name}")
|
||||
|
||||
# install as bundle with no dependencies included
|
||||
set(INSTALL_BUNDLE "nodeps" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||
|
||||
# Set RPATH
|
||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR})
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_PNG_256} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/256x256/apps" RENAME "${Launcher_AppID}.png")
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_Name}")
|
||||
|
||||
set(PLUGIN_DEST_DIR "plugins")
|
||||
set(BUNDLE_DEST_DIR ".")
|
||||
set(RESOURCES_DEST_DIR ".")
|
||||
if (INSTALL_BUNDLE STREQUAL full)
|
||||
set(PLUGIN_DEST_DIR "plugins")
|
||||
set(BUNDLE_DEST_DIR ".")
|
||||
set(RESOURCES_DEST_DIR ".")
|
||||
|
||||
# Apps to bundle
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${Launcher_APP_BINARY_NAME}")
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
|
||||
if(Launcher_ManPage)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6")
|
||||
|
|
@ -476,6 +460,15 @@ elseif(WIN32)
|
|||
set(PLUGIN_DEST_DIR ".")
|
||||
set(RESOURCES_DEST_DIR ".")
|
||||
set(JARS_DEST_DIR "jars")
|
||||
|
||||
# Apps to bundle
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.exe")
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
||||
# install as bundle
|
||||
set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||
else()
|
||||
message(FATAL_ERROR "Platform not supported")
|
||||
endif()
|
||||
|
|
@ -492,12 +485,70 @@ option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
|
|||
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
||||
add_subdirectory(libraries/libnbtplusplus)
|
||||
|
||||
add_subdirectory(libraries/systeminfo) # system information library
|
||||
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||
if(FORCE_BUNDLED_ZLIB)
|
||||
message(STATUS "Using bundled zlib")
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib
|
||||
set(SKIP_INSTALL_ALL ON)
|
||||
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
|
||||
|
||||
# On OS where unistd.h exists, zlib's generated header defines `Z_HAVE_UNISTD_H`, while the included header does not.
|
||||
# We cannot safely undo the rename on those systems, and they generally have packages for zlib anyway.
|
||||
check_include_file(unistd.h NEED_GENERATED_ZCONF)
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" AND NOT NEED_GENERATED_ZCONF)
|
||||
# zlib's cmake script renames a file, dirtying the submodule, see https://github.com/madler/zlib/issues/162
|
||||
message(STATUS "Undoing Rename")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
||||
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
||||
endif()
|
||||
|
||||
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" CACHE STRING "" FORCE)
|
||||
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
|
||||
add_library(ZLIB::ZLIB ALIAS zlibstatic)
|
||||
set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "zlib library name")
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
else()
|
||||
message(STATUS "Using system zlib")
|
||||
endif()
|
||||
if (FORCE_BUNDLED_QUAZIP)
|
||||
message(STATUS "Using bundled QuaZip")
|
||||
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
||||
set(QUAZIP_INSTALL 0)
|
||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||
else()
|
||||
message(STATUS "Using system QuaZip")
|
||||
endif()
|
||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||
if(NOT tomlplusplus_FOUND)
|
||||
message(STATUS "Using bundled tomlplusplus")
|
||||
add_subdirectory(libraries/tomlplusplus) # toml parser
|
||||
else()
|
||||
message(STATUS "Using system tomlplusplus")
|
||||
endif()
|
||||
if(NOT cmark_FOUND)
|
||||
message(STATUS "Using bundled cmark")
|
||||
set(ORIGINAL_BUILD_TESTING ${BUILD_TESTING})
|
||||
set(BUILD_TESTING 0)
|
||||
set(BUILD_SHARED_LIBS 0)
|
||||
add_subdirectory(libraries/cmark EXCLUDE_FROM_ALL) # Markdown parser
|
||||
add_library(cmark::cmark ALIAS cmark)
|
||||
set(BUILD_TESTING ${ORIGINAL_BUILD_TESTING})
|
||||
else()
|
||||
message(STATUS "Using system cmark")
|
||||
endif()
|
||||
add_subdirectory(libraries/gamemode)
|
||||
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API
|
||||
if (NOT ghc_filesystem_FOUND)
|
||||
message(STATUS "Using bundled ghc_filesystem")
|
||||
add_subdirectory(libraries/filesystem) # Implementation of std::filesystem for old C++, for usage in old macOS
|
||||
else()
|
||||
message(STATUS "Using system ghc_filesystem")
|
||||
endif()
|
||||
add_subdirectory(libraries/qdcss) # css parser
|
||||
|
||||
############################### Built Artifacts ###############################
|
||||
|
|
|
|||
|
|
@ -1,222 +0,0 @@
|
|||
{
|
||||
"$schema": "https://cmake.org/cmake/help/latest/_downloads/3e2d73bff478d88a7de0de736ba5e361/schema.json",
|
||||
"version": 8,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 28
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "base",
|
||||
"hidden": true,
|
||||
"binaryDir": "build",
|
||||
"installDir": "install",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"cacheVariables": {
|
||||
"Launcher_BUILD_ARTIFACT": "$penv{ARTIFACT_NAME}",
|
||||
"Launcher_BUILD_PLATFORM": "$penv{BUILD_PLATFORM}",
|
||||
"Launcher_ENABLE_JAVA_DOWNLOADER": "ON",
|
||||
"ENABLE_LTO": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux",
|
||||
"displayName": "Linux",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos",
|
||||
"displayName": "macOS",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos_universal",
|
||||
"displayName": "macOS (Universal Binary)",
|
||||
"inherits": [
|
||||
"macos"
|
||||
],
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"CMAKE_OSX_ARCHITECTURES": "x86_64;arm64",
|
||||
"VCPKG_TARGET_TRIPLET": "universal-osx"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows_mingw",
|
||||
"displayName": "Windows (MinGW)",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows_msvc",
|
||||
"displayName": "Windows (MSVC)",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "$penv{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "linux",
|
||||
"displayName": "Linux",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"configurePreset": "linux"
|
||||
},
|
||||
{
|
||||
"name": "macos",
|
||||
"displayName": "macOS",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"configurePreset": "macos"
|
||||
},
|
||||
{
|
||||
"name": "macos_universal",
|
||||
"displayName": "macOS (Universal Binary)",
|
||||
"inherits": [
|
||||
"macos"
|
||||
],
|
||||
"configurePreset": "macos_universal"
|
||||
},
|
||||
{
|
||||
"name": "windows_mingw",
|
||||
"displayName": "Windows (MinGW)",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"configurePreset": "windows_mingw"
|
||||
},
|
||||
{
|
||||
"name": "windows_msvc",
|
||||
"displayName": "Windows (MSVC)",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"configurePreset": "windows_msvc"
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "base",
|
||||
"hidden": true,
|
||||
"output": {
|
||||
"outputOnFailure": true,
|
||||
"verbosity": "extra"
|
||||
},
|
||||
"execution": {
|
||||
"noTestsAction": "error"
|
||||
},
|
||||
"filter": {
|
||||
"exclude": {
|
||||
"name": "^example64|example$"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux",
|
||||
"displayName": "Linux",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"configurePreset": "linux"
|
||||
},
|
||||
{
|
||||
"name": "macos",
|
||||
"displayName": "macOS",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"configurePreset": "macos"
|
||||
},
|
||||
{
|
||||
"name": "macos_universal",
|
||||
"displayName": "macOS (Universal Binary)",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"configurePreset": "macos_universal"
|
||||
},
|
||||
{
|
||||
"name": "windows_mingw",
|
||||
"displayName": "Windows (MinGW)",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"configurePreset": "windows_mingw"
|
||||
},
|
||||
{
|
||||
"name": "windows_msvc",
|
||||
"displayName": "Windows (MSVC)",
|
||||
"inherits": [
|
||||
"base"
|
||||
],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"configurePreset": "windows_msvc"
|
||||
}
|
||||
]
|
||||
}
|
||||
114
CONTRIBUTING.md
114
CONTRIBUTING.md
|
|
@ -1,113 +1,17 @@
|
|||
# Contributions Guidelines
|
||||
|
||||
## Restrictions on Generative AI Usage (AI Policy)
|
||||
## Code formatting
|
||||
|
||||
> [!NOTE]
|
||||
> The following is adapted from [matplotlib's contributing guide](https://matplotlib.org/devdocs/devel/contribute.html#generative-ai) and the [Linux Kernel policy guide](https://www.kernel.org/doc./html/next/process/coding-assistants.html)
|
||||
Try to follow the existing formatting.
|
||||
If there is no existing formatting, you may use `clang-format` with our included `.clang-format` configuration.
|
||||
|
||||
We expect authentic engagement in our community.
|
||||
In general, in order of importance:
|
||||
|
||||
- Do not post output from Large Language Models or similar generative AI as comments on GitHub or our discord server, as such comments tend to be formulaic and low-quality content.
|
||||
- If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach.
|
||||
|
||||
Make sure you have added value based on your personal competency to your contributions.
|
||||
Just taking some input, feeding it to an AI and posting the result is not of value to the project.
|
||||
To preserve precious core developer capacity, we reserve the right to rigorously reject seemingly AI generated low-value contributions.
|
||||
|
||||
### Signed-off-by and Developer Certificate of Origin
|
||||
|
||||
AI agents MUST NOT add Signed-off-by tags. Only humans can legally certify the Developer Certificate of Origin (DCO). The human submitter is responsible for:
|
||||
|
||||
- Reviewing all AI-generated code
|
||||
- Ensuring compliance with licensing requirements
|
||||
- Adding their own Signed-off-by tag to certify the DCO
|
||||
- Taking full responsibility for the contribution
|
||||
|
||||
See [Signing your work](#signing-your-work) for more information.
|
||||
|
||||
### Attribution
|
||||
|
||||
When AI tools contribute to development, proper attribution helps track the evolving role of AI in the development process. Contributions should include an Assisted-by tag in the commit message with the following format:
|
||||
|
||||
```text
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- `AGENT_NAME` is the name of the AI tool or framework
|
||||
- `MODEL_VERSION` is the specific model version used
|
||||
- `[TOOL1] [TOOL2]` are optional specialized analysis tools used (e.g., coccinelle, sparse, smatch, clang-tidy)
|
||||
|
||||
Basic development tools (git, gcc, make, editors) should not be listed.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
Assisted-by: Claude:claude-3-opus coccinelle sparse
|
||||
```
|
||||
|
||||
## Code style
|
||||
|
||||
All files are formatted with `clang-format` using the configuration in `.clang-format`. Ensure it is run on changed files before committing!
|
||||
|
||||
Please also follow the project's conventions for C++:
|
||||
|
||||
- Class and type names should be formatted as `PascalCase`: `MyClass`.
|
||||
- Private or protected class data members should be formatted as `camelCase` prefixed with `m_`: `m_myCounter`.
|
||||
- Private or protected `static` class data members should be formatted as `camelCase` prefixed with `s_`: `s_instance`.
|
||||
- Public class data members should be formatted as `camelCase` without the prefix: `dateOfBirth`.
|
||||
- Public, private or protected `static const` class data members should be formatted as `SCREAMING_SNAKE_CASE`: `MAX_VALUE`.
|
||||
- Class function members should be formatted as `camelCase` without a prefix: `incrementCounter`.
|
||||
- Global functions and non-`const` global variables should be formatted as `camelCase` without a prefix: `globalData`.
|
||||
- `const` global variables and macros should be formatted as `SCREAMING_SNAKE_CASE`: `LIGHT_GRAY`.
|
||||
- enum constants should be formatted as `PascalCase`: `CamelusBactrianus`
|
||||
- Avoid inventing acronyms or abbreviations especially for a name of multiple words - like `tp` for `texturePack`.
|
||||
- Avoid using `[[nodiscard]]` unless ignoring the return value is likely to cause a bug in cases such as:
|
||||
- A function allocates memory or another resource and the caller needs to clean it up.
|
||||
- A function has side effects and an error status is returned.
|
||||
- A function is likely be mistaken for having side effects.
|
||||
- A plain getter is unlikely to cause confusion and adding `[[nodiscard]]` can create clutter and inconsistency.
|
||||
|
||||
Most of these rules are included in the `.clang-tidy` file, so you can run `clang-tidy` to check for any violations.
|
||||
|
||||
Here is what these conventions with the formatting configuration look like:
|
||||
|
||||
```c++
|
||||
#define AWESOMENESS 10
|
||||
|
||||
constexpr double PI = 3.14159;
|
||||
|
||||
enum class PizzaToppings { HamAndPineapple, OreoAndKetchup };
|
||||
|
||||
struct Person {
|
||||
QString name;
|
||||
QDateTime dateOfBirth;
|
||||
|
||||
long daysOld() const { return dateOfBirth.daysTo(QDateTime::currentDateTime()); }
|
||||
};
|
||||
|
||||
class ImportantClass {
|
||||
public:
|
||||
void incrementCounter()
|
||||
{
|
||||
if (m_counter + 1 > MAX_COUNTER_VALUE)
|
||||
throw std::runtime_error("Counter has reached limit!");
|
||||
|
||||
++m_counter;
|
||||
}
|
||||
|
||||
int counter() const { return m_counter; }
|
||||
|
||||
private:
|
||||
static constexpr int MAX_COUNTER_VALUE = 100;
|
||||
int m_counter;
|
||||
};
|
||||
|
||||
ImportantClass importantClassInstance;
|
||||
```
|
||||
|
||||
If you see any names which do not follow these conventions, it is preferred that you leave them be - renames increase the number of changes therefore make reviewing harder and make your PR more prone to conflicts. However, if you're refactoring a whole class anyway, it's fine.
|
||||
- Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
|
||||
- Prefer readability over dogma.
|
||||
- Keep to the existing formatting.
|
||||
- Indent with 4 space unless it's in a submodule.
|
||||
- Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
|
||||
|
||||
## Signing your work
|
||||
|
||||
|
|
|
|||
91
COPYING.md
91
COPYING.md
|
|
@ -1,7 +1,7 @@
|
|||
## Prism Launcher
|
||||
|
||||
Prism Launcher - Minecraft Launcher
|
||||
Copyright (C) 2022-2026 Prism Launcher Contributors
|
||||
Copyright (C) 2022-2024 Prism Launcher Contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
|
||||
Information on third party licenses used in MinGW-w64 can be found in its COPYING.MinGW-w64-runtime.txt.
|
||||
|
||||
## Qt 6
|
||||
## Qt 5/6
|
||||
|
||||
Copyright (C) 2022 The Qt Company Ltd and other contributors.
|
||||
Contact: https://www.qt.io/licensing
|
||||
|
|
@ -212,6 +212,30 @@
|
|||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
## Quazip
|
||||
|
||||
Copyright (C) 2005-2021 Sergey A. Tachenov
|
||||
|
||||
The QuaZip library is licensed under the GNU Lesser General Public
|
||||
License V2.1 plus a static linking exception.
|
||||
|
||||
The original ZIP/UNZIP package (MiniZip) is copyrighted by Gilles
|
||||
Vollant and contributors, see quazip/(un)zip.h files for details.
|
||||
Basically it's the zlib license.
|
||||
|
||||
STATIC LINKING EXCEPTION
|
||||
|
||||
The copyright holders give you permission to link this library with
|
||||
independent modules to produce an executable, regardless of the license
|
||||
terms of these independent modules, and to copy and distribute the
|
||||
resulting executable under terms of your choice, provided that you also
|
||||
meet, for each linked independent module, the terms and conditions of
|
||||
the license of that module. An independent module is a module which is
|
||||
not derived from or based on this library. If you modify this library,
|
||||
you must extend this exception to your version of the library.
|
||||
|
||||
See COPYING file for the full LGPL text.
|
||||
|
||||
## launcher (`libraries/launcher`)
|
||||
|
||||
PolyMC - Minecraft Launcher
|
||||
|
|
@ -338,6 +362,28 @@
|
|||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## gulrak/filesystem
|
||||
|
||||
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## Breeze icons
|
||||
|
||||
Copyright (C) 2014 Uri Herrera <uri_herrera@nitrux.in> and others
|
||||
|
|
@ -379,44 +425,3 @@
|
|||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
## libqrencode (`fukuchi/libqrencode`)
|
||||
|
||||
Copyright (C) 2020 libqrencode Authors
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
## vcpkg (`cmake/vcpkg-ports`)
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies
|
||||
or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
ARG DEBIAN_VERSION=stable-slim
|
||||
|
||||
FROM docker.io/library/debian:${DEBIAN_VERSION}
|
||||
|
||||
ARG QT_ABI=gcc_64
|
||||
ARG QT_ARCH=
|
||||
ARG QT_HOST=linux
|
||||
ARG QT_TARGET=desktop
|
||||
ARG QT_VERSION=6.10.2
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get --assume-yes upgrade \
|
||||
&& apt-get --assume-yes autopurge
|
||||
|
||||
# Use Adoptium for Java 17
|
||||
RUN apt-get --assume-yes --no-install-recommends install \
|
||||
apt-transport-https ca-certificates curl gpg
|
||||
RUN curl -L https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg
|
||||
RUN echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
|
||||
RUN apt-get update
|
||||
|
||||
# Install base dependencies
|
||||
RUN apt-get --assume-yes --no-install-recommends install \
|
||||
# Compilers
|
||||
clang lld llvm temurin-17-jdk \
|
||||
# Build system
|
||||
cmake ninja-build extra-cmake-modules pkg-config \
|
||||
# Dependencies
|
||||
cmark gamemode-dev libarchive-dev libcmark-dev libgamemode0 libgl1-mesa-dev libqrencode-dev libtomlplusplus-dev scdoc zlib1g-dev \
|
||||
# Tooling
|
||||
clang-format clang-tidy git
|
||||
|
||||
# Use LLD by default for faster linking
|
||||
ENV CMAKE_LINKER_TYPE=lld
|
||||
|
||||
# Prepare and install Qt
|
||||
## Setup UTF-8 locale (required, apparently)
|
||||
RUN apt-get --assume-yes --no-install-recommends install locales
|
||||
RUN echo "C.UTF-8 UTF-8" > /etc/locale.gen
|
||||
RUN locale-gen
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
## Some libraries are required for the official binaries
|
||||
RUN apt-get --assume-yes --no-install-recommends install \
|
||||
libglib2.0-0t64 libxkbcommon0 python3-pip
|
||||
|
||||
RUN pip3 install --break-system-packages aqtinstall
|
||||
RUN aqt install-qt \
|
||||
${QT_HOST} ${QT_TARGET} ${QT_VERSION} ${QT_ARCH} \
|
||||
--outputdir /opt/qt \
|
||||
--modules qtimageformats qtnetworkauth
|
||||
|
||||
ENV PATH=/opt/qt/${QT_VERSION}/${QT_ABI}/bin:$PATH
|
||||
ENV QT_PLUGIN_PATH=/opt/qt/${QT_VERSION}/${QT_ABI}/plugins/
|
||||
|
||||
## We don't use these. Nuke them
|
||||
RUN rm -rf \
|
||||
"$QT_PLUGIN_PATH"/designer \
|
||||
"$QT_PLUGIN_PATH"/help \
|
||||
# "$QT_PLUGIN_PATH"/platformthemes/libqgtk3.so \
|
||||
"$QT_PLUGIN_PATH"/printsupport \
|
||||
"$QT_PLUGIN_PATH"/qmllint \
|
||||
"$QT_PLUGIN_PATH"/qmlls \
|
||||
"$QT_PLUGIN_PATH"/qmltooling \
|
||||
"$QT_PLUGIN_PATH"/sqldrivers
|
||||
|
||||
# Setup workspace
|
||||
RUN mkdir /work
|
||||
WORKDIR /work
|
||||
|
||||
ENTRYPOINT ["bash"]
|
||||
CMD ["-i"]
|
||||
25
README.md
25
README.md
|
|
@ -26,14 +26,18 @@ Please understand that these builds are not intended for most users. There may b
|
|||
|
||||
There are development builds available through:
|
||||
|
||||
- [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contributors)
|
||||
- [nightly.link](https://prismlauncher.org/nightly) (this will always point only to the latest version of develop)
|
||||
- [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contribuitors)
|
||||
- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/trigger_builds/develop) (this will always point only to the latest version of develop)
|
||||
|
||||
These have debug information in the binaries, so their file sizes are relatively larger.
|
||||
|
||||
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
|
||||
|
||||
On Linux, we also offer our own [Flatpak nightly repository](https://github.com/PrismLauncher/flatpak). Most software centers are able to install it by opening [this link](https://flatpak.prismlauncher.org/prismlauncher-nightly.flatpakref).
|
||||
For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
|
||||
|
||||
[](https://aur.archlinux.org/packages/prismlauncher-git) [](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [](https://build.opensuse.org/project/show/home:getchoo) [](https://packages.gentoo.org/packages/games-action/prismlauncher)
|
||||
|
||||
These packages are also available to all the distributions based on the ones mentioned above.
|
||||
|
||||
## Community & Support
|
||||
|
||||
|
|
@ -57,7 +61,12 @@ The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.
|
|||
|
||||
## Building
|
||||
|
||||
If you want to build Prism Launcher yourself, check the [build instructions](https://prismlauncher.org/wiki/development/build-instructions).
|
||||
If you want to build Prism Launcher yourself, check the build instructions:
|
||||
|
||||
- [Windows](https://prismlauncher.org/wiki/development/build-instructions/windows/)
|
||||
- [Linux](https://prismlauncher.org/wiki/development/build-instructions/linux/)
|
||||
- [MacOS](https://prismlauncher.org/wiki/development/build-instructions/macos/)
|
||||
- [OpenBSD](https://prismlauncher.org/wiki/development/build-instructions/openbsd/)
|
||||
|
||||
## Sponsors & Partners
|
||||
|
||||
|
|
@ -67,13 +76,7 @@ We thank all the wonderful backers over at Open Collective! Support Prism Launch
|
|||
|
||||
Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
|
||||
|
||||
<a href="https://jb.gg/OpenSource">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://www.jetbrains.com/company/brand/img/logo_jb_dos_4.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg">
|
||||
<img alt="JetBrains logo" src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" width="40%">
|
||||
</picture>
|
||||
</a>
|
||||
[](https://www.jetbrains.com/opensource/)
|
||||
|
||||
Thanks to Weblate for hosting our translation efforts.
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
#include <qstringliteral.h>
|
||||
#include "BuildConfig.h"
|
||||
#include <QObject>
|
||||
|
||||
const Config BuildConfig;
|
||||
|
||||
|
|
@ -48,16 +49,15 @@ Config::Config()
|
|||
LAUNCHER_DOMAIN = "@Launcher_Domain@";
|
||||
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
|
||||
LAUNCHER_GIT = "@Launcher_Git@";
|
||||
LAUNCHER_APPID = "@Launcher_AppID@";
|
||||
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
|
||||
LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@";
|
||||
LAUNCHER_ENVNAME = "@Launcher_ENVName@";
|
||||
|
||||
USER_AGENT = "@Launcher_UserAgent@";
|
||||
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
|
||||
|
||||
// Version information
|
||||
VERSION_MAJOR = @Launcher_VERSION_MAJOR@;
|
||||
VERSION_MINOR = @Launcher_VERSION_MINOR@;
|
||||
VERSION_PATCH = @Launcher_VERSION_PATCH@;
|
||||
|
||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||
BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@";
|
||||
|
|
@ -74,13 +74,14 @@ Config::Config()
|
|||
MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@";
|
||||
MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@";
|
||||
|
||||
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty()) {
|
||||
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty())
|
||||
{
|
||||
UPDATER_ENABLED = true;
|
||||
} else if (!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
|
||||
} else if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
|
||||
UPDATER_ENABLED = true;
|
||||
}
|
||||
|
||||
#cmakedefine01 Launcher_ENABLE_JAVA_DOWNLOADER
|
||||
#cmakedefine01 Launcher_ENABLE_JAVA_DOWNLOADER
|
||||
JAVA_DOWNLOADER_ENABLED = Launcher_ENABLE_JAVA_DOWNLOADER;
|
||||
|
||||
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
||||
|
|
@ -88,32 +89,39 @@ Config::Config()
|
|||
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
||||
|
||||
// Assume that builds outside of Git repos are "stable"
|
||||
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND") || GIT_TAG == QStringLiteral("GITDIR-NOTFOUND") ||
|
||||
GIT_REFSPEC == QStringLiteral("") || GIT_TAG == QStringLiteral("GIT-NOTFOUND")) {
|
||||
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|
||||
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")
|
||||
|| GIT_REFSPEC == QStringLiteral("")
|
||||
|| GIT_TAG == QStringLiteral("GIT-NOTFOUND"))
|
||||
{
|
||||
GIT_REFSPEC = "refs/heads/stable";
|
||||
GIT_TAG = versionString();
|
||||
GIT_COMMIT = "";
|
||||
}
|
||||
|
||||
if (GIT_REFSPEC.startsWith("refs/heads/")) {
|
||||
if (GIT_REFSPEC.startsWith("refs/heads/"))
|
||||
{
|
||||
VERSION_CHANNEL = GIT_REFSPEC;
|
||||
VERSION_CHANNEL.remove("refs/heads/");
|
||||
} else if (!GIT_COMMIT.isEmpty()) {
|
||||
VERSION_CHANNEL.remove("refs/heads/");
|
||||
}
|
||||
else if (!GIT_COMMIT.isEmpty())
|
||||
{
|
||||
VERSION_CHANNEL = GIT_COMMIT.mid(0, 8);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
VERSION_CHANNEL = "unknown";
|
||||
}
|
||||
|
||||
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
|
||||
NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
|
||||
WIKI_URL = "@Launcher_WIKI_URL@";
|
||||
HELP_URL = "@Launcher_HELP_URL@";
|
||||
LOGIN_CALLBACK_URL = "@Launcher_LOGIN_CALLBACK_URL@";
|
||||
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
||||
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
||||
FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
|
||||
META_URL = "@Launcher_META_URL@";
|
||||
LEGACY_FMLLIBS_BASE_URL = "@Launcher_LEGACY_FMLLIBS_BASE_URL@";
|
||||
FMLLIBS_BASE_URL = "@Launcher_FMLLIBS_BASE_URL@";
|
||||
|
||||
GLFW_LIBRARY_NAME = "@Launcher_GLFW_LIBRARY_NAME@";
|
||||
OPENAL_LIBRARY_NAME = "@Launcher_OPENAL_LIBRARY_NAME@";
|
||||
|
|
@ -128,7 +136,7 @@ Config::Config()
|
|||
|
||||
QString Config::versionString() const
|
||||
{
|
||||
return QString("%1.%2.%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_PATCH);
|
||||
return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR);
|
||||
}
|
||||
|
||||
QString Config::printableVersionString() const
|
||||
|
|
@ -136,7 +144,8 @@ QString Config::printableVersionString() const
|
|||
QString vstr = versionString();
|
||||
|
||||
// If the build is not a main release, append the channel
|
||||
if (VERSION_CHANNEL != "stable" && GIT_TAG != vstr) {
|
||||
if(VERSION_CHANNEL != "stable" && GIT_TAG != vstr)
|
||||
{
|
||||
vstr += "-" + VERSION_CHANNEL;
|
||||
}
|
||||
return vstr;
|
||||
|
|
@ -153,3 +162,4 @@ QString Config::systemID() const
|
|||
{
|
||||
return QStringLiteral("%1 %2 %3").arg(COMPILER_TARGET_SYSTEM, COMPILER_TARGET_SYSTEM_VERSION, COMPILER_TARGET_SYSTEM_PROCESSOR);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,16 +52,13 @@ class Config {
|
|||
QString LAUNCHER_DOMAIN;
|
||||
QString LAUNCHER_CONFIGFILE;
|
||||
QString LAUNCHER_GIT;
|
||||
QString LAUNCHER_APPID;
|
||||
QString LAUNCHER_DESKTOPFILENAME;
|
||||
QString LAUNCHER_SVGFILENAME;
|
||||
QString LAUNCHER_ENVNAME;
|
||||
|
||||
/// The major version number.
|
||||
int VERSION_MAJOR;
|
||||
/// The minor version number.
|
||||
int VERSION_MINOR;
|
||||
/// The patch version number.
|
||||
int VERSION_PATCH;
|
||||
|
||||
/**
|
||||
* The version channel
|
||||
|
|
@ -108,6 +105,9 @@ class Config {
|
|||
/// User-Agent to use.
|
||||
QString USER_AGENT;
|
||||
|
||||
/// User-Agent to use for uncached requests.
|
||||
QString USER_AGENT_UNCACHED;
|
||||
|
||||
/// The git commit hash of this build
|
||||
QString GIT_COMMIT;
|
||||
|
||||
|
|
@ -129,12 +129,7 @@ class Config {
|
|||
QString NEWS_OPEN_URL;
|
||||
|
||||
/**
|
||||
* URL that gets opened when the user clicks 'Launcher Help'
|
||||
*/
|
||||
QString WIKI_URL;
|
||||
|
||||
/**
|
||||
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help in a dialog window
|
||||
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help
|
||||
*/
|
||||
QString HELP_URL;
|
||||
|
||||
|
|
@ -172,13 +167,13 @@ class Config {
|
|||
QString DISCORD_URL;
|
||||
QString SUBREDDIT_URL;
|
||||
|
||||
QString DEFAULT_RESOURCE_BASE = "https://resources.download.minecraft.net/";
|
||||
QString RESOURCE_BASE = "https://resources.download.minecraft.net/";
|
||||
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
|
||||
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
|
||||
QString LEGACY_FMLLIBS_BASE_URL;
|
||||
QString FMLLIBS_BASE_URL;
|
||||
QString TRANSLATION_FILES_URL;
|
||||
|
||||
QString FTB_API_BASE_URL = "https://api.feed-the-beast.com/v1/modpacks/public";
|
||||
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
|
||||
|
||||
QString LEGACY_FTB_CDN_BASE_URL = "https://dist.creeper.host/FTB2/";
|
||||
|
||||
|
|
@ -194,10 +189,8 @@ class Config {
|
|||
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
|
||||
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
|
||||
QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" };
|
||||
QString MODRINTH_DOWNLOAD_HOST = "cdn.modrinth.com";
|
||||
|
||||
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
|
||||
QString FLAME_DOWNLOAD_HOST = "edge.forgecdn.net";
|
||||
|
||||
QString versionString() const;
|
||||
/**
|
||||
|
|
|
|||
163
cmake/CompilerWarnings.cmake
Normal file
163
cmake/CompilerWarnings.cmake
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
#
|
||||
# Function to set compiler warnings with reasonable defaults at the project level.
|
||||
# Taken from https://github.com/aminya/project_options/blob/main/src/CompilerWarnings.cmake
|
||||
# under the folowing license:
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2022-2100 Amin Yahyaabadi
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
include_guard()
|
||||
|
||||
function(_set_project_warnings_add_target_link_option TARGET OPTIONS)
|
||||
target_link_options(${_project_name} INTERFACE ${OPTIONS})
|
||||
endfunction()
|
||||
|
||||
# Set the compiler warnings
|
||||
#
|
||||
# https://clang.llvm.org/docs/DiagnosticsReference.html
|
||||
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
|
||||
function(
|
||||
set_project_warnings
|
||||
_project_name
|
||||
MSVC_WARNINGS
|
||||
CLANG_WARNINGS
|
||||
GCC_WARNINGS
|
||||
)
|
||||
if("${MSVC_WARNINGS}" STREQUAL "")
|
||||
set(MSVC_WARNINGS
|
||||
/W4 # Baseline reasonable warnings
|
||||
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
|
||||
/w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/w14263 # 'function': member function does not override any base class virtual member function
|
||||
/w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
|
||||
# be destructed correctly
|
||||
/w14287 # 'operator': unsigned/negative constant mismatch
|
||||
/we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
|
||||
# the for-loop scope
|
||||
/w14296 # 'operator': expression is always 'boolean_value'
|
||||
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
|
||||
/w14545 # expression before comma evaluates to a function which is missing an argument list
|
||||
/w14546 # function call before comma missing argument list
|
||||
/w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
|
||||
/w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
|
||||
/w14555 # expression has no effect; expected expression with side- effect
|
||||
/w14619 # pragma warning: there is no warning number 'number'
|
||||
/w14640 # Enable warning on thread un-safe static member initialization
|
||||
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
|
||||
/w14905 # wide string literal cast to 'LPSTR'
|
||||
/w14906 # string literal cast to 'LPWSTR'
|
||||
/w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
|
||||
/permissive- # standards conformance mode for MSVC compiler.
|
||||
|
||||
/we4062 # forbid omitting a possible value of an enum in a switch statement
|
||||
)
|
||||
endif()
|
||||
|
||||
if("${CLANG_WARNINGS}" STREQUAL "")
|
||||
set(CLANG_WARNINGS
|
||||
-Wall
|
||||
-Wextra # reasonable and standard
|
||||
-Wshadow # warn the user if a variable declaration shadows one from a parent context
|
||||
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
|
||||
# catch hard to track down memory errors
|
||||
-Wold-style-cast # warn for c-style casts
|
||||
-Wcast-align # warn for potential performance problem casts
|
||||
-Wunused # warn on anything being unused
|
||||
-Woverloaded-virtual # warn if you overload (not override) a virtual function
|
||||
-Wpedantic # warn if non-standard C++ is used
|
||||
-Wconversion # warn on type conversions that may lose data
|
||||
-Wsign-conversion # warn on sign conversions
|
||||
-Wnull-dereference # warn if a null dereference is detected
|
||||
-Wdouble-promotion # warn if float is implicit promoted to double
|
||||
-Wformat=2 # warn on security issues around functions that format output (ie printf)
|
||||
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
|
||||
# -Wgnu-zero-variadic-macro-arguments (part of -pedantic) is triggered by every qCDebug() call and therefore results
|
||||
# in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour
|
||||
# instead of the exact standard wording so we can safely ignore it
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
|
||||
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
|
||||
)
|
||||
endif()
|
||||
|
||||
if("${GCC_WARNINGS}" STREQUAL "")
|
||||
set(GCC_WARNINGS
|
||||
${CLANG_WARNINGS}
|
||||
-Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
|
||||
-Wduplicated-cond # warn if if / else chain has duplicated conditions
|
||||
-Wduplicated-branches # warn if if / else branches have duplicated code
|
||||
-Wlogical-op # warn about logical operations being used where bitwise were probably wanted
|
||||
-Wuseless-cast # warn if you perform a cast to the same type
|
||||
|
||||
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(PROJECT_WARNINGS_CXX ${MSVC_WARNINGS})
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||
set(PROJECT_WARNINGS_CXX ${CLANG_WARNINGS})
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(PROJECT_WARNINGS_CXX ${GCC_WARNINGS})
|
||||
else()
|
||||
message(AUTHOR_WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
|
||||
# TODO support Intel compiler
|
||||
endif()
|
||||
|
||||
# Add C warnings
|
||||
set(PROJECT_WARNINGS_C "${PROJECT_WARNINGS_CXX}")
|
||||
list(
|
||||
REMOVE_ITEM
|
||||
PROJECT_WARNINGS_C
|
||||
-Wnon-virtual-dtor
|
||||
-Wold-style-cast
|
||||
-Woverloaded-virtual
|
||||
-Wuseless-cast
|
||||
-Wextra-semi
|
||||
|
||||
-Werror=switch # forbid omitting a possible value of an enum in a switch statement
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
${_project_name}
|
||||
INTERFACE # C++ warnings
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
|
||||
# C warnings
|
||||
$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>
|
||||
)
|
||||
|
||||
# If we are using the compiler as a linker driver pass the warnings to it
|
||||
# (most useful when using LTO or warnings as errors)
|
||||
if(CMAKE_CXX_LINK_EXECUTABLE MATCHES "^<CMAKE_CXX_COMPILER>")
|
||||
_set_project_warnings_add_target_link_option(
|
||||
${_project_name} "$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_LINK_EXECUTABLE MATCHES "^<CMAKE_C_COMPILER>")
|
||||
_set_project_warnings_add_target_link_option(
|
||||
${_project_name} "$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>"
|
||||
)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
100
cmake/ECMQueryQt.cmake
Normal file
100
cmake/ECMQueryQt.cmake
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# SPDX-FileCopyrightText: 2014 Rohan Garg <rohan16garg@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
||||
# SPDX-FileCopyrightText: 2014-2016 Aleix Pol <aleixpol@kde.org>
|
||||
# SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
|
||||
# SPDX-FileCopyrightText: 2022 Ahmad Samir <a.samir78@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#[=======================================================================[.rst:
|
||||
ECMQueryQt
|
||||
---------------
|
||||
This module can be used to query the installation paths used by Qt.
|
||||
|
||||
For Qt5 this uses ``qmake``, and for Qt6 this used ``qtpaths`` (the latter has built-in
|
||||
support to query the paths of a target platform when cross-compiling).
|
||||
|
||||
This module defines the following function:
|
||||
::
|
||||
|
||||
ecm_query_qt(<result_variable> <qt_variable> [TRY])
|
||||
|
||||
Passing ``TRY`` will result in the method not making the build fail if the executable
|
||||
used for querying has not been found, but instead simply print a warning message and
|
||||
return an empty string.
|
||||
|
||||
Example usage:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
include(ECMQueryQt)
|
||||
ecm_query_qt(bin_dir QT_INSTALL_BINS)
|
||||
|
||||
If the call succeeds ``${bin_dir}`` will be set to ``<prefix>/path/to/bin/dir`` (e.g.
|
||||
``/usr/lib64/qt/bin/``).
|
||||
|
||||
Since: 5.93
|
||||
#]=======================================================================]
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/QtVersionOption.cmake)
|
||||
include(CheckLanguage)
|
||||
check_language(CXX)
|
||||
if (CMAKE_CXX_COMPILER)
|
||||
# Enable the CXX language to let CMake look for config files in library dirs.
|
||||
# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23266
|
||||
enable_language(CXX)
|
||||
endif()
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
# QUIET to accommodate the TRY option
|
||||
find_package(Qt${QT_MAJOR_VERSION}Core QUIET)
|
||||
if(TARGET Qt5::qmake)
|
||||
get_target_property(_qmake_executable_default Qt5::qmake LOCATION)
|
||||
|
||||
set(QUERY_EXECUTABLE ${_qmake_executable_default}
|
||||
CACHE FILEPATH "Location of the Qt5 qmake executable")
|
||||
set(_exec_name_text "Qt5 qmake")
|
||||
set(_cli_option "-query")
|
||||
endif()
|
||||
elseif(QT_MAJOR_VERSION STREQUAL "6")
|
||||
# QUIET to accommodate the TRY option
|
||||
find_package(Qt6 COMPONENTS CoreTools QUIET CONFIG)
|
||||
if (TARGET Qt6::qtpaths)
|
||||
get_target_property(_qtpaths_executable Qt6::qtpaths LOCATION)
|
||||
|
||||
set(QUERY_EXECUTABLE ${_qtpaths_executable}
|
||||
CACHE FILEPATH "Location of the Qt6 qtpaths executable")
|
||||
set(_exec_name_text "Qt6 qtpaths")
|
||||
set(_cli_option "--query")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(ecm_query_qt result_variable qt_variable)
|
||||
set(options TRY)
|
||||
set(oneValueArgs)
|
||||
set(multiValueArgs)
|
||||
|
||||
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT QUERY_EXECUTABLE)
|
||||
if(ARGS_TRY)
|
||||
set(${result_variable} "" PARENT_SCOPE)
|
||||
message(STATUS "No ${_exec_name_text} executable found. Can't check ${qt_variable}")
|
||||
return()
|
||||
else()
|
||||
message(FATAL_ERROR "No ${_exec_name_text} executable found. Can't check ${qt_variable} as required")
|
||||
endif()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${QUERY_EXECUTABLE} ${_cli_option} "${qt_variable}"
|
||||
RESULT_VARIABLE return_code
|
||||
OUTPUT_VARIABLE output
|
||||
)
|
||||
if(return_code EQUAL 0)
|
||||
string(STRIP "${output}" output)
|
||||
file(TO_CMAKE_PATH "${output}" output_path)
|
||||
set(${result_variable} "${output_path}" PARENT_SCOPE)
|
||||
else()
|
||||
message(WARNING "Failed call: ${_command} \"${qt_variable}\"")
|
||||
message(FATAL_ERROR "${_exec_name_text} call failed: ${return_code}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>A Minecraft mod wants to access your microphone.</string>
|
||||
<key>NSDownloadsFolderUsageDescription</key>
|
||||
<string>${Launcher_DisplayName} uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where ${Launcher_DisplayName} scans for downloaded mods in Settings or the prompt that appears.</string>
|
||||
<string>Prism uses access to your Downloads folder to help you more quickly add mods that can't be automatically downloaded to your instance. You can change where Prism scans for downloaded mods in Settings or the prompt that appears.</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>Minecraft uses the local network to find and connect to LAN servers.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
|
@ -21,9 +21,7 @@
|
|||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${Launcher_Name}</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>${Launcher_Name}</string>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
|
@ -44,8 +42,6 @@
|
|||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>SUPublicEDKey</key>
|
||||
|
|
@ -61,7 +57,7 @@
|
|||
<string>mrpack</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>${Launcher_DisplayName} instance</string>
|
||||
<string>Prism Launcher instance</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>TEXT</string>
|
||||
|
|
@ -87,11 +83,10 @@
|
|||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>${Launcher_Name}</string>
|
||||
<string>Prismlauncher</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>prismlauncher</string>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
|
|
|||
38
cmake/QtVersionOption.cmake
Normal file
38
cmake/QtVersionOption.cmake
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#.rst:
|
||||
# QtVersionOption
|
||||
# ---------------
|
||||
#
|
||||
# Adds a build option to select the major Qt version if necessary,
|
||||
# that is, if the major Qt version has not yet been determined otherwise
|
||||
# (e.g. by a corresponding find_package() call).
|
||||
#
|
||||
# This module is typically included by other modules requiring knowledge
|
||||
# about the major Qt version.
|
||||
#
|
||||
# ``QT_MAJOR_VERSION`` is defined to either be "5" or "6".
|
||||
#
|
||||
#
|
||||
# Since 5.82.0.
|
||||
|
||||
#=============================================================================
|
||||
# SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if (DEFINED QT_MAJOR_VERSION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (TARGET Qt5::Core)
|
||||
set(QT_MAJOR_VERSION 5)
|
||||
elseif (TARGET Qt6::Core)
|
||||
set(QT_MAJOR_VERSION 6)
|
||||
else()
|
||||
option(BUILD_WITH_QT6 "Build against Qt 6" OFF)
|
||||
|
||||
if (BUILD_WITH_QT6)
|
||||
set(QT_MAJOR_VERSION 6)
|
||||
else()
|
||||
set(QT_MAJOR_VERSION 5)
|
||||
endif()
|
||||
endif()
|
||||
97
cmake/QtVersionlessBackport.cmake
Normal file
97
cmake/QtVersionlessBackport.cmake
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#=============================================================================
|
||||
# Copyright 2005-2011 Kitware, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the name of Kitware, Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
# From Qt5CoreMacros.cmake
|
||||
|
||||
function(qt_generate_moc)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_generate_moc(${ARGV})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_generate_moc(${ARGV})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_wrap_cpp outfiles)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_wrap_cpp("${outfiles}" ${ARGN})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_wrap_cpp("${outfiles}" ${ARGN})
|
||||
endif()
|
||||
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_add_binary_resources)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_add_binary_resources(${ARGV})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_add_binary_resources(${ARGV})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_add_resources outfiles)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_add_resources("${outfiles}" ${ARGN})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_add_resources("${outfiles}" ${ARGN})
|
||||
endif()
|
||||
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_add_big_resources outfiles)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_add_big_resources(${outfiles} ${ARGN})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_add_big_resources(${outfiles} ${ARGN})
|
||||
endif()
|
||||
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_import_plugins)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_import_plugins(${ARGV})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_import_plugins(${ARGV})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# From Qt5WidgetsMacros.cmake
|
||||
|
||||
function(qt_wrap_ui outfiles)
|
||||
if(QT_VERSION_MAJOR EQUAL 5)
|
||||
qt5_wrap_ui("${outfiles}" ${ARGN})
|
||||
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt6_wrap_ui("${outfiles}" ${ARGN})
|
||||
endif()
|
||||
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
The only difference between this and the upstream vcpkg port is the addition of `universal-osx.patch`. It's very annoying we need to bundle this entire tree to do that.
|
||||
|
||||
-@getchoo
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py
|
||||
index 11a00be5d..89ae490ff 100644
|
||||
--- a/mesonbuild/cmake/toolchain.py
|
||||
+++ b/mesonbuild/cmake/toolchain.py
|
||||
@@ -202,7 +202,7 @@ class CMakeToolchain:
|
||||
@staticmethod
|
||||
def is_cmdline_option(compiler: 'Compiler', arg: str) -> bool:
|
||||
if compiler.get_argument_syntax() == 'msvc':
|
||||
- return arg.startswith('/')
|
||||
+ return arg.startswith(('/','-'))
|
||||
else:
|
||||
if os.path.basename(compiler.get_exe()) == 'zig' and arg in {'ar', 'cc', 'c++', 'dlltool', 'lib', 'ranlib', 'objcopy', 'rc'}:
|
||||
return True
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py
|
||||
index 883a29a..d9a82af 100644
|
||||
--- a/mesonbuild/dependencies/python.py
|
||||
+++ b/mesonbuild/dependencies/python.py
|
||||
@@ -232,8 +232,10 @@ class _PythonDependencyBase(_Base):
|
||||
else:
|
||||
if self.is_freethreaded:
|
||||
libpath = Path('libs') / f'python{vernum}t.lib'
|
||||
+ libpath = Path('libs') / f'..' / f'..' / f'..' / f'lib' / f'python{vernum}t.lib'
|
||||
else:
|
||||
libpath = Path('libs') / f'python{vernum}.lib'
|
||||
+ libpath = Path('libs') / f'..' / f'..' / f'..' / f'lib' / f'python{vernum}.lib'
|
||||
# For a debug build, pyconfig.h may force linking with
|
||||
# pythonX_d.lib (see meson#10776). This cannot be avoided
|
||||
# and won't work unless we also have a debug build of
|
||||
@@ -250,6 +252,8 @@ class _PythonDependencyBase(_Base):
|
||||
vscrt = self.env.coredata.optstore.get_value('b_vscrt')
|
||||
if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}:
|
||||
vscrt_debug = True
|
||||
+ if is_debug_build:
|
||||
+ libpath = Path('libs') / f'..' / f'..' / f'..' / f'debug/lib' / f'python{vernum}_d.lib'
|
||||
if is_debug_build and vscrt_debug and not self.variables.get('Py_DEBUG'):
|
||||
mlog.warning(textwrap.dedent('''\
|
||||
Using a debug build type with MSVC or an MSVC-compatible compiler
|
||||
@@ -350,9 +354,10 @@ class PythonSystemDependency(SystemDependency, _PythonDependencyBase):
|
||||
self.is_found = True
|
||||
|
||||
# compile args
|
||||
+ verdot = self.variables.get('py_version_short')
|
||||
inc_paths = mesonlib.OrderedSet([
|
||||
self.variables.get('INCLUDEPY'),
|
||||
- self.paths.get('include'),
|
||||
+ self.paths.get('include') + f'/../../../include/python${verdot}',
|
||||
self.paths.get('platinclude')])
|
||||
|
||||
self.compile_args += ['-I' + path for path in inc_paths if path]
|
||||
@@ -416,7 +421,7 @@ def python_factory(env: 'Environment', for_machine: 'MachineChoice',
|
||||
candidates.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation))
|
||||
# We only need to check both, if a python install has a LIBPC. It might point to the wrong location,
|
||||
# e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something.
|
||||
- if pkg_libdir is not None:
|
||||
+ if True or pkg_libdir is not None:
|
||||
candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation))
|
||||
else:
|
||||
candidates.append(functools.partial(PkgConfigDependency, 'python3', env, kwargs))
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
From a16ec8b0fb6d7035b669a13edd4d97ff0c307a0b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Martin=20D=C3=B8rum?= <martid0311@gmail.com>
|
||||
Date: Fri, 2 May 2025 10:56:28 +0200
|
||||
Subject: [PATCH] cpp: fix _LIBCPP_ENABLE_ASSERTIONS warning
|
||||
|
||||
libc++ deprecated _LIBCPP_ENABLE_ASSERTIONS from version 18.
|
||||
However, the libc++ shipped with Apple Clang backported that
|
||||
deprecation in version 17 already,
|
||||
which is the version which Apple currently ships for macOS.
|
||||
This PR changes the _LIBCPP_ENABLE_ASSERTIONS deprecation check
|
||||
to use version ">=17" on Apple Clang.
|
||||
---
|
||||
mesonbuild/compilers/cpp.py | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
|
||||
index 01b9bb9fa34f..f7dc150e8608 100644
|
||||
--- a/mesonbuild/compilers/cpp.py
|
||||
+++ b/mesonbuild/compilers/cpp.py
|
||||
@@ -311,6 +311,9 @@ def get_option_link_args(self, target: 'BuildTarget', env: 'Environment', subpro
|
||||
return libs
|
||||
return []
|
||||
|
||||
+ def is_libcpp_enable_assertions_deprecated(self) -> bool:
|
||||
+ return version_compare(self.version, ">=18")
|
||||
+
|
||||
def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]:
|
||||
if disable:
|
||||
return ['-DNDEBUG']
|
||||
@@ -323,7 +326,7 @@ def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]:
|
||||
if self.language_stdlib_provider(env) == 'stdc++':
|
||||
return ['-D_GLIBCXX_ASSERTIONS=1']
|
||||
else:
|
||||
- if version_compare(self.version, '>=18'):
|
||||
+ if self.is_libcpp_enable_assertions_deprecated():
|
||||
return ['-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST']
|
||||
elif version_compare(self.version, '>=15'):
|
||||
return ['-D_LIBCPP_ENABLE_ASSERTIONS=1']
|
||||
@@ -343,7 +346,12 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler):
|
||||
|
||||
|
||||
class AppleClangCPPCompiler(AppleCompilerMixin, AppleCPPStdsMixin, ClangCPPCompiler):
|
||||
- pass
|
||||
+ def is_libcpp_enable_assertions_deprecated(self) -> bool:
|
||||
+ # Upstream libc++ deprecated _LIBCPP_ENABLE_ASSERTIONS
|
||||
+ # in favor of _LIBCPP_HARDENING_MODE from version 18 onwards,
|
||||
+ # but Apple Clang 17's libc++ has back-ported that change.
|
||||
+ # See: https://github.com/mesonbuild/meson/issues/14440
|
||||
+ return version_compare(self.version, ">=17")
|
||||
|
||||
|
||||
class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/tools/meson")
|
||||
file(INSTALL "${SOURCE_PATH}/meson.py"
|
||||
"${SOURCE_PATH}/mesonbuild"
|
||||
DESTINATION "${CURRENT_PACKAGES_DIR}/tools/meson"
|
||||
)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
|
||||
--- a/mesonbuild/dependencies/misc.py
|
||||
+++ b/mesonbuild/dependencies/misc.py
|
||||
@@ -593,7 +593,8 @@ iconv_factory = DependencyFactory(
|
||||
|
||||
packages['intl'] = intl_factory = DependencyFactory(
|
||||
'intl',
|
||||
+ [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
|
||||
+ cmake_name='Intl',
|
||||
- [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
|
||||
builtin_class=IntlBuiltinDependency,
|
||||
system_class=IntlSystemDependency,
|
||||
)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
[binaries]
|
||||
cmake = ['@CMAKE_COMMAND@']
|
||||
ninja = ['@NINJA@']
|
||||
pkg-config = ['@PKGCONFIG@']
|
||||
@MESON_MT@
|
||||
@MESON_AR@
|
||||
@MESON_RC@
|
||||
@MESON_C@
|
||||
@MESON_C_LD@
|
||||
@MESON_CXX@
|
||||
@MESON_CXX_LD@
|
||||
@MESON_OBJC@
|
||||
@MESON_OBJC_LD@
|
||||
@MESON_OBJCPP@
|
||||
@MESON_OBJCPP_LD@
|
||||
@MESON_FC@
|
||||
@MESON_FC_LD@
|
||||
@MESON_WINDRES@
|
||||
@MESON_ADDITIONAL_BINARIES@
|
||||
[properties]
|
||||
cmake_toolchain_file = '@SCRIPTS@/buildsystems/vcpkg.cmake'
|
||||
@MESON_ADDITIONAL_PROPERTIES@
|
||||
[cmake]
|
||||
CMAKE_BUILD_TYPE = '@MESON_CMAKE_BUILD_TYPE@'
|
||||
VCPKG_TARGET_TRIPLET = '@TARGET_TRIPLET@'
|
||||
VCPKG_HOST_TRIPLET = '@_HOST_TRIPLET@'
|
||||
VCPKG_CHAINLOAD_TOOLCHAIN_FILE = '@VCPKG_CHAINLOAD_TOOLCHAIN_FILE@'
|
||||
VCPKG_CRT_LINKAGE = '@VCPKG_CRT_LINKAGE@'
|
||||
_VCPKG_INSTALLED_DIR = '@_VCPKG_INSTALLED_DIR@'
|
||||
@MESON_HOST_MACHINE@
|
||||
@MESON_BUILD_MACHINE@
|
||||
[built-in options]
|
||||
default_library = '@MESON_DEFAULT_LIBRARY@'
|
||||
werror = false
|
||||
@MESON_CFLAGS@
|
||||
@MESON_CXXFLAGS@
|
||||
@MESON_FCFLAGS@
|
||||
@MESON_OBJCFLAGS@
|
||||
@MESON_OBJCPPFLAGS@
|
||||
# b_vscrt
|
||||
@MESON_VSCRT_LINKAGE@
|
||||
# c_winlibs/cpp_winlibs
|
||||
@MESON_WINLIBS@
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# This port represents a dependency on the Meson build system.
|
||||
# In the future, it is expected that this port acquires and installs Meson.
|
||||
# Currently is used in ports that call vcpkg_find_acquire_program(MESON) in order to force rebuilds.
|
||||
|
||||
set(VCPKG_POLICY_CMAKE_HELPER_PORT enabled)
|
||||
|
||||
set(patches
|
||||
meson-intl.patch
|
||||
adjust-python-dep.patch
|
||||
adjust-args.patch
|
||||
remove-freebsd-pcfile-specialization.patch
|
||||
fix-libcpp-enable-assertions.patch # https://github.com/mesonbuild/meson/pull/14548, Remove in 1.8.3
|
||||
universal-osx.patch # NOTE(@getchoo): THIS IS THE ONLY CHANGE NEEDED FOR PRISM
|
||||
)
|
||||
set(scripts
|
||||
vcpkg-port-config.cmake
|
||||
vcpkg_configure_meson.cmake
|
||||
vcpkg_install_meson.cmake
|
||||
meson.template.in
|
||||
)
|
||||
set(to_hash
|
||||
"${CMAKE_CURRENT_LIST_DIR}/vcpkg.json"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/portfile.cmake"
|
||||
)
|
||||
foreach(file IN LISTS patches scripts)
|
||||
set(filepath "${CMAKE_CURRENT_LIST_DIR}/${file}")
|
||||
list(APPEND to_hash "${filepath}")
|
||||
file(COPY "${filepath}" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
|
||||
endforeach()
|
||||
|
||||
set(meson_path_hash "")
|
||||
foreach(filepath IN LISTS to_hash)
|
||||
file(SHA1 "${filepath}" to_append)
|
||||
string(APPEND meson_path_hash "${to_append}")
|
||||
endforeach()
|
||||
string(SHA512 meson_path_hash "${meson_path_hash}")
|
||||
|
||||
string(SUBSTRING "${meson_path_hash}" 0 6 MESON_SHORT_HASH)
|
||||
list(TRANSFORM patches REPLACE [[^(..*)$]] [["${CMAKE_CURRENT_LIST_DIR}/\0"]])
|
||||
list(JOIN patches "\n " PATCHES)
|
||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-port-config.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-port-config.cmake" @ONLY)
|
||||
|
||||
vcpkg_install_copyright(FILE_LIST "${VCPKG_ROOT_DIR}/LICENSE.txt")
|
||||
|
||||
include("${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-port-config.cmake")
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
|
||||
index cc0450a52..13501466d 100644
|
||||
--- a/mesonbuild/modules/pkgconfig.py
|
||||
+++ b/mesonbuild/modules/pkgconfig.py
|
||||
@@ -701,16 +701,8 @@ class PkgConfigModule(NewExtensionModule):
|
||||
pcfile = filebase + '.pc'
|
||||
pkgroot = pkgroot_name = kwargs['install_dir'] or default_install_dir
|
||||
if pkgroot is None:
|
||||
- m = state.environment.machines.host
|
||||
- if m.is_freebsd():
|
||||
- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('prefix'))), 'libdata', 'pkgconfig')
|
||||
- pkgroot_name = os.path.join('{prefix}', 'libdata', 'pkgconfig')
|
||||
- elif m.is_haiku():
|
||||
- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('prefix'))), 'develop', 'lib', 'pkgconfig')
|
||||
- pkgroot_name = os.path.join('{prefix}', 'develop', 'lib', 'pkgconfig')
|
||||
- else:
|
||||
- pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('libdir'))), 'pkgconfig')
|
||||
- pkgroot_name = os.path.join('{libdir}', 'pkgconfig')
|
||||
+ pkgroot = os.path.join(_as_str(state.environment.coredata.optstore.get_value_for(OptionKey('libdir'))), 'pkgconfig')
|
||||
+ pkgroot_name = os.path.join('{libdir}', 'pkgconfig')
|
||||
relocatable = state.get_option('pkgconfig.relocatable')
|
||||
self._generate_pkgconfig_file(state, deps, subdirs, name, description, url,
|
||||
version, pcfile, conflicts, variables,
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py
|
||||
index f57957f0b..a72e72a0b 100644
|
||||
--- a/mesonbuild/compilers/detect.py
|
||||
+++ b/mesonbuild/compilers/detect.py
|
||||
@@ -1472,6 +1472,11 @@ def _get_clang_compiler_defines(compiler: T.List[str], lang: str) -> T.Dict[str,
|
||||
"""
|
||||
from .mixins.clang import clang_lang_map
|
||||
|
||||
+ # Filter out `-arch` flags passed to the compiler for Universal Binaries
|
||||
+ # https://github.com/mesonbuild/meson/issues/5290
|
||||
+ # https://github.com/mesonbuild/meson/issues/8206
|
||||
+ compiler = [arg for i, arg in enumerate(compiler) if not (i > 0 and compiler[i - 1] == "-arch") and not arg == "-arch"]
|
||||
+
|
||||
def _try_obtain_compiler_defines(args: T.List[str]) -> str:
|
||||
mlog.debug(f'Running command: {join_args(args)}')
|
||||
p, output, error = Popen_safe(compiler + args, write='', stdin=subprocess.PIPE)
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
include("${CURRENT_HOST_INSTALLED_DIR}/share/vcpkg-cmake-get-vars/vcpkg-port-config.cmake")
|
||||
# Overwrite builtin scripts
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_configure_meson.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_install_meson.cmake")
|
||||
|
||||
set(meson_short_hash @MESON_SHORT_HASH@)
|
||||
|
||||
# Setup meson:
|
||||
set(program MESON)
|
||||
set(program_version @VERSION@)
|
||||
set(program_name meson)
|
||||
set(search_names meson meson.py)
|
||||
set(ref "${program_version}")
|
||||
set(path_to_search "${DOWNLOADS}/tools/meson-${program_version}-${meson_short_hash}")
|
||||
set(download_urls "https://github.com/mesonbuild/meson/archive/${ref}.tar.gz")
|
||||
set(download_filename "meson-${ref}.tar.gz")
|
||||
set(download_sha512 bd2e65f0863d9cb974e659ff502d773e937b8a60aaddfd7d81e34cd2c296c8e82bf214d790ac089ba441543059dfc2677ba95ed51f676df9da420859f404a907)
|
||||
|
||||
find_program(SCRIPT_MESON NAMES ${search_names} PATHS "${path_to_search}" NO_DEFAULT_PATH) # NO_DEFAULT_PATH due top patching
|
||||
|
||||
if(NOT SCRIPT_MESON)
|
||||
vcpkg_download_distfile(archive_path
|
||||
URLS ${download_urls}
|
||||
SHA512 "${download_sha512}"
|
||||
FILENAME "${download_filename}"
|
||||
)
|
||||
file(REMOVE_RECURSE "${path_to_search}")
|
||||
file(REMOVE_RECURSE "${path_to_search}-tmp")
|
||||
file(MAKE_DIRECTORY "${path_to_search}-tmp")
|
||||
file(ARCHIVE_EXTRACT INPUT "${archive_path}"
|
||||
DESTINATION "${path_to_search}-tmp"
|
||||
#PATTERNS "**/mesonbuild/*" "**/*.py"
|
||||
)
|
||||
z_vcpkg_apply_patches(
|
||||
SOURCE_PATH "${path_to_search}-tmp/meson-${ref}"
|
||||
PATCHES
|
||||
@PATCHES@
|
||||
)
|
||||
file(MAKE_DIRECTORY "${path_to_search}")
|
||||
file(RENAME "${path_to_search}-tmp/meson-${ref}/meson.py" "${path_to_search}/meson.py")
|
||||
file(RENAME "${path_to_search}-tmp/meson-${ref}/mesonbuild" "${path_to_search}/mesonbuild")
|
||||
file(REMOVE_RECURSE "${path_to_search}-tmp")
|
||||
set(SCRIPT_MESON "${path_to_search}/meson.py")
|
||||
endif()
|
||||
|
||||
# Check required python version
|
||||
vcpkg_find_acquire_program(PYTHON3)
|
||||
vcpkg_execute_in_download_mode(
|
||||
COMMAND "${PYTHON3}" --version
|
||||
OUTPUT_VARIABLE version_contents
|
||||
WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}"
|
||||
)
|
||||
string(REGEX MATCH [[[0-9]+\.[0-9]+\.[0-9]+]] python_ver "${version_contents}")
|
||||
|
||||
set(min_required 3.7)
|
||||
if(python_ver VERSION_LESS "${min_required}")
|
||||
message(FATAL_ERROR "Found Python version '${python_ver} at ${PYTHON3}' is insufficient for meson. meson requires at least version '${min_required}'")
|
||||
else()
|
||||
message(STATUS "Found Python version '${python_ver} at ${PYTHON3}'")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using meson: ${SCRIPT_MESON}")
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"name": "vcpkg-tool-meson",
|
||||
"version": "1.8.2",
|
||||
"description": "Meson build system",
|
||||
"homepage": "https://github.com/mesonbuild/meson",
|
||||
"license": "Apache-2.0",
|
||||
"supports": "native",
|
||||
"dependencies": [
|
||||
"vcpkg-cmake-get-vars"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,480 +0,0 @@
|
|||
function(z_vcpkg_meson_set_proglist_variables config_type)
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
set(proglist MT AR)
|
||||
else()
|
||||
set(proglist AR RANLIB STRIP NM OBJDUMP DLLTOOL MT)
|
||||
endif()
|
||||
foreach(prog IN LISTS proglist)
|
||||
if(VCPKG_DETECTED_CMAKE_${prog})
|
||||
if(meson_${prog})
|
||||
string(TOUPPER "MESON_${meson_${prog}}" var_to_set)
|
||||
set("${var_to_set}" "${meson_${prog}} = ['${VCPKG_DETECTED_CMAKE_${prog}}']" PARENT_SCOPE)
|
||||
elseif(${prog} STREQUAL AR AND VCPKG_COMBINED_STATIC_LINKER_FLAGS_${config_type})
|
||||
# Probably need to move AR somewhere else
|
||||
string(TOLOWER "${prog}" proglower)
|
||||
z_vcpkg_meson_convert_compiler_flags_to_list(ar_flags "${VCPKG_COMBINED_STATIC_LINKER_FLAGS_${config_type}}")
|
||||
list(PREPEND ar_flags "${VCPKG_DETECTED_CMAKE_${prog}}")
|
||||
z_vcpkg_meson_convert_list_to_python_array(ar_flags ${ar_flags})
|
||||
set("MESON_AR" "${proglower} = ${ar_flags}" PARENT_SCOPE)
|
||||
else()
|
||||
string(TOUPPER "MESON_${prog}" var_to_set)
|
||||
string(TOLOWER "${prog}" proglower)
|
||||
set("${var_to_set}" "${proglower} = ['${VCPKG_DETECTED_CMAKE_${prog}}']" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(compilers "${arg_LANGUAGES}")
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
list(APPEND compilers RC)
|
||||
endif()
|
||||
set(meson_RC windres)
|
||||
set(meson_Fortran fortran)
|
||||
set(meson_CXX cpp)
|
||||
foreach(prog IN LISTS compilers)
|
||||
if(VCPKG_DETECTED_CMAKE_${prog}_COMPILER)
|
||||
string(TOUPPER "MESON_${prog}" var_to_set)
|
||||
if(meson_${prog})
|
||||
if(VCPKG_COMBINED_${prog}_FLAGS_${config_type})
|
||||
# Need compiler flags in prog vars for sanity check.
|
||||
z_vcpkg_meson_convert_compiler_flags_to_list(${prog}flags "${VCPKG_COMBINED_${prog}_FLAGS_${config_type}}")
|
||||
endif()
|
||||
list(PREPEND ${prog}flags "${VCPKG_DETECTED_CMAKE_${prog}_COMPILER}")
|
||||
list(FILTER ${prog}flags EXCLUDE REGEX "(-|/)nologo") # Breaks compiler detection otherwise
|
||||
z_vcpkg_meson_convert_list_to_python_array(${prog}flags ${${prog}flags})
|
||||
set("${var_to_set}" "${meson_${prog}} = ${${prog}flags}" PARENT_SCOPE)
|
||||
if (DEFINED VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID
|
||||
AND NOT VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID MATCHES "^(GNU|Intel)$"
|
||||
AND VCPKG_DETECTED_CMAKE_LINKER)
|
||||
string(TOUPPER "MESON_${prog}_LD" var_to_set)
|
||||
set(${var_to_set} "${meson_${prog}}_ld = ['${VCPKG_DETECTED_CMAKE_LINKER}']" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
if(VCPKG_COMBINED_${prog}_FLAGS_${config_type})
|
||||
# Need compiler flags in prog vars for sanity check.
|
||||
z_vcpkg_meson_convert_compiler_flags_to_list(${prog}flags "${VCPKG_COMBINED_${prog}_FLAGS_${config_type}}")
|
||||
endif()
|
||||
list(PREPEND ${prog}flags "${VCPKG_DETECTED_CMAKE_${prog}_COMPILER}")
|
||||
list(FILTER ${prog}flags EXCLUDE REGEX "(-|/)nologo") # Breaks compiler detection otherwise
|
||||
z_vcpkg_meson_convert_list_to_python_array(${prog}flags ${${prog}flags})
|
||||
string(TOLOWER "${prog}" proglower)
|
||||
set("${var_to_set}" "${proglower} = ${${prog}flags}" PARENT_SCOPE)
|
||||
if (DEFINED VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID
|
||||
AND NOT VCPKG_DETECTED_CMAKE_${prog}_COMPILER_ID MATCHES "^(GNU|Intel)$"
|
||||
AND VCPKG_DETECTED_CMAKE_LINKER)
|
||||
string(TOUPPER "MESON_${prog}_LD" var_to_set)
|
||||
set(${var_to_set} "${proglower}_ld = ['${VCPKG_DETECTED_CMAKE_LINKER}']" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_meson_convert_compiler_flags_to_list out_var compiler_flags)
|
||||
separate_arguments(cmake_list NATIVE_COMMAND "${compiler_flags}")
|
||||
list(TRANSFORM cmake_list REPLACE ";" [[\\;]])
|
||||
set("${out_var}" "${cmake_list}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_meson_convert_list_to_python_array out_var)
|
||||
z_vcpkg_function_arguments(flag_list 1)
|
||||
vcpkg_list(REMOVE_ITEM flag_list "") # remove empty elements if any
|
||||
vcpkg_list(JOIN flag_list "', '" flag_list)
|
||||
set("${out_var}" "['${flag_list}']" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Generates the required compiler properties for meson
|
||||
function(z_vcpkg_meson_set_flags_variables config_type)
|
||||
if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
|
||||
set(libpath_flag /LIBPATH:)
|
||||
else()
|
||||
set(libpath_flag -L)
|
||||
endif()
|
||||
if(config_type STREQUAL "DEBUG")
|
||||
set(path_suffix "/debug")
|
||||
else()
|
||||
set(path_suffix "")
|
||||
endif()
|
||||
|
||||
set(includepath "-I${CURRENT_INSTALLED_DIR}/include")
|
||||
set(libpath "${libpath_flag}${CURRENT_INSTALLED_DIR}${path_suffix}/lib")
|
||||
|
||||
foreach(lang IN LISTS arg_LANGUAGES)
|
||||
z_vcpkg_meson_convert_compiler_flags_to_list(${lang}flags "${VCPKG_COMBINED_${lang}_FLAGS_${config_type}}")
|
||||
if(lang MATCHES "^(C|CXX)$")
|
||||
vcpkg_list(APPEND ${lang}flags "${includepath}")
|
||||
endif()
|
||||
z_vcpkg_meson_convert_list_to_python_array(${lang}flags ${${lang}flags})
|
||||
set(lang_mapping "${lang}")
|
||||
if(lang STREQUAL "Fortran")
|
||||
set(lang_mapping "FC")
|
||||
endif()
|
||||
string(TOLOWER "${lang_mapping}" langlower)
|
||||
if(lang STREQUAL "CXX")
|
||||
set(langlower cpp)
|
||||
endif()
|
||||
set(MESON_${lang_mapping}FLAGS "${langlower}_args = ${${lang}flags}\n")
|
||||
set(linker_flags "${VCPKG_COMBINED_SHARED_LINKER_FLAGS_${config_type}}")
|
||||
z_vcpkg_meson_convert_compiler_flags_to_list(linker_flags "${linker_flags}")
|
||||
vcpkg_list(APPEND linker_flags "${libpath}")
|
||||
z_vcpkg_meson_convert_list_to_python_array(linker_flags ${linker_flags})
|
||||
string(APPEND MESON_${lang_mapping}FLAGS "${langlower}_link_args = ${linker_flags}\n")
|
||||
set(MESON_${lang_mapping}FLAGS "${MESON_${lang_mapping}FLAGS}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_get_build_and_host_system build_system host_system is_cross) #https://mesonbuild.com/Cross-compilation.html
|
||||
set(build_unknown FALSE)
|
||||
if(CMAKE_HOST_WIN32)
|
||||
if(DEFINED ENV{PROCESSOR_ARCHITEW6432})
|
||||
set(build_arch $ENV{PROCESSOR_ARCHITEW6432})
|
||||
else()
|
||||
set(build_arch $ENV{PROCESSOR_ARCHITECTURE})
|
||||
endif()
|
||||
if(build_arch MATCHES "(amd|AMD)64")
|
||||
set(build_cpu_fam x86_64)
|
||||
set(build_cpu x86_64)
|
||||
elseif(build_arch MATCHES "(x|X)86")
|
||||
set(build_cpu_fam x86)
|
||||
set(build_cpu i686)
|
||||
elseif(build_arch MATCHES "^(ARM|arm)64$")
|
||||
set(build_cpu_fam aarch64)
|
||||
set(build_cpu armv8)
|
||||
elseif(build_arch MATCHES "^(ARM|arm)$")
|
||||
set(build_cpu_fam arm)
|
||||
set(build_cpu armv7hl)
|
||||
else()
|
||||
if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE)
|
||||
message(WARNING "Unsupported build architecture ${build_arch}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!")
|
||||
endif()
|
||||
set(build_unknown TRUE)
|
||||
endif()
|
||||
elseif(CMAKE_HOST_UNIX)
|
||||
# at this stage, CMAKE_HOST_SYSTEM_PROCESSOR is not defined
|
||||
execute_process(
|
||||
COMMAND uname -m
|
||||
OUTPUT_VARIABLE MACHINE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# Show real machine architecture to visually understand whether we are in a native Apple Silicon terminal or running under Rosetta emulation
|
||||
debug_message("Machine: ${MACHINE}")
|
||||
|
||||
if(MACHINE MATCHES "arm64|aarch64")
|
||||
set(build_cpu_fam aarch64)
|
||||
set(build_cpu armv8)
|
||||
elseif(MACHINE MATCHES "armv7h?l")
|
||||
set(build_cpu_fam arm)
|
||||
set(build_cpu ${MACHINE})
|
||||
elseif(MACHINE MATCHES "x86_64|amd64")
|
||||
set(build_cpu_fam x86_64)
|
||||
set(build_cpu x86_64)
|
||||
elseif(MACHINE MATCHES "x86|i686")
|
||||
set(build_cpu_fam x86)
|
||||
set(build_cpu i686)
|
||||
elseif(MACHINE MATCHES "i386")
|
||||
set(build_cpu_fam x86)
|
||||
set(build_cpu i386)
|
||||
elseif(MACHINE MATCHES "loongarch64")
|
||||
set(build_cpu_fam loongarch64)
|
||||
set(build_cpu loongarch64)
|
||||
else()
|
||||
# https://github.com/mesonbuild/meson/blob/master/docs/markdown/Reference-tables.md#cpu-families
|
||||
if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE)
|
||||
message(WARNING "Unhandled machine: ${MACHINE}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!")
|
||||
endif()
|
||||
set(build_unknown TRUE)
|
||||
endif()
|
||||
else()
|
||||
if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE)
|
||||
message(WARNING "Failed to detect the build architecture! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the build_machine entry!")
|
||||
endif()
|
||||
set(build_unknown TRUE)
|
||||
endif()
|
||||
|
||||
set(build "[build_machine]\n") # Machine the build is performed on
|
||||
string(APPEND build "endian = 'little'\n")
|
||||
if(CMAKE_HOST_WIN32)
|
||||
string(APPEND build "system = 'windows'\n")
|
||||
elseif(CMAKE_HOST_APPLE)
|
||||
string(APPEND build "system = 'darwin'\n")
|
||||
elseif(CYGWIN)
|
||||
string(APPEND build "system = 'cygwin'\n")
|
||||
elseif(CMAKE_HOST_UNIX)
|
||||
string(APPEND build "system = 'linux'\n")
|
||||
else()
|
||||
set(build_unknown TRUE)
|
||||
endif()
|
||||
|
||||
if(DEFINED build_cpu_fam)
|
||||
string(APPEND build "cpu_family = '${build_cpu_fam}'\n")
|
||||
endif()
|
||||
if(DEFINED build_cpu)
|
||||
string(APPEND build "cpu = '${build_cpu}'")
|
||||
endif()
|
||||
if(NOT build_unknown)
|
||||
set(${build_system} "${build}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(host_unkown FALSE)
|
||||
if(VCPKG_TARGET_ARCHITECTURE MATCHES "(amd|AMD|x|X)64")
|
||||
set(host_cpu_fam x86_64)
|
||||
set(host_cpu x86_64)
|
||||
elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "(x|X)86")
|
||||
set(host_cpu_fam x86)
|
||||
set(host_cpu i686)
|
||||
elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "^(ARM|arm)64$")
|
||||
set(host_cpu_fam aarch64)
|
||||
set(host_cpu armv8)
|
||||
elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "^(ARM|arm)$")
|
||||
set(host_cpu_fam arm)
|
||||
set(host_cpu armv7hl)
|
||||
elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "loongarch64")
|
||||
set(host_cpu_fam loongarch64)
|
||||
set(host_cpu loongarch64)
|
||||
elseif(VCPKG_TARGET_ARCHITECTURE MATCHES "wasm32")
|
||||
set(host_cpu_fam wasm32)
|
||||
set(host_cpu wasm32)
|
||||
else()
|
||||
if(NOT DEFINED VCPKG_MESON_CROSS_FILE OR NOT DEFINED VCPKG_MESON_NATIVE_FILE)
|
||||
message(WARNING "Unsupported target architecture ${VCPKG_TARGET_ARCHITECTURE}! Please set VCPKG_MESON_(CROSS|NATIVE)_FILE to a meson file containing the host_machine entry!" )
|
||||
endif()
|
||||
set(host_unkown TRUE)
|
||||
endif()
|
||||
|
||||
set(host "[host_machine]\n") # host=target in vcpkg.
|
||||
string(APPEND host "endian = 'little'\n")
|
||||
if(NOT VCPKG_CMAKE_SYSTEM_NAME OR VCPKG_TARGET_IS_MINGW OR VCPKG_TARGET_IS_UWP)
|
||||
set(meson_system_name "windows")
|
||||
else()
|
||||
string(TOLOWER "${VCPKG_CMAKE_SYSTEM_NAME}" meson_system_name)
|
||||
endif()
|
||||
string(APPEND host "system = '${meson_system_name}'\n")
|
||||
string(APPEND host "cpu_family = '${host_cpu_fam}'\n")
|
||||
string(APPEND host "cpu = '${host_cpu}'")
|
||||
if(NOT host_unkown)
|
||||
set(${host_system} "${host}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(NOT build_cpu_fam MATCHES "${host_cpu_fam}"
|
||||
OR VCPKG_TARGET_IS_ANDROID OR VCPKG_TARGET_IS_IOS OR VCPKG_TARGET_IS_UWP
|
||||
OR (VCPKG_TARGET_IS_MINGW AND NOT CMAKE_HOST_WIN32))
|
||||
set(${is_cross} TRUE PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_meson_setup_extra_windows_variables config_type)
|
||||
## b_vscrt
|
||||
if(VCPKG_CRT_LINKAGE STREQUAL "static")
|
||||
set(crt_type "mt")
|
||||
else()
|
||||
set(crt_type "md")
|
||||
endif()
|
||||
if(config_type STREQUAL "DEBUG")
|
||||
set(crt_type "${crt_type}d")
|
||||
endif()
|
||||
set(MESON_VSCRT_LINKAGE "b_vscrt = '${crt_type}'" PARENT_SCOPE)
|
||||
## winlibs
|
||||
separate_arguments(c_winlibs NATIVE_COMMAND "${VCPKG_DETECTED_CMAKE_C_STANDARD_LIBRARIES}")
|
||||
separate_arguments(cpp_winlibs NATIVE_COMMAND "${VCPKG_DETECTED_CMAKE_CXX_STANDARD_LIBRARIES}")
|
||||
z_vcpkg_meson_convert_list_to_python_array(c_winlibs ${c_winlibs})
|
||||
z_vcpkg_meson_convert_list_to_python_array(cpp_winlibs ${cpp_winlibs})
|
||||
set(MESON_WINLIBS "c_winlibs = ${c_winlibs}\n")
|
||||
string(APPEND MESON_WINLIBS "cpp_winlibs = ${cpp_winlibs}")
|
||||
set(MESON_WINLIBS "${MESON_WINLIBS}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_meson_setup_variables config_type)
|
||||
set(meson_var_list VSCRT_LINKAGE WINLIBS MT AR RC C C_LD CXX CXX_LD OBJC OBJC_LD OBJCXX OBJCXX_LD FC FC_LD WINDRES CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS FCFLAGS SHARED_LINKER_FLAGS)
|
||||
foreach(var IN LISTS meson_var_list)
|
||||
set(MESON_${var} "")
|
||||
endforeach()
|
||||
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
z_vcpkg_meson_setup_extra_windows_variables("${config_type}")
|
||||
endif()
|
||||
|
||||
z_vcpkg_meson_set_proglist_variables("${config_type}")
|
||||
z_vcpkg_meson_set_flags_variables("${config_type}")
|
||||
|
||||
foreach(var IN LISTS meson_var_list)
|
||||
set(MESON_${var} "${MESON_${var}}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(vcpkg_generate_meson_cmd_args)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
""
|
||||
"OUTPUT;CONFIG"
|
||||
"OPTIONS;LANGUAGES;ADDITIONAL_BINARIES;ADDITIONAL_PROPERTIES"
|
||||
)
|
||||
|
||||
if(NOT arg_LANGUAGES)
|
||||
set(arg_LANGUAGES C CXX)
|
||||
endif()
|
||||
|
||||
vcpkg_list(JOIN arg_ADDITIONAL_BINARIES "\n" MESON_ADDITIONAL_BINARIES)
|
||||
vcpkg_list(JOIN arg_ADDITIONAL_PROPERTIES "\n" MESON_ADDITIONAL_PROPERTIES)
|
||||
|
||||
set(buildtype "${arg_CONFIG}")
|
||||
|
||||
if(NOT VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
|
||||
z_vcpkg_select_default_vcpkg_chainload_toolchain()
|
||||
endif()
|
||||
vcpkg_list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS "-DVCPKG_LANGUAGES=${arg_LANGUAGES}")
|
||||
vcpkg_cmake_get_vars(cmake_vars_file)
|
||||
debug_message("Including cmake vars from: ${cmake_vars_file}")
|
||||
include("${cmake_vars_file}")
|
||||
|
||||
vcpkg_list(APPEND arg_OPTIONS --backend ninja --wrap-mode nodownload -Doptimization=plain)
|
||||
|
||||
z_vcpkg_get_build_and_host_system(MESON_HOST_MACHINE MESON_BUILD_MACHINE IS_CROSS)
|
||||
|
||||
if(arg_CONFIG STREQUAL "DEBUG")
|
||||
set(suffix "dbg")
|
||||
else()
|
||||
string(SUBSTRING "${arg_CONFIG}" 0 3 suffix)
|
||||
string(TOLOWER "${suffix}" suffix)
|
||||
endif()
|
||||
set(meson_input_file_${buildtype} "${CURRENT_BUILDTREES_DIR}/meson-${TARGET_TRIPLET}-${suffix}.log")
|
||||
|
||||
if(IS_CROSS)
|
||||
# VCPKG_CROSSCOMPILING is not used since it regresses a lot of ports in x64-windows-x triplets
|
||||
# For consistency this should proably be changed in the future?
|
||||
vcpkg_list(APPEND arg_OPTIONS --native "${SCRIPTS}/buildsystems/meson/none.txt")
|
||||
vcpkg_list(APPEND arg_OPTIONS --cross "${meson_input_file_${buildtype}}")
|
||||
else()
|
||||
vcpkg_list(APPEND arg_OPTIONS --native "${meson_input_file_${buildtype}}")
|
||||
endif()
|
||||
|
||||
# User provided cross/native files
|
||||
if(VCPKG_MESON_NATIVE_FILE)
|
||||
vcpkg_list(APPEND arg_OPTIONS --native "${VCPKG_MESON_NATIVE_FILE}")
|
||||
endif()
|
||||
if(VCPKG_MESON_NATIVE_FILE_${buildtype})
|
||||
vcpkg_list(APPEND arg_OPTIONS --native "${VCPKG_MESON_NATIVE_FILE_${buildtype}}")
|
||||
endif()
|
||||
if(VCPKG_MESON_CROSS_FILE)
|
||||
vcpkg_list(APPEND arg_OPTIONS --cross "${VCPKG_MESON_CROSS_FILE}")
|
||||
endif()
|
||||
if(VCPKG_MESON_CROSS_FILE_${buildtype})
|
||||
vcpkg_list(APPEND arg_OPTIONS --cross "${VCPKG_MESON_CROSS_FILE_${buildtype}}")
|
||||
endif()
|
||||
|
||||
vcpkg_list(APPEND arg_OPTIONS --libdir lib) # else meson install into an architecture describing folder
|
||||
vcpkg_list(APPEND arg_OPTIONS --pkgconfig.relocatable)
|
||||
|
||||
if(arg_CONFIG STREQUAL "RELEASE")
|
||||
vcpkg_list(APPEND arg_OPTIONS -Ddebug=false --prefix "${CURRENT_PACKAGES_DIR}")
|
||||
vcpkg_list(APPEND arg_OPTIONS "--pkg-config-path;['${CURRENT_INSTALLED_DIR}/lib/pkgconfig','${CURRENT_INSTALLED_DIR}/share/pkgconfig']")
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}/share']")
|
||||
else()
|
||||
vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/debug']")
|
||||
endif()
|
||||
elseif(arg_CONFIG STREQUAL "DEBUG")
|
||||
vcpkg_list(APPEND arg_OPTIONS -Ddebug=true --prefix "${CURRENT_PACKAGES_DIR}/debug" --includedir ../include)
|
||||
vcpkg_list(APPEND arg_OPTIONS "--pkg-config-path;['${CURRENT_INSTALLED_DIR}/debug/lib/pkgconfig','${CURRENT_INSTALLED_DIR}/share/pkgconfig']")
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}','${CURRENT_INSTALLED_DIR}/share']")
|
||||
else()
|
||||
vcpkg_list(APPEND arg_OPTIONS "-Dcmake_prefix_path=['${CURRENT_INSTALLED_DIR}/debug','${CURRENT_INSTALLED_DIR}']")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown configuration. Only DEBUG and RELEASE are valid values.")
|
||||
endif()
|
||||
|
||||
# Allow overrides / additional configuration variables from triplets
|
||||
if(DEFINED VCPKG_MESON_CONFIGURE_OPTIONS)
|
||||
vcpkg_list(APPEND arg_OPTIONS ${VCPKG_MESON_CONFIGURE_OPTIONS})
|
||||
endif()
|
||||
if(DEFINED VCPKG_MESON_CONFIGURE_OPTIONS_${buildtype})
|
||||
vcpkg_list(APPEND arg_OPTIONS ${VCPKG_MESON_CONFIGURE_OPTIONS_${buildtype}})
|
||||
endif()
|
||||
|
||||
if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic")
|
||||
set(MESON_DEFAULT_LIBRARY shared)
|
||||
else()
|
||||
set(MESON_DEFAULT_LIBRARY static)
|
||||
endif()
|
||||
set(MESON_CMAKE_BUILD_TYPE "${cmake_build_type_${buildtype}}")
|
||||
z_vcpkg_meson_setup_variables(${buildtype})
|
||||
configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/meson.template.in" "${meson_input_file_${buildtype}}" @ONLY)
|
||||
set("${arg_OUTPUT}" ${arg_OPTIONS} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(vcpkg_configure_meson)
|
||||
# parse parameters such that semicolons in options arguments to COMMAND don't get erased
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
"NO_PKG_CONFIG"
|
||||
"SOURCE_PATH"
|
||||
"OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE;LANGUAGES;ADDITIONAL_BINARIES;ADDITIONAL_NATIVE_BINARIES;ADDITIONAL_CROSS_BINARIES;ADDITIONAL_PROPERTIES"
|
||||
)
|
||||
|
||||
if(DEFINED arg_ADDITIONAL_NATIVE_BINARIES OR DEFINED arg_ADDITIONAL_CROSS_BINARIES)
|
||||
message(WARNING "Options ADDITIONAL_(NATIVE|CROSS)_BINARIES have been deprecated. Only use ADDITIONAL_BINARIES!")
|
||||
endif()
|
||||
vcpkg_list(APPEND arg_ADDITIONAL_BINARIES ${arg_ADDITIONAL_NATIVE_BINARIES} ${arg_ADDITIONAL_CROSS_BINARIES})
|
||||
vcpkg_list(REMOVE_DUPLICATES arg_ADDITIONAL_BINARIES)
|
||||
|
||||
file(REMOVE_RECURSE "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel")
|
||||
file(REMOVE_RECURSE "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg")
|
||||
|
||||
vcpkg_find_acquire_program(MESON)
|
||||
|
||||
get_filename_component(CMAKE_PATH "${CMAKE_COMMAND}" DIRECTORY)
|
||||
vcpkg_add_to_path("${CMAKE_PATH}") # Make CMake invokeable for Meson
|
||||
|
||||
vcpkg_find_acquire_program(NINJA)
|
||||
|
||||
if(NOT arg_NO_PKG_CONFIG)
|
||||
vcpkg_find_acquire_program(PKGCONFIG)
|
||||
set(ENV{PKG_CONFIG} "${PKGCONFIG}")
|
||||
endif()
|
||||
|
||||
vcpkg_find_acquire_program(PYTHON3)
|
||||
get_filename_component(PYTHON3_DIR "${PYTHON3}" DIRECTORY)
|
||||
vcpkg_add_to_path(PREPEND "${PYTHON3_DIR}")
|
||||
|
||||
set(buildtypes "")
|
||||
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
|
||||
set(buildname "DEBUG")
|
||||
set(cmake_build_type_${buildname} "Debug")
|
||||
vcpkg_list(APPEND buildtypes "${buildname}")
|
||||
set(path_suffix_${buildname} "debug/")
|
||||
set(suffix_${buildname} "dbg")
|
||||
endif()
|
||||
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
|
||||
set(buildname "RELEASE")
|
||||
set(cmake_build_type_${buildname} "Release")
|
||||
vcpkg_list(APPEND buildtypes "${buildname}")
|
||||
set(path_suffix_${buildname} "")
|
||||
set(suffix_${buildname} "rel")
|
||||
endif()
|
||||
|
||||
# configure build
|
||||
foreach(buildtype IN LISTS buildtypes)
|
||||
message(STATUS "Configuring ${TARGET_TRIPLET}-${suffix_${buildtype}}")
|
||||
file(MAKE_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix_${buildtype}}")
|
||||
|
||||
vcpkg_generate_meson_cmd_args(
|
||||
OUTPUT cmd_args
|
||||
CONFIG ${buildtype}
|
||||
LANGUAGES ${arg_LANGUAGES}
|
||||
OPTIONS ${arg_OPTIONS} ${arg_OPTIONS_${buildtype}}
|
||||
ADDITIONAL_BINARIES ${arg_ADDITIONAL_BINARIES}
|
||||
ADDITIONAL_PROPERTIES ${arg_ADDITIONAL_PROPERTIES}
|
||||
)
|
||||
|
||||
vcpkg_execute_required_process(
|
||||
COMMAND ${MESON} setup ${cmd_args} ${arg_SOURCE_PATH}
|
||||
WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${suffix_${buildtype}}"
|
||||
LOGNAME config-${TARGET_TRIPLET}-${suffix_${buildtype}}
|
||||
SAVE_LOG_FILES
|
||||
meson-logs/meson-log.txt
|
||||
meson-info/intro-dependencies.json
|
||||
meson-logs/install-log.txt
|
||||
)
|
||||
|
||||
message(STATUS "Configuring ${TARGET_TRIPLET}-${suffix_${buildtype}} done")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
function(vcpkg_install_meson)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg "ADD_BIN_TO_PATH" "" "")
|
||||
|
||||
vcpkg_find_acquire_program(NINJA)
|
||||
unset(ENV{DESTDIR}) # installation directory was already specified with '--prefix' option
|
||||
|
||||
if(VCPKG_TARGET_IS_OSX)
|
||||
vcpkg_backup_env_variables(VARS SDKROOT MACOSX_DEPLOYMENT_TARGET)
|
||||
set(ENV{SDKROOT} "${VCPKG_DETECTED_CMAKE_OSX_SYSROOT}")
|
||||
set(ENV{MACOSX_DEPLOYMENT_TARGET} "${VCPKG_DETECTED_CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||
endif()
|
||||
|
||||
foreach(buildtype IN ITEMS "debug" "release")
|
||||
if(DEFINED VCPKG_BUILD_TYPE AND NOT VCPKG_BUILD_TYPE STREQUAL buildtype)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if(buildtype STREQUAL "debug")
|
||||
set(short_buildtype "dbg")
|
||||
else()
|
||||
set(short_buildtype "rel")
|
||||
endif()
|
||||
|
||||
message(STATUS "Package ${TARGET_TRIPLET}-${short_buildtype}")
|
||||
if(arg_ADD_BIN_TO_PATH)
|
||||
vcpkg_backup_env_variables(VARS PATH)
|
||||
if(buildtype STREQUAL "debug")
|
||||
vcpkg_add_to_path(PREPEND "${CURRENT_INSTALLED_DIR}/debug/bin")
|
||||
else()
|
||||
vcpkg_add_to_path(PREPEND "${CURRENT_INSTALLED_DIR}/bin")
|
||||
endif()
|
||||
endif()
|
||||
vcpkg_execute_required_process(
|
||||
COMMAND "${NINJA}" install -v
|
||||
WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_buildtype}"
|
||||
LOGNAME package-${TARGET_TRIPLET}-${short_buildtype}
|
||||
)
|
||||
if(arg_ADD_BIN_TO_PATH)
|
||||
vcpkg_restore_env_variables(VARS PATH)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
vcpkg_list(SET renamed_libs)
|
||||
if(VCPKG_TARGET_IS_WINDOWS AND VCPKG_LIBRARY_LINKAGE STREQUAL static AND NOT VCPKG_TARGET_IS_MINGW)
|
||||
# Meson names all static libraries lib<name>.a which basically breaks the world
|
||||
file(GLOB_RECURSE gen_libraries "${CURRENT_PACKAGES_DIR}*/**/lib*.a")
|
||||
foreach(gen_library IN LISTS gen_libraries)
|
||||
get_filename_component(libdir "${gen_library}" DIRECTORY)
|
||||
get_filename_component(libname "${gen_library}" NAME)
|
||||
string(REGEX REPLACE ".a$" ".lib" fixed_librawname "${libname}")
|
||||
string(REGEX REPLACE "^lib" "" fixed_librawname "${fixed_librawname}")
|
||||
file(RENAME "${gen_library}" "${libdir}/${fixed_librawname}")
|
||||
# For cmake fixes.
|
||||
string(REGEX REPLACE ".a$" "" origin_librawname "${libname}")
|
||||
string(REGEX REPLACE ".lib$" "" fixed_librawname "${fixed_librawname}")
|
||||
vcpkg_list(APPEND renamed_libs ${fixed_librawname})
|
||||
set(${librawname}_old ${origin_librawname})
|
||||
set(${librawname}_new ${fixed_librawname})
|
||||
endforeach()
|
||||
file(GLOB_RECURSE cmake_files "${CURRENT_PACKAGES_DIR}*/*.cmake")
|
||||
foreach(cmake_file IN LISTS cmake_files)
|
||||
foreach(current_lib IN LISTS renamed_libs)
|
||||
vcpkg_replace_string("${cmake_file}" "${${current_lib}_old}" "${${current_lib}_new}" IGNORE_UNCHANGED)
|
||||
endforeach()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(VCPKG_TARGET_IS_OSX)
|
||||
vcpkg_restore_env_variables(VARS SDKROOT MACOSX_DEPLOYMENT_TARGET)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# See https://github.com/microsoft/vcpkg/discussions/19454
|
||||
# NOTE: Try to keep in sync with default arm64-osx definition
|
||||
set(VCPKG_TARGET_ARCHITECTURE x64)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
|
||||
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
|
||||
set(VCPKG_OSX_ARCHITECTURES "arm64;x86_64")
|
||||
13
default.nix
13
default.nix
|
|
@ -1,4 +1,9 @@
|
|||
(import (fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/ff81ac966bb2cae68946d5ed5fc4994f96d0ffec.tar.gz";
|
||||
sha256 = "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=";
|
||||
}) { src = ./.; }).defaultNix
|
||||
(import (
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
in
|
||||
fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
) { src = ./.; }).defaultNix
|
||||
|
|
|
|||
56
flake.lock
generated
56
flake.lock
generated
|
|
@ -1,13 +1,29 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"libnbtplusplus": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772016279,
|
||||
"narHash": "sha256-7itkptyjoRcXfGLwg1/jxajetZ3a4mDc66+w4X6yW8s=",
|
||||
"lastModified": 1699286814,
|
||||
"narHash": "sha256-yy0q+bky80LtK1GWzz7qpM+aAGrOqLuewbid8WT1ilk=",
|
||||
"owner": "PrismLauncher",
|
||||
"repo": "libnbtplusplus",
|
||||
"rev": "687e43031df0dc641984b4256bcca50d5b3f7de3",
|
||||
"rev": "23b955121b8217c1c348a9ed2483167a6f3ff4ad",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -16,22 +32,42 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-filter": {
|
||||
"locked": {
|
||||
"lastModified": 1710156097,
|
||||
"narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=",
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"rev": "3342559a24e85fc164b295c3444e8a139924675b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1778443072,
|
||||
"narHash": "sha256-rNDJzV2JTV5SUTwv1cgKZYMdyoUYU9/YfegSaUf3QfY=",
|
||||
"rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre995699.da5ad661ba4e/nixexprs.tar.xz"
|
||||
"lastModified": 1729256560,
|
||||
"narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"libnbtplusplus": "libnbtplusplus",
|
||||
"nix-filter": "nix-filter",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
205
flake.nix
205
flake.nix
|
|
@ -9,12 +9,34 @@
|
|||
};
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
libnbtplusplus = {
|
||||
url = "github:PrismLauncher/libnbtplusplus";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
nix-filter.url = "github:numtide/nix-filter";
|
||||
|
||||
/*
|
||||
Inputs below this are optional and can be removed
|
||||
|
||||
```
|
||||
{
|
||||
inputs.prismlauncher = {
|
||||
url = "github:PrismLauncher/PrismLauncher";
|
||||
inputs = {
|
||||
flake-compat.follows = "";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
*/
|
||||
|
||||
flake-compat = {
|
||||
url = "github:edolstra/flake-compat";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
|
@ -22,8 +44,9 @@
|
|||
self,
|
||||
nixpkgs,
|
||||
libnbtplusplus,
|
||||
nix-filter,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
|
|
@ -35,178 +58,47 @@
|
|||
forAllSystems = lib.genAttrs systems;
|
||||
nixpkgsFor = forAllSystems (system: nixpkgs.legacyPackages.${system});
|
||||
in
|
||||
|
||||
{
|
||||
checks = forAllSystems (
|
||||
system:
|
||||
|
||||
let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
llvm = pkgs.llvmPackages_22;
|
||||
checks' = nixpkgsFor.${system}.callPackage ./nix/checks.nix { inherit self; };
|
||||
in
|
||||
|
||||
{
|
||||
formatting =
|
||||
pkgs.runCommand "check-formatting"
|
||||
{
|
||||
nativeBuildInputs = with pkgs; [
|
||||
deadnix
|
||||
llvm.clang-tools
|
||||
markdownlint-cli
|
||||
nixfmt-rfc-style
|
||||
statix
|
||||
];
|
||||
}
|
||||
''
|
||||
cd ${self}
|
||||
|
||||
echo "Running clang-format...."
|
||||
clang-format --dry-run --style='file' --Werror */**.{c,cc,cpp,h,hh,hpp}
|
||||
|
||||
echo "Running deadnix..."
|
||||
deadnix --fail
|
||||
|
||||
echo "Running markdownlint..."
|
||||
markdownlint --dot .
|
||||
|
||||
echo "Running nixfmt..."
|
||||
find -type f -name '*.nix' -exec nixfmt --check {} +
|
||||
|
||||
echo "Running statix"
|
||||
statix check .
|
||||
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
lib.filterAttrs (_: lib.isDerivation) checks'
|
||||
);
|
||||
|
||||
devShells = forAllSystems (
|
||||
system:
|
||||
|
||||
let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
llvm = pkgs.llvmPackages_22;
|
||||
python = pkgs.python3;
|
||||
mkShell = pkgs.mkShell.override { inherit (llvm) stdenv; };
|
||||
|
||||
packages' = self.packages.${system};
|
||||
|
||||
welcomeMessage = ''
|
||||
Welcome to the Prism Launcher repository! 🌈
|
||||
|
||||
We just set some things up for you. To get building, you can run:
|
||||
|
||||
```
|
||||
$ cd "$cmakeBuildDir"
|
||||
$ ninjaBuildPhase
|
||||
$ ninjaInstallPhase
|
||||
```
|
||||
|
||||
Feel free to ask any questions in our Discord server or Matrix space:
|
||||
- https://prismlauncher.org/discord
|
||||
- https://matrix.to/#/#prismlauncher:matrix.org
|
||||
|
||||
And thanks for helping out :)
|
||||
'';
|
||||
|
||||
# Re-use our package wrapper to wrap our development environment
|
||||
qt-wrapper-env = packages'.prismlauncher.overrideAttrs (old: {
|
||||
name = "qt-wrapper-env";
|
||||
|
||||
# Required to use script-based makeWrapper below
|
||||
strictDeps = true;
|
||||
|
||||
# We don't need/want the unwrapped Prism package
|
||||
paths = [ ];
|
||||
|
||||
nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [
|
||||
# Ensure the wrapper is script based so it can be sourced
|
||||
pkgs.makeWrapper
|
||||
];
|
||||
|
||||
# Inspired by https://discourse.nixos.org/t/python-qt-woes/11808/10
|
||||
buildCommand = ''
|
||||
makeQtWrapper ${lib.getExe pkgs.runtimeShellPackage} "$out"
|
||||
sed -i '/^exec/d' "$out"
|
||||
'';
|
||||
});
|
||||
in
|
||||
|
||||
{
|
||||
default = mkShell {
|
||||
name = "prism-launcher";
|
||||
|
||||
inputsFrom = [ packages'.prismlauncher-unwrapped ];
|
||||
|
||||
packages = [
|
||||
pkgs.ccache
|
||||
llvm.clang-tools
|
||||
python # NOTE(@getchoo): Required for run-clang-tidy, etc.
|
||||
|
||||
(pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "clang-tidy-diff";
|
||||
inherit (llvm.clang) version;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.installShellFiles
|
||||
python.pkgs.wrapPython
|
||||
];
|
||||
|
||||
dontUnpack = true;
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
|
||||
postInstall = "installBin ${llvm.libclang.python}/share/clang/clang-tidy-diff.py";
|
||||
postFixup = "wrapPythonPrograms";
|
||||
})
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [ self.packages.${system}.prismlauncher-unwrapped ];
|
||||
buildInputs = with pkgs; [
|
||||
ccache
|
||||
ninja
|
||||
];
|
||||
|
||||
cmakeBuildType = "Debug";
|
||||
cmakeFlags = [ "-GNinja" ] ++ packages'.prismlauncher-unwrapped.cmakeFlags;
|
||||
dontFixCmake = true;
|
||||
|
||||
shellHook = ''
|
||||
echo "Sourcing ${qt-wrapper-env}"
|
||||
source ${qt-wrapper-env}
|
||||
|
||||
git submodule update --init --force
|
||||
|
||||
if [ ! -f compile_commands.json ]; then
|
||||
cmakeConfigurePhase
|
||||
cd ..
|
||||
ln -s "$cmakeBuildDir"/compile_commands.json compile_commands.json
|
||||
fi
|
||||
|
||||
echo ${lib.escapeShellArg welcomeMessage}
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
formatter = forAllSystems (system: nixpkgsFor.${system}.nixfmt-rfc-style);
|
||||
|
||||
overlays.default =
|
||||
final: prev:
|
||||
|
||||
let
|
||||
llvm = final.llvmPackages_22 or prev.llvmPackages_22;
|
||||
in
|
||||
|
||||
{
|
||||
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
|
||||
inherit (llvm) stdenv;
|
||||
inherit
|
||||
libnbtplusplus
|
||||
self
|
||||
;
|
||||
};
|
||||
|
||||
prismlauncher = final.callPackage ./nix/wrapper.nix { };
|
||||
overlays.default = final: prev: {
|
||||
prismlauncher-unwrapped = prev.callPackage ./nix/unwrapped.nix {
|
||||
inherit
|
||||
libnbtplusplus
|
||||
nix-filter
|
||||
self
|
||||
;
|
||||
};
|
||||
|
||||
prismlauncher = final.callPackage ./nix/wrapper.nix { };
|
||||
};
|
||||
|
||||
packages = forAllSystems (
|
||||
system:
|
||||
|
||||
let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
|
||||
|
|
@ -219,7 +111,6 @@
|
|||
default = prismPackages.prismlauncher;
|
||||
};
|
||||
in
|
||||
|
||||
# Only output them if they're available on the current system
|
||||
lib.filterAttrs (_: lib.meta.availableOn pkgs.stdenv.hostPlatform) packages
|
||||
);
|
||||
|
|
@ -227,18 +118,16 @@
|
|||
# We put these under legacyPackages as they are meant for CI, not end user consumption
|
||||
legacyPackages = forAllSystems (
|
||||
system:
|
||||
|
||||
let
|
||||
packages' = self.packages.${system};
|
||||
legacyPackages' = self.legacyPackages.${system};
|
||||
prismPackages = self.packages.${system};
|
||||
legacyPackages = self.legacyPackages.${system};
|
||||
in
|
||||
|
||||
{
|
||||
prismlauncher-debug = packages'.prismlauncher.override {
|
||||
prismlauncher-unwrapped = legacyPackages'.prismlauncher-unwrapped-debug;
|
||||
prismlauncher-debug = prismPackages.prismlauncher.override {
|
||||
prismlauncher-unwrapped = legacyPackages.prismlauncher-unwrapped-debug;
|
||||
};
|
||||
|
||||
prismlauncher-unwrapped-debug = packages'.prismlauncher-unwrapped.overrideAttrs {
|
||||
prismlauncher-unwrapped-debug = prismPackages.prismlauncher-unwrapped.overrideAttrs {
|
||||
cmakeBuildType = "Debug";
|
||||
dontStrip = true;
|
||||
};
|
||||
|
|
|
|||
20
flatpak/flite.json
Normal file
20
flatpak/flite.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "flite",
|
||||
"config-opts": [
|
||||
"--enable-shared",
|
||||
"--with-audio=pulseaudio"
|
||||
],
|
||||
"no-parallel-make": true,
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/festvox/flite.git",
|
||||
"tag": "v2.2",
|
||||
"commit": "e9e2e37c329dbe98bfeb27a1828ef9a71fa84f88",
|
||||
"x-checker-data": {
|
||||
"type": "git",
|
||||
"tag-pattern": "^v([\\d.]+)$"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
18
flatpak/libdecor.json
Normal file
18
flatpak/libdecor.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "libdecor",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Ddemo=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.freedesktop.org/libdecor/libdecor.git",
|
||||
"commit": "c2bd8ad6fa42c0cb17553ce77ad8a87d1f543b1f"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/pkgconfig"
|
||||
]
|
||||
}
|
||||
151
flatpak/org.prismlauncher.PrismLauncher.yml
Normal file
151
flatpak/org.prismlauncher.PrismLauncher.yml
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
id: org.prismlauncher.PrismLauncher
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: '6.8'
|
||||
sdk: org.kde.Sdk
|
||||
sdk-extensions:
|
||||
- org.freedesktop.Sdk.Extension.openjdk17
|
||||
|
||||
command: prismlauncher
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --socket=x11
|
||||
- --socket=wayland
|
||||
- --device=all
|
||||
- --share=network
|
||||
- --socket=pulseaudio
|
||||
# for Discord RPC mods
|
||||
- --filesystem=xdg-run/app/com.discordapp.Discord:create
|
||||
# Mod drag&drop
|
||||
- --filesystem=xdg-download:ro
|
||||
# FTBApp import
|
||||
- --filesystem=~/.ftba:ro
|
||||
# Userspace visibility for manual hugepages configuration
|
||||
# Required for -XX:+UseLargePages
|
||||
- --filesystem=/sys/kernel/mm/hugepages:ro
|
||||
# Userspace visibility for transparent hugepages configuration
|
||||
# Required for -XX:+UseTransparentHugePages
|
||||
- --filesystem=/sys/kernel/mm/transparent_hugepage:ro
|
||||
|
||||
modules:
|
||||
# Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31)
|
||||
- shared-modules/libusb/libusb.json
|
||||
|
||||
# Needed for proper Wayland support
|
||||
- libdecor.json
|
||||
|
||||
# Text to Speech in the game
|
||||
- flite.json
|
||||
|
||||
- name: prismlauncher
|
||||
buildsystem: cmake-ninja
|
||||
builddir: true
|
||||
config-opts:
|
||||
- -DLauncher_BUILD_PLATFORM=flatpak
|
||||
# This allows us to manage and update Java independently of this Flatpak
|
||||
- -DLauncher_ENABLE_JAVA_DOWNLOADER=ON
|
||||
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
build-options:
|
||||
env:
|
||||
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
|
||||
JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac
|
||||
run-tests: true
|
||||
sources:
|
||||
- type: dir
|
||||
path: ../
|
||||
|
||||
- name: glfw
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
- -DBUILD_SHARED_LIBS:BOOL=ON
|
||||
- -DGLFW_BUILD_WAYLAND:BOOL=ON
|
||||
- -DGLFW_BUILD_DOCS:BOOL=OFF
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/glfw/glfw.git
|
||||
commit: 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 # 3.4
|
||||
- type: patch
|
||||
path: patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
|
||||
cleanup:
|
||||
- /include
|
||||
- /lib/cmake
|
||||
- /lib/pkgconfig
|
||||
|
||||
- name: xrandr
|
||||
buildsystem: autotools
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.3.tar.xz
|
||||
sha256: f8dd7566adb74147fab9964680b6bbadee87cf406a7fcff51718a5e6949b841c
|
||||
x-checker-data:
|
||||
type: anitya
|
||||
project-id: 14957
|
||||
stable-only: true
|
||||
url-template: https://xorg.freedesktop.org/archive/individual/app/xrandr-$version.tar.xz
|
||||
cleanup:
|
||||
- /share/man
|
||||
- /bin/xkeystone
|
||||
|
||||
- name: gamemode
|
||||
buildsystem: meson
|
||||
config-opts:
|
||||
- -Dwith-sd-bus-provider=no-daemon
|
||||
- -Dwith-examples=false
|
||||
post-install:
|
||||
# gamemoderun is installed for users who want to use wrapper commands
|
||||
# post-install is running inside the build dir, we need it from the source though
|
||||
- install -Dm755 ../data/gamemoderun -t /app/bin
|
||||
sources:
|
||||
- type: archive
|
||||
dest-filename: gamemode.tar.gz
|
||||
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.8.2
|
||||
sha256: 2886d4ce543c78bd2a364316d5e7fd59ef06b71de63f896b37c6d3dc97658f60
|
||||
x-checker-data:
|
||||
type: json
|
||||
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest
|
||||
version-query: .tag_name
|
||||
url-query: .tarball_url
|
||||
timestamp-query: .published_at
|
||||
cleanup:
|
||||
- /include
|
||||
- /lib/pkgconfig
|
||||
- /lib/libgamemodeauto.a
|
||||
|
||||
- name: glxinfo
|
||||
buildsystem: meson
|
||||
config-opts:
|
||||
- --bindir=/app/mesa-demos
|
||||
- -Degl=disabled
|
||||
- -Dglut=disabled
|
||||
- -Dosmesa=disabled
|
||||
- -Dvulkan=disabled
|
||||
- -Dwayland=disabled
|
||||
post-install:
|
||||
- mv -v /app/mesa-demos/glxinfo /app/bin
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://archive.mesa3d.org/demos/mesa-demos-9.0.0.tar.xz
|
||||
sha256: 3046a3d26a7b051af7ebdd257a5f23bfeb160cad6ed952329cdff1e9f1ed496b
|
||||
x-checker-data:
|
||||
type: anitya
|
||||
project-id: 16781
|
||||
stable-only: true
|
||||
url-template: https://archive.mesa3d.org/demos/mesa-demos-$version.tar.xz
|
||||
cleanup:
|
||||
- /include
|
||||
- /mesa-demos
|
||||
- /share
|
||||
modules:
|
||||
- shared-modules/glu/glu-9.json
|
||||
|
||||
- name: enhance
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- install -Dm755 prime-run /app/bin/prime-run
|
||||
- mv /app/bin/prismlauncher /app/bin/prismrun
|
||||
- install -Dm755 prismlauncher /app/bin/prismlauncher
|
||||
sources:
|
||||
- type: file
|
||||
path: prime-run
|
||||
- type: file
|
||||
path: prismlauncher
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
From 9997ae55a47de469ea26f8437c30b51483abda5f Mon Sep 17 00:00:00 2001
|
||||
From: Dan Klishch <danilklishch@gmail.com>
|
||||
Date: Sat, 30 Sep 2023 23:38:05 -0400
|
||||
Subject: Defer setting cursor position until the cursor is locked
|
||||
|
||||
---
|
||||
src/wl_platform.h | 3 +++
|
||||
src/wl_window.c | 14 ++++++++++++--
|
||||
2 files changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/wl_platform.h b/src/wl_platform.h
|
||||
index ca34f66e..cd1f227f 100644
|
||||
--- a/src/wl_platform.h
|
||||
+++ b/src/wl_platform.h
|
||||
@@ -403,6 +403,9 @@ typedef struct _GLFWwindowWayland
|
||||
int scaleSize;
|
||||
int compositorPreferredScale;
|
||||
|
||||
+ double askedCursorPosX, askedCursorPosY;
|
||||
+ GLFWbool didAskForSetCursorPos;
|
||||
+
|
||||
struct zwp_relative_pointer_v1* relativePointer;
|
||||
struct zwp_locked_pointer_v1* lockedPointer;
|
||||
struct zwp_confined_pointer_v1* confinedPointer;
|
||||
diff --git a/src/wl_window.c b/src/wl_window.c
|
||||
index 1de26558..0df16747 100644
|
||||
--- a/src/wl_window.c
|
||||
+++ b/src/wl_window.c
|
||||
@@ -2586,8 +2586,9 @@ void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
|
||||
void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
|
||||
{
|
||||
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||
- "Wayland: The platform does not support setting the cursor position");
|
||||
+ window->wl.didAskForSetCursorPos = true;
|
||||
+ window->wl.askedCursorPosX = x;
|
||||
+ window->wl.askedCursorPosY = y;
|
||||
}
|
||||
|
||||
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
||||
@@ -2819,6 +2820,15 @@ static const struct zwp_relative_pointer_v1_listener relativePointerListener =
|
||||
static void lockedPointerHandleLocked(void* userData,
|
||||
struct zwp_locked_pointer_v1* lockedPointer)
|
||||
{
|
||||
+ _GLFWwindow* window = userData;
|
||||
+
|
||||
+ if (window->wl.didAskForSetCursorPos)
|
||||
+ {
|
||||
+ window->wl.didAskForSetCursorPos = false;
|
||||
+ zwp_locked_pointer_v1_set_cursor_position_hint(window->wl.lockedPointer,
|
||||
+ wl_fixed_from_double(window->wl.askedCursorPosX),
|
||||
+ wl_fixed_from_double(window->wl.askedCursorPosY));
|
||||
+ }
|
||||
}
|
||||
|
||||
static void lockedPointerHandleUnlocked(void* userData,
|
||||
--
|
||||
2.42.0
|
||||
|
||||
4
flatpak/prime-run
Normal file
4
flatpak/prime-run
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
export __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||||
exec "$@"
|
||||
11
flatpak/prismlauncher
Normal file
11
flatpak/prismlauncher
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
# discord RPC
|
||||
for i in {0..9}; do
|
||||
test -S "$XDG_RUNTIME_DIR"/discord-ipc-"$i" || ln -sf {app/com.discordapp.Discord,"$XDG_RUNTIME_DIR"}/discord-ipc-"$i";
|
||||
done
|
||||
|
||||
export PATH="${PATH}${PATH:+:}/usr/lib/extensions/vulkan/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin"
|
||||
export VK_LAYER_PATH="/usr/lib/extensions/vulkan/share/vulkan/implicit_layer.d/"
|
||||
|
||||
exec /app/bin/prismrun "$@"
|
||||
1
flatpak/shared-modules
Submodule
1
flatpak/shared-modules
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit f2b0c16a2a217a1822ce5a6538ba8f755ed1dd32
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
|
@ -46,16 +44,16 @@
|
|||
#include <QIcon>
|
||||
#include <QMutex>
|
||||
#include <QUrl>
|
||||
#include <memory>
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include <BaseInstance.h>
|
||||
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "minecraft/launch/MinecraftTarget.h"
|
||||
|
||||
class LaunchController;
|
||||
class LocalPeer;
|
||||
class InstanceWindow;
|
||||
class MainWindow;
|
||||
class ViewLogWindow;
|
||||
class SetupWizard;
|
||||
class GenericPageProvider;
|
||||
class QFile;
|
||||
|
|
@ -74,12 +72,6 @@ class ITheme;
|
|||
class MCEditTool;
|
||||
class ThemeManager;
|
||||
class IconTheme;
|
||||
class BaseInstance;
|
||||
|
||||
class LogModel;
|
||||
|
||||
struct MinecraftTarget;
|
||||
class MinecraftAccount;
|
||||
|
||||
namespace Meta {
|
||||
class Index;
|
||||
|
|
@ -97,6 +89,7 @@ class Index;
|
|||
#define APPLICATION_DYN (dynamic_cast<Application*>(QCoreApplication::instance()))
|
||||
|
||||
class Application : public QApplication {
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Status { StartingUp, Failed, Succeeded, Initialized };
|
||||
|
|
@ -117,29 +110,29 @@ class Application : public QApplication {
|
|||
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
SettingsObject* settings() const { return m_settings.get(); }
|
||||
std::shared_ptr<SettingsObject> settings() const { return m_settings; }
|
||||
|
||||
qint64 timeSinceStart() const { return m_startTime.msecsTo(QDateTime::currentDateTime()); }
|
||||
qint64 timeSinceStart() const { return startTime.msecsTo(QDateTime::currentDateTime()); }
|
||||
|
||||
QIcon logo();
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
|
||||
ThemeManager* themeManager() { return m_themeManager.get(); }
|
||||
|
||||
ExternalUpdater* updater() { return m_updater.get(); }
|
||||
shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }
|
||||
|
||||
void triggerUpdateCheck();
|
||||
|
||||
TranslationsModel* translations();
|
||||
std::shared_ptr<TranslationsModel> translations();
|
||||
|
||||
JavaInstallList* javalist();
|
||||
std::shared_ptr<JavaInstallList> javalist();
|
||||
|
||||
InstanceList* instances() const { return m_instances.get(); }
|
||||
std::shared_ptr<InstanceList> instances() const { return m_instances; }
|
||||
|
||||
IconList* icons() const { return m_icons.get(); }
|
||||
std::shared_ptr<IconList> icons() const { return m_icons; }
|
||||
|
||||
MCEditTool* mcedit() const { return m_mcedit.get(); }
|
||||
|
||||
AccountList* accounts() const { return m_accounts.get(); }
|
||||
shared_qobject_ptr<AccountList> accounts() const { return m_accounts; }
|
||||
|
||||
Status status() const { return m_status; }
|
||||
|
||||
|
|
@ -147,11 +140,11 @@ class Application : public QApplication {
|
|||
|
||||
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
|
||||
|
||||
QNetworkAccessManager* network();
|
||||
shared_qobject_ptr<QNetworkAccessManager> network();
|
||||
|
||||
HttpMetaCache* metacache();
|
||||
shared_qobject_ptr<HttpMetaCache> metacache();
|
||||
|
||||
Meta::Index* metadataIndex();
|
||||
shared_qobject_ptr<Meta::Index> metadataIndex();
|
||||
|
||||
void updateCapabilities();
|
||||
|
||||
|
|
@ -167,6 +160,7 @@ class Application : public QApplication {
|
|||
QString getFlameAPIKey();
|
||||
QString getModrinthAPIToken();
|
||||
QString getUserAgent();
|
||||
QString getUserAgentUncached();
|
||||
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString& root() { return m_rootPath; }
|
||||
|
|
@ -187,9 +181,8 @@ class Application : public QApplication {
|
|||
*/
|
||||
bool openJsonEditor(const QString& filename);
|
||||
|
||||
InstanceWindow* showInstanceWindow(BaseInstance* instance, QString page = QString());
|
||||
InstanceWindow* showInstanceWindow(InstancePtr instance, QString page = QString());
|
||||
MainWindow* showMainWindow(bool minimized = false);
|
||||
ViewLogWindow* showLogWindow();
|
||||
|
||||
void updateIsRunning(bool running);
|
||||
bool updatesAreAllowed();
|
||||
|
|
@ -199,12 +192,12 @@ class Application : public QApplication {
|
|||
bool updaterEnabled();
|
||||
QString updaterBinaryName();
|
||||
|
||||
QUrl normalizeImportUrl(const QString& url);
|
||||
QUrl normalizeImportUrl(QString const& url);
|
||||
|
||||
signals:
|
||||
void updateAllowedChanged(bool status);
|
||||
void globalSettingsAboutToOpen();
|
||||
void globalSettingsApplied();
|
||||
void globalSettingsClosed();
|
||||
int currentCatChanged(int index);
|
||||
|
||||
void oauthReplyRecieved(QVariantMap);
|
||||
|
|
@ -214,18 +207,19 @@ class Application : public QApplication {
|
|||
#endif
|
||||
|
||||
public slots:
|
||||
bool launch(BaseInstance* instance,
|
||||
LaunchMode mode = LaunchMode::Normal,
|
||||
std::shared_ptr<MinecraftTarget> targetToJoin = nullptr,
|
||||
shared_qobject_ptr<MinecraftAccount> accountToUse = nullptr,
|
||||
const QString& offlineName = QString());
|
||||
bool kill(BaseInstance* instance);
|
||||
bool launch(InstancePtr instance,
|
||||
bool online = true,
|
||||
bool demo = false,
|
||||
MinecraftTarget::Ptr targetToJoin = nullptr,
|
||||
MinecraftAccountPtr accountToUse = nullptr);
|
||||
bool kill(InstancePtr instance);
|
||||
void closeCurrentWindow();
|
||||
|
||||
private slots:
|
||||
void on_windowClose();
|
||||
void messageReceived(const QByteArray& message);
|
||||
void controllerFinished();
|
||||
void controllerSucceeded();
|
||||
void controllerFailed(const QString& error);
|
||||
void setupWizardFinished(int status);
|
||||
|
||||
private:
|
||||
|
|
@ -242,26 +236,22 @@ class Application : public QApplication {
|
|||
bool shouldExitNow() const;
|
||||
|
||||
private:
|
||||
QHash<QString, int> m_qsaveResources;
|
||||
mutable QMutex m_qsaveResourcesMutex;
|
||||
QDateTime startTime;
|
||||
|
||||
private:
|
||||
QDateTime m_startTime;
|
||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||
|
||||
std::unique_ptr<QNetworkAccessManager> m_network;
|
||||
shared_qobject_ptr<ExternalUpdater> m_updater;
|
||||
shared_qobject_ptr<AccountList> m_accounts;
|
||||
|
||||
std::unique_ptr<ExternalUpdater> m_updater;
|
||||
std::unique_ptr<AccountList> m_accounts;
|
||||
shared_qobject_ptr<HttpMetaCache> m_metacache;
|
||||
shared_qobject_ptr<Meta::Index> m_metadataIndex;
|
||||
|
||||
std::unique_ptr<HttpMetaCache> m_metacache;
|
||||
std::unique_ptr<Meta::Index> m_metadataIndex;
|
||||
|
||||
std::unique_ptr<SettingsObject> m_settings;
|
||||
std::unique_ptr<InstanceList> m_instances;
|
||||
std::unique_ptr<IconList> m_icons;
|
||||
std::unique_ptr<JavaInstallList> m_javalist;
|
||||
std::unique_ptr<TranslationsModel> m_translations;
|
||||
std::unique_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
std::shared_ptr<IconList> m_icons;
|
||||
std::shared_ptr<JavaInstallList> m_javalist;
|
||||
std::shared_ptr<TranslationsModel> m_translations;
|
||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::unique_ptr<MCEditTool> m_mcedit;
|
||||
QSet<QString> m_features;
|
||||
std::unique_ptr<ThemeManager> m_themeManager;
|
||||
|
|
@ -278,10 +268,15 @@ class Application : public QApplication {
|
|||
Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive;
|
||||
#endif
|
||||
|
||||
#if defined Q_OS_WIN32
|
||||
// used on Windows to attach the standard IO streams
|
||||
bool consoleAttached = false;
|
||||
#endif
|
||||
|
||||
// FIXME: attach to instances instead.
|
||||
struct InstanceXtras {
|
||||
InstanceWindow* window = nullptr;
|
||||
std::unique_ptr<LaunchController> controller;
|
||||
shared_qobject_ptr<LaunchController> controller;
|
||||
};
|
||||
std::map<QString, InstanceXtras> m_instanceExtras;
|
||||
mutable QMutex m_instanceExtrasMutex;
|
||||
|
|
@ -294,9 +289,6 @@ class Application : public QApplication {
|
|||
// main window, if any
|
||||
MainWindow* m_mainWindow = nullptr;
|
||||
|
||||
// log window, if any
|
||||
ViewLogWindow* m_viewLogWindow = nullptr;
|
||||
|
||||
// peer launcher instance connector - used to implement single instance launcher and signalling
|
||||
LocalPeer* m_peerInstance = nullptr;
|
||||
|
||||
|
|
@ -309,17 +301,17 @@ class Application : public QApplication {
|
|||
QString m_serverToJoin;
|
||||
QString m_worldToJoin;
|
||||
QString m_profileToUse;
|
||||
bool m_launchOffline = false;
|
||||
QString m_offlineName;
|
||||
bool m_liveCheck = false;
|
||||
QList<QUrl> m_urlsToImport;
|
||||
QString m_instanceIdToShowWindowOf;
|
||||
bool m_showMainWindow = false;
|
||||
std::unique_ptr<QFile> logFile;
|
||||
std::unique_ptr<LogModel> logModel;
|
||||
|
||||
public:
|
||||
void addQSavePath(QString);
|
||||
void removeQSavePath(QString);
|
||||
bool checkQSavePath(QString);
|
||||
|
||||
private:
|
||||
QHash<QString, int> m_qsaveResources;
|
||||
mutable QMutex m_qsaveResourcesMutex;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2025 Octol1ttle <l1ttleofficial@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(ASSERT_NEVER)
|
||||
#error ASSERT_NEVER already defined
|
||||
#else
|
||||
#define ASSERT_NEVER(cond) (Q_ASSERT((cond) == false), (cond))
|
||||
#endif
|
||||
|
|
@ -42,10 +42,8 @@
|
|||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Json.h"
|
||||
#include "launch/LaunchTask.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "settings/OverrideSetting.h"
|
||||
#include "settings/Setting.h"
|
||||
|
|
@ -54,26 +52,9 @@
|
|||
#include "Commandline.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
int getConsoleMaxLines(SettingsObject* settings)
|
||||
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : QObject()
|
||||
{
|
||||
auto lineSetting = settings->getSetting("ConsoleMaxLines");
|
||||
bool conversionOk = false;
|
||||
int maxLines = lineSetting->get().toInt(&conversionOk);
|
||||
if (!conversionOk) {
|
||||
maxLines = lineSetting->defValue().toInt();
|
||||
qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
|
||||
}
|
||||
return maxLines;
|
||||
}
|
||||
|
||||
bool shouldStopOnConsoleOverflow(SettingsObject* settings)
|
||||
{
|
||||
return settings->get("ConsoleOverflowStop").toBool();
|
||||
}
|
||||
|
||||
BaseInstance::BaseInstance(SettingsObject* globalSettings, std::unique_ptr<SettingsObject> settings, const QString& rootDir) : QObject()
|
||||
{
|
||||
m_settings = std::move(settings);
|
||||
m_settings = settings;
|
||||
m_global_settings = globalSettings;
|
||||
m_rootDir = rootDir;
|
||||
|
||||
|
|
@ -88,7 +69,6 @@ BaseInstance::BaseInstance(SettingsObject* globalSettings, std::unique_ptr<Setti
|
|||
m_settings->registerSetting("lastTimePlayed", 0);
|
||||
|
||||
m_settings->registerSetting("linkedInstances", "[]");
|
||||
m_settings->registerSetting("shortcuts", QString());
|
||||
|
||||
// Game time override
|
||||
auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false);
|
||||
|
|
@ -123,13 +103,10 @@ BaseInstance::BaseInstance(SettingsObject* globalSettings, std::unique_ptr<Setti
|
|||
m_settings->registerSetting("ManagedPackName", "");
|
||||
m_settings->registerSetting("ManagedPackVersionID", "");
|
||||
m_settings->registerSetting("ManagedPackVersionName", "");
|
||||
m_settings->registerSetting("ManagedPackURL", "");
|
||||
|
||||
m_settings->registerSetting("Profiler", "");
|
||||
}
|
||||
|
||||
BaseInstance::~BaseInstance() {}
|
||||
|
||||
QString BaseInstance::getPreLaunchCommand()
|
||||
{
|
||||
return settings()->get("PreLaunchCommand").toString();
|
||||
|
|
@ -197,35 +174,46 @@ void BaseInstance::copyManagedPack(BaseInstance& other)
|
|||
m_settings->set("ManagedPackName", other.getManagedPackName());
|
||||
m_settings->set("ManagedPackVersionID", other.getManagedPackVersionID());
|
||||
m_settings->set("ManagedPackVersionName", other.getManagedPackVersionName());
|
||||
}
|
||||
|
||||
if (APPLICATION->settings()->get("AutomaticJavaSwitch").toBool() && m_settings->get("AutomaticJava").toBool() &&
|
||||
m_settings->get("OverrideJavaLocation").toBool()) {
|
||||
m_settings->set("OverrideJavaLocation", false);
|
||||
m_settings->set("JavaPath", "");
|
||||
int BaseInstance::getConsoleMaxLines() const
|
||||
{
|
||||
auto lineSetting = m_settings->getSetting("ConsoleMaxLines");
|
||||
bool conversionOk = false;
|
||||
int maxLines = lineSetting->get().toInt(&conversionOk);
|
||||
if (!conversionOk) {
|
||||
maxLines = lineSetting->defValue().toInt();
|
||||
qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
|
||||
}
|
||||
return maxLines;
|
||||
}
|
||||
|
||||
bool BaseInstance::shouldStopOnConsoleOverflow() const
|
||||
{
|
||||
return m_settings->get("ConsoleOverflowStop").toBool();
|
||||
}
|
||||
|
||||
QStringList BaseInstance::getLinkedInstances() const
|
||||
{
|
||||
auto setting = m_settings->get("linkedInstances").toString();
|
||||
return Json::toStringList(setting);
|
||||
return m_settings->get("linkedInstances").toStringList();
|
||||
}
|
||||
|
||||
void BaseInstance::setLinkedInstances(const QStringList& list)
|
||||
{
|
||||
m_settings->set("linkedInstances", Json::fromStringList(list));
|
||||
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||
m_settings->set("linkedInstances", list);
|
||||
}
|
||||
|
||||
void BaseInstance::addLinkedInstanceId(const QString& id)
|
||||
{
|
||||
auto linkedInstances = getLinkedInstances();
|
||||
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||
linkedInstances.append(id);
|
||||
setLinkedInstances(linkedInstances);
|
||||
}
|
||||
|
||||
bool BaseInstance::removeLinkedInstanceId(const QString& id)
|
||||
{
|
||||
auto linkedInstances = getLinkedInstances();
|
||||
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||
int numRemoved = linkedInstances.removeAll(id);
|
||||
setLinkedInstances(linkedInstances);
|
||||
return numRemoved > 0;
|
||||
|
|
@ -233,7 +221,7 @@ bool BaseInstance::removeLinkedInstanceId(const QString& id)
|
|||
|
||||
bool BaseInstance::isLinkedToInstanceId(const QString& id) const
|
||||
{
|
||||
auto linkedInstances = getLinkedInstances();
|
||||
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||
return linkedInstances.contains(id);
|
||||
}
|
||||
|
||||
|
|
@ -339,11 +327,11 @@ QString BaseInstance::instanceRoot() const
|
|||
return m_rootDir;
|
||||
}
|
||||
|
||||
SettingsObject* BaseInstance::settings()
|
||||
SettingsObjectPtr BaseInstance::settings()
|
||||
{
|
||||
loadSpecificSettings();
|
||||
|
||||
return m_settings.get();
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
bool BaseInstance::canLaunch() const
|
||||
|
|
@ -398,63 +386,6 @@ void BaseInstance::setName(QString val)
|
|||
emit propertiesChanged(this);
|
||||
}
|
||||
|
||||
bool BaseInstance::syncInstanceDirName(const QString& newRoot) const
|
||||
{
|
||||
auto oldRoot = instanceRoot();
|
||||
return oldRoot == newRoot || QFile::rename(oldRoot, newRoot);
|
||||
}
|
||||
|
||||
void BaseInstance::registerShortcut(const ShortcutData& data)
|
||||
{
|
||||
auto currentShortcuts = shortcuts();
|
||||
currentShortcuts.append(data);
|
||||
qDebug() << "Registering shortcut for instance" << id() << "with name" << data.name << "and path" << data.filePath;
|
||||
setShortcuts(currentShortcuts);
|
||||
}
|
||||
|
||||
void BaseInstance::setShortcuts(const QList<ShortcutData>& shortcuts)
|
||||
{
|
||||
// FIXME: if no change, do not set. setting involves saving a file.
|
||||
QJsonArray array;
|
||||
for (const auto& elem : shortcuts) {
|
||||
array.append(QJsonObject{ { "name", elem.name }, { "filePath", elem.filePath }, { "target", static_cast<int>(elem.target) } });
|
||||
}
|
||||
|
||||
QJsonDocument document;
|
||||
document.setArray(array);
|
||||
m_settings->set("shortcuts", QString::fromUtf8(document.toJson(QJsonDocument::Compact)));
|
||||
}
|
||||
|
||||
QList<ShortcutData> BaseInstance::shortcuts() const
|
||||
{
|
||||
auto data = m_settings->get("shortcuts").toString().toUtf8();
|
||||
QJsonParseError parseError;
|
||||
auto document = QJsonDocument::fromJson(data, &parseError);
|
||||
if (parseError.error != QJsonParseError::NoError || !document.isArray())
|
||||
return {};
|
||||
|
||||
QList<ShortcutData> results;
|
||||
for (const auto& elem : document.array()) {
|
||||
if (!elem.isObject())
|
||||
continue;
|
||||
auto dict = elem.toObject();
|
||||
if (!dict.contains("name") || !dict.contains("filePath") || !dict.contains("target"))
|
||||
continue;
|
||||
int value = dict["target"].toInt(-1);
|
||||
if (!dict["name"].isString() || !dict["filePath"].isString() || value < 0 || value >= 3)
|
||||
continue;
|
||||
|
||||
QString shortcutName = dict["name"].toString();
|
||||
QString filePath = dict["filePath"].toString();
|
||||
if (!QDir(filePath).exists()) {
|
||||
qWarning() << "Shortcut" << shortcutName << "for instance" << name() << "have non-existent path" << filePath;
|
||||
continue;
|
||||
}
|
||||
results.append({ shortcutName, filePath, static_cast<ShortcutTarget>(value) });
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
QString BaseInstance::name() const
|
||||
{
|
||||
return m_settings->get("name").toString();
|
||||
|
|
@ -471,17 +402,12 @@ QStringList BaseInstance::extraArguments()
|
|||
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
|
||||
}
|
||||
|
||||
LaunchTask* BaseInstance::getLaunchTask()
|
||||
shared_qobject_ptr<LaunchTask> BaseInstance::getLaunchTask()
|
||||
{
|
||||
return m_launchProcess.get();
|
||||
return m_launchProcess;
|
||||
}
|
||||
|
||||
void BaseInstance::updateRuntimeContext()
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
bool BaseInstance::isLegacy()
|
||||
{
|
||||
return traits().contains("legacyLaunch") || traits().contains("alphaLaunch");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@
|
|||
#pragma once
|
||||
#include <cassert>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QMenu>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
|
|
@ -52,6 +50,7 @@
|
|||
#include "BaseVersionList.h"
|
||||
#include "MessageLevel.h"
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "pathmatcher/IPathMatcher.h"
|
||||
#include "settings/INIFile.h"
|
||||
|
||||
#include "net/Mode.h"
|
||||
|
|
@ -64,19 +63,8 @@ class Task;
|
|||
class LaunchTask;
|
||||
class BaseInstance;
|
||||
|
||||
/// Shortcut saving target representations
|
||||
enum class ShortcutTarget { Desktop, Applications, Other };
|
||||
|
||||
/// Shortcut data representation
|
||||
struct ShortcutData {
|
||||
QString name;
|
||||
QString filePath;
|
||||
ShortcutTarget target = ShortcutTarget::Other;
|
||||
};
|
||||
|
||||
/// Console settings
|
||||
int getConsoleMaxLines(SettingsObject* settings);
|
||||
bool shouldStopOnConsoleOverflow(SettingsObject* settings);
|
||||
// pointer for lazy people
|
||||
using InstancePtr = std::shared_ptr<BaseInstance>;
|
||||
|
||||
/*!
|
||||
* \brief Base class for instances.
|
||||
|
|
@ -86,11 +74,11 @@ bool shouldStopOnConsoleOverflow(SettingsObject* settings);
|
|||
* To create a new instance type, create a new class inheriting from this class
|
||||
* and implement the pure virtual functions.
|
||||
*/
|
||||
class BaseInstance : public QObject {
|
||||
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance> {
|
||||
Q_OBJECT
|
||||
protected:
|
||||
/// no-touchy!
|
||||
BaseInstance(SettingsObject* globalSettings, std::unique_ptr<SettingsObject> settings, const QString& rootDir);
|
||||
BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir);
|
||||
|
||||
public: /* types */
|
||||
enum class Status {
|
||||
|
|
@ -100,7 +88,7 @@ class BaseInstance : public QObject {
|
|||
|
||||
public:
|
||||
/// virtual destructor to make sure the destruction is COMPLETE
|
||||
virtual ~BaseInstance();
|
||||
virtual ~BaseInstance() {}
|
||||
|
||||
virtual void saveNow() = 0;
|
||||
|
||||
|
|
@ -138,14 +126,6 @@ class BaseInstance : public QObject {
|
|||
QString name() const;
|
||||
void setName(QString val);
|
||||
|
||||
/// Sync name and rename instance dir accordingly; returns true if successful
|
||||
bool syncInstanceDirName(const QString& newRoot) const;
|
||||
|
||||
/// Register a created shortcut
|
||||
void registerShortcut(const ShortcutData& data);
|
||||
QList<ShortcutData> shortcuts() const;
|
||||
void setShortcuts(const QList<ShortcutData>& shortcuts);
|
||||
|
||||
/// Value used for instance window titles
|
||||
QString windowTitle() const;
|
||||
|
||||
|
|
@ -168,6 +148,9 @@ class BaseInstance : public QObject {
|
|||
void setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version);
|
||||
void copyManagedPack(BaseInstance& other);
|
||||
|
||||
/// guess log level from a line of game log
|
||||
virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString& line, MessageLevel::Enum level) { return level; }
|
||||
|
||||
virtual QStringList extraArguments();
|
||||
|
||||
/// Traits. Normally inside the version, depends on instance implementation.
|
||||
|
|
@ -190,7 +173,7 @@ class BaseInstance : public QObject {
|
|||
*
|
||||
* \return A pointer to this instance's settings object.
|
||||
*/
|
||||
virtual SettingsObject* settings();
|
||||
virtual SettingsObjectPtr settings();
|
||||
|
||||
/*!
|
||||
* \brief Loads settings specific to an instance type if they're not already loaded.
|
||||
|
|
@ -201,10 +184,10 @@ class BaseInstance : public QObject {
|
|||
virtual QList<Task::Ptr> createUpdateTask() = 0;
|
||||
|
||||
/// returns a valid launcher (task container)
|
||||
virtual LaunchTask* createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
|
||||
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
|
||||
|
||||
/// returns the current launch task (if any)
|
||||
LaunchTask* getLaunchTask();
|
||||
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
||||
|
||||
/*!
|
||||
* Create envrironment variables for running the instance
|
||||
|
|
@ -212,10 +195,15 @@ class BaseInstance : public QObject {
|
|||
virtual QProcessEnvironment createEnvironment() = 0;
|
||||
virtual QProcessEnvironment createLaunchEnvironment() = 0;
|
||||
|
||||
/*!
|
||||
* Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
|
||||
*/
|
||||
virtual IPathMatcher::Ptr getLogFileMatcher() = 0;
|
||||
|
||||
/*!
|
||||
* Returns the root folder to use for looking up log files
|
||||
*/
|
||||
virtual QStringList getLogFileSearchPaths() = 0;
|
||||
virtual QString getLogFileRoot() = 0;
|
||||
|
||||
virtual QString getStatusbarDescription() = 0;
|
||||
|
||||
|
|
@ -272,18 +260,19 @@ class BaseInstance : public QObject {
|
|||
|
||||
Status currentStatus() const;
|
||||
|
||||
int getConsoleMaxLines() const;
|
||||
bool shouldStopOnConsoleOverflow() const;
|
||||
|
||||
QStringList getLinkedInstances() const;
|
||||
void setLinkedInstances(const QStringList& list);
|
||||
void addLinkedInstanceId(const QString& id);
|
||||
bool removeLinkedInstanceId(const QString& id);
|
||||
bool isLinkedToInstanceId(const QString& id) const;
|
||||
|
||||
bool isLegacy();
|
||||
|
||||
protected:
|
||||
void changeStatus(Status newStatus);
|
||||
|
||||
SettingsObject* globalSettings() const { return m_global_settings; }
|
||||
SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); }
|
||||
|
||||
bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; }
|
||||
void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; }
|
||||
|
|
@ -294,7 +283,7 @@ class BaseInstance : public QObject {
|
|||
*/
|
||||
void propertiesChanged(BaseInstance* inst);
|
||||
|
||||
void launchTaskChanged(LaunchTask*);
|
||||
void launchTaskChanged(shared_qobject_ptr<LaunchTask>);
|
||||
|
||||
void runningStatusChanged(bool running);
|
||||
|
||||
|
|
@ -307,10 +296,10 @@ class BaseInstance : public QObject {
|
|||
|
||||
protected: /* data */
|
||||
QString m_rootDir;
|
||||
std::unique_ptr<SettingsObject> m_settings;
|
||||
SettingsObjectPtr m_settings;
|
||||
// InstanceFlags m_flags;
|
||||
bool m_isRunning = false;
|
||||
std::unique_ptr<LaunchTask> m_launchProcess;
|
||||
shared_qobject_ptr<LaunchTask> m_launchProcess;
|
||||
QDateTime m_timeStarted;
|
||||
RuntimeContext m_runtimeContext;
|
||||
|
||||
|
|
@ -320,7 +309,7 @@ class BaseInstance : public QObject {
|
|||
bool m_hasUpdate = false;
|
||||
bool m_hasBrokenVersion = false;
|
||||
|
||||
SettingsObject* m_global_settings;
|
||||
SettingsObjectWeakPtr m_global_settings;
|
||||
bool m_specific_settings_loaded = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -24,28 +24,27 @@
|
|||
*/
|
||||
class BaseVersion {
|
||||
public:
|
||||
// TODO: delete
|
||||
using Ptr = std::shared_ptr<BaseVersion>;
|
||||
virtual ~BaseVersion() {}
|
||||
/*!
|
||||
* A string used to identify this version in config files.
|
||||
* This should be unique within the version list or shenanigans will occur.
|
||||
*/
|
||||
virtual QString descriptor() const = 0;
|
||||
virtual QString descriptor() = 0;
|
||||
|
||||
/*!
|
||||
* The name of this version as it is displayed to the user.
|
||||
* For example: "1.5.1"
|
||||
*/
|
||||
virtual QString name() const = 0;
|
||||
virtual QString name() = 0;
|
||||
|
||||
/*!
|
||||
* This should return a string that describes
|
||||
* the kind of version this is (Stable, Beta, Snapshot, whatever)
|
||||
*/
|
||||
virtual QString typeString() const = 0;
|
||||
virtual bool operator<(BaseVersion& a) const { return name() < a.name(); }
|
||||
virtual bool operator>(BaseVersion& a) const { return name() > a.name(); }
|
||||
virtual bool operator<(BaseVersion& a) { return name() < a.name(); }
|
||||
virtual bool operator>(BaseVersion& a) { return name() > a.name(); }
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(BaseVersion::Ptr)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class BaseVersionList : public QAbstractListModel {
|
|||
* The task returned by this function should reset the model when it's done.
|
||||
* \return A pointer to a task that reloads the version list.
|
||||
*/
|
||||
virtual Task::Ptr getLoadTask(bool forceReload = false) = 0;
|
||||
virtual Task::Ptr getLoadTask() = 0;
|
||||
|
||||
//! Checks whether or not the list is loaded. If this returns false, the list should be
|
||||
// loaded.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
#include <QtConcurrent>
|
||||
|
||||
DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, Filter pathMatcher)
|
||||
DataMigrationTask::DataMigrationTask(const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathMatcher)
|
||||
: Task(), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
|
||||
{
|
||||
m_copy.matcher(m_pathMatcher).whitelist(true);
|
||||
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
|
||||
}
|
||||
|
||||
void DataMigrationTask::executeTask()
|
||||
|
|
@ -24,7 +24,7 @@ void DataMigrationTask::executeTask()
|
|||
|
||||
// 1. Scan
|
||||
// Check how many files we gotta copy
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||
return m_copy(true); // dry run to collect amount of files
|
||||
});
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||
|
|
@ -37,7 +37,11 @@ void DataMigrationTask::dryRunFinished()
|
|||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
||||
#else
|
||||
if (!m_copyFuture.result()) {
|
||||
#endif
|
||||
emitFailed(tr("Failed to scan source path."));
|
||||
return;
|
||||
}
|
||||
|
|
@ -53,7 +57,7 @@ void DataMigrationTask::dryRunFinished()
|
|||
setProgress(m_copy.totalCopied(), m_toCopy);
|
||||
setStatus(tr("Copying %1…").arg(shortenedName));
|
||||
});
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||
return m_copy(false); // actually copy now
|
||||
});
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||
|
|
@ -63,7 +67,7 @@ void DataMigrationTask::dryRunFinished()
|
|||
|
||||
void DataMigrationTask::dryRunAborted()
|
||||
{
|
||||
emitAborted();
|
||||
emitFailed(tr("Aborted"));
|
||||
}
|
||||
|
||||
void DataMigrationTask::copyFinished()
|
||||
|
|
@ -71,7 +75,11 @@ void DataMigrationTask::copyFinished()
|
|||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
||||
#else
|
||||
if (!m_copyFuture.result()) {
|
||||
#endif
|
||||
emitFailed(tr("Some paths could not be copied!"));
|
||||
return;
|
||||
}
|
||||
|
|
@ -81,5 +89,5 @@ void DataMigrationTask::copyFinished()
|
|||
|
||||
void DataMigrationTask::copyAborted()
|
||||
{
|
||||
emitAborted();
|
||||
emitFailed(tr("Aborted"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "Filter.h"
|
||||
#include "pathmatcher/IPathMatcher.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
#include <QFuture>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
class DataMigrationTask : public Task {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DataMigrationTask(const QString& sourcePath, const QString& targetPath, Filter pathmatcher);
|
||||
explicit DataMigrationTask(const QString& sourcePath, const QString& targetPath, IPathMatcher::Ptr pathmatcher);
|
||||
~DataMigrationTask() override = default;
|
||||
|
||||
protected:
|
||||
|
|
@ -33,7 +33,7 @@ class DataMigrationTask : public Task {
|
|||
private:
|
||||
const QString& m_sourcePath;
|
||||
const QString& m_targetPath;
|
||||
const Filter m_pathMatcher;
|
||||
const IPathMatcher::Ptr m_pathMatcher;
|
||||
|
||||
FS::copy m_copy;
|
||||
int m_toCopy = 0;
|
||||
|
|
|
|||
23
launcher/DefaultVariable.h
Normal file
23
launcher/DefaultVariable.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
template <typename T>
|
||||
class DefaultVariable {
|
||||
public:
|
||||
DefaultVariable(const T& value) { defaultValue = value; }
|
||||
DefaultVariable<T>& operator=(const T& value)
|
||||
{
|
||||
currentValue = value;
|
||||
is_default = currentValue == defaultValue;
|
||||
is_explicit = true;
|
||||
return *this;
|
||||
}
|
||||
operator const T&() const { return is_default ? defaultValue : currentValue; }
|
||||
bool isDefault() const { return is_default; }
|
||||
bool isExplicit() const { return is_explicit; }
|
||||
|
||||
private:
|
||||
T currentValue;
|
||||
T defaultValue;
|
||||
bool is_default = true;
|
||||
bool is_explicit = false;
|
||||
};
|
||||
|
|
@ -44,4 +44,4 @@ QIcon FastFileIconProvider::icon(const QFileInfo& info) const
|
|||
}
|
||||
|
||||
return QApplication::style()->standardIcon(icon);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,4 +23,4 @@
|
|||
class FastFileIconProvider : public QFileIconProvider {
|
||||
public:
|
||||
QIcon icon(const QFileInfo& info) const override;
|
||||
};
|
||||
};
|
||||
|
|
@ -40,11 +40,12 @@
|
|||
#include <QFileSystemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStack>
|
||||
#include <algorithm>
|
||||
#include "FileSystem.h"
|
||||
#include "SeparatorPrefixTree.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), m_root(root) {}
|
||||
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {}
|
||||
// NOTE: Sadly, we have to do sorting ourselves.
|
||||
bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||
{
|
||||
|
|
@ -103,10 +104,10 @@ QVariant FileIgnoreProxy::data(const QModelIndex& index, int role) const
|
|||
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto cover = m_blocked.cover(blockedPath);
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
if (!cover.isNull()) {
|
||||
return QVariant(Qt::Unchecked);
|
||||
} else if (m_blocked.exists(blockedPath)) {
|
||||
} else if (blocked.exists(blockedPath)) {
|
||||
return QVariant(Qt::PartiallyChecked);
|
||||
} else {
|
||||
return QVariant(Qt::Checked);
|
||||
|
|
@ -129,7 +130,7 @@ bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, i
|
|||
|
||||
QString FileIgnoreProxy::relPath(const QString& path) const
|
||||
{
|
||||
return QDir(m_root).relativeFilePath(path);
|
||||
return QDir(root).relativeFilePath(path);
|
||||
}
|
||||
|
||||
bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
|
||||
|
|
@ -145,18 +146,18 @@ bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
|
|||
bool changed = false;
|
||||
if (state == Qt::Unchecked) {
|
||||
// blocking a path
|
||||
auto& node = m_blocked.insert(blockedPath);
|
||||
auto& node = blocked.insert(blockedPath);
|
||||
// get rid of all blocked nodes below
|
||||
node.clear();
|
||||
changed = true;
|
||||
} else if (state == Qt::Checked || state == Qt::PartiallyChecked) {
|
||||
if (!m_blocked.remove(blockedPath)) {
|
||||
auto cover = m_blocked.cover(blockedPath);
|
||||
if (!blocked.remove(blockedPath)) {
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
qDebug() << "Blocked by cover" << cover;
|
||||
// uncover
|
||||
m_blocked.remove(cover);
|
||||
blocked.remove(cover);
|
||||
// block all contents, except for any cover
|
||||
QModelIndex rootIndex = fsm->index(FS::PathCombine(m_root, cover));
|
||||
QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover));
|
||||
QModelIndex doing = rootIndex;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
|
|
@ -178,7 +179,7 @@ bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
|
|||
todo.push(node);
|
||||
} else {
|
||||
// or just block this one.
|
||||
m_blocked.insert(relpath);
|
||||
blocked.insert(relpath);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
|
|
@ -228,7 +229,7 @@ bool FileIgnoreProxy::shouldExpand(QModelIndex index)
|
|||
return false;
|
||||
}
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto found = m_blocked.find(blockedPath);
|
||||
auto found = blocked.find(blockedPath);
|
||||
if (found) {
|
||||
return !found->leaf();
|
||||
}
|
||||
|
|
@ -238,8 +239,8 @@ bool FileIgnoreProxy::shouldExpand(QModelIndex index)
|
|||
void FileIgnoreProxy::setBlockedPaths(QStringList paths)
|
||||
{
|
||||
beginResetModel();
|
||||
m_blocked.clear();
|
||||
m_blocked.insert(paths);
|
||||
blocked.clear();
|
||||
blocked.insert(paths);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
|
@ -266,45 +267,10 @@ bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceP
|
|||
|
||||
bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const
|
||||
{
|
||||
if (m_ignoreFiles.contains(fileInfo.fileName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& suffix : m_ignoreFilesSuffixes) {
|
||||
if (fileInfo.fileName().endsWith(suffix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath()))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return m_ignoreFiles.contains(fileInfo.fileName()) || m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath()));
|
||||
}
|
||||
|
||||
bool FileIgnoreProxy::filterFile(const QFileInfo& file) const
|
||||
bool FileIgnoreProxy::filterFile(const QString& fileName) const
|
||||
{
|
||||
return m_blocked.covers(relPath(file.absoluteFilePath())) || ignoreFile(file);
|
||||
}
|
||||
|
||||
void FileIgnoreProxy::loadBlockedPathsFromFile(const QString& fileName)
|
||||
{
|
||||
QFile ignoreFile(fileName);
|
||||
if (!ignoreFile.open(QIODevice::ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
auto ignoreData = ignoreFile.readAll();
|
||||
auto string = QString::fromUtf8(ignoreData);
|
||||
setBlockedPaths(string.split('\n', Qt::SkipEmptyParts));
|
||||
}
|
||||
|
||||
void FileIgnoreProxy::saveBlockedPathsToFile(const QString& fileName)
|
||||
{
|
||||
auto ignoreData = blockedPaths().toStringList().join('\n').toUtf8();
|
||||
try {
|
||||
FS::write(fileName, ignoreData);
|
||||
} catch (const Exception& e) {
|
||||
qWarning() << e.cause();
|
||||
}
|
||||
return blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(root), fileName));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,20 +61,15 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
|
|||
|
||||
void setBlockedPaths(QStringList paths);
|
||||
|
||||
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return m_blocked; }
|
||||
inline SeparatorPrefixTree<'/'>& blockedPaths() { return m_blocked; }
|
||||
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; }
|
||||
inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; }
|
||||
|
||||
// list of file names that need to be removed completely from model
|
||||
inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; }
|
||||
inline QStringList& ignoreFilesWithSuffix() { return m_ignoreFilesSuffixes; }
|
||||
// list of relative paths that need to be removed completely from model
|
||||
inline SeparatorPrefixTree<'/'>& ignoreFilesWithPath() { return m_ignoreFilePaths; }
|
||||
|
||||
bool filterFile(const QFileInfo& fileName) const;
|
||||
|
||||
void loadBlockedPathsFromFile(const QString& fileName);
|
||||
|
||||
void saveBlockedPathsToFile(const QString& fileName);
|
||||
bool filterFile(const QString& fileName) const;
|
||||
|
||||
protected:
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const;
|
||||
|
|
@ -83,9 +78,8 @@ class FileIgnoreProxy : public QSortFilterProxyModel {
|
|||
bool ignoreFile(QFileInfo file) const;
|
||||
|
||||
private:
|
||||
const QString m_root;
|
||||
SeparatorPrefixTree<'/'> m_blocked;
|
||||
const QString root;
|
||||
SeparatorPrefixTree<'/'> blocked;
|
||||
QStringList m_ignoreFiles;
|
||||
QStringList m_ignoreFilesSuffixes;
|
||||
SeparatorPrefixTree<'/'> m_ignoreFilePaths;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
*/
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include <qcontainerfwd.h>
|
||||
#include <QPair>
|
||||
|
||||
#include "BuildConfig.h"
|
||||
|
|
@ -60,8 +59,10 @@
|
|||
#if defined Q_OS_WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <objbase.h>
|
||||
#include <objidl.h>
|
||||
#include <shlguid.h>
|
||||
#include <shlobj.h>
|
||||
#include <shobjidl.h>
|
||||
#include <sys/utime.h>
|
||||
#include <versionhelpers.h>
|
||||
|
|
@ -76,8 +77,24 @@
|
|||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
|
||||
#endif // __APPLE__
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#endif // MacOS min version check
|
||||
#endif // Other OSes version check
|
||||
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
#endif
|
||||
|
||||
// clone
|
||||
#if defined(Q_OS_LINUX)
|
||||
|
|
@ -106,10 +123,6 @@ namespace fs = std::filesystem;
|
|||
|
||||
#if defined(__MINGW32__)
|
||||
|
||||
// Avoid re-defining structs retroactively added to MinGW
|
||||
// https://github.com/mingw-w64/mingw-w64/issues/90#issuecomment-2829284729
|
||||
#if __MINGW64_VERSION_MAJOR < 13
|
||||
|
||||
struct _DUPLICATE_EXTENTS_DATA {
|
||||
HANDLE FileHandle;
|
||||
LARGE_INTEGER SourceFileOffset;
|
||||
|
|
@ -119,7 +132,6 @@ struct _DUPLICATE_EXTENTS_DATA {
|
|||
|
||||
using DUPLICATE_EXTENTS_DATA = _DUPLICATE_EXTENTS_DATA;
|
||||
using PDUPLICATE_EXTENTS_DATA = _DUPLICATE_EXTENTS_DATA*;
|
||||
#endif
|
||||
|
||||
struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
|
||||
WORD ChecksumAlgorithm; // Checksum algorithm. e.g. CHECKSUM_TYPE_UNCHANGED, CHECKSUM_TYPE_NONE, CHECKSUM_TYPE_CRC32
|
||||
|
|
@ -283,9 +295,6 @@ bool copyFileAttributes(QString src, QString dst)
|
|||
if (attrs == INVALID_FILE_ATTRIBUTES)
|
||||
return false;
|
||||
return SetFileAttributesW(dst.toStdWString().c_str(), attrs);
|
||||
#else
|
||||
Q_UNUSED(src);
|
||||
Q_UNUSED(dst);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
@ -332,8 +341,8 @@ bool copy::operator()(const QString& offset, bool dryRun)
|
|||
opt |= copy_opts::overwrite_existing;
|
||||
|
||||
// Function that'll do the actual copying
|
||||
auto copy_file = [this, dryRun, src, dst, opt, &err](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist))
|
||||
auto copy_file = [&](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
|
||||
return;
|
||||
|
||||
auto dst_path = PathCombine(dst, relative_dst_path);
|
||||
|
|
@ -419,8 +428,8 @@ void create_link::make_link_list(const QString& offset)
|
|||
m_recursive = true;
|
||||
|
||||
// Function that'll do the actual linking
|
||||
auto link_file = [this, dst](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist)) {
|
||||
auto link_file = [&](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) {
|
||||
qDebug() << "path" << relative_dst_path << "in black list or not in whitelist";
|
||||
return;
|
||||
}
|
||||
|
|
@ -436,7 +445,7 @@ void create_link::make_link_list(const QString& offset)
|
|||
link_file(src, "");
|
||||
} else {
|
||||
if (m_debug)
|
||||
qDebug().nospace() << "linking recursively: " << src << " to " << dst << ", max_depth: " << m_max_depth;
|
||||
qDebug() << "linking recursively:" << src << "to" << dst << ", max_depth:" << m_max_depth;
|
||||
QDir src_dir(src);
|
||||
QDirIterator source_it(src, QDir::Filter::Files | QDir::Filter::Hidden, QDirIterator::Subdirectories);
|
||||
|
||||
|
|
@ -514,7 +523,7 @@ void create_link::runPrivileged(const QString& offset)
|
|||
|
||||
QString serverName = BuildConfig.LAUNCHER_APP_BINARY_NAME + "_filelink_server" + StringUtils::getRandomAlphaNumeric();
|
||||
|
||||
connect(&m_linkServer, &QLocalServer::newConnection, this, [this, &gotResults]() {
|
||||
connect(&m_linkServer, &QLocalServer::newConnection, this, [&]() {
|
||||
qDebug() << "Client connected, sending out pairs";
|
||||
// construct block of data to send
|
||||
QByteArray block;
|
||||
|
|
@ -596,7 +605,7 @@ void create_link::runPrivileged(const QString& offset)
|
|||
}
|
||||
|
||||
ExternalLinkFileProcess* linkFileProcess = new ExternalLinkFileProcess(serverName, m_useHardLinks, this);
|
||||
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [this, &gotResults]() { emit finishedPrivileged(gotResults); });
|
||||
connect(linkFileProcess, &ExternalLinkFileProcess::processExited, this, [&]() { emit finishedPrivileged(gotResults); });
|
||||
connect(linkFileProcess, &ExternalLinkFileProcess::finished, linkFileProcess, &QObject::deleteLater);
|
||||
|
||||
linkFileProcess->start();
|
||||
|
|
@ -684,34 +693,11 @@ bool deletePath(QString path)
|
|||
return err.value() == 0;
|
||||
}
|
||||
|
||||
bool deleteContents(const QString& path)
|
||||
{
|
||||
const QFileInfo info(path);
|
||||
if (!info.exists()) {
|
||||
return true;
|
||||
}
|
||||
if (!info.isDir()) {
|
||||
qWarning() << "Attempted to delete contents of non-directory path:" << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(StringUtils::toStdString(path))) {
|
||||
std::error_code err;
|
||||
|
||||
fs::remove_all(entry.path(), err);
|
||||
if (err.value() != 0) {
|
||||
qWarning().nospace() << "Could not delete directory entry " << entry.path() << ": " << QString::fromStdString(err.message());
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool trash(QString path, QString* pathInTrash)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
return false;
|
||||
#else
|
||||
// FIXME: Figure out trash in Flatpak. Qt seemingly doesn't use the Trash portal
|
||||
if (DesktopServices::isFlatpak())
|
||||
return false;
|
||||
|
|
@ -720,6 +706,7 @@ bool trash(QString path, QString* pathInTrash)
|
|||
return false;
|
||||
#endif
|
||||
return QFile::moveToTrash(path, pathInTrash);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString PathCombine(const QString& path1, const QString& path2)
|
||||
|
|
@ -753,7 +740,11 @@ int pathDepth(const QString& path)
|
|||
|
||||
QFileInfo info(path);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
auto parts = QDir::toNativeSeparators(info.path()).split(QDir::separator(), QString::SkipEmptyParts);
|
||||
#else
|
||||
auto parts = QDir::toNativeSeparators(info.path()).split(QDir::separator(), Qt::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
int numParts = parts.length();
|
||||
numParts -= parts.count(".");
|
||||
|
|
@ -773,7 +764,11 @@ QString pathTruncate(const QString& path, int depth)
|
|||
return pathTruncate(trunc, depth);
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
auto parts = QDir::toNativeSeparators(trunc).split(QDir::separator(), QString::SkipEmptyParts);
|
||||
#else
|
||||
auto parts = QDir::toNativeSeparators(trunc).split(QDir::separator(), Qt::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
if (parts.startsWith(".") && !path.startsWith(".")) {
|
||||
parts.removeFirst();
|
||||
|
|
@ -823,33 +818,68 @@ QString NormalizePath(QString path)
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
const QString g_badChars = "<>:\"|?*\r\n!";
|
||||
QString removeChars(QString source, QChar replace, const QString& extraChars = "")
|
||||
{
|
||||
auto badChars = g_badChars;
|
||||
if (!extraChars.isEmpty()) {
|
||||
badChars += extraChars;
|
||||
}
|
||||
static const QString BAD_WIN_CHARS = "<>:\"|?*\r\n";
|
||||
static const QString BAD_NTFS_CHARS = "<>:\"|?*";
|
||||
static const QString BAD_HFS_CHARS = ":";
|
||||
|
||||
for (auto& c : source) {
|
||||
if (c.unicode() < 0x20 || !c.isPrint() || badChars.contains(c)) {
|
||||
c = replace;
|
||||
}
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
} // namespace
|
||||
static const QString BAD_FILENAME_CHARS = BAD_WIN_CHARS + "\\/";
|
||||
|
||||
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
|
||||
{
|
||||
return removeChars(std::move(string), replaceWith, "\\/");
|
||||
for (int i = 0; i < string.length(); i++)
|
||||
if (string.at(i) < ' ' || BAD_FILENAME_CHARS.contains(string.at(i)))
|
||||
string[i] = replaceWith;
|
||||
return string;
|
||||
}
|
||||
|
||||
QString RemoveInvalidPathChars(QString string, QChar replaceWith)
|
||||
QString RemoveInvalidPathChars(QString path, QChar replaceWith)
|
||||
{
|
||||
return removeChars(std::move(string), replaceWith);
|
||||
QString invalidChars;
|
||||
#ifdef Q_OS_WIN
|
||||
invalidChars = BAD_WIN_CHARS;
|
||||
#endif
|
||||
|
||||
// the null character is ignored in this check as it was not a problem until now
|
||||
switch (statFS(path).fsType) {
|
||||
case FilesystemType::FAT: // similar to NTFS
|
||||
/* fallthrough */
|
||||
case FilesystemType::NTFS:
|
||||
/* fallthrough */
|
||||
case FilesystemType::REFS: // similar to NTFS(should be available only on windows)
|
||||
invalidChars += BAD_NTFS_CHARS;
|
||||
break;
|
||||
// case FilesystemType::EXT:
|
||||
// case FilesystemType::EXT_2_OLD:
|
||||
// case FilesystemType::EXT_2_3_4:
|
||||
// case FilesystemType::XFS:
|
||||
// case FilesystemType::BTRFS:
|
||||
// case FilesystemType::NFS:
|
||||
// case FilesystemType::ZFS:
|
||||
case FilesystemType::APFS:
|
||||
/* fallthrough */
|
||||
case FilesystemType::HFS:
|
||||
/* fallthrough */
|
||||
case FilesystemType::HFSPLUS:
|
||||
/* fallthrough */
|
||||
case FilesystemType::HFSX:
|
||||
invalidChars += BAD_HFS_CHARS;
|
||||
break;
|
||||
// case FilesystemType::FUSEBLK:
|
||||
// case FilesystemType::F2FS:
|
||||
// case FilesystemType::UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (invalidChars.size() != 0) {
|
||||
for (int i = 0; i < path.length(); i++) {
|
||||
if (path.at(i) < ' ' || invalidChars.contains(path.at(i))) {
|
||||
path[i] = replaceWith;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
QString DirNameFromString(QString string, QString inDir)
|
||||
|
|
@ -885,70 +915,48 @@ QString getDesktopDir()
|
|||
return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
}
|
||||
|
||||
QString getApplicationsDir()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
|
||||
}
|
||||
|
||||
QString quoteArgs(const QStringList& args, const QString& wrap, const QString& escapeChar, bool wrapOnlyIfNeeded = false)
|
||||
{
|
||||
QString result;
|
||||
|
||||
auto size = args.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
QString arg = args[i];
|
||||
arg.replace(wrap, escapeChar);
|
||||
|
||||
bool needsWrapping = !wrapOnlyIfNeeded || arg.contains(' ') || arg.contains('\t') || arg.contains(wrap);
|
||||
|
||||
if (needsWrapping)
|
||||
result += wrap + arg + wrap;
|
||||
else
|
||||
result += arg;
|
||||
|
||||
if (i < size - 1)
|
||||
result += ' ';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Cross-platform Shortcut creation
|
||||
QString createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
||||
{
|
||||
if (destination.isEmpty()) {
|
||||
destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name));
|
||||
}
|
||||
if (!ensureFilePathExists(destination)) {
|
||||
qWarning() << "Destination path can't be created!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
#if defined(Q_OS_MACOS)
|
||||
QDir application = destination + ".app/";
|
||||
// Create the Application
|
||||
QDir applicationDirectory =
|
||||
QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/";
|
||||
|
||||
if (!applicationDirectory.mkpath(".")) {
|
||||
qWarning() << "Couldn't create application directory";
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir application = applicationDirectory.path() + "/" + name + ".app/";
|
||||
|
||||
if (application.exists()) {
|
||||
qWarning() << "Application already exists!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!application.mkpath(".")) {
|
||||
qWarning() << "Couldn't create application";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir content = application.path() + "/Contents/";
|
||||
QDir resources = content.path() + "/Resources/";
|
||||
QDir binaryDir = content.path() + "/MacOS/";
|
||||
QFile info(content.path() + "/Info.plist");
|
||||
QFile info = content.path() + "/Info.plist";
|
||||
|
||||
if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) {
|
||||
qWarning() << "Couldn't create directories within application";
|
||||
return QString();
|
||||
}
|
||||
if (!info.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qWarning() << "Failed to open file" << info.fileName() << "for writing:" << info.errorString();
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
info.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
|
||||
QFile(icon).rename(resources.path() + "/Icon.icns");
|
||||
|
||||
|
|
@ -956,13 +964,12 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
|
|||
QString exec = binaryDir.path() + "/Run.command";
|
||||
|
||||
QFile f(exec);
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qWarning() << "Failed to open file" << f.fileName() << "for writing:" << f.errorString();
|
||||
return QString();
|
||||
}
|
||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream stream(&f);
|
||||
|
||||
auto argstring = quoteArgs(args, "\"", "\\\"");
|
||||
QString argstring;
|
||||
if (!args.empty())
|
||||
argstring = " \"" + args.join("\" \"") + "\"";
|
||||
|
||||
stream << "#!/bin/bash" << "\n";
|
||||
stream << "\"" << target << "\" " << argstring << "\n";
|
||||
|
|
@ -996,23 +1003,22 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
|
|||
"</dict>\n"
|
||||
"</plist>";
|
||||
|
||||
return application.path();
|
||||
return true;
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||
if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated
|
||||
destination += ".desktop";
|
||||
QFile f(destination);
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qWarning() << "Failed to open file" << f.fileName() << "for writing:" << f.errorString();
|
||||
return QString();
|
||||
}
|
||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream stream(&f);
|
||||
|
||||
auto argstring = quoteArgs(args, "'", "'\\''");
|
||||
QString argstring;
|
||||
if (!args.empty())
|
||||
argstring = " '" + args.join("' '") + "'";
|
||||
|
||||
stream << "[Desktop Entry]" << "\n";
|
||||
stream << "Type=Application" << "\n";
|
||||
stream << "Categories=Game;ActionGame;AdventureGame;Simulation" << "\n";
|
||||
stream << "Exec=\"" << target.toLocal8Bit() << "\" " << argstring.toLocal8Bit() << "\n";
|
||||
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
|
||||
stream << "Name=" << name.toLocal8Bit() << "\n";
|
||||
if (!icon.isEmpty()) {
|
||||
stream << "Icon=" << icon.toLocal8Bit() << "\n";
|
||||
|
|
@ -1023,38 +1029,51 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
|
|||
|
||||
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
||||
|
||||
return destination;
|
||||
return true;
|
||||
#elif defined(Q_OS_WIN)
|
||||
QFileInfo targetInfo(target);
|
||||
|
||||
if (!targetInfo.exists()) {
|
||||
qWarning() << "Target file does not exist!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
target = targetInfo.absoluteFilePath();
|
||||
|
||||
if (target.length() >= MAX_PATH) {
|
||||
qWarning() << "Target file path is too long!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!icon.isEmpty() && icon.length() >= MAX_PATH) {
|
||||
qWarning() << "Icon path is too long!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
destination += ".lnk";
|
||||
|
||||
if (destination.length() >= MAX_PATH) {
|
||||
qWarning() << "Destination path is too long!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString argStr;
|
||||
int argCount = args.count();
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
if (args[i].contains(' ')) {
|
||||
argStr.append('"').append(args[i]).append('"');
|
||||
} else {
|
||||
argStr.append(args[i]);
|
||||
}
|
||||
|
||||
if (i < argCount - 1) {
|
||||
argStr.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
auto argStr = quoteArgs(args, "\"", "\\\"", true);
|
||||
if (argStr.length() >= MAX_PATH) {
|
||||
qWarning() << "Arguments string is too long!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hres;
|
||||
|
|
@ -1063,7 +1082,7 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
|
|||
hres = CoInitialize(nullptr);
|
||||
if (FAILED(hres)) {
|
||||
qWarning() << "Failed to initialize COM!";
|
||||
return QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
WCHAR wsz[MAX_PATH];
|
||||
|
|
@ -1101,28 +1120,26 @@ QString createShortcut(QString destination, QString target, QStringList args, QS
|
|||
hres = ppf->Save(wsz, TRUE);
|
||||
if (FAILED(hres)) {
|
||||
qWarning() << "IPresistFile->Save() failed";
|
||||
qWarning() << "hres =" << hres;
|
||||
qWarning() << "hres = " << hres;
|
||||
}
|
||||
ppf->Release();
|
||||
} else {
|
||||
qWarning() << "Failed to query IPersistFile interface from IShellLink instance";
|
||||
qWarning() << "hres =" << hres;
|
||||
qWarning() << "hres = " << hres;
|
||||
}
|
||||
psl->Release();
|
||||
} else {
|
||||
qWarning() << "Failed to create IShellLink instance";
|
||||
qWarning() << "hres =" << hres;
|
||||
qWarning() << "hres = " << hres;
|
||||
}
|
||||
|
||||
// go away COM, nobody likes you
|
||||
CoUninitialize();
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
return destination;
|
||||
return QString();
|
||||
return SUCCEEDED(hres);
|
||||
#else
|
||||
qWarning("Desktop Shortcuts not supported on your platform!");
|
||||
return QString();
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1278,8 +1295,8 @@ bool clone::operator()(const QString& offset, bool dryRun)
|
|||
std::error_code err;
|
||||
|
||||
// Function that'll do the actual cloneing
|
||||
auto cloneFile = [this, dryRun, dst, &err](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher(relative_dst_path) != m_whitelist))
|
||||
auto cloneFile = [&](QString src_path, QString relative_dst_path) {
|
||||
if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist))
|
||||
return;
|
||||
|
||||
auto dst_path = PathCombine(dst, relative_dst_path);
|
||||
|
|
@ -1400,14 +1417,14 @@ bool win_ioctl_clone(const std::wstring& src_path, const std::wstring& dst_path,
|
|||
ULONG fs_flags;
|
||||
if (!GetVolumeInformationByHandleW(hSourceFile, nullptr, 0, nullptr, nullptr, &fs_flags, nullptr, 0)) {
|
||||
ec = std::error_code(GetLastError(), std::system_category());
|
||||
qDebug() << "Failed to get Filesystem information for" << src_path.c_str();
|
||||
qDebug() << "Failed to get Filesystem information for " << src_path.c_str();
|
||||
CloseHandle(hSourceFile);
|
||||
return false;
|
||||
}
|
||||
if (!(fs_flags & FILE_SUPPORTS_BLOCK_REFCOUNTING)) {
|
||||
SetLastError(ERROR_NOT_CAPABLE);
|
||||
ec = std::error_code(GetLastError(), std::system_category());
|
||||
qWarning() << "Filesystem at" << src_path.c_str() << "does not support reflink";
|
||||
qWarning() << "Filesystem at " << src_path.c_str() << " does not support reflink";
|
||||
CloseHandle(hSourceFile);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1703,14 +1720,4 @@ QString getUniqueResourceName(const QString& filePath)
|
|||
|
||||
return newFileName;
|
||||
}
|
||||
bool removeFiles(QStringList listFile)
|
||||
{
|
||||
bool ret = true;
|
||||
// For each file
|
||||
for (int i = 0; i < listFile.count(); i++) {
|
||||
// Remove
|
||||
ret = ret && QFile::remove(listFile.at(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace FS
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Exception.h"
|
||||
#include "Filter.h"
|
||||
#include "pathmatcher/IPathMatcher.h"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
|
|
@ -115,9 +115,9 @@ class copy : public QObject {
|
|||
m_followSymlinks = follow;
|
||||
return *this;
|
||||
}
|
||||
copy& matcher(Filter filter)
|
||||
copy& matcher(const IPathMatcher* filter)
|
||||
{
|
||||
m_matcher = std::move(filter);
|
||||
m_matcher = filter;
|
||||
return *this;
|
||||
}
|
||||
copy& whitelist(bool whitelist)
|
||||
|
|
@ -147,7 +147,7 @@ class copy : public QObject {
|
|||
|
||||
private:
|
||||
bool m_followSymlinks = true;
|
||||
Filter m_matcher = nullptr;
|
||||
const IPathMatcher* m_matcher = nullptr;
|
||||
bool m_whitelist = false;
|
||||
bool m_overwrite = false;
|
||||
QDir m_src;
|
||||
|
|
@ -209,9 +209,9 @@ class create_link : public QObject {
|
|||
m_useHardLinks = useHard;
|
||||
return *this;
|
||||
}
|
||||
create_link& matcher(Filter filter)
|
||||
create_link& matcher(const IPathMatcher* filter)
|
||||
{
|
||||
m_matcher = std::move(filter);
|
||||
m_matcher = filter;
|
||||
return *this;
|
||||
}
|
||||
create_link& whitelist(bool whitelist)
|
||||
|
|
@ -260,7 +260,7 @@ class create_link : public QObject {
|
|||
|
||||
private:
|
||||
bool m_useHardLinks = false;
|
||||
Filter m_matcher = nullptr;
|
||||
const IPathMatcher* m_matcher = nullptr;
|
||||
bool m_whitelist = false;
|
||||
bool m_recursive = true;
|
||||
|
||||
|
|
@ -291,15 +291,6 @@ bool move(const QString& source, const QString& dest);
|
|||
*/
|
||||
bool deletePath(QString path);
|
||||
|
||||
/**
|
||||
* Delete a folder's contents recursively but not the folder itself.
|
||||
* @param path The path to the folder.
|
||||
* @return Whether the deletion was completely successful.
|
||||
*/
|
||||
bool deleteContents(const QString& path);
|
||||
|
||||
bool removeFiles(QStringList listFile);
|
||||
|
||||
/**
|
||||
* Trash a folder / file
|
||||
*/
|
||||
|
|
@ -362,18 +353,14 @@ bool checkProblemticPathJava(QDir folder);
|
|||
// Get the Directory representing the User's Desktop
|
||||
QString getDesktopDir();
|
||||
|
||||
// Get the Directory representing the User's Applications directory
|
||||
QString getApplicationsDir();
|
||||
|
||||
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
||||
// Equivalent to doing QDir::rename, but allowing for overrides
|
||||
bool overrideFolder(QString overwritten_path, QString override_path);
|
||||
|
||||
/**
|
||||
* Creates a shortcut to the specified target file at the specified destination path.
|
||||
* Returns null QString if creation failed; otherwise returns the path to the created shortcut.
|
||||
*/
|
||||
QString createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
||||
|
||||
enum class FilesystemType {
|
||||
FAT,
|
||||
|
|
@ -501,9 +488,9 @@ class clone : public QObject {
|
|||
m_src.setPath(src);
|
||||
m_dst.setPath(dst);
|
||||
}
|
||||
clone& matcher(Filter filter)
|
||||
clone& matcher(const IPathMatcher* filter)
|
||||
{
|
||||
m_matcher = std::move(filter);
|
||||
m_matcher = filter;
|
||||
return *this;
|
||||
}
|
||||
clone& whitelist(bool whitelist)
|
||||
|
|
@ -527,7 +514,7 @@ class clone : public QObject {
|
|||
bool operator()(const QString& offset, bool dryRun = false);
|
||||
|
||||
private:
|
||||
Filter m_matcher = nullptr;
|
||||
const IPathMatcher* m_matcher = nullptr;
|
||||
bool m_whitelist = false;
|
||||
QDir m_src;
|
||||
QDir m_dst;
|
||||
|
|
|
|||
37
launcher/Filter.cpp
Normal file
37
launcher/Filter.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "Filter.h"
|
||||
|
||||
ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {}
|
||||
bool ContainsFilter::accepts(const QString& value)
|
||||
{
|
||||
return value.contains(pattern);
|
||||
}
|
||||
|
||||
ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {}
|
||||
bool ExactFilter::accepts(const QString& value)
|
||||
{
|
||||
return value == pattern;
|
||||
}
|
||||
|
||||
ExactIfPresentFilter::ExactIfPresentFilter(const QString& pattern) : pattern(pattern) {}
|
||||
bool ExactIfPresentFilter::accepts(const QString& value)
|
||||
{
|
||||
return value.isEmpty() || value == pattern;
|
||||
}
|
||||
|
||||
RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert)
|
||||
{
|
||||
pattern.setPattern(regexp);
|
||||
pattern.optimize();
|
||||
}
|
||||
bool RegexpFilter::accepts(const QString& value)
|
||||
{
|
||||
auto match = pattern.match(value);
|
||||
bool matched = match.hasMatch();
|
||||
return invert ? (!matched) : (matched);
|
||||
}
|
||||
|
||||
ExactListFilter::ExactListFilter(const QStringList& pattern) : m_pattern(pattern) {}
|
||||
bool ExactListFilter::accepts(const QString& value)
|
||||
{
|
||||
return m_pattern.isEmpty() || m_pattern.contains(value);
|
||||
}
|
||||
|
|
@ -3,52 +3,59 @@
|
|||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
using Filter = std::function<bool(const QString&)>;
|
||||
class Filter {
|
||||
public:
|
||||
virtual ~Filter() = default;
|
||||
virtual bool accepts(const QString& value) = 0;
|
||||
};
|
||||
|
||||
namespace Filters {
|
||||
inline Filter inverse(Filter filter)
|
||||
{
|
||||
return [filter = std::move(filter)](const QString& src) { return !filter(src); };
|
||||
}
|
||||
class ContainsFilter : public Filter {
|
||||
public:
|
||||
ContainsFilter(const QString& pattern);
|
||||
virtual ~ContainsFilter() = default;
|
||||
bool accepts(const QString& value) override;
|
||||
|
||||
inline Filter any(QList<Filter> filters)
|
||||
{
|
||||
return [filters = std::move(filters)](const QString& src) {
|
||||
for (auto& filter : filters)
|
||||
if (filter(src))
|
||||
return true;
|
||||
private:
|
||||
QString pattern;
|
||||
};
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
class ExactFilter : public Filter {
|
||||
public:
|
||||
ExactFilter(const QString& pattern);
|
||||
virtual ~ExactFilter() = default;
|
||||
bool accepts(const QString& value) override;
|
||||
|
||||
inline Filter equals(QString pattern)
|
||||
{
|
||||
return [pattern = std::move(pattern)](const QString& src) { return src == pattern; };
|
||||
}
|
||||
private:
|
||||
QString pattern;
|
||||
};
|
||||
|
||||
inline Filter equalsAny(QStringList patterns = {})
|
||||
{
|
||||
return [patterns = std::move(patterns)](const QString& src) { return patterns.isEmpty() || patterns.contains(src); };
|
||||
}
|
||||
class ExactIfPresentFilter : public Filter {
|
||||
public:
|
||||
ExactIfPresentFilter(const QString& pattern);
|
||||
virtual ~ExactIfPresentFilter() override = default;
|
||||
bool accepts(const QString& value) override;
|
||||
|
||||
inline Filter equalsOrEmpty(QString pattern)
|
||||
{
|
||||
return [pattern = std::move(pattern)](const QString& src) { return src.isEmpty() || src == pattern; };
|
||||
}
|
||||
private:
|
||||
QString pattern;
|
||||
};
|
||||
|
||||
inline Filter contains(QString pattern)
|
||||
{
|
||||
return [pattern = std::move(pattern)](const QString& src) { return src.contains(pattern); };
|
||||
}
|
||||
class RegexpFilter : public Filter {
|
||||
public:
|
||||
RegexpFilter(const QString& regexp, bool invert);
|
||||
virtual ~RegexpFilter() = default;
|
||||
bool accepts(const QString& value) override;
|
||||
|
||||
inline Filter startsWith(QString pattern)
|
||||
{
|
||||
return [pattern = std::move(pattern)](const QString& src) { return src.startsWith(pattern); };
|
||||
}
|
||||
private:
|
||||
QRegularExpression pattern;
|
||||
bool invert = false;
|
||||
};
|
||||
|
||||
inline Filter regexp(QRegularExpression pattern)
|
||||
{
|
||||
return [pattern = std::move(pattern)](const QString& src) { return pattern.match(src).hasMatch(); };
|
||||
}
|
||||
} // namespace Filters
|
||||
class ExactListFilter : public Filter {
|
||||
public:
|
||||
ExactListFilter(const QStringList& pattern = {});
|
||||
virtual ~ExactListFilter() = default;
|
||||
bool accepts(const QString& value) override;
|
||||
|
||||
private:
|
||||
QStringList m_pattern;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
#include "GZip.h"
|
||||
#include <zlib.h>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes)
|
||||
{
|
||||
|
|
@ -138,82 +136,3 @@ bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int inf(QFile* source, std::function<bool(const QByteArray&)> handleBlock)
|
||||
{
|
||||
constexpr auto CHUNK = 16384;
|
||||
int ret;
|
||||
unsigned have;
|
||||
z_stream strm;
|
||||
memset(&strm, 0, sizeof(strm));
|
||||
char in[CHUNK];
|
||||
unsigned char out[CHUNK];
|
||||
|
||||
ret = inflateInit2(&strm, (16 + MAX_WBITS));
|
||||
if (ret != Z_OK)
|
||||
return ret;
|
||||
|
||||
/* decompress until deflate stream ends or end of file */
|
||||
do {
|
||||
strm.avail_in = source->read(in, CHUNK);
|
||||
if (source->error()) {
|
||||
(void)inflateEnd(&strm);
|
||||
return Z_ERRNO;
|
||||
}
|
||||
if (strm.avail_in == 0)
|
||||
break;
|
||||
strm.next_in = reinterpret_cast<Bytef*>(in);
|
||||
|
||||
/* run inflate() on input until output buffer not full */
|
||||
do {
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
ret = Z_DATA_ERROR;
|
||||
[[fallthrough]];
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
(void)inflateEnd(&strm);
|
||||
return ret;
|
||||
}
|
||||
have = CHUNK - strm.avail_out;
|
||||
if (!handleBlock(QByteArray(reinterpret_cast<const char*>(out), have))) {
|
||||
(void)inflateEnd(&strm);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
/* done when inflate() says it's done */
|
||||
} while (ret != Z_STREAM_END);
|
||||
|
||||
/* clean up and return */
|
||||
(void)inflateEnd(&strm);
|
||||
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
QString zerr(int ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case Z_ERRNO:
|
||||
return QObject::tr("error handling file");
|
||||
case Z_STREAM_ERROR:
|
||||
return QObject::tr("invalid compression level");
|
||||
case Z_DATA_ERROR:
|
||||
return QObject::tr("invalid or incomplete deflate data");
|
||||
case Z_MEM_ERROR:
|
||||
return QObject::tr("out of memory");
|
||||
case Z_VERSION_ERROR:
|
||||
return QObject::tr("zlib version mismatch!");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString GZip::readGzFileByBlocks(QFile* source, std::function<bool(const QByteArray&)> handleBlock)
|
||||
{
|
||||
auto ret = inf(source, handleBlock);
|
||||
return zerr(ret);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
#pragma once
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
|
||||
namespace GZip {
|
||||
|
||||
bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
|
||||
bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
|
||||
QString readGzFileByBlocks(QFile* source, std::function<bool(const QByteArray&)> handleBlock);
|
||||
|
||||
} // namespace GZip
|
||||
class GZip {
|
||||
public:
|
||||
static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
|
||||
static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,355 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "HardwareInfo.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
namespace {
|
||||
QString afterColon(QString str)
|
||||
{
|
||||
return str.remove(0, str.indexOf(':') + 2).trimmed();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
bool readFromOutput(const char* command, F function)
|
||||
{
|
||||
FILE* file = popen(command, "r"); // NOLINT(*-command-processor)
|
||||
if (!file) {
|
||||
qWarning().nospace() << "Could not execute command '" << command << "': " << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr size_t bufferSize = 512;
|
||||
std::array<char, bufferSize> buffer{};
|
||||
while (fgets(buffer.data(), bufferSize, file) != nullptr) {
|
||||
function(buffer.data());
|
||||
}
|
||||
|
||||
const int exitCode = pclose(file);
|
||||
if (exitCode != 0) {
|
||||
if (exitCode == -1) {
|
||||
qWarning().nospace() << "Could not close stream for command '" << command << "': " << strerror(errno);
|
||||
} else {
|
||||
qWarning().nospace() << "Command '" << command << "' exited with code " << exitCode;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <QSettings>
|
||||
|
||||
#include <dxgi1_6.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <wrl/client.h>
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
QString HardwareInfo::cpuInfo()
|
||||
{
|
||||
const QSettings registry(R"(HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0)", QSettings::NativeFormat);
|
||||
return registry.value("ProcessorNameString").toString();
|
||||
}
|
||||
|
||||
uint64_t HardwareInfo::totalRamMiB()
|
||||
{
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof status;
|
||||
|
||||
if (GlobalMemoryStatusEx(&status) == TRUE) {
|
||||
// transforming bytes -> mib
|
||||
return status.ullTotalPhys / 1024 / 1024;
|
||||
}
|
||||
|
||||
qWarning() << "Could not get total RAM: GlobalMemoryStatusEx";
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t HardwareInfo::availableRamMiB()
|
||||
{
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof status;
|
||||
|
||||
if (GlobalMemoryStatusEx(&status) == TRUE) {
|
||||
// transforming bytes -> mib
|
||||
return status.ullAvailPhys / 1024 / 1024;
|
||||
}
|
||||
|
||||
qWarning() << "Could not get available RAM: GlobalMemoryStatusEx";
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList HardwareInfo::gpuInfo()
|
||||
{
|
||||
ComPtr<IDXGIFactory6> factory;
|
||||
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
|
||||
if (FAILED(hr)) {
|
||||
qWarning() << "Could not create DXGI factory:" << Qt::hex << hr;
|
||||
return { "GPU discovery failed: could not create DXGI factory" };
|
||||
}
|
||||
|
||||
UINT i = 0;
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
QStringList out;
|
||||
while (factory->EnumAdapterByGpuPreference(i, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) != DXGI_ERROR_NOT_FOUND) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
hr = adapter->GetDesc(&desc);
|
||||
if (SUCCEEDED(hr)) {
|
||||
out << "GPU: " + QString::fromWCharArray(desc.Description); // NOLINT(*-pro-bounds-array-to-pointer-decay, *-no-array-decay)
|
||||
} else {
|
||||
qWarning() << "Could not get DXGI adapter description:" << Qt::hex << hr;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#include "sys/sysctl.h"
|
||||
|
||||
QString HardwareInfo::cpuInfo()
|
||||
{
|
||||
std::array<char, 512> buffer{};
|
||||
size_t bufferSize = buffer.size();
|
||||
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &bufferSize, nullptr, 0) == 0) {
|
||||
return { buffer.data() };
|
||||
}
|
||||
|
||||
qWarning() << "Could not get CPU model: sysctlbyname";
|
||||
return "";
|
||||
}
|
||||
|
||||
uint64_t HardwareInfo::totalRamMiB()
|
||||
{
|
||||
uint64_t memsize = 0;
|
||||
size_t memsizeSize = sizeof memsize;
|
||||
if (sysctlbyname("hw.memsize", &memsize, &memsizeSize, nullptr, 0) == 0) {
|
||||
// transforming bytes -> mib
|
||||
return memsize / 1024 / 1024;
|
||||
}
|
||||
|
||||
qWarning() << "Could not get total RAM: sysctlbyname";
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t HardwareInfo::availableRamMiB()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
MacOSHardwareInfo::MemoryPressureLevel MacOSHardwareInfo::memoryPressureLevel()
|
||||
{
|
||||
uint32_t level = 0;
|
||||
size_t levelSize = sizeof level;
|
||||
if (sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &levelSize, nullptr, 0) == 0) {
|
||||
return static_cast<MemoryPressureLevel>(level);
|
||||
}
|
||||
|
||||
qWarning() << "Could not get memory pressure level: sysctlbyname";
|
||||
return MemoryPressureLevel::Normal;
|
||||
}
|
||||
|
||||
QString MacOSHardwareInfo::memoryPressureLevelName()
|
||||
{
|
||||
// The names are internal, users refer to levels by their graph colors in Activity Monitor
|
||||
switch (memoryPressureLevel()) {
|
||||
case MemoryPressureLevel::Normal:
|
||||
return "Green";
|
||||
case MemoryPressureLevel::Warning:
|
||||
return "Yellow";
|
||||
case MemoryPressureLevel::Critical:
|
||||
return "Red";
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QStringList HardwareInfo::gpuInfo()
|
||||
{
|
||||
QStringList out;
|
||||
const bool success = readFromOutput("system_profiler SPDisplaysDataType", [&](const QString& str) {
|
||||
// Chipset Model: Intel HD Graphics 620
|
||||
if (str.contains("Chipset Model")) {
|
||||
out << "GPU: " + afterColon(str);
|
||||
}
|
||||
});
|
||||
if (!success) {
|
||||
return { "GPU discovery failed: could not read from system_profiler" };
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
#include <fstream>
|
||||
|
||||
QString HardwareInfo::cpuInfo()
|
||||
{
|
||||
std::ifstream cpuin("/proc/cpuinfo");
|
||||
for (std::string line; std::getline(cpuin, line);) {
|
||||
// model name : AMD Ryzen 7 5800X 8-Core Processor
|
||||
if (const QString str = QString::fromStdString(line); str.startsWith("model name")) {
|
||||
return afterColon(str);
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Could not get CPU model: /proc/cpuinfo";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint64_t readMemInfo(const QString& searchTarget)
|
||||
{
|
||||
std::ifstream memin("/proc/meminfo");
|
||||
for (std::string line; std::getline(memin, line);) {
|
||||
// MemTotal: 16287480 kB
|
||||
if (const QString str = QString::fromStdString(line); str.startsWith(searchTarget)) {
|
||||
bool ok = false;
|
||||
const uint total = str.simplified().section(' ', 1, 1).toUInt(&ok);
|
||||
if (!ok) {
|
||||
qWarning() << "Could not read /proc/meminfo: failed to parse string:" << str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// transforming kib -> mib
|
||||
return total / 1024;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Could not read /proc/meminfo: search target not found:" << searchTarget;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
uint64_t HardwareInfo::totalRamMiB()
|
||||
{
|
||||
return readMemInfo("MemTotal");
|
||||
}
|
||||
|
||||
uint64_t HardwareInfo::availableRamMiB()
|
||||
{
|
||||
return readMemInfo("MemAvailable");
|
||||
}
|
||||
|
||||
QStringList HardwareInfo::gpuInfo()
|
||||
{
|
||||
bool readingGpuInfo = false;
|
||||
QString gpu;
|
||||
QString driverInUse = "NONE";
|
||||
QString driversAvailable = "NONE";
|
||||
QStringList out;
|
||||
|
||||
const bool success = readFromOutput("lspci -k", [&](const QString& str) {
|
||||
// clang-format off
|
||||
// 04:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (rev e7)
|
||||
// Subsystem: Sapphire Technology Limited Radeon RX 580 Pulse 4GB
|
||||
// Kernel driver in use: amdgpu
|
||||
// Kernel modules: amdgpu
|
||||
// clang-format on
|
||||
if (str.contains("VGA compatible controller") || str.contains("3D controller")) {
|
||||
readingGpuInfo = true;
|
||||
} else if (!str.startsWith('\t')) {
|
||||
if (readingGpuInfo) {
|
||||
out << QString("GPU: %1 (driver in use: %2; drivers available: %3)").arg(gpu, driverInUse, driversAvailable);
|
||||
driverInUse = "NONE";
|
||||
driversAvailable = "NONE";
|
||||
}
|
||||
readingGpuInfo = false;
|
||||
}
|
||||
|
||||
if (!readingGpuInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString value = afterColon(str);
|
||||
if (str.contains("Subsystem")) {
|
||||
gpu = value;
|
||||
}
|
||||
if (str.contains("Kernel driver in use")) {
|
||||
driverInUse = value;
|
||||
}
|
||||
if (str.contains("Kernel modules")) {
|
||||
driversAvailable = value;
|
||||
}
|
||||
});
|
||||
if (!success) {
|
||||
return { "GPU discovery failed: could not read from lspci" };
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
QString HardwareInfo::cpuInfo()
|
||||
{
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#if defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||
#include <cstdio>
|
||||
|
||||
uint64_t HardwareInfo::totalRamMiB()
|
||||
{
|
||||
uint64_t out = 0;
|
||||
|
||||
const bool success = readFromOutput("sysctl hw.physmem", [&](const QString& str) {
|
||||
const uint64_t mem = str.mid(12).toULong();
|
||||
|
||||
// transforming kib -> mib
|
||||
out = mem / 1024;
|
||||
});
|
||||
if (!success) {
|
||||
qWarning() << "Could not get total RAM: could not read from sysctl";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#else
|
||||
uint64_t HardwareInfo::totalRamMiB()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t HardwareInfo::availableRamMiB()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList HardwareInfo::gpuInfo()
|
||||
{
|
||||
return { "GPU discovery failed: not implemented for this OS" };
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <cstdint>
|
||||
|
||||
namespace HardwareInfo {
|
||||
QString cpuInfo();
|
||||
uint64_t totalRamMiB();
|
||||
uint64_t availableRamMiB();
|
||||
QStringList gpuInfo();
|
||||
} // namespace HardwareInfo
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
namespace MacOSHardwareInfo {
|
||||
enum class MemoryPressureLevel : uint8_t {
|
||||
Normal = 1,
|
||||
Warning = 2,
|
||||
Critical = 4,
|
||||
};
|
||||
|
||||
MemoryPressureLevel memoryPressureLevel();
|
||||
QString memoryPressureLevelName();
|
||||
} // namespace MacOSHardwareInfo
|
||||
#endif
|
||||
|
|
@ -189,4 +189,4 @@ void InstanceCopyPrefs::enableDontLinkSaves(bool b)
|
|||
void InstanceCopyPrefs::enableUseClone(bool b)
|
||||
{
|
||||
useClone = b;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,23 +8,23 @@
|
|||
|
||||
struct InstanceCopyPrefs {
|
||||
public:
|
||||
bool allTrue() const;
|
||||
QString getSelectedFiltersAsRegex() const;
|
||||
QString getSelectedFiltersAsRegex(const QStringList& additionalFilters) const;
|
||||
[[nodiscard]] bool allTrue() const;
|
||||
[[nodiscard]] QString getSelectedFiltersAsRegex() const;
|
||||
[[nodiscard]] QString getSelectedFiltersAsRegex(const QStringList& additionalFilters) const;
|
||||
// Getters
|
||||
bool isCopySavesEnabled() const;
|
||||
bool isKeepPlaytimeEnabled() const;
|
||||
bool isCopyGameOptionsEnabled() const;
|
||||
bool isCopyResourcePacksEnabled() const;
|
||||
bool isCopyShaderPacksEnabled() const;
|
||||
bool isCopyServersEnabled() const;
|
||||
bool isCopyModsEnabled() const;
|
||||
bool isCopyScreenshotsEnabled() const;
|
||||
bool isUseSymLinksEnabled() const;
|
||||
bool isLinkRecursivelyEnabled() const;
|
||||
bool isUseHardLinksEnabled() const;
|
||||
bool isDontLinkSavesEnabled() const;
|
||||
bool isUseCloneEnabled() const;
|
||||
[[nodiscard]] bool isCopySavesEnabled() const;
|
||||
[[nodiscard]] bool isKeepPlaytimeEnabled() const;
|
||||
[[nodiscard]] bool isCopyGameOptionsEnabled() const;
|
||||
[[nodiscard]] bool isCopyResourcePacksEnabled() const;
|
||||
[[nodiscard]] bool isCopyShaderPacksEnabled() const;
|
||||
[[nodiscard]] bool isCopyServersEnabled() const;
|
||||
[[nodiscard]] bool isCopyModsEnabled() const;
|
||||
[[nodiscard]] bool isCopyScreenshotsEnabled() const;
|
||||
[[nodiscard]] bool isUseSymLinksEnabled() const;
|
||||
[[nodiscard]] bool isLinkRecursivelyEnabled() const;
|
||||
[[nodiscard]] bool isUseHardLinksEnabled() const;
|
||||
[[nodiscard]] bool isDontLinkSavesEnabled() const;
|
||||
[[nodiscard]] bool isUseCloneEnabled() const;
|
||||
// Setters
|
||||
void enableCopySaves(bool b);
|
||||
void enableKeepPlaytime(bool b);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
#include <QtConcurrentRun>
|
||||
#include <memory>
|
||||
#include "FileSystem.h"
|
||||
#include "Filter.h"
|
||||
#include "NullInstance.h"
|
||||
#include "pathmatcher/RegexpMatcher.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
InstanceCopyTask::InstanceCopyTask(BaseInstance* origInstance, const InstanceCopyPrefs& prefs)
|
||||
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs)
|
||||
{
|
||||
m_origInstance = origInstance;
|
||||
m_keepPlaytime = prefs.isKeepPlaytimeEnabled();
|
||||
|
|
@ -30,8 +30,9 @@ InstanceCopyTask::InstanceCopyTask(BaseInstance* origInstance, const InstanceCop
|
|||
if (!filters.isEmpty()) {
|
||||
// Set regex filter:
|
||||
// FIXME: get this from the original instance type...
|
||||
QRegularExpression regexp(filters, QRegularExpression::CaseInsensitiveOption);
|
||||
m_matcher = Filters::regexp(regexp);
|
||||
auto matcherReal = new RegexpMatcher(filters);
|
||||
matcherReal->caseSensitive(false);
|
||||
m_matcher.reset(matcherReal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ void InstanceCopyTask::executeTask()
|
|||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this] {
|
||||
if (m_useClone) {
|
||||
FS::clone folderClone(m_origInstance->instanceRoot(), m_stagingPath);
|
||||
folderClone.matcher(m_matcher);
|
||||
folderClone.matcher(m_matcher.get());
|
||||
|
||||
folderClone(true);
|
||||
setProgress(0, folderClone.totalCloned());
|
||||
|
|
@ -64,13 +65,14 @@ void InstanceCopyTask::executeTask()
|
|||
|
||||
savesCopy = std::make_unique<FS::copy>(FS::PathCombine(m_origInstance->gameRoot(), "saves"),
|
||||
FS::PathCombine(staging_mc_dir, "saves"));
|
||||
savesCopy->followSymlinks(true);
|
||||
(*savesCopy)(true);
|
||||
setProgress(0, savesCopy->totalCopied());
|
||||
connect(savesCopy.get(), &FS::copy::fileCopied, [this](QString src) { setProgress(m_progress + 1, m_progressTotal); });
|
||||
}
|
||||
FS::create_link folderLink(m_origInstance->instanceRoot(), m_stagingPath);
|
||||
int depth = m_linkRecursively ? -1 : 0; // we need to at least link the top level instead of the instance folder
|
||||
folderLink.linkRecursively(true).setMaxDepth(depth).useHardLinks(m_useHardLinks).matcher(m_matcher);
|
||||
folderLink.linkRecursively(true).setMaxDepth(depth).useHardLinks(m_useHardLinks).matcher(m_matcher.get());
|
||||
|
||||
folderLink(true);
|
||||
setProgress(0, m_progressTotal + folderLink.totalToLink());
|
||||
|
|
@ -89,7 +91,7 @@ void InstanceCopyTask::executeTask()
|
|||
QEventLoop loop;
|
||||
bool got_priv_results = false;
|
||||
|
||||
connect(&folderLink, &FS::create_link::finishedPrivileged, this, [&got_priv_results, &loop](bool gotResults) {
|
||||
connect(&folderLink, &FS::create_link::finishedPrivileged, this, [&](bool gotResults) {
|
||||
if (!gotResults) {
|
||||
qDebug() << "Privileged run exited without results!";
|
||||
}
|
||||
|
|
@ -125,11 +127,11 @@ void InstanceCopyTask::executeTask()
|
|||
return !there_were_errors;
|
||||
}
|
||||
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
|
||||
folderCopy.matcher(m_matcher);
|
||||
folderCopy.followSymlinks(false).matcher(m_matcher.get());
|
||||
|
||||
folderCopy(true);
|
||||
setProgress(0, folderCopy.totalCopied());
|
||||
connect(&folderCopy, &FS::copy::fileCopied, [this]() { setProgress(m_progress + 1, m_progressTotal); });
|
||||
connect(&folderCopy, &FS::copy::fileCopied, [this](QString src) { setProgress(m_progress + 1, m_progressTotal); });
|
||||
return folderCopy();
|
||||
});
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
|
||||
|
|
@ -146,9 +148,9 @@ void InstanceCopyTask::copyFinished()
|
|||
}
|
||||
|
||||
// FIXME: shouldn't this be able to report errors?
|
||||
auto instanceSettings = std::make_unique<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
||||
auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
|
||||
|
||||
BaseInstance* inst(new NullInstance(m_globalSettings, std::move(instanceSettings), m_stagingPath));
|
||||
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
||||
inst->setName(name());
|
||||
inst->setIconKey(m_instIcon);
|
||||
if (!m_keepPlaytime) {
|
||||
|
|
@ -196,4 +198,4 @@ bool InstanceCopyTask::abort()
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
#include <QUrl>
|
||||
#include "BaseInstance.h"
|
||||
#include "BaseVersion.h"
|
||||
#include "Filter.h"
|
||||
#include "InstanceCopyPrefs.h"
|
||||
#include "InstanceTask.h"
|
||||
#include "net/NetJob.h"
|
||||
|
|
@ -15,7 +14,7 @@
|
|||
class InstanceCopyTask : public InstanceTask {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstanceCopyTask(BaseInstance* origInstance, const InstanceCopyPrefs& prefs);
|
||||
explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs);
|
||||
|
||||
protected:
|
||||
//! Entry point for tasks.
|
||||
|
|
@ -26,10 +25,10 @@ class InstanceCopyTask : public InstanceTask {
|
|||
|
||||
private:
|
||||
/* data */
|
||||
BaseInstance* m_origInstance;
|
||||
InstancePtr m_origInstance;
|
||||
QFuture<bool> m_copyFuture;
|
||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||
Filter m_matcher;
|
||||
std::unique_ptr<IPathMatcher> m_matcher;
|
||||
bool m_keepPlaytime;
|
||||
bool m_useLinks = false;
|
||||
bool m_useHardLinks = false;
|
||||
|
|
|
|||
|
|
@ -2,25 +2,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
#include "Application.h"
|
||||
#include "InstanceTask.h"
|
||||
#include "minecraft/MinecraftLoadAndCheck.h"
|
||||
#include "tasks/SequentialTask.h"
|
||||
|
||||
bool InstanceCreationTask::abort()
|
||||
{
|
||||
if (!canAbort()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_abort = true;
|
||||
if (m_gameFilesTask) {
|
||||
return m_gameFilesTask->abort();
|
||||
}
|
||||
|
||||
return InstanceTask::abort();
|
||||
}
|
||||
#include "FileSystem.h"
|
||||
|
||||
void InstanceCreationTask::executeTask()
|
||||
{
|
||||
|
|
@ -37,15 +19,13 @@ void InstanceCreationTask::executeTask()
|
|||
return;
|
||||
}
|
||||
|
||||
m_instance = createInstance();
|
||||
if (!m_instance) {
|
||||
if (m_abort) {
|
||||
if (!createInstance()) {
|
||||
if (m_abort)
|
||||
return;
|
||||
}
|
||||
|
||||
qWarning() << "Instance creation failed!";
|
||||
if (!m_error_message.isEmpty()) {
|
||||
qWarning() << "Reason:" << m_error_message;
|
||||
qWarning() << "Reason: " << m_error_message;
|
||||
emitFailed(tr("Error while creating new instance:\n%1").arg(m_error_message));
|
||||
} else {
|
||||
emitFailed(tr("Error while creating new instance."));
|
||||
|
|
@ -64,10 +44,9 @@ void InstanceCreationTask::executeTask()
|
|||
setStatus(tr("Removing old conflicting files..."));
|
||||
qDebug() << "Removing old files";
|
||||
|
||||
for (const QString& path : m_filesToRemove) {
|
||||
if (!QFile::exists(path)) {
|
||||
for (const QString& path : m_files_to_remove) {
|
||||
if (!QFile::exists(path))
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug() << "Removing" << path;
|
||||
|
||||
|
|
@ -82,61 +61,6 @@ void InstanceCreationTask::executeTask()
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_abort) {
|
||||
if (!APPLICATION->settings()->get("DownloadGameFilesDuringInstanceCreation").toBool()) {
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
setAbortable(true);
|
||||
setAbortButtonText(tr("Skip"));
|
||||
qDebug() << "Downloading game files";
|
||||
|
||||
auto updateTasks = m_instance->createUpdateTask();
|
||||
if (updateTasks.isEmpty()) {
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
auto task = makeShared<SequentialTask>();
|
||||
task->addTask(makeShared<MinecraftLoadAndCheck>(m_instance.get(), Net::Mode::Online));
|
||||
for (const auto& t : updateTasks) {
|
||||
task->addTask(t);
|
||||
}
|
||||
connect(task.get(), &Task::finished, this, [this, task] {
|
||||
if (task->wasSuccessful() || m_abort) {
|
||||
emitSucceeded();
|
||||
} else {
|
||||
emitFailed(tr("Could not download game files: %1").arg(task->failReason()));
|
||||
}
|
||||
});
|
||||
propagateFromOther(task.get());
|
||||
setDetails(tr("Downloading game files"));
|
||||
|
||||
m_gameFilesTask = task;
|
||||
m_gameFilesTask->start();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceCreationTask::scheduleToDelete(QWidget* parent, const QDir& dir, const QString& path, bool checkDisabled)
|
||||
{
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (path.startsWith("saves/")) {
|
||||
if (m_shouldDeleteSaves == ShouldDeleteSaves::NotAsked) {
|
||||
m_shouldDeleteSaves = askIfShouldDeleteSaves(parent);
|
||||
}
|
||||
if (m_shouldDeleteSaves == ShouldDeleteSaves::No) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
qDebug() << "Scheduling" << path << "for removal";
|
||||
m_filesToRemove.append(dir.absoluteFilePath(path));
|
||||
if (checkDisabled) {
|
||||
if (path.endsWith(".disabled")) { // remove it if it was enabled/disabled by user
|
||||
m_filesToRemove.append(dir.absoluteFilePath(path.chopped(9)));
|
||||
} else {
|
||||
m_filesToRemove.append(dir.absoluteFilePath(path + ".disabled"));
|
||||
}
|
||||
}
|
||||
if (!m_abort)
|
||||
emitSucceeded();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "BaseVersion.h"
|
||||
#include "InstanceTask.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
|
||||
class InstanceCreationTask : public InstanceTask {
|
||||
Q_OBJECT
|
||||
|
|
@ -10,8 +9,6 @@ class InstanceCreationTask : public InstanceTask {
|
|||
InstanceCreationTask() = default;
|
||||
virtual ~InstanceCreationTask() = default;
|
||||
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
void executeTask() final override;
|
||||
|
||||
|
|
@ -30,24 +27,20 @@ class InstanceCreationTask : public InstanceTask {
|
|||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* Returns the instance if it was created or nullptr otherwise.
|
||||
* Returns whether the instance creation was successful (true) or not (false).
|
||||
*/
|
||||
virtual std::unique_ptr<MinecraftInstance> createInstance() { return nullptr; }
|
||||
virtual bool createInstance() { return false; };
|
||||
|
||||
QString getError() const { return m_error_message; }
|
||||
|
||||
protected:
|
||||
void setError(const QString& message) { m_error_message = message; };
|
||||
void scheduleToDelete(QWidget* parent, const QDir& dir, const QString& path, bool checkDisabled = false);
|
||||
|
||||
protected:
|
||||
bool m_abort = false;
|
||||
|
||||
QStringList m_filesToRemove;
|
||||
ShouldDeleteSaves m_shouldDeleteSaves;
|
||||
QStringList m_files_to_remove;
|
||||
|
||||
private:
|
||||
QString m_error_message;
|
||||
std::unique_ptr<MinecraftInstance> m_instance;
|
||||
Task::Ptr m_gameFilesTask;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "InstanceDirUpdate.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
||||
#include "Application.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include "InstanceList.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
|
||||
QString askToUpdateInstanceDirName(BaseInstance* instance, const QString& oldName, const QString& newName, QWidget* parent)
|
||||
{
|
||||
if (oldName == newName)
|
||||
return QString();
|
||||
|
||||
QString renamingMode = APPLICATION->settings()->get("InstRenamingMode").toString();
|
||||
if (renamingMode == "MetadataOnly")
|
||||
return QString();
|
||||
|
||||
auto oldRoot = instance->instanceRoot();
|
||||
auto newDirName = FS::DirNameFromString(newName, QFileInfo(oldRoot).dir().absolutePath());
|
||||
auto newRoot = FS::PathCombine(QFileInfo(oldRoot).dir().absolutePath(), newDirName);
|
||||
if (oldRoot == newRoot)
|
||||
return QString();
|
||||
if (oldRoot == FS::PathCombine(QFileInfo(oldRoot).dir().absolutePath(), newName))
|
||||
return QString();
|
||||
|
||||
// Check for conflict
|
||||
if (QDir(newRoot).exists()) {
|
||||
QMessageBox::warning(parent, QObject::tr("Cannot rename instance"),
|
||||
QObject::tr("New instance root (%1) already exists. <br />Only the metadata will be renamed.").arg(newRoot));
|
||||
return QString();
|
||||
}
|
||||
|
||||
// Ask if we should rename
|
||||
if (renamingMode == "AskEverytime") {
|
||||
auto checkBox = new QCheckBox(QObject::tr("&Remember my choice"), parent);
|
||||
auto dialog =
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Rename instance folder"),
|
||||
QObject::tr("Would you also like to rename the instance folder?\n\n"
|
||||
"Old name: %1\n"
|
||||
"New name: %2")
|
||||
.arg(oldName, newName),
|
||||
QMessageBox::Question, QMessageBox::No | QMessageBox::Yes, QMessageBox::NoButton, checkBox);
|
||||
|
||||
auto res = dialog->exec();
|
||||
if (checkBox->isChecked()) {
|
||||
if (res == QMessageBox::Yes)
|
||||
APPLICATION->settings()->set("InstRenamingMode", "PhysicalDir");
|
||||
else
|
||||
APPLICATION->settings()->set("InstRenamingMode", "MetadataOnly");
|
||||
}
|
||||
if (res == QMessageBox::No)
|
||||
return QString();
|
||||
}
|
||||
|
||||
// Check for linked instances
|
||||
if (!checkLinkedInstances(instance->id(), parent, QObject::tr("Renaming")))
|
||||
return QString();
|
||||
|
||||
// Now we can confirm that a renaming is happening
|
||||
if (!instance->syncInstanceDirName(newRoot)) {
|
||||
QMessageBox::warning(parent, QObject::tr("Cannot rename instance"),
|
||||
QObject::tr("An error occurred when performing the following renaming operation: <br/>"
|
||||
" - Old instance root: %1<br/>"
|
||||
" - New instance root: %2<br/>"
|
||||
"Only the metadata is renamed.")
|
||||
.arg(oldRoot, newRoot));
|
||||
return QString();
|
||||
}
|
||||
return newRoot;
|
||||
}
|
||||
|
||||
bool checkLinkedInstances(const QString& id, QWidget* parent, const QString& verb)
|
||||
{
|
||||
auto linkedInstances = APPLICATION->instances()->getLinkedInstancesById(id);
|
||||
if (!linkedInstances.empty()) {
|
||||
auto response = CustomMessageBox::selectable(parent, QObject::tr("There are linked instances"),
|
||||
QObject::tr("The following instance(s) might reference files in this instance:\n\n"
|
||||
"%1\n\n"
|
||||
"%2 it could break the other instance(s), \n\n"
|
||||
"Do you wish to proceed?",
|
||||
nullptr, linkedInstances.count())
|
||||
.arg(linkedInstances.join("\n"))
|
||||
.arg(verb),
|
||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
||||
->exec();
|
||||
if (response != QMessageBox::Yes)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseInstance.h"
|
||||
|
||||
/// Update instanceRoot to make it sync with name/id; return newRoot if a directory rename happened
|
||||
QString askToUpdateInstanceDirName(BaseInstance* instance, const QString& oldName, const QString& newName, QWidget* parent);
|
||||
|
||||
/// Check if there are linked instances, and display a warning; return true if the operation should proceed
|
||||
bool checkLinkedInstances(const QString& id, QWidget* parent, const QString& verb);
|
||||
|
|
@ -38,11 +38,10 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "FileSystem.h"
|
||||
#include "MMCZip.h"
|
||||
#include "NullInstance.h"
|
||||
|
||||
#include "QObjectPtr.h"
|
||||
#include "archive/ArchiveReader.h"
|
||||
#include "archive/ExtractZipTask.h"
|
||||
#include "icons/IconList.h"
|
||||
#include "icons/IconUtils.h"
|
||||
|
||||
|
|
@ -55,10 +54,12 @@
|
|||
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QtConcurrentRun>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <quazip/quazipdir.h>
|
||||
|
||||
InstanceImportTask::InstanceImportTask(const QUrl& sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
|
||||
: m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
|
||||
{}
|
||||
|
|
@ -71,6 +72,7 @@ bool InstanceImportTask::abort()
|
|||
bool wasAborted = false;
|
||||
if (m_task)
|
||||
wasAborted = m_task->abort();
|
||||
Task::abort();
|
||||
return wasAborted;
|
||||
}
|
||||
|
||||
|
|
@ -108,14 +110,39 @@ void InstanceImportTask::downloadFromUrl()
|
|||
filesNetJob->start();
|
||||
}
|
||||
|
||||
QString cleanPath(QString path)
|
||||
QString InstanceImportTask::getRootFromZip(QuaZip* zip, const QString& root)
|
||||
{
|
||||
if (path == ".")
|
||||
return QString();
|
||||
QString result = path;
|
||||
if (result.startsWith("./"))
|
||||
result = result.mid(2);
|
||||
return result;
|
||||
if (!isRunning()) {
|
||||
return {};
|
||||
}
|
||||
QuaZipDir rootDir(zip, root);
|
||||
for (auto&& fileName : rootDir.entryList(QDir::Files)) {
|
||||
setDetails(fileName);
|
||||
if (fileName == "instance.cfg") {
|
||||
qDebug() << "MultiMC:" << true;
|
||||
m_modpackType = ModpackType::MultiMC;
|
||||
return root;
|
||||
}
|
||||
if (fileName == "manifest.json") {
|
||||
qDebug() << "Flame:" << true;
|
||||
m_modpackType = ModpackType::Flame;
|
||||
return root;
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
// Recurse the search to non-ignored subfolders
|
||||
for (auto&& fileName : rootDir.entryList(QDir::Dirs)) {
|
||||
if ("overrides/" == fileName)
|
||||
continue;
|
||||
|
||||
QString result = getRootFromZip(zip, root + fileName);
|
||||
if (!result.isEmpty())
|
||||
return result;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void InstanceImportTask::processZipPack()
|
||||
|
|
@ -125,47 +152,33 @@ void InstanceImportTask::processZipPack()
|
|||
qDebug() << "Attempting to create instance from" << m_archivePath;
|
||||
|
||||
// open the zip and find relevant files in it
|
||||
MMCZip::ArchiveReader packZip(m_archivePath);
|
||||
auto packZip = std::make_shared<QuaZip>(m_archivePath);
|
||||
if (!packZip->open(QuaZip::mdUnzip)) {
|
||||
emitFailed(tr("Unable to open supplied modpack zip file."));
|
||||
return;
|
||||
}
|
||||
|
||||
QuaZipDir packZipDir(packZip.get());
|
||||
qDebug() << "Attempting to determine instance type";
|
||||
|
||||
QString root;
|
||||
|
||||
// NOTE: Prioritize modpack platforms that aren't searched for recursively.
|
||||
// Especially Flame has a very common filename for its manifest, which may appear inside overrides for example
|
||||
// https://docs.modrinth.com/docs/modpacks/format_definition/#storage
|
||||
auto detectInstance = [this, &extractDir, &root](MMCZip::ArchiveReader::File* f, bool& stop) {
|
||||
if (!isRunning()) {
|
||||
stop = true;
|
||||
return true;
|
||||
}
|
||||
auto fileName = f->filename();
|
||||
if (fileName == "modrinth.index.json") {
|
||||
// process as Modrinth pack
|
||||
qDebug() << "Modrinth:" << true;
|
||||
m_modpackType = ModpackType::Modrinth;
|
||||
stop = true;
|
||||
} else if (fileName == "bin/modpack.jar" || fileName == "bin/version.json") {
|
||||
// process as Technic pack
|
||||
qDebug() << "Technic:" << true;
|
||||
extractDir.mkpath("minecraft");
|
||||
extractDir.cd("minecraft");
|
||||
m_modpackType = ModpackType::Technic;
|
||||
stop = true;
|
||||
} else if (fileName == "manifest.json") {
|
||||
qDebug() << "Flame:" << true;
|
||||
m_modpackType = ModpackType::Flame;
|
||||
stop = true;
|
||||
} else if (QFileInfo fileInfo(fileName); fileInfo.fileName() == "instance.cfg") {
|
||||
qDebug() << "MultiMC:" << true;
|
||||
m_modpackType = ModpackType::MultiMC;
|
||||
root = cleanPath(fileInfo.path());
|
||||
stop = true;
|
||||
}
|
||||
QCoreApplication::processEvents();
|
||||
return true;
|
||||
};
|
||||
if (!packZip.parse(detectInstance)) {
|
||||
emitFailed(tr("Unable to open supplied modpack zip file."));
|
||||
return;
|
||||
if (packZipDir.exists("/modrinth.index.json")) {
|
||||
// process as Modrinth pack
|
||||
qDebug() << "Modrinth:" << true;
|
||||
m_modpackType = ModpackType::Modrinth;
|
||||
} else if (packZipDir.exists("/bin/modpack.jar") || packZipDir.exists("/bin/version.json")) {
|
||||
// process as Technic pack
|
||||
qDebug() << "Technic:" << true;
|
||||
extractDir.mkpath("minecraft");
|
||||
extractDir.cd("minecraft");
|
||||
m_modpackType = ModpackType::Technic;
|
||||
} else {
|
||||
root = getRootFromZip(packZip.get());
|
||||
setDetails("");
|
||||
}
|
||||
if (m_modpackType == ModpackType::Unknown) {
|
||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||
|
|
@ -174,7 +187,7 @@ void InstanceImportTask::processZipPack()
|
|||
setStatus(tr("Extracting modpack"));
|
||||
|
||||
// make sure we extract just the pack
|
||||
auto zipTask = makeShared<MMCZip::ExtractZipTask>(m_archivePath, extractDir, root);
|
||||
auto zipTask = makeShared<MMCZip::ExtractZipTask>(packZip, extractDir, root);
|
||||
|
||||
auto progressStep = std::make_shared<TaskStepProgress>();
|
||||
connect(zipTask.get(), &Task::finished, this, [this, progressStep] {
|
||||
|
|
@ -199,7 +212,6 @@ void InstanceImportTask::processZipPack()
|
|||
progressStep->status = status;
|
||||
stepProgress(*progressStep);
|
||||
});
|
||||
connect(zipTask.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
|
||||
m_task.reset(zipTask);
|
||||
zipTask->start();
|
||||
}
|
||||
|
|
@ -251,25 +263,6 @@ void InstanceImportTask::extractFinished()
|
|||
}
|
||||
}
|
||||
|
||||
bool installIcon(QString root, QString instIconKey)
|
||||
{
|
||||
auto importIconPath = IconUtils::findBestIconIn(root, instIconKey);
|
||||
if (importIconPath.isNull() || !QFile::exists(importIconPath))
|
||||
importIconPath = IconUtils::findBestIconIn(root, "icon.png");
|
||||
if (importIconPath.isNull() || !QFile::exists(importIconPath))
|
||||
importIconPath = IconUtils::findBestIconIn(FS::PathCombine(root, "overrides"), "icon.png");
|
||||
if (!importIconPath.isNull() && QFile::exists(importIconPath)) {
|
||||
// import icon
|
||||
auto iconList = APPLICATION->icons();
|
||||
if (iconList->iconFileExists(instIconKey)) {
|
||||
iconList->deleteIcon(instIconKey);
|
||||
}
|
||||
iconList->installIcon(importIconPath, instIconKey + "." + QFileInfo(importIconPath).suffix());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InstanceImportTask::processFlame()
|
||||
{
|
||||
shared_qobject_ptr<FlameCreationTask> inst_creation_task = nullptr;
|
||||
|
|
@ -295,14 +288,6 @@ void InstanceImportTask::processFlame()
|
|||
}
|
||||
|
||||
inst_creation_task->setName(*this);
|
||||
// if the icon was specified by user, use that. otherwise pull icon from the pack
|
||||
if (m_instIcon == "default") {
|
||||
auto iconKey = QString("Flame_%1_Icon").arg(name());
|
||||
|
||||
if (installIcon(m_stagingPath, iconKey)) {
|
||||
m_instIcon = iconKey;
|
||||
}
|
||||
}
|
||||
inst_creation_task->setIcon(m_instIcon);
|
||||
inst_creation_task->setGroup(m_instGroup);
|
||||
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
|
||||
|
|
@ -320,11 +305,8 @@ void InstanceImportTask::processFlame()
|
|||
connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
|
||||
connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
|
||||
|
||||
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
|
||||
connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
|
||||
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
|
||||
connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText);
|
||||
|
||||
connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
|
||||
|
||||
m_task.reset(inst_creation_task);
|
||||
setAbortable(true);
|
||||
|
|
@ -342,9 +324,9 @@ void InstanceImportTask::processTechnic()
|
|||
void InstanceImportTask::processMultiMC()
|
||||
{
|
||||
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||
auto instanceSettings = std::make_unique<INISettingsObject>(configPath);
|
||||
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
||||
|
||||
NullInstance instance(m_globalSettings, std::move(instanceSettings), m_stagingPath);
|
||||
NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||
|
||||
// reset time played on import... because packs.
|
||||
instance.resetTimePlayed();
|
||||
|
|
@ -358,7 +340,17 @@ void InstanceImportTask::processMultiMC()
|
|||
} else {
|
||||
m_instIcon = instance.iconKey();
|
||||
|
||||
installIcon(instance.instanceRoot(), m_instIcon);
|
||||
auto importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), m_instIcon);
|
||||
if (importIconPath.isNull() || !QFile::exists(importIconPath))
|
||||
importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), "icon.png");
|
||||
if (!importIconPath.isNull() && QFile::exists(importIconPath)) {
|
||||
// import icon
|
||||
auto iconList = APPLICATION->icons();
|
||||
if (iconList->iconFileExists(m_instIcon)) {
|
||||
iconList->deleteIcon(m_instIcon);
|
||||
}
|
||||
iconList->installIcon(importIconPath, m_instIcon);
|
||||
}
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
|
|
@ -386,8 +378,8 @@ void InstanceImportTask::processModrinth()
|
|||
} else {
|
||||
QString pack_id;
|
||||
if (!m_sourceUrl.isEmpty()) {
|
||||
static const QRegularExpression s_regex(R"(data\/([^\/]*)\/versions)");
|
||||
pack_id = s_regex.match(m_sourceUrl.toString()).captured(1);
|
||||
QRegularExpression regex(R"(data\/([^\/]*)\/versions)");
|
||||
pack_id = regex.match(m_sourceUrl.toString()).captured(1);
|
||||
}
|
||||
|
||||
// FIXME: Find a way to get the ID in directly imported ZIPs
|
||||
|
|
@ -395,14 +387,6 @@ void InstanceImportTask::processModrinth()
|
|||
}
|
||||
|
||||
inst_creation_task->setName(*this);
|
||||
// if the icon was specified by user, use that. otherwise pull icon from the pack
|
||||
if (m_instIcon == "default") {
|
||||
auto iconKey = QString("Modrinth_%1_Icon").arg(name());
|
||||
|
||||
if (installIcon(m_stagingPath, iconKey)) {
|
||||
m_instIcon = iconKey;
|
||||
}
|
||||
}
|
||||
inst_creation_task->setIcon(m_instIcon);
|
||||
inst_creation_task->setGroup(m_instGroup);
|
||||
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
|
||||
|
|
@ -420,11 +404,8 @@ void InstanceImportTask::processModrinth()
|
|||
connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
|
||||
connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
|
||||
|
||||
connect(inst_creation_task.get(), &Task::aborted, this, &InstanceImportTask::emitAborted);
|
||||
connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
|
||||
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
|
||||
connect(inst_creation_task.get(), &Task::abortButtonTextChanged, this, &Task::setAbortButtonText);
|
||||
|
||||
connect(inst_creation_task.get(), &Task::warningLogged, this, [this](const QString& line) { m_Warnings.append(line); });
|
||||
|
||||
m_task.reset(inst_creation_task);
|
||||
setAbortable(true);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue