diff --git a/.clang-format b/.clang-format
index 005a1006b..114bcba50 100644
--- a/.clang-format
+++ b/.clang-format
@@ -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
diff --git a/.clang-tidy b/.clang-tidy
index c5eb09533..436dcf244 100644
--- a/.clang-tidy
+++ b/.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
diff --git a/.editorconfig b/.editorconfig
index 03b99379b..56166b207 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -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
diff --git a/.envrc b/.envrc
index 1d11c5354..190b5b2b3 100644
--- a/.envrc
+++ b/.envrc
@@ -1,2 +1,2 @@
-use nix
+use flake
watch_file nix/*.nix
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index c7d36db27..528b128b1 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -5,9 +5,3 @@ bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9
# (nix) alejandra -> nixfmt
4c81d8c53d09196426568c4a31a4e752ed05397a
-
-# reformat codebase
-1d468ac35ad88d8c77cc83f25e3704d9bd7df01b
-
-# format a part of codebase
-5c8481a118c8fefbfe901001d7828eaf6866eac4
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 3574bf20d..ea1fbfdd9 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -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.
diff --git a/.github/ISSUE_TEMPLATE/rfc.yml b/.github/ISSUE_TEMPLATE/rfc.yml
index 5e6d68e65..fa7cdbe61 100644
--- a/.github/ISSUE_TEMPLATE/rfc.yml
+++ b/.github/ISSUE_TEMPLATE/rfc.yml
@@ -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:
diff --git a/.github/ISSUE_TEMPLATE/suggestion.yml b/.github/ISSUE_TEMPLATE/suggestion.yml
index 18a202ae1..ddee86b65 100644
--- a/.github/ISSUE_TEMPLATE/suggestion.yml
+++ b/.github/ISSUE_TEMPLATE/suggestion.yml
@@ -1,6 +1,6 @@
name: Suggestion
description: Make a suggestion
-labels: ["type: enhancement", "status: needs triage"]
+labels: [enhancement]
body:
- type: markdown
attributes:
diff --git a/.github/actions/package/linux/action.yml b/.github/actions/package/linux/action.yml
deleted file mode 100644
index 2ce6ca955..000000000
--- a/.github/actions/package/linux/action.yml
+++ /dev/null
@@ -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
diff --git a/.github/actions/package/macos/action.yml b/.github/actions/package/macos/action.yml
deleted file mode 100644
index 1af01250f..000000000
--- a/.github/actions/package/macos/action.yml
+++ /dev/null
@@ -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
diff --git a/.github/actions/package/windows/action.yml b/.github/actions/package/windows/action.yml
deleted file mode 100644
index 532f3db44..000000000
--- a/.github/actions/package/windows/action.yml
+++ /dev/null
@@ -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
diff --git a/.github/actions/setup-dependencies/action.yml b/.github/actions/setup-dependencies/action.yml
deleted file mode 100644
index b73c7509a..000000000
--- a/.github/actions/setup-dependencies/action.yml
+++ /dev/null
@@ -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' }}
diff --git a/.github/actions/setup-dependencies/linux/action.yml b/.github/actions/setup-dependencies/linux/action.yml
deleted file mode 100644
index fa5af702b..000000000
--- a/.github/actions/setup-dependencies/linux/action.yml
+++ /dev/null
@@ -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"
diff --git a/.github/actions/setup-dependencies/macos/action.yml b/.github/actions/setup-dependencies/macos/action.yml
deleted file mode 100644
index a90544be0..000000000
--- a/.github/actions/setup-dependencies/macos/action.yml
+++ /dev/null
@@ -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"
diff --git a/.github/actions/setup-dependencies/windows/action.yml b/.github/actions/setup-dependencies/windows/action.yml
deleted file mode 100644
index 24ad51d8f..000000000
--- a/.github/actions/setup-dependencies/windows/action.yml
+++ /dev/null
@@ -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
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index 9cde3307d..4146cddf4 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -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: |-
diff --git a/.github/workflows/blocked-prs.yml b/.github/workflows/blocked-prs.yml
deleted file mode 100644
index 001080154..000000000
--- a/.github/workflows/blocked-prs.yml
+++ /dev/null
@@ -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 '
PR Dependencies :pushpin:
' > "$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<> "$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
-
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0596906c8..991ddcd8c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -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
diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml
deleted file mode 100644
index d72994c50..000000000
--- a/.github/workflows/clang-tidy.yml
+++ /dev/null
@@ -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
- '
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index f9705bf53..5255f865b 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -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
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
deleted file mode 100644
index 7af2c1ccb..000000000
--- a/.github/workflows/container.yml
+++ /dev/null
@@ -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
diff --git a/.github/workflows/merge-blocking-pr.yml b/.github/workflows/merge-blocking-pr.yml
deleted file mode 100644
index 3542a470e..000000000
--- a/.github/workflows/merge-blocking-pr.yml
+++ /dev/null
@@ -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:` 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")
-
diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml
deleted file mode 100644
index 58f4d263a..000000000
--- a/.github/workflows/nix.yml
+++ /dev/null
@@ -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"
diff --git a/.github/workflows/trigger_builds.yml b/.github/workflows/trigger_builds.yml
new file mode 100644
index 000000000..0b8386d69
--- /dev/null
+++ b/.github/workflows/trigger_builds.yml
@@ -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 }}
diff --git a/.github/workflows/release.yml b/.github/workflows/trigger_release.yml
similarity index 62%
rename from .github/workflows/release.yml
rename to .github/workflows/trigger_release.yml
index e332488c3..e800653e3 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/trigger_release.yml
@@ -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
diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml
index fa3e3b4d3..5e978f356 100644
--- a/.github/workflows/update-flake.yml
+++ b/.github/workflows/update-flake.yml
@@ -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
diff --git a/.github/workflows/publish.yml b/.github/workflows/winget.yml
similarity index 55%
rename from .github/workflows/publish.yml
rename to .github/workflows/winget.yml
index 1bb1c5b50..eacf23099 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/winget.yml
@@ -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 }}
diff --git a/.gitignore b/.gitignore
index 00afabbfa..b5523f685 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/.gitmodules b/.gitmodules
index 42c566fa8..0f437d277 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -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
diff --git a/.markdownlintignore b/.markdownlintignore
index 96f627ad9..a8669d01d 100644
--- a/.markdownlintignore
+++ b/.markdownlintignore
@@ -1 +1,2 @@
libraries/nbtplusplus
+libraries/quazip
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12afdefcc..4e7f14ac6 100644
--- a/CMakeLists.txt
+++ b/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($<$>: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
- "$<$:/GS>"
-
- # /Gw helps reduce binary size
- # /Gy allows the compiler to package individual functions
- # /guard:cf enables control flow guard
- "$<$,$>:/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
- "$<$:/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("$<$,$>:/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 "$<$: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("$<$:-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("$<$,$>:-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("$<$:-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("$<$,$>:-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 $,$>)
- 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 ###############################
diff --git a/CMakePresets.json b/CMakePresets.json
deleted file mode 100644
index f8496acb6..000000000
--- a/CMakePresets.json
+++ /dev/null
@@ -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"
- }
- ]
-}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f4b12d08b..072916772 100644
--- a/CONTRIBUTING.md
+++ b/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
diff --git a/COPYING.md b/COPYING.md
index 52f29f2e6..111587060 100644
--- a/COPYING.md
+++ b/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
+
+ 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 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 .
-
-## 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.
diff --git a/Containerfile b/Containerfile
deleted file mode 100644
index 59595fe55..000000000
--- a/Containerfile
+++ /dev/null
@@ -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"]
diff --git a/README.md b/README.md
index ac6cfd96b..9c4909509 100644
--- a/README.md
+++ b/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)
[](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/).
-
-
-
-
-
-
-
+[](https://www.jetbrains.com/opensource/)
Thanks to Weblate for hosting our translation efforts.
diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in
index 14d8236d8..b48232b43 100644
--- a/buildconfig/BuildConfig.cpp.in
+++ b/buildconfig/BuildConfig.cpp.in
@@ -33,8 +33,9 @@
* limitations under the License.
*/
-#include
+#include
#include "BuildConfig.h"
+#include
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);
}
+
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index a5851bfba..ae705d098 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -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;
/**
diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake
new file mode 100644
index 000000000..51d2fb13a
--- /dev/null
+++ b/cmake/CompilerWarnings.cmake
@@ -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
+ $<$:${PROJECT_WARNINGS_CXX}>
+ # C warnings
+ $<$:${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 "^")
+ _set_project_warnings_add_target_link_option(
+ ${_project_name} "$<$:${PROJECT_WARNINGS_CXX}>"
+ )
+ endif()
+
+ if(CMAKE_C_LINK_EXECUTABLE MATCHES "^")
+ _set_project_warnings_add_target_link_option(
+ ${_project_name} "$<$:${PROJECT_WARNINGS_C}>"
+ )
+ endif()
+
+ endfunction()
diff --git a/cmake/ECMQueryQt.cmake b/cmake/ECMQueryQt.cmake
new file mode 100644
index 000000000..98eb50089
--- /dev/null
+++ b/cmake/ECMQueryQt.cmake
@@ -0,0 +1,100 @@
+# SPDX-FileCopyrightText: 2014 Rohan Garg
+# SPDX-FileCopyrightText: 2014 Alex Merry
+# SPDX-FileCopyrightText: 2014-2016 Aleix Pol
+# SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau
+# SPDX-FileCopyrightText: 2022 Ahmad Samir
+#
+# 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( [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 ``/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()
diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in
index eb40bacfd..3a8c8fbfe 100644
--- a/cmake/MacOSXBundleInfo.plist.in
+++ b/cmake/MacOSXBundleInfo.plist.in
@@ -7,7 +7,7 @@
NSMicrophoneUsageDescription
A Minecraft mod wants to access your microphone.
NSDownloadsFolderUsageDescription
- ${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.
+ 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.
NSLocalNetworkUsageDescription
Minecraft uses the local network to find and connect to LAN servers.
NSPrincipalClass
@@ -21,9 +21,7 @@
CFBundleGetInfoString
${MACOSX_BUNDLE_INFO_STRING}
CFBundleIconFile
- ${Launcher_Name}
- CFBundleIconName
- ${Launcher_Name}
+ ${MACOSX_BUNDLE_ICON_FILE}
CFBundleIdentifier
${MACOSX_BUNDLE_GUI_IDENTIFIER}
CFBundleInfoDictionaryVersion
@@ -44,8 +42,6 @@
LSRequiresCarbon
- LSApplicationCategoryType
- public.app-category.games
NSHumanReadableCopyright
${MACOSX_BUNDLE_COPYRIGHT}
SUPublicEDKey
@@ -61,7 +57,7 @@
mrpack
CFBundleTypeName
- ${Launcher_DisplayName} instance
+ Prism Launcher instance
CFBundleTypeOSTypes
TEXT
@@ -87,11 +83,10 @@
CFBundleURLName
- ${Launcher_Name}
+ Prismlauncher
CFBundleURLSchemes
prismlauncher
- ${MACOSX_BUNDLE_EXECUTABLE_NAME}
diff --git a/cmake/QtVersionOption.cmake b/cmake/QtVersionOption.cmake
new file mode 100644
index 000000000..1390f9db6
--- /dev/null
+++ b/cmake/QtVersionOption.cmake
@@ -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
+#
+# 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()
diff --git a/cmake/QtVersionlessBackport.cmake b/cmake/QtVersionlessBackport.cmake
new file mode 100644
index 000000000..46792db58
--- /dev/null
+++ b/cmake/QtVersionlessBackport.cmake
@@ -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()
+
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/README.md b/cmake/vcpkg-ports/vcpkg-tool-meson/README.md
deleted file mode 100644
index 9047c8037..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/README.md
+++ /dev/null
@@ -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
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch
deleted file mode 100644
index ad800aa66..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-args.patch
+++ /dev/null
@@ -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
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch
deleted file mode 100644
index 0cbfe717d..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/adjust-python-dep.patch
+++ /dev/null
@@ -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))
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch
deleted file mode 100644
index 394b064dc..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/fix-libcpp-enable-assertions.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From a16ec8b0fb6d7035b669a13edd4d97ff0c307a0b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Martin=20D=C3=B8rum?=
-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):
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake
deleted file mode 100644
index 84201aa1a..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/install.cmake
+++ /dev/null
@@ -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"
-)
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch
deleted file mode 100644
index 8f2a029de..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/meson-intl.patch
+++ /dev/null
@@ -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,
- )
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in b/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in
deleted file mode 100644
index df21b753b..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/meson.template.in
+++ /dev/null
@@ -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@
\ No newline at end of file
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake
deleted file mode 100644
index fdea886a7..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/portfile.cmake
+++ /dev/null
@@ -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")
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch
deleted file mode 100644
index 947345ccf..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/remove-freebsd-pcfile-specialization.patch
+++ /dev/null
@@ -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,
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch b/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch
deleted file mode 100644
index 58b96d5ce..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/universal-osx.patch
+++ /dev/null
@@ -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)
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake
deleted file mode 100644
index c0dee3a38..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg-port-config.cmake
+++ /dev/null
@@ -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}")
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json
deleted file mode 100644
index 04a0cbbec..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg.json
+++ /dev/null
@@ -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"
- ]
-}
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake
deleted file mode 100644
index 6b00200d1..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_configure_meson.cmake
+++ /dev/null
@@ -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()
diff --git a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake b/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake
deleted file mode 100644
index 0351f271a..000000000
--- a/cmake/vcpkg-ports/vcpkg-tool-meson/vcpkg_install_meson.cmake
+++ /dev/null
@@ -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.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()
diff --git a/cmake/vcpkg-triplets/universal-osx.cmake b/cmake/vcpkg-triplets/universal-osx.cmake
deleted file mode 100644
index 1c91a5650..000000000
--- a/cmake/vcpkg-triplets/universal-osx.cmake
+++ /dev/null
@@ -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")
diff --git a/default.nix b/default.nix
index 5ecef5590..6466507b7 100644
--- a/default.nix
+++ b/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
diff --git a/flake.lock b/flake.lock
index 640d2bcf1..a82e6f65f 100644
--- a/flake.lock
+++ b/flake.lock
@@ -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"
}
}
diff --git a/flake.nix b/flake.nix
index 289e0ec1c..54add656d 100644
--- a/flake.nix
+++ b/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;
};
diff --git a/flatpak/flite.json b/flatpak/flite.json
new file mode 100644
index 000000000..1bf280af1
--- /dev/null
+++ b/flatpak/flite.json
@@ -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.]+)$"
+ }
+ }
+ ]
+}
diff --git a/flatpak/libdecor.json b/flatpak/libdecor.json
new file mode 100644
index 000000000..1652a2f04
--- /dev/null
+++ b/flatpak/libdecor.json
@@ -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"
+ ]
+}
diff --git a/flatpak/org.prismlauncher.PrismLauncher.yml b/flatpak/org.prismlauncher.PrismLauncher.yml
new file mode 100644
index 000000000..136aef91a
--- /dev/null
+++ b/flatpak/org.prismlauncher.PrismLauncher.yml
@@ -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
diff --git a/flatpak/patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch b/flatpak/patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
new file mode 100644
index 000000000..70cec9981
--- /dev/null
+++ b/flatpak/patches/0009-Defer-setting-cursor-position-until-the-cursor-is-lo.patch
@@ -0,0 +1,59 @@
+From 9997ae55a47de469ea26f8437c30b51483abda5f Mon Sep 17 00:00:00 2001
+From: Dan Klishch
+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
+
diff --git a/flatpak/prime-run b/flatpak/prime-run
new file mode 100644
index 000000000..946c28dd5
--- /dev/null
+++ b/flatpak/prime-run
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+export __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia
+exec "$@"
diff --git a/flatpak/prismlauncher b/flatpak/prismlauncher
new file mode 100644
index 000000000..039d890d2
--- /dev/null
+++ b/flatpak/prismlauncher
@@ -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 "$@"
diff --git a/flatpak/shared-modules b/flatpak/shared-modules
new file mode 160000
index 000000000..f2b0c16a2
--- /dev/null
+++ b/flatpak/shared-modules
@@ -0,0 +1 @@
+Subproject commit f2b0c16a2a217a1822ce5a6538ba8f755ed1dd32
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index ddeb30588..1d5efe7fc 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -46,12 +46,12 @@
#include "DataMigrationTask.h"
#include "java/JavaInstallList.h"
#include "net/PasteUpload.h"
+#include "pathmatcher/MultiMatcher.h"
+#include "pathmatcher/SimplePrefixMatcher.h"
#include "tasks/Task.h"
#include "tools/GenericProfiler.h"
#include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
-#include "ui/ToolTipFilter.h"
-#include "ui/ViewLogWindow.h"
#include "ui/dialogs/ProgressDialog.h"
#include "ui/instanceview/AccessibleInstanceView.h"
@@ -59,7 +59,8 @@
#include "ui/pages/BasePageProvider.h"
#include "ui/pages/global/APIPage.h"
#include "ui/pages/global/AccountListPage.h"
-#include "ui/pages/global/AppearancePage.h"
+#include "ui/pages/global/CustomCommandsPage.h"
+#include "ui/pages/global/EnvironmentVariablesPage.h"
#include "ui/pages/global/ExternalToolsPage.h"
#include "ui/pages/global/JavaPage.h"
#include "ui/pages/global/LanguagePage.h"
@@ -97,7 +98,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -109,6 +109,8 @@
#include "icons/IconList.h"
#include "net/HttpMetaCache.h"
+#include "java/JavaInstallList.h"
+
#include "updater/ExternalUpdater.h"
#include "tools/JProfiler.h"
@@ -126,11 +128,12 @@
#include
#include
+#include
#include "SysInfo.h"
#ifdef Q_OS_LINUX
#include
-#include "LibraryUtils.h"
+#include "MangoHud.h"
#include "gamemode_client.h"
#endif
@@ -152,15 +155,10 @@
#endif
#if defined Q_OS_WIN32
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
#include
-#include
+#include "WindowsConsole.h"
#endif
-#include "console/Console.h"
-
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
@@ -168,63 +166,6 @@ static const QLatin1String liveCheckFile("live.check");
PixmapCache* PixmapCache::s_instance = nullptr;
-static bool isANSIColorConsole;
-
-static QString defaultLogFormat = QStringLiteral(
- "%{time process}"
- " "
- "%{if-debug}Debug:%{endif}"
- "%{if-info}Info:%{endif}"
- "%{if-warning}Warning:%{endif}"
- "%{if-critical}Critical:%{endif}"
- "%{if-fatal}Fatal:%{endif}"
- " "
- "%{if-category}[%{category}] %{endif}"
- "%{message}"
- " "
- "(%{function}:%{line})");
-
-#define ansi_reset "\x1b[0m"
-#define ansi_bold "\x1b[1m"
-#define ansi_reset_bold "\x1b[22m"
-#define ansi_faint "\x1b[2m"
-#define ansi_italic "\x1b[3m"
-#define ansi_red_fg "\x1b[31m"
-#define ansi_green_fg "\x1b[32m"
-#define ansi_yellow_fg "\x1b[33m"
-#define ansi_blue_fg "\x1b[34m"
-#define ansi_purple_fg "\x1b[35m"
-#define ansi_inverse "\x1b[7m"
-
-// clang-format off
-static QString ansiLogFormat = QStringLiteral(
- ansi_faint "%{time process}" ansi_reset
- " "
- "%{if-debug}" ansi_bold ansi_green_fg "D:" ansi_reset "%{endif}"
- "%{if-info}" ansi_bold ansi_blue_fg "I:" ansi_reset "%{endif}"
- "%{if-warning}" ansi_bold ansi_yellow_fg "W:" ansi_reset_bold "%{endif}"
- "%{if-critical}" ansi_bold ansi_red_fg "C:" ansi_reset_bold "%{endif}"
- "%{if-fatal}" ansi_bold ansi_inverse ansi_red_fg "F:" ansi_reset_bold "%{endif}"
- " "
- "%{if-category}" ansi_bold "[%{category}]" ansi_reset_bold " %{endif}"
- "%{message}"
- " "
- ansi_reset ansi_faint "(%{function}:%{line})" ansi_reset
-);
-// clang-format on
-
-#undef ansi_inverse
-#undef ansi_purple_fg
-#undef ansi_blue_fg
-#undef ansi_yellow_fg
-#undef ansi_green_fg
-#undef ansi_red_fg
-#undef ansi_italic
-#undef ansi_faint
-#undef ansi_bold
-#undef ansi_reset_bold
-#undef ansi_reset
-
namespace {
/** This is used so that we can output to the log file in addition to the CLI. */
@@ -233,27 +174,11 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt
static std::mutex loggerMutex;
const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe
- if (isANSIColorConsole) {
- // ensure default is set for log file
- qSetMessagePattern(defaultLogFormat);
- }
-
QString out = qFormatLogMessage(type, context, msg);
- if (APPLICATION->logModel) {
- APPLICATION->logModel->append(MessageLevel::fromQtMsgType(type), out);
- }
-
out += QChar::LineFeed;
+
APPLICATION->logFile->write(out.toUtf8());
APPLICATION->logFile->flush();
-
- if (isANSIColorConsole) {
- // format ansi for console;
- qSetMessagePattern(ansiLogFormat);
- out = qFormatLogMessage(type, context, msg);
- out += QChar::LineFeed;
- }
-
QTextStream(stderr) << out.toLocal8Bit();
fflush(stderr);
}
@@ -290,17 +215,19 @@ std::tuple read_lock_File(const Q
Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{
- if (console::isConsole()) {
- isANSIColorConsole = true;
+#if defined Q_OS_WIN32
+ // attach the parent console if stdout not already captured
+ if (AttachWindowsConsole()) {
+ consoleAttached = true;
}
-
+#endif
setOrganizationName(BuildConfig.LAUNCHER_NAME);
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
setApplicationName(BuildConfig.LAUNCHER_NAME);
setApplicationDisplayName(QString("%1 %2").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()));
setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT);
- setDesktopFileName(BuildConfig.LAUNCHER_APPID);
- m_startTime = QDateTime::currentDateTime();
+ setDesktopFileName(BuildConfig.LAUNCHER_DESKTOPFILENAME);
+ startTime = QDateTime::currentDateTime();
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -316,9 +243,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
{ { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" },
{ { "w", "world" }, "Join the specified world on launch (only valid in combination with --launch)", "world" },
{ { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" },
- { { "o", "offline" }, "Launch offline, with given player name (only valid in combination with --launch)", "offline" },
{ "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" },
- { "show-window", "Show the main launcher window (useful in combination with --launch)" },
{ { "I", "import" }, "Import instance or resource from specified local path or URL", "url" },
{ "show", "Opens the window for the specified instance (by instance ID)", "show" } });
// Has to be positional for some OS to handle that properly
@@ -333,14 +258,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_serverToJoin = parser.value("server");
m_worldToJoin = parser.value("world");
m_profileToUse = parser.value("profile");
- if (parser.isSet("offline")) {
- m_launchOffline = true;
- m_offlineName = parser.value("offline");
- }
m_liveCheck = parser.isSet("alive");
m_instanceIdToShowWindowOf = parser.value("show");
- m_showMainWindow = parser.isSet("show-window");
for (auto url : parser.values("import")) {
m_urlsToImport.append(normalizeImportUrl(url));
@@ -352,9 +272,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
// error if --launch is missing with --server or --profile
- if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_launchOffline) &&
- m_instanceIdToLaunch.isEmpty()) {
- std::cerr << "--server, --profile and --offline can only be used in combination with --launch!" << std::endl;
+ if (((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty()) || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) {
+ std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed;
return;
}
@@ -394,7 +313,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
} else {
QDir foo;
if (DesktopServices::isSnap()) {
- foo = QDir(qEnvironmentVariable("SNAP_USER_COMMON"));
+ foo = QDir(getenv("SNAP_USER_COMMON"));
} else {
foo = QDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), ".."));
}
@@ -451,20 +370,19 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_peerInstance = new LocalPeer(this, appID);
connect(m_peerInstance, &LocalPeer::messageReceived, this, &Application::messageReceived);
if (m_peerInstance->isClient()) {
- bool sentMessage = false;
int timeout = 2000;
if (m_instanceIdToLaunch.isEmpty()) {
ApplicationMessage activate;
activate.command = "activate";
- sentMessage = m_peerInstance->sendMessage(activate.serialize(), timeout);
+ m_peerInstance->sendMessage(activate.serialize(), timeout);
if (!m_urlsToImport.isEmpty()) {
for (auto url : m_urlsToImport) {
ApplicationMessage import;
import.command = "import";
import.args.insert("url", url.toString());
- sentMessage = m_peerInstance->sendMessage(import.serialize(), timeout);
+ m_peerInstance->sendMessage(import.serialize(), timeout);
}
}
} else {
@@ -480,20 +398,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!m_profileToUse.isEmpty()) {
launch.args["profile"] = m_profileToUse;
}
- if (m_launchOffline) {
- launch.args["offline_enabled"] = "true";
- launch.args["offline_name"] = m_offlineName;
- }
- sentMessage = m_peerInstance->sendMessage(launch.serialize(), timeout);
- }
- if (sentMessage) {
- m_status = Application::Succeeded;
- return;
- } else {
- std::cerr << "Unable to redirect command to already running instance\n";
- // C function not Qt function - event loop not started yet
- ::exit(1);
+ m_peerInstance->sendMessage(launch.serialize(), timeout);
}
+ m_status = Application::Succeeded;
+ return;
}
}
@@ -514,27 +422,37 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
logFile = std::unique_ptr(new QFile(logBase.arg(0)));
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
showFatalErrorMessage("The launcher data folder is not writable!",
- QString("The launcher couldn't create a log file - %1.\n"
+ QString("The launcher couldn't create a log file - the data folder is not writable.\n"
"\n"
"Make sure you have write permissions to the data folder.\n"
- "(%2)\n"
+ "(%1)\n"
"\n"
"The launcher cannot continue until you fix this problem.")
- .arg(logFile->errorString())
.arg(dataPath));
return;
}
qInstallMessageHandler(appDebugOutput);
- qSetMessagePattern(defaultLogFormat);
- logModel.reset(new LogModel(this));
+ qSetMessagePattern(
+ "%{time process}"
+ " "
+ "%{if-debug}D%{endif}"
+ "%{if-info}I%{endif}"
+ "%{if-warning}W%{endif}"
+ "%{if-critical}C%{endif}"
+ "%{if-fatal}F%{endif}"
+ " "
+ "|"
+ " "
+ "%{if-category}[%{category}]: %{endif}"
+ "%{message}");
bool foundLoggingRules = false;
auto logRulesFile = QStringLiteral("qtlogging.ini");
auto logRulesPath = FS::PathCombine(dataPath, logRulesFile);
- qInfo() << "Testing" << logRulesPath << "...";
+ qDebug() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
// search the dataPath()
@@ -542,7 +460,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!foundLoggingRules && !isPortable() && dirParam.isEmpty() && dataDirEnv.isEmpty()) {
logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile));
if (!logRulesPath.isEmpty()) {
- qInfo() << "Found" << logRulesPath << "...";
+ qDebug() << "Found" << logRulesPath << "...";
foundLoggingRules = true;
}
}
@@ -553,69 +471,71 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
#else
logRulesPath = FS::PathCombine(m_rootPath, logRulesFile);
#endif
- qInfo() << "Testing" << logRulesPath << "...";
+ qDebug() << "Testing" << logRulesPath << "...";
foundLoggingRules = QFile::exists(logRulesPath);
}
if (foundLoggingRules) {
// load and set logging rules
- qInfo() << "Loading logging rules from:" << logRulesPath;
+ qDebug() << "Loading logging rules from:" << logRulesPath;
QSettings loggingRules(logRulesPath, QSettings::IniFormat);
loggingRules.beginGroup("Rules");
QStringList rule_names = loggingRules.childKeys();
QStringList rules;
- qInfo() << "Setting log rules:";
+ qDebug() << "Setting log rules:";
for (auto rule_name : rule_names) {
auto rule = QString("%1=%2").arg(rule_name).arg(loggingRules.value(rule_name).toString());
rules.append(rule);
- qInfo() << " " << rule;
+ qDebug() << " " << rule;
}
auto rules_str = rules.join("\n");
QLoggingCategory::setFilterRules(rules_str);
}
- qInfo() << "<> Log initialized.";
+ qDebug() << "<> Log initialized.";
}
{
- auto migrated = handleDataMigration(
- dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC",
- "polymc.cfg");
- if (!migrated) {
- handleDataMigration(dataPath,
- FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"),
- "MultiMC", "multimc.cfg");
- }
+ bool migrated = false;
+
+ if (!migrated)
+ migrated = handleDataMigration(
+ dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC",
+ "polymc.cfg");
+ if (!migrated)
+ migrated = handleDataMigration(
+ dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC",
+ "multimc.cfg");
}
{
- qInfo() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
- qInfo() << "Version :" << BuildConfig.printableVersionString();
- qInfo() << "Platform :" << BuildConfig.BUILD_PLATFORM;
- qInfo() << "Git commit :" << BuildConfig.GIT_COMMIT;
- qInfo() << "Git refspec :" << BuildConfig.GIT_REFSPEC;
- qInfo() << "Compiled for :" << BuildConfig.systemID();
- qInfo() << "Compiled by :" << BuildConfig.compilerID();
- qInfo() << "Build Artifact :" << BuildConfig.BUILD_ARTIFACT;
- qInfo() << "Updates Enabled :" << (updaterEnabled() ? "Yes" : "No");
+ qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
+ qDebug() << "Version : " << BuildConfig.printableVersionString();
+ qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
+ qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
+ qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
+ qDebug() << "Compiled for : " << BuildConfig.systemID();
+ qDebug() << "Compiled by : " << BuildConfig.compilerID();
+ qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
+ qDebug() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
if (adjustedBy.size()) {
- qInfo() << "Work dir before adjustment :" << origcwdPath;
- qInfo() << "Work dir after adjustment :" << QDir::currentPath();
- qInfo() << "Adjusted by :" << adjustedBy;
+ qDebug() << "Work dir before adjustment : " << origcwdPath;
+ qDebug() << "Work dir after adjustment : " << QDir::currentPath();
+ qDebug() << "Adjusted by : " << adjustedBy;
} else {
- qInfo() << "Work dir :" << QDir::currentPath();
+ qDebug() << "Work dir : " << QDir::currentPath();
}
- qInfo() << "Binary path :" << binPath;
- qInfo() << "Application root path :" << m_rootPath;
+ qDebug() << "Binary path : " << binPath;
+ qDebug() << "Application root path : " << m_rootPath;
if (!m_instanceIdToLaunch.isEmpty()) {
- qInfo() << "ID of instance to launch :" << m_instanceIdToLaunch;
+ qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
}
if (!m_serverToJoin.isEmpty()) {
- qInfo() << "Address of server to join :" << m_serverToJoin;
+ qDebug() << "Address of server to join :" << m_serverToJoin;
} else if (!m_worldToJoin.isEmpty()) {
- qInfo() << "Name of the world to join :" << m_worldToJoin;
+ qDebug() << "Name of the world to join :" << m_worldToJoin;
}
- qInfo() << "<> Paths set.";
+ qDebug() << "<> Paths set.";
}
if (m_liveCheck) {
@@ -625,11 +545,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (check.write(payload) == payload.size()) {
check.close();
} else {
- qWarning() << "Could not write into" << liveCheckFile << "error:" << check.errorString();
+ qWarning() << "Could not write into" << liveCheckFile << "!";
check.remove(); // also closes file!
}
} else {
- qWarning() << "Could not open" << liveCheckFile << "for writing:" << check.errorString();
+ qWarning() << "Could not open" << liveCheckFile << "for writing!";
}
}
@@ -672,38 +592,23 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
QFontInfo consoleFontInfo(consoleFont);
QString resolvedDefaultMonospace = consoleFontInfo.family();
QFont resolvedFont(resolvedDefaultMonospace);
- qDebug().nospace() << "Detected default console font: " << resolvedDefaultMonospace
- << ", substitutions: " << resolvedFont.substitutions().join(',');
+ qDebug() << "Detected default console font:" << resolvedDefaultMonospace
+ << ", substitutions:" << resolvedFont.substitutions().join(',');
m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace);
m_settings->registerSetting("ConsoleFontSize", defaultSize);
m_settings->registerSetting("ConsoleMaxLines", 100000);
m_settings->registerSetting("ConsoleOverflowStop", true);
- logModel->setMaxLines(getConsoleMaxLines(settings()));
- logModel->setStopOnOverflow(shouldStopOnConsoleOverflow(settings()));
- logModel->setOverflowMessage(tr("Cannot display this log since the log length surpassed %1 lines.").arg(logModel->getMaxLines()));
-
// Folders
m_settings->registerSetting("InstanceDir", "instances");
m_settings->registerSetting({ "CentralModsDir", "ModsDir" }, "mods");
m_settings->registerSetting("IconsDir", "icons");
m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
m_settings->registerSetting("DownloadsDirWatchRecursive", false);
- m_settings->registerSetting("MoveModsFromDownloadsDir", false);
m_settings->registerSetting("SkinsDir", "skins");
m_settings->registerSetting("JavaDir", "java");
-#ifdef Q_OS_MACOS
- // Folder security-scoped bookmarks
- m_settings->registerSetting("InstanceDirBookmark", "");
- m_settings->registerSetting("CentralModsDirBookmark", "");
- m_settings->registerSetting("IconsDirBookmark", "");
- m_settings->registerSetting("DownloadsDirBookmark", "");
- m_settings->registerSetting("SkinsDirBookmark", "");
- m_settings->registerSetting("JavaDirBookmark", "");
-#endif
-
// Editors
m_settings->registerSetting("JsonEditor", QString());
@@ -731,9 +636,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// Memory
m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512);
- m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::defaultMaxJvmMem());
+ m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, SysInfo::suitableMaxMem());
m_settings->registerSetting("PermGen", 128);
- m_settings->registerSetting("LowMemWarning", true);
// Java Settings
m_settings->registerSetting("JavaPath", "");
@@ -776,8 +680,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("ModMetadataDisabled", false);
m_settings->registerSetting("ModDependenciesDisabled", false);
m_settings->registerSetting("SkipModpackUpdatePrompt", false);
- m_settings->registerSetting("ShowModIncompat", false);
- m_settings->registerSetting("DownloadGameFilesDuringInstanceCreation", true);
// Minecraft offline player name
m_settings->registerSetting("LastOfflinePlayerName", "");
@@ -792,15 +694,12 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// The cat
m_settings->registerSetting("TheCat", false);
m_settings->registerSetting("CatOpacity", 100);
- m_settings->registerSetting("CatFit", "fit");
m_settings->registerSetting("StatusBarVisible", true);
m_settings->registerSetting("ToolbarsLocked", false);
- // Instance
m_settings->registerSetting("InstSortMode", "Name");
- m_settings->registerSetting("InstRenamingMode", "AskEverytime");
m_settings->registerSetting("SelectedInstance", QString());
// Window state and geometry
@@ -818,17 +717,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("UpdateDialogGeometry", "");
- m_settings->registerSetting("NewsGeometry", "");
-
m_settings->registerSetting("ModDownloadGeometry", "");
m_settings->registerSetting("RPDownloadGeometry", "");
m_settings->registerSetting("TPDownloadGeometry", "");
m_settings->registerSetting("ShaderDownloadGeometry", "");
- m_settings->registerSetting("DataPackDownloadGeometry", "");
-
- // data pack window
- // in future, more pages may be added - so this name is chosen to avoid needing migration
- m_settings->registerSetting("WorldManagementGeometry", "");
// HACK: This code feels so stupid is there a less stupid way of doing this?
{
@@ -854,27 +746,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
{
- auto resetIfInvalid = [this](const Setting* setting) {
- if (const QUrl url(setting->get().toString()); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) {
- m_settings->reset(setting->id());
- }
- };
-
// Meta URL
- resetIfInvalid(m_settings->registerSetting("MetaURLOverride", "").get());
+ m_settings->registerSetting("MetaURLOverride", "");
- // Resource URL
- resetIfInvalid(m_settings->registerSetting({ "ResourceURLOverride", "ResourceURL" }, "").get());
+ QUrl metaUrl(m_settings->get("MetaURLOverride").toString());
- // Legacy FML libs URL
- resetIfInvalid(m_settings->registerSetting("LegacyFMLLibsURLOverride", "").get());
+ // get rid of invalid meta urls
+ if (!metaUrl.isValid() || (metaUrl.scheme() != "http" && metaUrl.scheme() != "https"))
+ m_settings->reset("MetaURLOverride");
}
- m_settings->registerSetting("MetaRefreshOnLaunch", true);
m_settings->registerSetting("CloseAfterLaunch", false);
m_settings->registerSetting("QuitAfterGameStop", false);
- m_settings->registerSetting("Env", "{}");
+ m_settings->registerSetting("Env", QVariant(QMap()));
// Custom Microsoft Authentication Client ID
m_settings->registerSetting("MSAClientIDOverride", "");
@@ -890,7 +775,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->set("FlameKeyOverride", flameKey);
m_settings->reset("CFKeyOverride");
}
- m_settings->registerSetting("FallbackMRBlockedMods", true);
m_settings->registerSetting("ModrinthToken", "");
m_settings->registerSetting("UserAgentOverride", "");
@@ -902,21 +786,22 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
// Init page provider
{
- m_globalSettingsProvider = std::make_unique(tr("Settings"));
+ m_globalSettingsProvider = std::make_shared(tr("Settings"));
m_globalSettingsProvider->addPage();
- m_globalSettingsProvider->addPage();
- m_globalSettingsProvider->addPage();
m_globalSettingsProvider->addPage();
m_globalSettingsProvider->addPage();
+ m_globalSettingsProvider->addPage();
+ m_globalSettingsProvider->addPage();
+ m_globalSettingsProvider->addPage();
+ m_globalSettingsProvider->addPage();
+ m_globalSettingsProvider->addPage();
m_globalSettingsProvider->addPage();
m_globalSettingsProvider->addPage();
- m_globalSettingsProvider->addPage();
- m_globalSettingsProvider->addPage();
}
PixmapCache::setInstance(new PixmapCache(this));
- qInfo() << "<> Settings loaded.";
+ qDebug() << "<> Settings loaded.";
}
#ifndef QT_NO_ACCESSIBILITY
@@ -932,7 +817,16 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
QString user = settings()->get("ProxyUser").toString();
QString pass = settings()->get("ProxyPass").toString();
updateProxySettings(proxyTypeStr, addr, port, user, pass);
- qInfo() << "<> Network done.";
+ qDebug() << "<> Network done.";
+ }
+
+ // load translations
+ {
+ m_translations.reset(new TranslationsModel("translations"));
+ auto bcp47Name = m_settings->get("Language").toString();
+ m_translations->selectLanguage(bcp47Name);
+ qDebug() << "Your language is" << bcp47Name;
+ qDebug() << "<> Translations loaded.";
}
// Instance icons
@@ -942,53 +836,38 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
":/icons/multimc/128x128/instances/", ":/icons/multimc/scalable/instances/" };
m_icons.reset(new IconList(instFolders, setting->get().toString()));
connect(setting.get(), &Setting::SettingChanged,
- [this](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); });
- qInfo() << "<> Instance icons initialized.";
+ [&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); });
+ qDebug() << "<> Instance icons initialized.";
}
// Themes
m_themeManager = std::make_unique();
-#ifdef Q_OS_MACOS
- // for macOS: getting directory settings will generate URL security-scoped bookmarks if needed and not present
- // this facilitates a smooth transition from a non-sandboxed version of the launcher, that likely can access the directory,
- // and a sandboxed version that can't access the directory without a bookmark
- // this section can likely be removed once the sandboxed version has been released for a while and migrations aren't done anymore
- {
- m_settings->get("InstanceDir");
- m_settings->get("CentralModsDir");
- m_settings->get("IconsDir");
- m_settings->get("DownloadsDir");
- m_settings->get("SkinsDir");
- m_settings->get("JavaDir");
- }
-#endif
-
// initialize and load all instances
{
auto InstDirSetting = m_settings->getSetting("InstanceDir");
// instance path: check for problems with '!' in instance path and warn the user in the log
// and remember that we have to show him a dialog when the gui starts (if it does so)
- QString instDir = m_settings->get("InstanceDir").toString();
- qInfo() << "Instance path :" << instDir;
+ QString instDir = InstDirSetting->get().toString();
+ qDebug() << "Instance path : " << instDir;
if (FS::checkProblemticPathJava(QDir(instDir))) {
qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!";
}
- m_instances.reset(new InstanceList(m_settings.get(), instDir, this));
+ m_instances.reset(new InstanceList(m_settings, instDir, this));
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instances.get(), &InstanceList::on_InstFolderChanged);
- qInfo() << "Loading Instances...";
+ qDebug() << "Loading Instances...";
m_instances->loadList();
- qInfo() << "<> Instances loaded.";
+ qDebug() << "<> Instances loaded.";
}
// and accounts
{
m_accounts.reset(new AccountList(this));
- qInfo() << "Loading accounts...";
+ qDebug() << "Loading accounts...";
m_accounts->setListFilePath("accounts.json", true);
m_accounts->loadList();
m_accounts->fillQueue();
- qInfo() << "<> Accounts loaded.";
+ qDebug() << "<> Accounts loaded.";
}
// init the http meta cache
@@ -1008,30 +887,24 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_metacache->addBase("translations", QDir("translations").absolutePath());
m_metacache->addBase("meta", QDir("meta").absolutePath());
m_metacache->addBase("java", QDir("cache/java").absolutePath());
- m_metacache->addBase("feed", QDir("cache/feed").absolutePath());
m_metacache->Load();
- qInfo() << "<> Cache initialized.";
+ qDebug() << "<> Cache initialized.";
}
- // load translations
- {
- m_translations.reset(new TranslationsModel("translations"));
- m_translations->downloadIndex();
- qInfo() << "Your language is" << m_translations->selectedLanguage();
- qInfo() << "<> Translations loaded.";
- }
+ // now we have network, download translation updates
+ m_translations->downloadIndex();
// FIXME: what to do with these?
m_profilers.insert("jprofiler", std::shared_ptr(new JProfilerFactory()));
m_profilers.insert("jvisualvm", std::shared_ptr(new JVisualVMFactory()));
m_profilers.insert("generic", std::shared_ptr(new GenericProfilerFactory()));
for (auto profiler : m_profilers.values()) {
- profiler->registerSettings(m_settings.get());
+ profiler->registerSettings(m_settings);
}
// Create the MCEdit thing... why is this here?
{
- m_mcedit.reset(new MCEditTool(m_settings.get()));
+ m_mcedit.reset(new MCEditTool(m_settings));
}
#ifdef Q_OS_MACOS
@@ -1188,10 +1061,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
- if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") {
- installEventFilter(new ToolTipFilter);
- }
-
if (createSetupWizard()) {
return;
}
@@ -1202,11 +1071,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
bool Application::createSetupWizard()
{
- bool javaRequired = [this]() {
- if (BuildConfig.JAVA_DOWNLOADER_ENABLED && settings()->get("AutomaticJavaDownload").toBool()) {
+ bool javaRequired = [&]() {
+ if (BuildConfig.JAVA_DOWNLOADER_ENABLED && m_settings->get("AutomaticJavaDownload").toBool()) {
return false;
}
- bool ignoreJavaWizard = settings()->get("IgnoreJavaWizard").toBool();
+ bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool();
if (ignoreJavaWizard) {
return false;
}
@@ -1220,8 +1089,8 @@ bool Application::createSetupWizard()
QString actualPath = FS::ResolveExecutable(currentJavaPath);
return actualPath.isNull();
}();
- bool askjava = BuildConfig.JAVA_DOWNLOADER_ENABLED && !javaRequired && !settings()->get("AutomaticJavaDownload").toBool() &&
- !settings()->get("AutomaticJavaSwitch").toBool() && !settings()->get("UserAskedAboutAutomaticJavaDownload").toBool();
+ bool askjava = BuildConfig.JAVA_DOWNLOADER_ENABLED && !javaRequired && !m_settings->get("AutomaticJavaDownload").toBool() &&
+ !m_settings->get("AutomaticJavaSwitch").toBool() && !m_settings->get("UserAskedAboutAutomaticJavaDownload").toBool();
bool languageRequired = settings()->get("Language").toString().isEmpty();
bool pasteInterventionRequired = settings()->get("PastebinURL") != "";
bool validWidgets = m_themeManager->isValidApplicationTheme(settings()->get("ApplicationTheme").toString());
@@ -1233,16 +1102,8 @@ bool Application::createSetupWizard()
// set default theme after going into theme wizard
if (!validIcons)
settings()->set("IconTheme", QString("pe_colored"));
- if (!validWidgets) {
-#if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
- const QString style =
- QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark ? QStringLiteral("dark") : QStringLiteral("bright");
-#else
- const QString style = QStringLiteral("system");
-#endif
-
- settings()->set("ApplicationTheme", style);
- }
+ if (!validWidgets)
+ settings()->set("ApplicationTheme", QString("system"));
m_themeManager->applyCurrentlySelectedTheme(true);
@@ -1309,9 +1170,6 @@ bool Application::event(QEvent* event)
#endif
if (event->type() == QEvent::FileOpen) {
- if (!m_mainWindow) {
- showMainWindow(false);
- }
auto ev = static_cast(event);
m_mainWindow->processURLs({ ev->url() });
}
@@ -1352,11 +1210,8 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse;
}
- launch(inst, m_launchOffline ? LaunchMode::Offline : LaunchMode::Normal, targetToJoin, accountToUse, m_offlineName);
-
- if (!m_showMainWindow) {
- return;
- }
+ launch(inst, true, false, targetToJoin, accountToUse);
+ return;
}
}
if (!m_instanceIdToShowWindowOf.isEmpty()) {
@@ -1409,6 +1264,16 @@ Application::~Application()
{
// Shut down logger by setting the logger function to nothing
qInstallMessageHandler(nullptr);
+
+#if defined Q_OS_WIN32
+ // Detach from Windows console
+ if (consoleAttached) {
+ fclose(stdout);
+ fclose(stdin);
+ fclose(stderr);
+ FreeConsole();
+ }
+#endif
}
void Application::messageReceived(const QByteArray& message)
@@ -1438,19 +1303,14 @@ void Application::messageReceived(const QByteArray& message)
qWarning() << "Received" << command << "message without a zip path/URL.";
return;
}
- if (!m_mainWindow) {
- showMainWindow(false);
- }
m_mainWindow->processURLs({ normalizeImportUrl(url) });
} else if (command == "launch") {
QString id = received.args["id"];
QString server = received.args["server"];
QString world = received.args["world"];
QString profile = received.args["profile"];
- bool offline = received.args["offline_enabled"] == "true";
- QString offlineName = received.args["offline_name"];
- BaseInstance* instance;
+ InstancePtr instance;
if (!id.isEmpty()) {
instance = instances()->getInstanceById(id);
if (!instance) {
@@ -1478,28 +1338,31 @@ void Application::messageReceived(const QByteArray& message)
}
}
- launch(instance, offline ? LaunchMode::Offline : LaunchMode::Normal, serverObject, accountObject, offlineName);
+ launch(instance, true, false, serverObject, accountObject);
} else {
qWarning() << "Received invalid message" << message;
}
}
-TranslationsModel* Application::translations()
+std::shared_ptr Application::translations()
{
- return m_translations.get();
+ return m_translations;
}
-JavaInstallList* Application::javalist()
+std::shared_ptr Application::javalist()
{
if (!m_javalist) {
m_javalist.reset(new JavaInstallList());
}
- return m_javalist.get();
+ return m_javalist;
}
-QIcon Application::logo()
+QIcon Application::getThemedIcon(const QString& name)
{
- return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME);
+ if (name == "logo") {
+ return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME);
+ }
+ return QIcon::fromTheme(name);
}
bool Application::openJsonEditor(const QString& filename)
@@ -1513,11 +1376,7 @@ bool Application::openJsonEditor(const QString& filename)
}
}
-bool Application::launch(BaseInstance* instance,
- LaunchMode mode,
- MinecraftTarget::Ptr targetToJoin,
- MinecraftAccountPtr accountToUse,
- const QString& offlineName)
+bool Application::launch(InstancePtr instance, bool online, bool demo, MinecraftTarget::Ptr targetToJoin, MinecraftAccountPtr accountToUse)
{
if (m_updateRunning) {
qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed.";
@@ -1533,17 +1392,19 @@ bool Application::launch(BaseInstance* instance,
auto& controller = extras.controller;
controller.reset(new LaunchController());
controller->setInstance(instance);
- controller->setLaunchMode(mode);
+ controller->setOnline(online);
+ controller->setDemo(demo);
controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get());
controller->setTargetToJoin(targetToJoin);
controller->setAccountToUse(accountToUse);
- controller->setOfflineName(offlineName);
if (window) {
controller->setParentWidget(window);
} else if (m_mainWindow) {
controller->setParentWidget(m_mainWindow);
}
- connect(controller.get(), &LaunchController::finished, this, &Application::controllerFinished);
+ connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded);
+ connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed);
+ connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); });
addRunningInstance();
QMetaObject::invokeMethod(controller.get(), &Task::start, Qt::QueuedConnection);
return true;
@@ -1557,7 +1418,7 @@ bool Application::launch(BaseInstance* instance,
return false;
}
-bool Application::kill(BaseInstance* instance)
+bool Application::kill(InstancePtr instance)
{
if (!instance->isRunning()) {
qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running.";
@@ -1566,7 +1427,7 @@ bool Application::kill(BaseInstance* instance)
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instance->id()];
// NOTE: copy of the shared pointer keeps it alive
- auto& controller = extras.controller;
+ auto controller = extras.controller;
locker.unlock();
if (controller) {
return controller->abort();
@@ -1615,19 +1476,18 @@ void Application::updateIsRunning(bool running)
m_updateRunning = running;
}
-void Application::controllerFinished()
+void Application::controllerSucceeded()
{
- auto controller = qobject_cast(sender());
+ auto controller = qobject_cast(QObject::sender());
if (!controller)
return;
auto id = controller->id();
QMutexLocker locker(&m_instanceExtrasMutex);
- auto& extras = m_instanceExtras.at(id);
+ auto& extras = m_instanceExtras[id];
- const bool wasSuccessful = controller->wasSuccessful();
// on success, do...
- if (wasSuccessful && controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
+ if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) {
if (extras.window) {
QMetaObject::invokeMethod(extras.window, &QWidget::close, Qt::QueuedConnection);
}
@@ -1637,8 +1497,29 @@ void Application::controllerFinished()
// quit when there are no more windows.
if (shouldExitNow()) {
- m_status = wasSuccessful ? Succeeded : Failed;
- exit(wasSuccessful ? 0 : 1);
+ m_status = Status::Succeeded;
+ exit(0);
+ }
+}
+
+void Application::controllerFailed(const QString& error)
+{
+ Q_UNUSED(error);
+ auto controller = qobject_cast(QObject::sender());
+ if (!controller)
+ return;
+ auto id = controller->id();
+ QMutexLocker locker(&m_instanceExtrasMutex);
+ auto& extras = m_instanceExtras[id];
+
+ // on failure, do... nothing
+ extras.controller.reset();
+ subRunningInstance();
+
+ // quit when there are no more windows.
+ if (shouldExitNow()) {
+ m_status = Status::Failed;
+ exit(1);
}
}
@@ -1651,9 +1532,9 @@ void Application::ShowGlobalSettings(class QWidget* parent, QString open_page)
{
SettingsObject::Lock lock(APPLICATION->settings());
PageDialog dlg(m_globalSettingsProvider.get(), open_page, parent);
- connect(&dlg, &PageDialog::applied, this, &Application::globalSettingsApplied);
dlg.exec();
}
+ emit globalSettingsClosed();
}
MainWindow* Application::showMainWindow(bool minimized)
@@ -1664,8 +1545,8 @@ MainWindow* Application::showMainWindow(bool minimized)
m_mainWindow->activateWindow();
} else {
m_mainWindow = new MainWindow();
- m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toString().toUtf8()));
- m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toString().toUtf8()));
+ m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray()));
+ m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray()));
if (minimized) {
m_mainWindow->showMinimized();
@@ -1681,21 +1562,7 @@ MainWindow* Application::showMainWindow(bool minimized)
return m_mainWindow;
}
-ViewLogWindow* Application::showLogWindow()
-{
- if (m_viewLogWindow) {
- m_viewLogWindow->setWindowState(m_viewLogWindow->windowState() & ~Qt::WindowMinimized);
- m_viewLogWindow->raise();
- m_viewLogWindow->activateWindow();
- } else {
- m_viewLogWindow = new ViewLogWindow();
- connect(m_viewLogWindow, &ViewLogWindow::isClosing, this, &Application::on_windowClose);
- m_openWindows++;
- }
- return m_viewLogWindow;
-}
-
-InstanceWindow* Application::showInstanceWindow(BaseInstance* instance, QString page)
+InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString page)
{
if (!instance)
return nullptr;
@@ -1736,7 +1603,7 @@ InstanceWindow* Application::showInstanceWindow(BaseInstance* instance, QString
void Application::on_windowClose()
{
m_openWindows--;
- auto instWindow = qobject_cast(sender());
+ auto instWindow = qobject_cast(QObject::sender());
if (instWindow) {
QMutexLocker locker(&m_instanceExtrasMutex);
auto& extras = m_instanceExtras[instWindow->instanceId()];
@@ -1745,14 +1612,10 @@ void Application::on_windowClose()
extras.controller->setParentWidget(m_mainWindow);
}
}
- auto mainWindow = qobject_cast(sender());
+ auto mainWindow = qobject_cast(QObject::sender());
if (mainWindow) {
m_mainWindow = nullptr;
}
- auto logWindow = qobject_cast(sender());
- if (logWindow) {
- m_viewLogWindow = nullptr;
- }
// quit when there are no more windows.
if (shouldExitNow()) {
exit(0);
@@ -1807,22 +1670,22 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po
qDebug() << proxyDesc;
}
-HttpMetaCache* Application::metacache()
+shared_qobject_ptr Application::metacache()
{
- return m_metacache.get();
+ return m_metacache;
}
-QNetworkAccessManager* Application::network()
+shared_qobject_ptr Application::network()
{
- return m_network.get();
+ return m_network;
}
-Meta::Index* Application::metadataIndex()
+shared_qobject_ptr Application::metadataIndex()
{
if (!m_metadataIndex) {
m_metadataIndex.reset(new Meta::Index());
}
- return m_metadataIndex.get();
+ return m_metadataIndex;
}
void Application::updateCapabilities()
@@ -1837,7 +1700,7 @@ void Application::updateCapabilities()
if (gamemode_query_status() >= 0)
m_capabilities |= SupportsGameMode;
- if (!LibraryUtils::findMangoHud().isEmpty())
+ if (!MangoHud::getLibraryString().isEmpty())
m_capabilities |= SupportsMangoHud;
#endif
}
@@ -1845,8 +1708,8 @@ void Application::updateCapabilities()
void Application::detectLibraries()
{
#ifdef Q_OS_LINUX
- m_detectedGLFWPath = LibraryUtils::find(BuildConfig.GLFW_LIBRARY_NAME);
- m_detectedOpenALPath = LibraryUtils::find(BuildConfig.OPENAL_LIBRARY_NAME);
+ m_detectedGLFWPath = MangoHud::findLibrary(BuildConfig.GLFW_LIBRARY_NAME);
+ m_detectedOpenALPath = MangoHud::findLibrary(BuildConfig.OPENAL_LIBRARY_NAME);
qDebug() << "Detected native libraries:" << m_detectedGLFWPath << m_detectedOpenALPath;
#endif
}
@@ -1907,6 +1770,17 @@ QString Application::getUserAgent()
return BuildConfig.USER_AGENT;
}
+QString Application::getUserAgentUncached()
+{
+ QString uaOverride = m_settings->get("UserAgentOverride").toString();
+ if (!uaOverride.isEmpty()) {
+ uaOverride += " (Uncached)";
+ return uaOverride.replace("$LAUNCHER_VER", BuildConfig.printableVersionString());
+ }
+
+ return BuildConfig.USER_AGENT_UNCACHED;
+}
+
bool Application::handleDataMigration(const QString& currentData,
const QString& oldData,
const QString& name,
@@ -1952,9 +1826,7 @@ bool Application::handleDataMigration(const QString& currentData,
auto setDoNotMigrate = [&nomigratePath] {
QFile file(nomigratePath);
- if (!file.open(QIODevice::WriteOnly)) {
- qWarning() << "setDoNotMigrate failed; Failed to open file" << file.fileName() << "for writing:" << file.errorString();
- }
+ file.open(QIODevice::WriteOnly);
};
// create no-migrate file if user doesn't want to migrate
@@ -1966,23 +1838,22 @@ bool Application::handleDataMigration(const QString& currentData,
if (!currentExists) {
// Migrate!
- using namespace Filters;
-
- QList filters;
- filters.append(equals(configFile));
- filters.append(equals(BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before
- filters.append(startsWith("logs/"));
- filters.append(equals("accounts.json"));
- filters.append(startsWith("accounts/"));
- filters.append(startsWith("assets/"));
- filters.append(startsWith("icons/"));
- filters.append(startsWith("instances/"));
- filters.append(startsWith("libraries/"));
- filters.append(startsWith("mods/"));
- filters.append(startsWith("themes/"));
+ auto matcher = std::make_shared();
+ matcher->add(std::make_shared(configFile));
+ matcher->add(std::make_shared(
+ BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before
+ matcher->add(std::make_shared("logs/"));
+ matcher->add(std::make_shared("accounts.json"));
+ matcher->add(std::make_shared("accounts/"));
+ matcher->add(std::make_shared("assets/"));
+ matcher->add(std::make_shared("icons/"));
+ matcher->add(std::make_shared("instances/"));
+ matcher->add(std::make_shared("libraries/"));
+ matcher->add(std::make_shared("mods/"));
+ matcher->add(std::make_shared("themes/"));
ProgressDialog diag;
- DataMigrationTask task(oldData, currentData, any(std::move(filters)));
+ DataMigrationTask task(oldData, currentData, matcher);
if (diag.execWithTask(&task)) {
qDebug() << "<> Migration succeeded";
setDoNotMigrate();
@@ -2007,7 +1878,7 @@ void Application::triggerUpdateCheck()
}
}
-QUrl Application::normalizeImportUrl(const QString& url)
+QUrl Application::normalizeImportUrl(QString const& url)
{
auto local_file = QFileInfo(url);
if (local_file.exists()) {
@@ -2048,4 +1919,4 @@ bool Application::checkQSavePath(QString path)
}
}
return false;
-}
+}
\ No newline at end of file
diff --git a/launcher/Application.h b/launcher/Application.h
index 936e13d71..164ec3a4f 100644
--- a/launcher/Application.h
+++ b/launcher/Application.h
@@ -37,8 +37,6 @@
#pragma once
-#include
-
#include
#include
#include
@@ -46,16 +44,16 @@
#include
#include
#include
+#include
-#include "QObjectPtr.h"
+#include
-#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(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 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 updater() { return m_updater; }
void triggerUpdateCheck();
- TranslationsModel* translations();
+ std::shared_ptr translations();
- JavaInstallList* javalist();
+ std::shared_ptr javalist();
- InstanceList* instances() const { return m_instances.get(); }
+ std::shared_ptr instances() const { return m_instances; }
- IconList* icons() const { return m_icons.get(); }
+ std::shared_ptr icons() const { return m_icons; }
MCEditTool* mcedit() const { return m_mcedit.get(); }
- AccountList* accounts() const { return m_accounts.get(); }
+ shared_qobject_ptr 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 network();
- HttpMetaCache* metacache();
+ shared_qobject_ptr metacache();
- Meta::Index* metadataIndex();
+ shared_qobject_ptr 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 targetToJoin = nullptr,
- shared_qobject_ptr 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 m_qsaveResources;
- mutable QMutex m_qsaveResourcesMutex;
+ QDateTime startTime;
- private:
- QDateTime m_startTime;
+ shared_qobject_ptr m_network;
- std::unique_ptr m_network;
+ shared_qobject_ptr m_updater;
+ shared_qobject_ptr m_accounts;
- std::unique_ptr m_updater;
- std::unique_ptr m_accounts;
+ shared_qobject_ptr m_metacache;
+ shared_qobject_ptr m_metadataIndex;
- std::unique_ptr m_metacache;
- std::unique_ptr m_metadataIndex;
-
- std::unique_ptr m_settings;
- std::unique_ptr m_instances;
- std::unique_ptr m_icons;
- std::unique_ptr m_javalist;
- std::unique_ptr m_translations;
- std::unique_ptr m_globalSettingsProvider;
+ std::shared_ptr m_settings;
+ std::shared_ptr m_instances;
+ std::shared_ptr m_icons;
+ std::shared_ptr m_javalist;
+ std::shared_ptr m_translations;
+ std::shared_ptr m_globalSettingsProvider;
std::unique_ptr m_mcedit;
QSet m_features;
std::unique_ptr 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 controller;
+ shared_qobject_ptr controller;
};
std::map 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 m_urlsToImport;
QString m_instanceIdToShowWindowOf;
- bool m_showMainWindow = false;
std::unique_ptr logFile;
- std::unique_ptr logModel;
public:
void addQSavePath(QString);
void removeQSavePath(QString);
bool checkQSavePath(QString);
+
+ private:
+ QHash m_qsaveResources;
+ mutable QMutex m_qsaveResourcesMutex;
};
diff --git a/launcher/AssertHelpers.h b/launcher/AssertHelpers.h
deleted file mode 100644
index 0b1cdb742..000000000
--- a/launcher/AssertHelpers.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- * Prism Launcher - Minecraft Launcher
- * Copyright (C) 2025 Octol1ttle
- *
- * 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 .
- */
-
-#pragma once
-
-#if defined(ASSERT_NEVER)
-#error ASSERT_NEVER already defined
-#else
-#define ASSERT_NEVER(cond) (Q_ASSERT((cond) == false), (cond))
-#endif
diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp
index 0080cc516..69cf95e3c 100644
--- a/launcher/BaseInstance.cpp
+++ b/launcher/BaseInstance.cpp
@@ -42,10 +42,8 @@
#include
#include
#include
+#include
-#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 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_ptrregisterSetting("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_ptrregisterSetting("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& 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(elem.target) } });
- }
-
- QJsonDocument document;
- document.setArray(array);
- m_settings->set("shortcuts", QString::fromUtf8(document.toJson(QJsonDocument::Compact)));
-}
-
-QList 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 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(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 BaseInstance::getLaunchTask()
{
- return m_launchProcess.get();
+ return m_launchProcess;
}
void BaseInstance::updateRuntimeContext()
{
// NOOP
}
-
-bool BaseInstance::isLegacy()
-{
- return traits().contains("legacyLaunch") || traits().contains("alphaLaunch");
-}
diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h
index 9280d2e1c..2be28d1ec 100644
--- a/launcher/BaseInstance.h
+++ b/launcher/BaseInstance.h
@@ -38,9 +38,7 @@
#pragma once
#include
-#include
#include
-#include
#include
#include
#include
@@ -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;
/*!
* \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 {
Q_OBJECT
protected:
/// no-touchy!
- BaseInstance(SettingsObject* globalSettings, std::unique_ptr 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 shortcuts() const;
- void setShortcuts(const QList& 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 createUpdateTask() = 0;
/// returns a valid launcher (task container)
- virtual LaunchTask* createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
+ virtual shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftTarget::Ptr targetToJoin) = 0;
/// returns the current launch task (if any)
- LaunchTask* getLaunchTask();
+ shared_qobject_ptr 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);
void runningStatusChanged(bool running);
@@ -307,10 +296,10 @@ class BaseInstance : public QObject {
protected: /* data */
QString m_rootDir;
- std::unique_ptr m_settings;
+ SettingsObjectPtr m_settings;
// InstanceFlags m_flags;
bool m_isRunning = false;
- std::unique_ptr m_launchProcess;
+ shared_qobject_ptr 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;
};
diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h
index e442c60df..2837ff3a9 100644
--- a/launcher/BaseVersion.h
+++ b/launcher/BaseVersion.h
@@ -24,28 +24,27 @@
*/
class BaseVersion {
public:
- // TODO: delete
using Ptr = std::shared_ptr;
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)
diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h
index ba546e955..673d13562 100644
--- a/launcher/BaseVersionList.h
+++ b/launcher/BaseVersionList.h
@@ -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.
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 7d4430fd2..0f0949a3a 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -21,19 +21,11 @@ set(CORE_SOURCES
BaseVersion.h
BaseInstance.h
BaseInstance.cpp
- InstanceDirUpdate.h
- InstanceDirUpdate.cpp
NullInstance.h
MMCZip.h
MMCZip.cpp
- archive/ArchiveReader.cpp
- archive/ArchiveReader.h
- archive/ArchiveWriter.cpp
- archive/ArchiveWriter.h
- archive/ExportToZipTask.cpp
- archive/ExportToZipTask.h
- archive/ExtractZipTask.cpp
- archive/ExtractZipTask.h
+ Untar.h
+ Untar.cpp
StringUtils.h
StringUtils.cpp
QVariantUtils.h
@@ -62,6 +54,7 @@ set(CORE_SOURCES
# String filters
Filter.h
+ Filter.cpp
# JSON parsing helpers
Json.h
@@ -75,6 +68,9 @@ set(CORE_SOURCES
# RW lock protected map
RWStorage.h
+ # A variable that has an implicit default value and keeps track of changes
+ DefaultVariable.h
+
# a smart pointer wrapper intended for safer use with Qt signal/slot mechanisms
QObjectPtr.h
@@ -99,27 +95,32 @@ set(CORE_SOURCES
MMCTime.cpp
MTPixmapCache.h
-
- # Assertion helper
- AssertHelpers.h
)
if (UNIX AND NOT CYGWIN AND NOT APPLE)
- set(CORE_SOURCES
+set(CORE_SOURCES
${CORE_SOURCES}
- # LibraryUtils
- LibraryUtils.h
- LibraryUtils.cpp
+ # MangoHud
+ MangoHud.h
+ MangoHud.cpp
)
endif()
+set(PATHMATCHER_SOURCES
+ # Path matchers
+ pathmatcher/FSTreeMatcher.h
+ pathmatcher/IPathMatcher.h
+ pathmatcher/MultiMatcher.h
+ pathmatcher/RegexpMatcher.h
+ pathmatcher/SimplePrefixMatcher.h
+)
+
set(NET_SOURCES
# network stuffs
net/ByteArraySink.h
net/ChecksumValidator.h
net/Download.cpp
net/Download.h
- net/DummySink.h
net/FileSink.cpp
net/FileSink.h
net/HttpMetaCache.cpp
@@ -172,8 +173,6 @@ set(LAUNCH_SOURCES
launch/LogModel.h
launch/TaskStepWrapper.cpp
launch/TaskStepWrapper.h
- logs/LogParser.cpp
- logs/LogParser.h
)
# Old update system
@@ -244,13 +243,18 @@ set(MINECRAFT_SOURCES
minecraft/auth/steps/MSAStep.h
minecraft/auth/steps/XboxAuthorizationStep.cpp
minecraft/auth/steps/XboxAuthorizationStep.h
+ minecraft/auth/steps/XboxProfileStep.cpp
+ minecraft/auth/steps/XboxProfileStep.h
minecraft/auth/steps/XboxUserStep.cpp
minecraft/auth/steps/XboxUserStep.h
+ minecraft/gameoptions/GameOptions.h
+ minecraft/gameoptions/GameOptions.cpp
+
minecraft/update/AssetUpdateTask.h
minecraft/update/AssetUpdateTask.cpp
- minecraft/update/LegacyFMLLibrariesTask.cpp
- minecraft/update/LegacyFMLLibrariesTask.h
+ minecraft/update/FMLLibrariesTask.cpp
+ minecraft/update/FMLLibrariesTask.h
minecraft/update/FoldersTask.cpp
minecraft/update/FoldersTask.h
minecraft/update/LibrariesTask.cpp
@@ -260,10 +264,6 @@ set(MINECRAFT_SOURCES
minecraft/launch/ClaimAccount.h
minecraft/launch/CreateGameFolders.cpp
minecraft/launch/CreateGameFolders.h
- minecraft/launch/EnsureAvailableMemory.cpp
- minecraft/launch/EnsureAvailableMemory.h
- minecraft/launch/EnsureOfflineLibraries.cpp
- minecraft/launch/EnsureOfflineLibraries.h
minecraft/launch/ModMinecraftJar.cpp
minecraft/launch/ModMinecraftJar.h
minecraft/launch/ExtractNatives.cpp
@@ -306,8 +306,6 @@ set(MINECRAFT_SOURCES
minecraft/ParseUtils.h
minecraft/ProfileUtils.cpp
minecraft/ProfileUtils.h
- minecraft/ShortcutUtils.cpp
- minecraft/ShortcutUtils.h
minecraft/Library.cpp
minecraft/Library.h
minecraft/MojangDownloadInfo.h
@@ -334,8 +332,6 @@ set(MINECRAFT_SOURCES
minecraft/mod/ResourceFolderModel.cpp
minecraft/mod/DataPack.h
minecraft/mod/DataPack.cpp
- minecraft/mod/DataPackFolderModel.h
- minecraft/mod/DataPackFolderModel.cpp
minecraft/mod/ResourcePack.h
minecraft/mod/ResourcePack.cpp
minecraft/mod/ResourcePackFolderModel.h
@@ -349,15 +345,17 @@ set(MINECRAFT_SOURCES
minecraft/mod/TexturePackFolderModel.h
minecraft/mod/TexturePackFolderModel.cpp
minecraft/mod/ShaderPackFolderModel.h
- minecraft/mod/ShaderPackFolderModel.cpp
- minecraft/mod/tasks/ResourceFolderLoadTask.h
- minecraft/mod/tasks/ResourceFolderLoadTask.cpp
+ minecraft/mod/tasks/BasicFolderLoadTask.h
+ minecraft/mod/tasks/ModFolderLoadTask.h
+ minecraft/mod/tasks/ModFolderLoadTask.cpp
minecraft/mod/tasks/LocalModParseTask.h
minecraft/mod/tasks/LocalModParseTask.cpp
- minecraft/mod/tasks/LocalResourceUpdateTask.h
- minecraft/mod/tasks/LocalResourceUpdateTask.cpp
+ minecraft/mod/tasks/LocalModUpdateTask.h
+ minecraft/mod/tasks/LocalModUpdateTask.cpp
minecraft/mod/tasks/LocalDataPackParseTask.h
minecraft/mod/tasks/LocalDataPackParseTask.cpp
+ minecraft/mod/tasks/LocalResourcePackParseTask.h
+ minecraft/mod/tasks/LocalResourcePackParseTask.cpp
minecraft/mod/tasks/LocalTexturePackParseTask.h
minecraft/mod/tasks/LocalTexturePackParseTask.cpp
minecraft/mod/tasks/LocalShaderPackParseTask.h
@@ -491,11 +489,8 @@ set(META_SOURCES
set(API_SOURCES
modplatform/ModIndex.h
modplatform/ModIndex.cpp
- modplatform/ResourceType.h
- modplatform/ResourceType.cpp
modplatform/ResourceAPI.h
- modplatform/ResourceAPI.cpp
modplatform/EnsureMetadataTask.h
modplatform/EnsureMetadataTask.cpp
@@ -506,6 +501,8 @@ set(API_SOURCES
modplatform/flame/FlameAPI.cpp
modplatform/modrinth/ModrinthAPI.h
modplatform/modrinth/ModrinthAPI.cpp
+ modplatform/helpers/NetworkResourceAPI.h
+ modplatform/helpers/NetworkResourceAPI.cpp
modplatform/helpers/HashUtils.h
modplatform/helpers/HashUtils.cpp
modplatform/helpers/OverrideUtils.h
@@ -529,15 +526,12 @@ set(FTB_SOURCES
modplatform/import_ftb/PackInstallTask.cpp
modplatform/import_ftb/PackHelpers.h
modplatform/import_ftb/PackHelpers.cpp
-
- modplatform/ftb/FTBPackInstallTask.h
- modplatform/ftb/FTBPackInstallTask.cpp
- modplatform/ftb/FTBPackManifest.h
- modplatform/ftb/FTBPackManifest.cpp
)
set(FLAME_SOURCES
# Flame
+ modplatform/flame/FlamePackIndex.cpp
+ modplatform/flame/FlamePackIndex.h
modplatform/flame/FlameModIndex.cpp
modplatform/flame/FlameModIndex.h
modplatform/flame/PackManifest.h
@@ -555,6 +549,8 @@ set(FLAME_SOURCES
set(MODRINTH_SOURCES
modplatform/modrinth/ModrinthPackIndex.cpp
modplatform/modrinth/ModrinthPackIndex.h
+ modplatform/modrinth/ModrinthPackManifest.cpp
+ modplatform/modrinth/ModrinthPackManifest.h
modplatform/modrinth/ModrinthCheckUpdate.cpp
modplatform/modrinth/ModrinthCheckUpdate.h
modplatform/modrinth/ModrinthInstanceCreationTask.cpp
@@ -592,8 +588,8 @@ set(ATLAUNCHER_SOURCES
)
set(LINKEXE_SOURCES
- console/WindowsConsole.h
- console/WindowsConsole.cpp
+ WindowsConsole.cpp
+ WindowsConsole.h
filelink/FileLink.h
filelink/FileLink.cpp
@@ -630,10 +626,6 @@ set(PRISMUPDATER_SOURCES
# Zip
MMCZip.h
MMCZip.cpp
- archive/ArchiveReader.cpp
- archive/ArchiveReader.h
- archive/ArchiveWriter.cpp
- archive/ArchiveWriter.h
# Time
MMCTime.h
@@ -666,14 +658,6 @@ set(PRISMUPDATER_SOURCES
)
-if(WIN32)
- set(PRISMUPDATER_SOURCES
- console/WindowsConsole.h
- console/WindowsConsole.cpp
- ${PRISMUPDATER_SOURCES}
- )
-endif()
-
######## Logging categories ########
ecm_qt_declare_logging_category(CORE_SOURCES
@@ -761,6 +745,7 @@ endif()
set(LOGIC_SOURCES
${CORE_SOURCES}
+ ${PATHMATCHER_SOURCES}
${NET_SOURCES}
${LAUNCH_SOURCES}
${UPDATE_SOURCES}
@@ -799,11 +784,6 @@ SET(LAUNCHER_SOURCES
ApplicationMessage.cpp
SysInfo.h
SysInfo.cpp
- HardwareInfo.cpp
- HardwareInfo.h
-
- # console utils
- console/Console.h
# GUI - general utilities
DesktopServices.h
@@ -817,16 +797,28 @@ SET(LAUNCHER_SOURCES
KonamiCode.h
KonamiCode.cpp
+ # Bundled resources
+ resources/backgrounds/backgrounds.qrc
+ resources/multimc/multimc.qrc
+ resources/pe_dark/pe_dark.qrc
+ resources/pe_light/pe_light.qrc
+ resources/pe_colored/pe_colored.qrc
+ resources/pe_blue/pe_blue.qrc
+ resources/breeze_dark/breeze_dark.qrc
+ resources/breeze_light/breeze_light.qrc
+ resources/OSX/OSX.qrc
+ resources/iOS/iOS.qrc
+ resources/flat/flat.qrc
+ resources/flat_white/flat_white.qrc
+ resources/documents/documents.qrc
+ ../${Launcher_Branding_LogoQRC}
+
# Icons
icons/MMCIcon.h
icons/MMCIcon.cpp
icons/IconList.h
icons/IconList.cpp
- # log utils
- logs/AnonymizeLog.cpp
- logs/AnonymizeLog.h
-
# GUI - windows
ui/GuiUtil.h
ui/GuiUtil.cpp
@@ -834,10 +826,6 @@ SET(LAUNCHER_SOURCES
ui/MainWindow.cpp
ui/InstanceWindow.h
ui/InstanceWindow.cpp
- ui/ViewLogWindow.h
- ui/ViewLogWindow.cpp
- ui/ToolTipFilter.h
- ui/ToolTipFilter.cpp
# FIXME: maybe find a better home for this.
FileIgnoreProxy.cpp
@@ -855,6 +843,7 @@ SET(LAUNCHER_SOURCES
ui/setupwizard/LanguageWizardPage.h
ui/setupwizard/PasteWizardPage.cpp
ui/setupwizard/PasteWizardPage.h
+ ui/setupwizard/ThemeWizardPage.cpp
ui/setupwizard/ThemeWizardPage.h
ui/setupwizard/AutoJavaWizardPage.cpp
ui/setupwizard/AutoJavaWizardPage.h
@@ -882,11 +871,8 @@ SET(LAUNCHER_SOURCES
ui/themes/ThemeManager.h
ui/themes/CatPack.cpp
ui/themes/CatPack.h
- ui/themes/CatPainter.cpp
- ui/themes/CatPainter.h
# Processes
- LaunchMode.h
LaunchController.h
LaunchController.cpp
@@ -905,12 +891,12 @@ SET(LAUNCHER_SOURCES
# GUI - instance pages
ui/pages/instance/ExternalResourcesPage.cpp
ui/pages/instance/ExternalResourcesPage.h
+ ui/pages/instance/GameOptionsPage.cpp
+ ui/pages/instance/GameOptionsPage.h
ui/pages/instance/VersionPage.cpp
ui/pages/instance/VersionPage.h
ui/pages/instance/ManagedPackPage.cpp
ui/pages/instance/ManagedPackPage.h
- ui/pages/instance/DataPackPage.h
- ui/pages/instance/DataPackPage.cpp
ui/pages/instance/TexturePackPage.h
ui/pages/instance/TexturePackPage.cpp
ui/pages/instance/ResourcePackPage.h
@@ -923,6 +909,7 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/NotesPage.h
ui/pages/instance/LogPage.cpp
ui/pages/instance/LogPage.h
+ ui/pages/instance/InstanceSettingsPage.cpp
ui/pages/instance/InstanceSettingsPage.h
ui/pages/instance/ScreenshotsPage.cpp
ui/pages/instance/ScreenshotsPage.h
@@ -932,26 +919,24 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/ServersPage.h
ui/pages/instance/WorldListPage.cpp
ui/pages/instance/WorldListPage.h
- ui/pages/instance/McClient.cpp
- ui/pages/instance/McClient.h
- ui/pages/instance/McResolver.cpp
- ui/pages/instance/McResolver.h
- ui/pages/instance/ServerPingTask.cpp
- ui/pages/instance/ServerPingTask.h
# GUI - global settings pages
ui/pages/global/AccountListPage.cpp
ui/pages/global/AccountListPage.h
+ ui/pages/global/CustomCommandsPage.cpp
+ ui/pages/global/CustomCommandsPage.h
+ ui/pages/global/EnvironmentVariablesPage.cpp
+ ui/pages/global/EnvironmentVariablesPage.h
ui/pages/global/ExternalToolsPage.cpp
ui/pages/global/ExternalToolsPage.h
ui/pages/global/JavaPage.cpp
ui/pages/global/JavaPage.h
ui/pages/global/LanguagePage.cpp
ui/pages/global/LanguagePage.h
+ ui/pages/global/MinecraftPage.cpp
ui/pages/global/MinecraftPage.h
ui/pages/global/LauncherPage.cpp
ui/pages/global/LauncherPage.h
- ui/pages/global/AppearancePage.h
ui/pages/global/ProxyPage.cpp
ui/pages/global/ProxyPage.h
ui/pages/global/APIPage.cpp
@@ -981,8 +966,6 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/ShaderPackPage.cpp
ui/pages/modplatform/ShaderPackModel.cpp
- ui/pages/modplatform/DataPackPage.cpp
- ui/pages/modplatform/DataPackModel.cpp
ui/pages/modplatform/ModpackProviderBasePage.h
@@ -997,13 +980,6 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp
ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h
- ui/pages/modplatform/ftb/FtbFilterModel.cpp
- ui/pages/modplatform/ftb/FtbFilterModel.h
- ui/pages/modplatform/ftb/FtbListModel.cpp
- ui/pages/modplatform/ftb/FtbListModel.h
- ui/pages/modplatform/ftb/FtbPage.cpp
- ui/pages/modplatform/ftb/FtbPage.h
-
ui/pages/modplatform/legacy_ftb/Page.cpp
ui/pages/modplatform/legacy_ftb/Page.h
ui/pages/modplatform/legacy_ftb/ListModel.h
@@ -1039,6 +1015,8 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/OptionalModDialog.cpp
ui/pages/modplatform/OptionalModDialog.h
+ ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp
+ ui/pages/modplatform/modrinth/ModrinthResourceModels.h
ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp
ui/pages/modplatform/modrinth/ModrinthResourcePages.h
@@ -1051,10 +1029,10 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ProfileSetupDialog.h
ui/dialogs/CopyInstanceDialog.cpp
ui/dialogs/CopyInstanceDialog.h
- ui/dialogs/CreateShortcutDialog.cpp
- ui/dialogs/CreateShortcutDialog.h
ui/dialogs/CustomMessageBox.cpp
ui/dialogs/CustomMessageBox.h
+ ui/dialogs/EditAccountDialog.cpp
+ ui/dialogs/EditAccountDialog.h
ui/dialogs/ExportInstanceDialog.cpp
ui/dialogs/ExportInstanceDialog.h
ui/dialogs/ExportPackDialog.cpp
@@ -1067,8 +1045,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ImportResourceDialog.h
ui/dialogs/MSALoginDialog.cpp
ui/dialogs/MSALoginDialog.h
- ui/dialogs/NetworkJobFailedDialog.cpp
- ui/dialogs/NetworkJobFailedDialog.h
+ ui/dialogs/OfflineLoginDialog.cpp
+ ui/dialogs/OfflineLoginDialog.h
ui/dialogs/NewComponentDialog.cpp
ui/dialogs/NewComponentDialog.h
ui/dialogs/NewInstanceDialog.cpp
@@ -1091,23 +1069,14 @@ SET(LAUNCHER_SOURCES
ui/dialogs/BlockedModsDialog.h
ui/dialogs/ChooseProviderDialog.h
ui/dialogs/ChooseProviderDialog.cpp
- ui/dialogs/ResourceUpdateDialog.cpp
- ui/dialogs/ResourceUpdateDialog.h
+ ui/dialogs/ModUpdateDialog.cpp
+ ui/dialogs/ModUpdateDialog.h
ui/dialogs/InstallLoaderDialog.cpp
ui/dialogs/InstallLoaderDialog.h
- ui/dialogs/ChooseOfflineNameDialog.cpp
- ui/dialogs/ChooseOfflineNameDialog.h
ui/dialogs/skins/SkinManageDialog.cpp
ui/dialogs/skins/SkinManageDialog.h
- ui/dialogs/skins/draw/SkinOpenGLWindow.h
- ui/dialogs/skins/draw/SkinOpenGLWindow.cpp
- ui/dialogs/skins/draw/Scene.h
- ui/dialogs/skins/draw/Scene.cpp
- ui/dialogs/skins/draw/BoxGeometry.h
- ui/dialogs/skins/draw/BoxGeometry.cpp
-
# GUI - widgets
ui/widgets/CheckComboBox.cpp
ui/widgets/CheckComboBox.h
@@ -1117,14 +1086,20 @@ SET(LAUNCHER_SOURCES
ui/widgets/CustomCommands.h
ui/widgets/EnvironmentVariables.cpp
ui/widgets/EnvironmentVariables.h
+ ui/widgets/DropLabel.cpp
+ ui/widgets/DropLabel.h
+ ui/widgets/FocusLineEdit.cpp
+ ui/widgets/FocusLineEdit.h
ui/widgets/IconLabel.cpp
ui/widgets/IconLabel.h
- ui/widgets/JavaWizardWidget.cpp
- ui/widgets/JavaWizardWidget.h
+ ui/widgets/JavaSettingsWidget.cpp
+ ui/widgets/JavaSettingsWidget.h
ui/widgets/LabeledToolButton.cpp
ui/widgets/LabeledToolButton.h
ui/widgets/LanguageSelectionWidget.cpp
ui/widgets/LanguageSelectionWidget.h
+ ui/widgets/LineSeparator.cpp
+ ui/widgets/LineSeparator.h
ui/widgets/LogView.cpp
ui/widgets/LogView.h
ui/widgets/InfoFrame.cpp
@@ -1152,12 +1127,8 @@ SET(LAUNCHER_SOURCES
ui/widgets/ProgressWidget.cpp
ui/widgets/WideBar.h
ui/widgets/WideBar.cpp
- ui/widgets/AppearanceWidget.h
- ui/widgets/AppearanceWidget.cpp
- ui/widgets/MinecraftSettingsWidget.h
- ui/widgets/MinecraftSettingsWidget.cpp
- ui/widgets/JavaSettingsWidget.h
- ui/widgets/JavaSettingsWidget.cpp
+ ui/widgets/ThemeCustomizationWidget.h
+ ui/widgets/ThemeCustomizationWidget.cpp
# GUI - instance group view
ui/instanceview/InstanceProxyModel.cpp
@@ -1173,15 +1144,8 @@ SET(LAUNCHER_SOURCES
ui/instanceview/VisualGroup.h
)
-if (APPLE)
- set(LAUNCHER_SOURCES
- ${LAUNCHER_SOURCES}
- ui/themes/ThemeManager.mm
- )
-endif()
-
if (NOT Apple)
- set(LAUNCHER_SOURCES
+set(LAUNCHER_SOURCES
${LAUNCHER_SOURCES}
ui/dialogs/UpdateAvailableDialog.h
@@ -1189,21 +1153,86 @@ if (NOT Apple)
)
endif()
-if (APPLE)
+if(WIN32)
set(LAUNCHER_SOURCES
+ WindowsConsole.cpp
+ WindowsConsole.h
${LAUNCHER_SOURCES}
-
- macsandbox/SecurityBookmarkFileAccess.h
- macsandbox/SecurityBookmarkFileAccess.mm
)
endif()
-if(WIN32)
- set(LAUNCHER_SOURCES
- console/WindowsConsole.h
- console/WindowsConsole.cpp
- ${LAUNCHER_SOURCES}
- )
+qt_wrap_ui(LAUNCHER_UI
+ ui/MainWindow.ui
+ ui/setupwizard/PasteWizardPage.ui
+ ui/setupwizard/AutoJavaWizardPage.ui
+ ui/setupwizard/LoginWizardPage.ui
+ ui/setupwizard/ThemeWizardPage.ui
+ ui/pages/global/AccountListPage.ui
+ ui/pages/global/JavaPage.ui
+ ui/pages/global/LauncherPage.ui
+ ui/pages/global/APIPage.ui
+ ui/pages/global/ProxyPage.ui
+ ui/pages/global/MinecraftPage.ui
+ ui/pages/global/ExternalToolsPage.ui
+ ui/pages/instance/ExternalResourcesPage.ui
+ ui/pages/instance/NotesPage.ui
+ ui/pages/instance/LogPage.ui
+ ui/pages/instance/ServersPage.ui
+ ui/pages/instance/GameOptionsPage.ui
+ ui/pages/instance/OtherLogsPage.ui
+ ui/pages/instance/InstanceSettingsPage.ui
+ ui/pages/instance/VersionPage.ui
+ ui/pages/instance/ManagedPackPage.ui
+ ui/pages/instance/WorldListPage.ui
+ ui/pages/instance/ScreenshotsPage.ui
+ ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
+ ui/pages/modplatform/atlauncher/AtlPage.ui
+ ui/pages/modplatform/CustomPage.ui
+ ui/pages/modplatform/ResourcePage.ui
+ ui/pages/modplatform/flame/FlamePage.ui
+ ui/pages/modplatform/legacy_ftb/Page.ui
+ ui/pages/modplatform/import_ftb/ImportFTBPage.ui
+ ui/pages/modplatform/ImportPage.ui
+ ui/pages/modplatform/OptionalModDialog.ui
+ ui/pages/modplatform/modrinth/ModrinthPage.ui
+ ui/pages/modplatform/technic/TechnicPage.ui
+ ui/widgets/InstanceCardWidget.ui
+ ui/widgets/CustomCommands.ui
+ ui/widgets/EnvironmentVariables.ui
+ ui/widgets/InfoFrame.ui
+ ui/widgets/ModFilterWidget.ui
+ ui/widgets/SubTaskProgressBar.ui
+ ui/widgets/ThemeCustomizationWidget.ui
+ ui/dialogs/CopyInstanceDialog.ui
+ ui/dialogs/ProfileSetupDialog.ui
+ ui/dialogs/ProgressDialog.ui
+ ui/dialogs/NewInstanceDialog.ui
+ ui/dialogs/NewComponentDialog.ui
+ ui/dialogs/NewsDialog.ui
+ ui/dialogs/ProfileSelectDialog.ui
+ ui/dialogs/ExportInstanceDialog.ui
+ ui/dialogs/ExportPackDialog.ui
+ ui/dialogs/ExportToModListDialog.ui
+ ui/dialogs/IconPickerDialog.ui
+ ui/dialogs/ImportResourceDialog.ui
+ ui/dialogs/MSALoginDialog.ui
+ ui/dialogs/OfflineLoginDialog.ui
+ ui/dialogs/AboutDialog.ui
+ ui/dialogs/EditAccountDialog.ui
+ ui/dialogs/ReviewMessageBox.ui
+ ui/dialogs/ScrollMessageBox.ui
+ ui/dialogs/BlockedModsDialog.ui
+ ui/dialogs/ChooseProviderDialog.ui
+
+ ui/dialogs/skins/SkinManageDialog.ui
+)
+
+qt_wrap_ui(PRISM_UPDATE_UI
+ ui/dialogs/UpdateAvailableDialog.ui
+)
+
+if (NOT Apple)
+ set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI})
endif()
qt_add_resources(LAUNCHER_RESOURCES
@@ -1218,10 +1247,14 @@ qt_add_resources(LAUNCHER_RESOURCES
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
resources/flat/flat.qrc
- resources/flat_white/flat_white.qrc
resources/documents/documents.qrc
- resources/shaders/shaders.qrc
- "${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_LogoQRC}"
+ ../${Launcher_Branding_LogoQRC}
+)
+
+qt_wrap_ui(PRISMUPDATER_UI
+ updater/prismupdater/SelectReleaseDialog.ui
+ ui/widgets/SubTaskProgressBar.ui
+ ui/dialogs/ProgressDialog.ui
)
######## Windows resource files ########
@@ -1229,56 +1262,29 @@ if(WIN32)
set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC})
endif()
-######## Precompiled Headers ###########
-
-if(${Launcher_USE_PCH})
- message(STATUS "Using precompiled headers for applicable launcher targets")
- set(PRECOMPILED_HEADERS
- include/base.pch.hpp
- include/qtcore.pch.hpp
- include/qtgui.pch.hpp
- )
-endif()
-
-####### Targets ########
+include(CompilerWarnings)
# Add executable
-add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_RESOURCES})
+add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
+set_project_warnings(Launcher_logic
+ "${Launcher_MSVC_WARNINGS}"
+ "${Launcher_CLANG_WARNINGS}"
+ "${Launcher_GCC_WARNINGS}")
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
-
-if(${Launcher_USE_PCH})
- target_precompile_headers(Launcher_logic PRIVATE ${PRECOMPILED_HEADERS})
-endif()
-
target_link_libraries(Launcher_logic
+ systeminfo
Launcher_murmur2
nbt++
${ZLIB_LIBRARIES}
+ tomlplusplus::tomlplusplus
qdcss
BuildConfig
Qt${QT_VERSION_MAJOR}::Widgets
+ ghcFilesystem::ghc_filesystem
)
-if(TARGET PkgConfig::libqrencode)
- target_link_libraries(Launcher_logic PkgConfig::libqrencode)
-else()
- target_include_directories(Launcher_logic PRIVATE ${LIBQRENCODE_INCLUDE_DIR})
- target_link_libraries(Launcher_logic ${LIBQRENCODE_LIBRARIES})
-endif()
-
-if(TARGET PkgConfig::tomlplusplus)
- target_link_libraries(Launcher_logic PkgConfig::tomlplusplus)
-else()
- target_link_libraries(Launcher_logic tomlplusplus::tomlplusplus)
-endif()
-if(TARGET PkgConfig::libarchive)
- target_link_libraries(Launcher_logic PkgConfig::libarchive)
-else()
- target_link_libraries(Launcher_logic LibArchive::LibArchive)
-endif()
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if (UNIX AND NOT CYGWIN AND NOT APPLE)
target_link_libraries(Launcher_logic
gamemode
)
@@ -1292,29 +1298,24 @@ target_link_libraries(Launcher_logic
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::NetworkAuth
- Qt${QT_VERSION_MAJOR}::OpenGL
- ${Launcher_QT_DBUS}
${Launcher_QT_LIBS}
)
target_link_libraries(Launcher_logic
+ QuaZip::QuaZip
cmark::cmark
LocalPeer
Launcher_rainbow
)
-if (TARGET ${Launcher_QT_DBUS})
- add_compile_definitions(WITH_QTDBUS)
-endif()
-
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks/")
if(Launcher_ENABLE_UPDATER)
- file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256})
- file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle)
+ file(DOWNLOAD ${MACOSX_SPARKLE_DOWNLOAD_URL} ${CMAKE_BINARY_DIR}/Sparkle.tar.xz EXPECTED_HASH SHA256=${MACOSX_SPARKLE_SHA256})
+ file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/Sparkle.tar.xz DESTINATION ${CMAKE_BINARY_DIR}/frameworks/Sparkle)
- find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
- add_compile_definitions(SPARKLE_ENABLED)
+ find_library(SPARKLE_FRAMEWORK Sparkle "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
+ add_compile_definitions(SPARKLE_ENABLED)
endif()
target_link_libraries(Launcher_logic
@@ -1324,16 +1325,13 @@ if(APPLE)
"-framework ApplicationServices"
)
if(Launcher_ENABLE_UPDATER)
- target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK})
+ target_link_libraries(Launcher_logic ${SPARKLE_FRAMEWORK})
endif()
endif()
+target_link_libraries(Launcher_logic)
+
add_executable(${Launcher_Name} MACOSX_BUNDLE WIN32 main.cpp ${LAUNCHER_RCS})
-
-if(${Launcher_USE_PCH})
- target_precompile_headers(${Launcher_Name} REUSE_FROM Launcher_logic)
-endif()
-
target_link_libraries(${Launcher_Name} Launcher_logic)
if(DEFINED Launcher_APP_BINARY_NAME)
@@ -1349,50 +1347,33 @@ if(DEFINED Launcher_APP_BINARY_DEFS)
endif()
install(TARGETS ${Launcher_Name}
- RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET
BUNDLE DESTINATION "." COMPONENT Runtime
LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
)
-# Deploy PDBs
-if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
- install(FILES $ DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
-endif()
-
if(Launcher_BUILD_UPDATER)
# Updater
- add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES})
+ add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-
- if(${Launcher_USE_PCH})
- target_precompile_headers(prism_updater_logic PRIVATE ${PRECOMPILED_HEADERS})
- endif()
-
target_link_libraries(prism_updater_logic
+ QuaZip::QuaZip
${ZLIB_LIBRARIES}
+ systeminfo
BuildConfig
+ ghcFilesystem::ghc_filesystem
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
${Launcher_QT_LIBS}
cmark::cmark
)
- if(TARGET PkgConfig::libarchive)
- target_link_libraries(prism_updater_logic PkgConfig::libarchive)
- else()
- target_link_libraries(prism_updater_logic LibArchive::LibArchive)
- endif()
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)
target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest)
target_link_libraries("${Launcher_Name}_updater" prism_updater_logic)
- if(${Launcher_USE_PCH})
- target_precompile_headers("${Launcher_Name}_updater" REUSE_FROM prism_updater_logic)
- endif()
-
if(DEFINED Launcher_APP_BINARY_NAME)
set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater")
endif()
@@ -1406,25 +1387,21 @@ if(Launcher_BUILD_UPDATER)
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
)
-
- # Deploy PDBs
- if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
- install(FILES $ DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
- endif()
endif()
if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
# File link
add_library(filelink_logic STATIC ${LINKEXE_SOURCES})
+ set_project_warnings(filelink_logic
+ "${Launcher_MSVC_WARNINGS}"
+ "${Launcher_CLANG_WARNINGS}"
+ "${Launcher_GCC_WARNINGS}")
target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-
- if(${Launcher_USE_PCH})
- target_precompile_headers(filelink_logic PRIVATE ${PRECOMPILED_HEADERS})
- endif()
-
target_link_libraries(filelink_logic
+ systeminfo
BuildConfig
+ ghcFilesystem::ghc_filesystem
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
@@ -1433,19 +1410,9 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
)
add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp)
+
target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest)
- if(${Launcher_USE_PCH})
- target_precompile_headers("${Launcher_Name}_filelink" REUSE_FROM filelink_logic)
- endif()
-
- # HACK: Fix manifest issues with Ninja in release mode (and only release mode) and MSVC
- # I have no idea why this works or why it's needed. UPDATE THIS IF YOU EDIT THE MANIFEST!!! -@getchoo
- # Thank you 2018 CMake mailing list thread https://cmake.cmake.narkive.com/LnotZXus/conflicting-msvc-manifests
- if(MSVC)
- set_property(TARGET "${Launcher_Name}_filelink" PROPERTY LINK_FLAGS "/MANIFESTUAC:level='requireAdministrator'")
- endif()
-
target_link_libraries("${Launcher_Name}_filelink" filelink_logic)
if(DEFINED Launcher_APP_BINARY_NAME)
@@ -1461,11 +1428,6 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime
FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime
)
-
- # Deploy PDBs
- if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
- install(FILES $ DESTINATION ${BINARY_DEST_DIR} OPTIONAL)
- endif()
endif()
if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER)
@@ -1475,142 +1437,187 @@ if (UNIX AND APPLE AND Launcher_ENABLE_UPDATER)
install(DIRECTORY ${MACOSX_SPARKLE_DIR}/Sparkle.framework DESTINATION ${FRAMEWORK_DEST_DIR} USE_SOURCE_PERMISSIONS)
endif()
-# Set basic compiler warning/error flags for all targets
-get_property(Launcher_TARGETS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS)
-foreach(target ${Launcher_TARGETS})
- message(STATUS "Enabling all warnings as errors for target '${target}'")
- if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
- target_compile_options(${target} PRIVATE /W4 /WX /permissive-)
- else()
- target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror)
- endif()
-endforeach()
-
-# Disable some warnings in main launcher target due to being present in a lot of places. TODO: Fix them.
-if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
- target_compile_options(Launcher_logic PRIVATE /wd4100) # C4100 - unused parameter
- target_compile_options(${Launcher_Name} PRIVATE /wd4100) # C4100 - unused parameter
-else()
- # sfinae-incomplete is a new GCC warning and triggers in Qt headers
- # no-unknown-warning-option so that compilers that don't have sfinae-incomplete don't error
- target_compile_options(Launcher_logic PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete)
- target_compile_options(${Launcher_Name} PRIVATE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-warning-option -Wno-sfinae-incomplete)
-endif()
-
#### The bundle mess! ####
-# Bundle utilities are used to complete packages for different platforms - they add all the libraries that would otherwise be missing on the target system.
+# Bundle utilities are used to complete the portable packages - they add all the libraries that would otherwise be missing on the target system.
# NOTE: it seems that this absolutely has to be here, and nowhere else.
-if(WIN32 OR (UNIX AND APPLE))
- if(WIN32)
- set(QT_DEPLOY_TOOL_OPTIONS "--no-opengl-sw --no-quick-import --no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types generic,networkinformation")
- endif()
-
- qt_generate_deploy_script(
- TARGET ${Launcher_Name}
- OUTPUT_SCRIPT QT_DEPLOY_SCRIPT
- CONTENT "
- qt_deploy_runtime_dependencies(
- EXECUTABLE ${BINARY_DEST_DIR}/$
- BIN_DIR ${BINARY_DEST_DIR}
- LIBEXEC_DIR ${LIBRARY_DEST_DIR}
- LIB_DIR ${LIBRARY_DEST_DIR}
- PLUGINS_DIR ${PLUGIN_DEST_DIR}
- NO_OVERWRITE
- NO_TRANSLATIONS
- NO_COMPILER_RUNTIME
- DEPLOY_TOOL_OPTIONS ${QT_DEPLOY_TOOL_OPTIONS}
- )"
- )
-
- # Bundle our linked dependencies
- install(
- RUNTIME_DEPENDENCY_SET LAUNCHER_DEPENDENCY_SET
- COMPONENT bundle
- DIRECTORIES
- ${CMAKE_SYSTEM_LIBRARY_PATH}
- ${QT_LIBS_DIR}
- ${QT_LIBEXECS_DIR}
- PRE_EXCLUDE_REGEXES
- "^(api-ms-win|ext-ms)-.*\\.dll$"
- # FIXME: Why aren't these caught by the below regex???
- "^azure.*\\.dll$"
- "^vcruntime.*\\.dll$"
- POST_EXCLUDE_REGEXES
- "system32"
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
- RUNTIME DESTINATION ${BINARY_DEST_DIR}
- FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR}
- )
- # Deploy Qt plugins
- install(
- SCRIPT ${QT_DEPLOY_SCRIPT}
- COMPONENT bundle
- )
- # FIXME: remove this crap once we stop using msys2
- if(MINGW)
- # i've not found a solution better than injecting the config vars like this...
- # with install(CODE" for everything everything just breaks
- install(CODE "
- set(QT_PLUGINS_DIR \"${QT_PLUGINS_DIR}\")
- set(QT_LIBS_DIR \"${QT_LIBS_DIR}\")
- set(QT_LIBEXECS_DIR \"${QT_LIBEXECS_DIR}\")
- set(CMAKE_SYSTEM_LIBRARY_PATH \"${CMAKE_SYSTEM_LIBRARY_PATH}\")
- set(CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\")
- "
- COMPONENT bundle)
-
- install(CODE [[
- file(GLOB QT_IMAGEFORMAT_DLLS "${QT_PLUGINS_DIR}/imageformats/*.dll")
- set(CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL objdump)
- file(GET_RUNTIME_DEPENDENCIES
- RESOLVED_DEPENDENCIES_VAR imageformatdeps
- LIBRARIES ${QT_IMAGEFORMAT_DLLS}
- DIRECTORIES
- ${CMAKE_SYSTEM_LIBRARY_PATH}
- ${QT_PLUGINS_DIR}
- ${QT_LIBS_DIR}
- ${QT_LIBEXECS_DIR}
- PRE_EXCLUDE_REGEXES
- "^(api-ms-win|ext-ms)-.*\\.dll$"
- # FIXME: Why aren't these caught by the below regex???
- "^azure.*\\.dll$"
- "^vcruntime.*\\.dll$"
- POST_EXCLUDE_REGEXES
- "system32"
- )
- foreach(_lib ${imageformatdeps})
- file(INSTALL
- DESTINATION ${CMAKE_INSTALL_PREFIX}
- TYPE SHARED_LIBRARY
- FOLLOW_SYMLINK_CHAIN
- FILES ${_lib}
- )
- endforeach()
- ]]
- COMPONENT bundle)
- endif()
-
+if(INSTALL_BUNDLE STREQUAL "full")
# Add qt.conf - this makes Qt stop looking for things outside the bundle
install(
CODE "file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}/qt.conf\" \" \")"
- COMPONENT bundle
+ COMPONENT Runtime
)
- # Add qtlogging.ini as a config file
+ # add qtlogging.ini as a config file
install(
FILES "qtlogging.ini"
DESTINATION ${CMAKE_INSTALL_PREFIX}/${RESOURCES_DEST_DIR}
- COMPONENT bundle
+ COMPONENT Runtime
)
-endif()
-
-find_program(CLANG_FORMAT clang-format OPTIONAL)
-if(CLANG_FORMAT)
- message(STATUS "Creating clang-format target")
- add_custom_target(
- clang-format
- COMMAND ${CLANG_FORMAT} -i --style=file:${CMAKE_SOURCE_DIR}/.clang-format ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${PRISMUPDATER_SOURCES} ${LINKEXE_SOURCES} ${PRECOMPILED_HEADERS}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ # Bundle plugins
+ # Image formats
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "tga|tiff|mng" EXCLUDE
)
-else()
- message(WARNING "Unable to find `clang-format`. Not creating custom target")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "tga|tiff|mng" EXCLUDE
+ REGEX "d\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ # Icon engines
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "fontawesome" EXCLUDE
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "fontawesome" EXCLUDE
+ REGEX "d\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ # Platform plugins
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/platforms"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "minimal|linuxfb|offscreen" EXCLUDE
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/platforms"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "minimal|linuxfb|offscreen" EXCLUDE
+ REGEX "[^2]d\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ # Style plugins
+ if(EXISTS "${QT_PLUGINS_DIR}/styles")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/styles"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/styles"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "d\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ endif()
+ # TLS plugins (Qt 6 only)
+ if(EXISTS "${QT_PLUGINS_DIR}/tls")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/tls"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ PATTERN "*qcertonlybackend*" EXCLUDE
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/tls"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "dd\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ PATTERN "*qcertonlybackend*" EXCLUDE
+ )
+ endif()
+ # Wayland support
+ if(EXISTS "${QT_PLUGINS_DIR}/wayland-graphics-integration-client")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-client"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-client"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "dd\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ endif()
+ if(EXISTS "${QT_PLUGINS_DIR}/wayland-graphics-integration-server")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-server"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-graphics-integration-server"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "dd\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ endif()
+ if(EXISTS "${QT_PLUGINS_DIR}/wayland-decoration-client")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-decoration-client"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-decoration-client"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "dd\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ endif()
+ if(EXISTS "${QT_PLUGINS_DIR}/wayland-shell-integration")
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-shell-integration"
+ CONFIGURATIONS Debug RelWithDebInfo ""
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ )
+ install(
+ DIRECTORY "${QT_PLUGINS_DIR}/wayland-shell-integration"
+ CONFIGURATIONS Release MinSizeRel
+ DESTINATION ${PLUGIN_DEST_DIR}
+ COMPONENT Runtime
+ REGEX "dd\\." EXCLUDE
+ REGEX "_debug\\." EXCLUDE
+ REGEX "\\.dSYM" EXCLUDE
+ )
+ endif()
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake"
+ @ONLY
+ )
+ install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" COMPONENT Runtime)
endif()
diff --git a/launcher/DataMigrationTask.cpp b/launcher/DataMigrationTask.cpp
index cab22089e..4ffa26fd4 100644
--- a/launcher/DataMigrationTask.cpp
+++ b/launcher/DataMigrationTask.cpp
@@ -12,10 +12,10 @@
#include
-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::finished, this, &DataMigrationTask::dryRunFinished);
@@ -37,7 +37,11 @@ void DataMigrationTask::dryRunFinished()
disconnect(&m_copyFutureWatcher, &QFutureWatcher::finished, this, &DataMigrationTask::dryRunFinished);
disconnect(&m_copyFutureWatcher, &QFutureWatcher::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::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::finished, this, &DataMigrationTask::copyFinished);
disconnect(&m_copyFutureWatcher, &QFutureWatcher::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"));
}
diff --git a/launcher/DataMigrationTask.h b/launcher/DataMigrationTask.h
index 9a2b0adb8..fc613cd5e 100644
--- a/launcher/DataMigrationTask.h
+++ b/launcher/DataMigrationTask.h
@@ -5,7 +5,7 @@
#pragma once
#include "FileSystem.h"
-#include "Filter.h"
+#include "pathmatcher/IPathMatcher.h"
#include "tasks/Task.h"
#include
@@ -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;
diff --git a/launcher/DefaultVariable.h b/launcher/DefaultVariable.h
new file mode 100644
index 000000000..b082091c7
--- /dev/null
+++ b/launcher/DefaultVariable.h
@@ -0,0 +1,23 @@
+#pragma once
+
+template
+class DefaultVariable {
+ public:
+ DefaultVariable(const T& value) { defaultValue = value; }
+ DefaultVariable& 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;
+};
diff --git a/launcher/FastFileIconProvider.cpp b/launcher/FastFileIconProvider.cpp
index 1dbab27ba..f2b6f4425 100644
--- a/launcher/FastFileIconProvider.cpp
+++ b/launcher/FastFileIconProvider.cpp
@@ -44,4 +44,4 @@ QIcon FastFileIconProvider::icon(const QFileInfo& info) const
}
return QApplication::style()->standardIcon(icon);
-}
+}
\ No newline at end of file
diff --git a/launcher/FastFileIconProvider.h b/launcher/FastFileIconProvider.h
index 7799b7879..208534044 100644
--- a/launcher/FastFileIconProvider.h
+++ b/launcher/FastFileIconProvider.h
@@ -23,4 +23,4 @@
class FastFileIconProvider : public QFileIconProvider {
public:
QIcon icon(const QFileInfo& info) const override;
-};
+};
\ No newline at end of file
diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp
index 445c2a881..df06c3c75 100644
--- a/launcher/FileIgnoreProxy.cpp
+++ b/launcher/FileIgnoreProxy.cpp
@@ -40,11 +40,12 @@
#include
#include
#include
+#include
#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(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 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));
}
diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h
index 0f149ecb6..e01a2651e 100644
--- a/launcher/FileIgnoreProxy.h
+++ b/launcher/FileIgnoreProxy.h
@@ -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;
};
diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp
index ef56e3e65..512de28c2 100644
--- a/launcher/FileSystem.cpp
+++ b/launcher/FileSystem.cpp
@@ -36,7 +36,6 @@
*/
#include "FileSystem.h"
-#include
#include
#include "BuildConfig.h"
@@ -60,8 +59,10 @@
#if defined Q_OS_WIN32
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
+#include
#include
#include
+#include
#include
#include
#include
@@ -76,8 +77,24 @@
#include
#endif
+// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header
+
+#ifdef __APPLE__
+#include // 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() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
+#define GHC_USE_STD_FS
#include
namespace fs = std::filesystem;
+#endif // MacOS min version check
+#endif // Other OSes version check
+
+#ifndef GHC_USE_STD_FS
+#include
+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
"\n"
"";
- 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
diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h
index 6d9b01178..c5beef7bd 100644
--- a/launcher/FileSystem.h
+++ b/launcher/FileSystem.h
@@ -38,7 +38,7 @@
#pragma once
#include "Exception.h"
-#include "Filter.h"
+#include "pathmatcher/IPathMatcher.h"
#include
@@ -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;
diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp
new file mode 100644
index 000000000..adeb2209e
--- /dev/null
+++ b/launcher/Filter.cpp
@@ -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);
+}
\ No newline at end of file
diff --git a/launcher/Filter.h b/launcher/Filter.h
index 317f5b067..ae835e724 100644
--- a/launcher/Filter.h
+++ b/launcher/Filter.h
@@ -3,52 +3,59 @@
#include
#include
-using Filter = std::function;
+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 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;
+};
diff --git a/launcher/GZip.cpp b/launcher/GZip.cpp
index 201dcd572..1c2539e08 100644
--- a/launcher/GZip.cpp
+++ b/launcher/GZip.cpp
@@ -36,8 +36,6 @@
#include "GZip.h"
#include
#include
-#include
-#include
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 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(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(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 handleBlock)
-{
- auto ret = inf(source, handleBlock);
- return zerr(ret);
-}
diff --git a/launcher/GZip.h b/launcher/GZip.h
index b736ca93f..0bdb70407 100644
--- a/launcher/GZip.h
+++ b/launcher/GZip.h
@@ -1,11 +1,8 @@
#pragma once
#include
-#include
-namespace GZip {
-
-bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
-bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
-QString readGzFileByBlocks(QFile* source, std::function handleBlock);
-
-} // namespace GZip
+class GZip {
+ public:
+ static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
+ static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
+};
diff --git a/launcher/HardwareInfo.cpp b/launcher/HardwareInfo.cpp
deleted file mode 100644
index 36b6f7783..000000000
--- a/launcher/HardwareInfo.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- * Prism Launcher - Minecraft Launcher
- * Copyright (C) 2026 Octol1ttle
- *
- * 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 .
- */
-
-#include "HardwareInfo.h"
-
-#include
-#include
-
-#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
-namespace {
-QString afterColon(QString str)
-{
- return str.remove(0, str.indexOf(':') + 2).trimmed();
-}
-
-template
-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 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
-
-#include
-#include
-
-#include
-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