mirror of https://git.citron-emu.org/citron/emu
Compare commits
260 Commits
v0.1-canar
...
master
Author | SHA1 | Date |
---|---|---|
|
046538bb47 | |
|
2d64059f14 | |
|
7a668a98d7 | |
|
f45d818a64 | |
|
ac850bdf90 | |
|
7e58599d69 | |
|
6969005c54 | |
|
f3f18cede9 | |
|
03aab9becc | |
|
a5f722b6d9 | |
|
ba98d0f15c | |
|
fc88c06769 | |
|
7d213efca8 | |
|
791b95822d | |
|
f706427815 | |
|
6c10e0034f | |
|
44dfea60a9 | |
|
46abf95383 | |
|
5d3e75c25f | |
|
1bf27ebbb9 | |
|
eec0f34204 | |
|
257aad2431 | |
|
65dfe3234f | |
|
57cf5a0daf | |
|
020492f1fa | |
|
21ca0b3119 | |
|
58401f5b39 | |
|
1ad69f3545 | |
|
48eed78d1a | |
|
5f962dd1c6 | |
|
25abfe36a3 | |
|
2f57a35d2d | |
|
66bdd6ed27 | |
|
ff9c61e7c7 | |
|
e72d695115 | |
|
0cdd546152 | |
|
3205c9b691 | |
|
f1e169e060 | |
|
278486d059 | |
|
bbd3253169 | |
|
a1f3414bde | |
|
175a427c27 | |
|
18def48dfe | |
|
a4088f3a1e | |
|
b66b3ca639 | |
|
3a1c178711 | |
|
964bbf489a | |
|
19febba866 | |
|
0dac3c1dbd | |
|
5d952717ff | |
|
b25c7653e6 | |
|
edfb500ee7 | |
|
ebfc9d8347 | |
|
1fd5fefcb1 | |
|
55dc3f8ec1 | |
|
7edbccbdc9 | |
|
e06526cbbc | |
|
0448d8146f | |
|
98c515871e | |
|
278ac75a37 | |
|
ec402a0510 | |
|
8cb6e6d5d4 | |
|
51800e249b | |
|
21594b73aa | |
|
d869045b77 | |
|
f2931c7566 | |
|
12c63997d2 | |
|
1023125be5 | |
|
dad8859679 | |
|
834cc89548 | |
|
38b259d099 | |
|
e7e9453667 | |
|
ae75413cc3 | |
|
6a31da5905 | |
|
a5125d008a | |
|
b24dd921aa | |
|
9a65205dba | |
|
af4f08be33 | |
|
0d0963d32f | |
|
4491127f52 | |
|
c304afe2b3 | |
|
b8240b4214 | |
|
91487f6d96 | |
|
031c635095 | |
|
90a8165f77 | |
|
6565055865 | |
|
ee3d858935 | |
|
31694994f2 | |
|
4197fa84a0 | |
|
e4342324fe | |
|
78b0080b96 | |
|
644ed69285 | |
|
3554f55fc9 | |
|
dc9532b4d1 | |
|
1308e2b935 | |
|
5caecd8151 | |
|
dc9fbcc893 | |
|
b1d5d4e5be | |
|
f0d8daf755 | |
|
cbb9a35166 | |
|
cfe437aacf | |
|
9b293c3a98 | |
|
84e5fbc089 | |
|
a442078ee4 | |
|
cc610ad9b6 | |
|
5a65f9a094 | |
|
5ca1f0e365 | |
|
a36baad0f0 | |
|
ed115d3f72 | |
|
d9619b7eed | |
|
dbe5bf1d18 | |
|
7903415fa4 | |
|
3bb4d97e9e | |
|
a41f7b7a56 | |
|
18f8a0f997 | |
|
4d50d2ba16 | |
|
0576d40bf0 | |
|
6917530ba5 | |
|
43495b6045 | |
|
c5e480e55d | |
|
1c9e17496b | |
|
7730d14b4a | |
|
677b8f476a | |
|
5cbde61d3c | |
|
33a1996ca4 | |
|
a7af4d001b | |
|
ef884ce39c | |
|
1aad9fd4e3 | |
|
f45f339ef9 | |
|
298e797592 | |
|
8bfafb4755 | |
|
33d54e595f | |
|
13ada2d705 | |
|
8bf4660bac | |
|
b07751ed43 | |
|
b3c60b4cbe | |
|
dcf6f9a071 | |
|
b42a0fb227 | |
|
5af4803e42 | |
|
becaf850ab | |
|
d4ad55ed21 | |
|
6e16a8db1c | |
|
384a18927b | |
|
76716b5248 | |
|
6917a22a2c | |
|
646af3c143 | |
|
d1b7aebe8c | |
|
d783806b1e | |
|
268d322d7f | |
|
92b70b31e0 | |
|
4792ba752e | |
|
b8fe6b6f7c | |
|
0acfbc5fa1 | |
|
e3128c6e98 | |
|
b89a85e228 | |
|
cc48197448 | |
|
0010882f36 | |
|
28350f7af8 | |
|
7ecb890a16 | |
|
c31768ec15 | |
|
227db142e2 | |
|
3aa9c0d151 | |
|
7b6495aced | |
|
d4eca46bba | |
|
df1ae19742 | |
|
4cc01f6c71 | |
|
89ecb641f1 | |
|
3857e6afe9 | |
|
42f44a0c09 | |
|
94c4ef8946 | |
|
14065ae7cb | |
|
9eb32d2d85 | |
|
71e652123b | |
|
ddd5e7e887 | |
|
6b9c239fbd | |
|
cf43fd8038 | |
|
a1cbcee7ab | |
|
19ce9d695e | |
|
44944c4d80 | |
|
8bda64895f | |
|
f4b9e54b22 | |
|
70a9f20ae1 | |
|
076d0e618d | |
|
ecc32958ec | |
|
e8bbdbce42 | |
|
0216eaa071 | |
|
137034ca2c | |
|
8f76ef2579 | |
|
4e8d00f034 | |
|
f638922129 | |
|
a96216ff35 | |
|
6ab82e8eeb | |
|
733721f0a1 | |
|
613099703a | |
|
9a3d4f0489 | |
|
8c630a8bea | |
|
2e4db14bc1 | |
|
c36151d6e3 | |
|
33f8cd0c7e | |
|
c5a2689cef | |
|
f380744c61 | |
|
b7e11d3724 | |
|
be191f740a | |
|
a5d62fa4ec | |
|
a6063bbd64 | |
|
924c06d88f | |
|
b55be320b7 | |
|
5ba970b574 | |
|
58ed33dd9f | |
|
c279df9cfe | |
|
0adeac26af | |
|
37677052c1 | |
|
774d8d9eba | |
|
d7dc87bbf3 | |
|
07024f7ea6 | |
|
04f9d8b61a | |
|
b574aba98b | |
|
6d225eb94a | |
|
5a1a2f3eca | |
|
d4d3061eb7 | |
|
450d80fc81 | |
|
b938893599 | |
|
07b949025f | |
|
913cc27e3a | |
|
3698478977 | |
|
382999025a | |
|
ee0beea82a | |
|
62de5aa9de | |
|
43170513b6 | |
|
3635b6e602 | |
|
f560ac024d | |
|
496b010927 | |
|
498d016873 | |
|
132077e18f | |
|
236ad28d61 | |
|
9ae0eeeb87 | |
|
d028ac291c | |
|
cc897c3f0e | |
|
cce4abbb0b | |
|
6d5475a9cf | |
|
2d7f9d921b | |
|
d3ed42af8f | |
|
0cf545858d | |
|
08be9b0617 | |
|
3f151c5111 | |
|
c65c8ac45e | |
|
dae1524eb5 | |
|
66b6d5b2da | |
|
83393a6c6b | |
|
60cb826e93 | |
|
3100d13fc0 | |
|
08f1ed4011 | |
|
21f94d5825 | |
|
8f5e3516fe | |
|
9be4bf9aa5 | |
|
e11c6c03ec | |
|
27d662ad0e | |
|
ab82a115f5 | |
|
18eb054ab6 | |
|
b685d5701d |
|
@ -0,0 +1,14 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: merge
|
||||||
|
displayName: 'merge'
|
||||||
|
jobs:
|
||||||
|
- template: ./templates/merge-private.yml
|
|
@ -0,0 +1,59 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: build
|
||||||
|
displayName: 'build'
|
||||||
|
jobs:
|
||||||
|
- job: linux
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'linux'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
maxParallel: 10
|
||||||
|
matrix:
|
||||||
|
linux:
|
||||||
|
BuildSuffix: 'linux'
|
||||||
|
ScriptFolder: 'linux'
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-single.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: $(parameters.cache)
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
- job: msvc
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'windows'
|
||||||
|
pool:
|
||||||
|
vmImage: windows-2022
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-msvc.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: $(parameters.cache)
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
- stage: release
|
||||||
|
displayName: 'release'
|
||||||
|
dependsOn: build
|
||||||
|
jobs:
|
||||||
|
- job: release
|
||||||
|
displayName: 'source'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- template: ./templates/release-private-tag.yml
|
|
@ -0,0 +1,106 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
||||||
|
BuildName: 'stable'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: build
|
||||||
|
displayName: 'build'
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'standard'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
maxParallel: 10
|
||||||
|
matrix:
|
||||||
|
linux:
|
||||||
|
BuildSuffix: 'linux'
|
||||||
|
ScriptFolder: 'linux'
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-single.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: 'true'
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
# Make tokens available to scripts
|
||||||
|
- task: Bash@3
|
||||||
|
inputs:
|
||||||
|
targetType: 'inline'
|
||||||
|
script: |
|
||||||
|
echo "##vso[task.setvariable variable=EARLY_ACCESS_TOKEN]$(EARLY_ACCESS_TOKEN)"
|
||||||
|
echo "##vso[task.setvariable variable=CI_RELEASE_TOKEN]$(CI_RELEASE_TOKEN)"
|
||||||
|
|
||||||
|
- stage: build_win
|
||||||
|
displayName: 'build-windows'
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'msvc'
|
||||||
|
pool:
|
||||||
|
vmImage: windows-2022
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-msvc.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: 'true'
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
# Make tokens available to scripts
|
||||||
|
- task: PowerShell@2
|
||||||
|
inputs:
|
||||||
|
targetType: 'inline'
|
||||||
|
script: |
|
||||||
|
Write-Host "##vso[task.setvariable variable=EARLY_ACCESS_TOKEN]$(EARLY_ACCESS_TOKEN)"
|
||||||
|
Write-Host "##vso[task.setvariable variable=CI_RELEASE_TOKEN]$(CI_RELEASE_TOKEN)"
|
||||||
|
|
||||||
|
- stage: build_android
|
||||||
|
displayName: 'build-android'
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'android'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- task: Bash@3
|
||||||
|
inputs:
|
||||||
|
targetType: 'inline'
|
||||||
|
script: |
|
||||||
|
export USE_DEBUG_KEYSTORE=true
|
||||||
|
chmod +x ./.ci/scripts/android/build.sh
|
||||||
|
./.ci/scripts/android/build.sh
|
||||||
|
- publish: artifacts
|
||||||
|
artifact: 'citron-$(BuildName)-android'
|
||||||
|
displayName: 'Upload Android Artifacts'
|
||||||
|
|
||||||
|
- stage: release
|
||||||
|
displayName: 'release'
|
||||||
|
dependsOn:
|
||||||
|
- build
|
||||||
|
- build_win
|
||||||
|
- build_android
|
||||||
|
jobs:
|
||||||
|
- job: github
|
||||||
|
displayName: 'github'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- template: ./templates/release-github.yml
|
|
@ -0,0 +1,22 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: copy
|
||||||
|
displayName: 'Sync Repository'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- script: echo 'https://$(GitUsername):$(GitAccessToken)@dev.azure.com' > $HOME/.git-credentials
|
||||||
|
displayName: 'Load Credentials'
|
||||||
|
- script: git config --global credential.helper store
|
||||||
|
displayName: 'Register Credential Helper'
|
||||||
|
- script: git remote add other $(GitRepoPushChangesURL)
|
||||||
|
displayName: 'Register Repository'
|
||||||
|
- script: git push --force other HEAD:$(GitPushBranch)
|
||||||
|
displayName: 'Update Code'
|
||||||
|
- script: rm -rf $HOME/.git-credentials
|
||||||
|
displayName: 'Clear Cached Credentials'
|
|
@ -0,0 +1,14 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: merge
|
||||||
|
displayName: 'merge'
|
||||||
|
jobs:
|
||||||
|
- template: ./templates/merge.yml
|
|
@ -0,0 +1,64 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: build
|
||||||
|
displayName: 'build'
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'standard'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
maxParallel: 10
|
||||||
|
matrix:
|
||||||
|
linux:
|
||||||
|
BuildSuffix: 'linux'
|
||||||
|
ScriptFolder: 'linux'
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-single.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: 'true'
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
- stage: build_win
|
||||||
|
displayName: 'build-windows'
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
timeoutInMinutes: 120
|
||||||
|
displayName: 'msvc'
|
||||||
|
pool:
|
||||||
|
vmImage: windows-2022
|
||||||
|
steps:
|
||||||
|
- template: ./templates/sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./templates/build-msvc.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: 'true'
|
||||||
|
version: $(DisplayVersion)
|
||||||
|
- stage: release
|
||||||
|
displayName: 'release'
|
||||||
|
dependsOn:
|
||||||
|
- build
|
||||||
|
- build_win
|
||||||
|
jobs:
|
||||||
|
- job: github
|
||||||
|
displayName: 'github'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- template: ./templates/release-github.yml
|
|
@ -0,0 +1,23 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: format
|
||||||
|
displayName: 'format'
|
||||||
|
jobs:
|
||||||
|
- job: format
|
||||||
|
displayName: 'clang'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- template: ./templates/format-check.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
- stage: build
|
||||||
|
displayName: 'build'
|
||||||
|
dependsOn: format
|
||||||
|
jobs:
|
||||||
|
- template: ./templates/build-standard.yml
|
||||||
|
parameters:
|
||||||
|
cache: 'false'
|
||||||
|
- template: ./templates/build-testing.yml
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
export NDK_CCACHE="$(which ccache)"
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
BUILD_FLAVOR="stable"
|
||||||
|
|
||||||
|
mkdir -p "artifacts"
|
||||||
|
|
||||||
|
BUILD_TYPE="release"
|
||||||
|
if [ "${GITHUB_REPOSITORY}" == "Citron-Project/Cit" ]; then
|
||||||
|
BUILD_TYPE="relWithDebInfo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We'll use the Android debug keystore for builds
|
||||||
|
# This removes the requirement for storing a keystore in secrets
|
||||||
|
# For production builds, this should be replaced with a proper signing configuration
|
||||||
|
export USE_DEBUG_KEYSTORE=true
|
||||||
|
|
||||||
|
cd src/android
|
||||||
|
chmod +x ./gradlew
|
||||||
|
./gradlew clean
|
||||||
|
./gradlew app:assemble${BUILD_FLAVOR}${BUILD_TYPE}
|
||||||
|
|
||||||
|
ccache -s
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
export NDK_CCACHE="$(which ccache)"
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
||||||
|
export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/service-account-key.json"
|
||||||
|
|
||||||
|
base64 --decode <<< "${CANARY_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
chmod 600 "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "${SERVICE_ACCOUNT_KEY_PATH}")"
|
||||||
|
base64 --decode <<< "${CANARY_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
|
||||||
|
./gradlew "publishCanaryReleaseBundle"
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
rm "${ANDROID_KEYSTORE_FILE}" "${SERVICE_ACCOUNT_KEY_PATH}"
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2024 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
export NDK_CCACHE="$(which ccache)"
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
||||||
|
base64 --decode <<< "${EA_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
export ANDROID_KEY_ALIAS="${PLAY_ANDROID_KEY_ALIAS}"
|
||||||
|
export ANDROID_KEYSTORE_PASS="${PLAY_ANDROID_KEYSTORE_PASS}"
|
||||||
|
export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/sa.json"
|
||||||
|
base64 --decode <<< "${EA_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
|
||||||
|
./gradlew "publishEaReleaseBundle"
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
|
||||||
|
rm "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
fi
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
export NDK_CCACHE="$(which ccache)"
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
|
||||||
|
export SERVICE_ACCOUNT_KEY_PATH="${GITHUB_WORKSPACE}/service-account-key.json"
|
||||||
|
|
||||||
|
base64 --decode <<< "${STABLE_PLAY_ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
chmod 600 "${ANDROID_KEYSTORE_FILE}"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "${SERVICE_ACCOUNT_KEY_PATH}")"
|
||||||
|
base64 --decode <<< "${STABLE_SERVICE_ACCOUNT_KEY_B64}" > "${SERVICE_ACCOUNT_KEY_PATH}"
|
||||||
|
./gradlew "publishStableReleaseBundle"
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
rm "${ANDROID_KEYSTORE_FILE}" "${SERVICE_ACCOUNT_KEY_PATH}"
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
. .ci/scripts/common/pre-upload.sh
|
||||||
|
|
||||||
|
APPNAME="org.citron.citron"
|
||||||
|
|
||||||
|
REV_NAME="${APPNAME}-${GITDATE}-${GITREV}"
|
||||||
|
|
||||||
|
APK="${REV_NAME}.apk"
|
||||||
|
|
||||||
|
if [ "${GITHUB_REPOSITORY}" == "Citron-Project/Cit" ]; then
|
||||||
|
cd src/android
|
||||||
|
./gradlew app:bundleRelease
|
||||||
|
# RELEASE_BODY gets reset here, but its fine since we're uploading after the GitHub Release
|
||||||
|
. .ci/scripts/common/post-upload.sh
|
||||||
|
|
||||||
|
sudo apt-get install -y jq
|
||||||
|
|
||||||
|
ls app/build/outputs/bundle/release/
|
||||||
|
|
||||||
|
echo "Downloading CI scripts bundle"
|
||||||
|
ARTIFACTS_DIR="/tmp/artifact-pool"
|
||||||
|
mkdir -p "$ARTIFACTS_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_FLAVOR="stable"
|
||||||
|
|
||||||
|
BUILD_TYPE_LOWER="release"
|
||||||
|
BUILD_TYPE_UPPER="Release"
|
||||||
|
if [ "${GITHUB_REPOSITORY}" == "Citron-Project/Cit" ]; then
|
||||||
|
BUILD_TYPE_LOWER="relWithDebInfo"
|
||||||
|
BUILD_TYPE_UPPER="RelWithDebInfo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp src/android/app/build/outputs/apk/"${BUILD_FLAVOR}/${BUILD_TYPE_LOWER}/app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.apk" \
|
||||||
|
"artifacts/${REV_NAME}.apk"
|
||||||
|
cp src/android/app/build/outputs/bundle/"${BUILD_FLAVOR}${BUILD_TYPE_UPPER}"/"app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.aab" \
|
||||||
|
"artifacts/${REV_NAME}.aab"
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2021 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Exit on error, rather than continuing with the rest of the script.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
mkdir build || true && cd build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||||
|
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ \
|
||||||
|
-DCMAKE_C_COMPILER=/usr/lib/ccache/clang \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
|
-DDISPLAY_VERSION=$1 \
|
||||||
|
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||||
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
|
-DUSE_DISCORD_PRESENCE=ON \
|
||||||
|
-DCITRON_CRASH_DUMPS=ON \
|
||||||
|
-DCITRON_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||||
|
-DCITRON_USE_BUNDLED_FFMPEG=ON \
|
||||||
|
-GNinja
|
||||||
|
|
||||||
|
ninja
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
ctest -VV -C Release
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2021 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
mkdir -p "ccache" || true
|
||||||
|
chmod a+x ./.ci/scripts/clang/docker.sh
|
||||||
|
# the UID for the container citron user is 1027
|
||||||
|
sudo chown -R 1027 ./
|
||||||
|
docker run -e ENABLE_COMPATIBILITY_REPORTING -e CCACHE_DIR=/citron/ccache -v "$(pwd):/citron" -w /citron yuzu-emu-mirror/build-environments:linux-fresh /bin/bash /citron/.ci/scripts/clang/docker.sh "$1"
|
||||||
|
sudo chown -R $UID ./
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
. .ci/scripts/common/pre-upload.sh
|
||||||
|
|
||||||
|
REV_NAME="citron-linux-clang-${GITDATE}-${GITREV}"
|
||||||
|
ARCHIVE_NAME="${REV_NAME}.tar.xz"
|
||||||
|
COMPRESSION_FLAGS="-cJvf"
|
||||||
|
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ]; then
|
||||||
|
DIR_NAME="${REV_NAME}"
|
||||||
|
else
|
||||||
|
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $DIR_NAME
|
||||||
|
|
||||||
|
cp build/bin/citron "$DIR_NAME"
|
||||||
|
cp build/bin/citron-cmd "$DIR_NAME"
|
||||||
|
|
||||||
|
. .ci/scripts/common/post-upload.sh
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Copy documentation
|
||||||
|
cp LICENSE.txt "$DIR_NAME"
|
||||||
|
cp README.md "$DIR_NAME"
|
||||||
|
|
||||||
|
if [[ -z "${NO_SOURCE_PACK}" ]]; then
|
||||||
|
git clone --depth 1 file://$(readlink -e .) ${REV_NAME}-source
|
||||||
|
tar -cJvf "${REV_NAME}-source.tar.xz" ${REV_NAME}-source
|
||||||
|
cp -v "${REV_NAME}-source.tar.xz" "$DIR_NAME"
|
||||||
|
cp -v "${REV_NAME}-source.tar.xz" "${ARTIFACTS_DIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME"
|
||||||
|
|
||||||
|
# move the compiled archive into the artifacts directory to be uploaded by travis releases
|
||||||
|
mv "$ARCHIVE_NAME" "${ARTIFACTS_DIR}/"
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
||||||
|
GITREV="`git show -s --format='%h'`"
|
||||||
|
ARTIFACTS_DIR="$PWD/artifacts"
|
||||||
|
|
||||||
|
mkdir -p "${ARTIFACTS_DIR}/"
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Run clang-format
|
||||||
|
cd /citron
|
||||||
|
chmod a+x ./.ci/scripts/format/script.sh
|
||||||
|
./.ci/scripts/format/script.sh
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
chmod a+x ./.ci/scripts/format/docker.sh
|
||||||
|
# the UID for the container citron user is 1027
|
||||||
|
sudo chown -R 1027 ./
|
||||||
|
docker run -v "$(pwd):/citron" -w /citron yuzu-emu-mirror/build-environments:linux-clang-format /bin/bash -ex /citron/.ci/scripts/format/docker.sh
|
||||||
|
sudo chown -R $UID ./
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
shopt -s nullglob globstar
|
||||||
|
|
||||||
|
if git grep -nrI '\s$' src **/*.yml **/*.txt **/*.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop dist/*.svg dist/*.xml; then
|
||||||
|
echo Trailing whitespace found, aborting
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default clang-format points to default 3.5 version one
|
||||||
|
CLANG_FORMAT="${CLANG_FORMAT:-clang-format-15}"
|
||||||
|
"$CLANG_FORMAT" --version
|
||||||
|
|
||||||
|
# Turn off tracing for this because it's too verbose
|
||||||
|
set +x
|
||||||
|
|
||||||
|
# Check everything for branch pushes
|
||||||
|
FILES_TO_LINT="$(find src/ -name '*.cpp' -or -name '*.h')"
|
||||||
|
|
||||||
|
for f in $FILES_TO_LINT; do
|
||||||
|
echo "$f"
|
||||||
|
"$CLANG_FORMAT" -i "$f"
|
||||||
|
done
|
||||||
|
|
||||||
|
DIFF=$(git -c core.fileMode=false diff)
|
||||||
|
|
||||||
|
if [ ! -z "$DIFF" ]; then
|
||||||
|
echo "!!! Not compliant to coding style, here is the fix:"
|
||||||
|
echo "$DIFF"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd src/android
|
||||||
|
./gradlew ktlintCheck
|
|
@ -0,0 +1,79 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Exit on error, rather than continuing with the rest of the script.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
mkdir build || true && cd build
|
||||||
|
cmake .. \
|
||||||
|
-DBoost_USE_STATIC_LIBS=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||||
|
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
||||||
|
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
|
-DDISPLAY_VERSION=$1 \
|
||||||
|
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||||
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
|
-DUSE_DISCORD_PRESENCE=ON \
|
||||||
|
-DCITRON_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||||
|
-DCITRON_USE_BUNDLED_FFMPEG=ON \
|
||||||
|
-DCITRON_ENABLE_LTO=ON \
|
||||||
|
-DCITRON_CRASH_DUMPS=ON \
|
||||||
|
-GNinja
|
||||||
|
|
||||||
|
ninja
|
||||||
|
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
ctest -VV -C Release
|
||||||
|
|
||||||
|
# Separate debug symbols from specified executables
|
||||||
|
for EXE in citron; do
|
||||||
|
EXE_PATH="bin/$EXE"
|
||||||
|
# Copy debug symbols out
|
||||||
|
objcopy --only-keep-debug $EXE_PATH $EXE_PATH.debug
|
||||||
|
# Add debug link and strip debug symbols
|
||||||
|
objcopy -g --add-gnu-debuglink=$EXE_PATH.debug $EXE_PATH $EXE_PATH.out
|
||||||
|
# Overwrite original with stripped copy
|
||||||
|
mv $EXE_PATH.out $EXE_PATH
|
||||||
|
done
|
||||||
|
# Strip debug symbols from all executables
|
||||||
|
find bin/ -type f -not -regex '.*.debug' -exec strip -g {} ';'
|
||||||
|
|
||||||
|
DESTDIR="$PWD/AppDir" ninja install
|
||||||
|
rm -vf AppDir/usr/bin/citron-cmd AppDir/usr/bin/citron-tester
|
||||||
|
|
||||||
|
# Download tools needed to build an AppImage
|
||||||
|
wget -nc https://raw.githubusercontent.com/yuzu-emu-mirror/ext-linux-bin/main/appimage/deploy-linux.sh || wget -nc https://raw.githubusercontent.com/AppImage/AppImageKit/master/appimagetool/deploy-linux.sh
|
||||||
|
wget -nc https://raw.githubusercontent.com/yuzu-emu-mirror/AppImageKit-checkrt/old/AppRun.sh || wget -nc https://raw.githubusercontent.com/darealshinji/AppImageKit-checkrt/master/AppRun.sh
|
||||||
|
wget -nc https://github.com/yuzu-emu-mirror/ext-linux-bin/raw/main/appimage/exec-x86_64.so || wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so
|
||||||
|
# Set executable bit
|
||||||
|
chmod 755 \
|
||||||
|
deploy-linux.sh \
|
||||||
|
AppRun.sh \
|
||||||
|
exec-x86_64.so
|
||||||
|
|
||||||
|
# Workaround for https://github.com/AppImage/AppImageKit/issues/828
|
||||||
|
export APPIMAGE_EXTRACT_AND_RUN=1
|
||||||
|
|
||||||
|
mkdir -p AppDir/usr/optional
|
||||||
|
mkdir -p AppDir/usr/optional/libstdc++
|
||||||
|
mkdir -p AppDir/usr/optional/libgcc_s
|
||||||
|
|
||||||
|
# Deploy citron's needed dependencies
|
||||||
|
DEPLOY_QT=1 ./deploy-linux.sh AppDir/usr/bin/citron AppDir
|
||||||
|
|
||||||
|
# Workaround for libQt5MultimediaGstTools indirectly requiring libwayland-client and breaking Vulkan usage on end-user systems
|
||||||
|
find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print
|
||||||
|
|
||||||
|
# Workaround for building citron with GCC 10 but also trying to distribute it to Ubuntu 18.04 et al.
|
||||||
|
# See https://github.com/darealshinji/AppImageKit-checkrt
|
||||||
|
cp exec-x86_64.so AppDir/usr/optional/exec.so
|
||||||
|
cp AppRun.sh AppDir/AppRun
|
||||||
|
cp --dereference /usr/lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6
|
||||||
|
cp --dereference /lib/x86_64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
mkdir -p "ccache" || true
|
||||||
|
chmod a+x ./.ci/scripts/linux/docker.sh
|
||||||
|
# the UID for the container citron user is 1027
|
||||||
|
sudo chown -R 1027 ./
|
||||||
|
|
||||||
|
# The environment variables listed below:
|
||||||
|
# AZURECIREPO TITLEBARFORMATIDLE TITLEBARFORMATRUNNING DISPLAYVERSION
|
||||||
|
# are requested in src/common/CMakeLists.txt and appear to be provided somewhere in Azure DevOps
|
||||||
|
|
||||||
|
docker run -e AZURECIREPO -e TITLEBARFORMATIDLE -e TITLEBARFORMATRUNNING -e DISPLAYVERSION -e ENABLE_COMPATIBILITY_REPORTING -e CCACHE_DIR=/citron/ccache -v "$(pwd):/citron" -w /citron yuzu-emu-mirror/build-environments:linux-fresh /bin/bash /citron/.ci/scripts/linux/docker.sh "$1"
|
||||||
|
sudo chown -R $UID ./
|
|
@ -0,0 +1,67 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
. .ci/scripts/common/pre-upload.sh
|
||||||
|
|
||||||
|
APPIMAGE_NAME="citron-${RELEASE_NAME}-${GITDATE}-${GITREV}.AppImage"
|
||||||
|
BASE_NAME="citron-linux"
|
||||||
|
REV_NAME="${BASE_NAME}-${GITDATE}-${GITREV}"
|
||||||
|
ARCHIVE_NAME="${REV_NAME}.tar.xz"
|
||||||
|
COMPRESSION_FLAGS="-cJvf"
|
||||||
|
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ] || [ "${RELEASE_NAME}" = "canary" ]; then
|
||||||
|
DIR_NAME="${BASE_NAME}-${RELEASE_NAME}"
|
||||||
|
else
|
||||||
|
DIR_NAME="${REV_NAME}-${RELEASE_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir "$DIR_NAME"
|
||||||
|
|
||||||
|
cp build/bin/citron-cmd "$DIR_NAME"
|
||||||
|
if [ "${RELEASE_NAME}" != "canary" ] && [ "${RELEASE_NAME}" != "stable" ]; then
|
||||||
|
cp build/bin/citron "$DIR_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build an AppImage
|
||||||
|
cd build
|
||||||
|
|
||||||
|
wget -nc https://github.com/yuzu-emu-mirror/ext-linux-bin/raw/main/appimage/appimagetool-x86_64.AppImage || wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||||
|
chmod 755 appimagetool-x86_64.AppImage
|
||||||
|
|
||||||
|
# if FUSE is not available, then fallback to extract and run
|
||||||
|
if ! ./appimagetool-x86_64.AppImage --version; then
|
||||||
|
export APPIMAGE_EXTRACT_AND_RUN=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Don't let AppImageLauncher ask to integrate EA
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ] || [ "${RELEASE_NAME}" = "canary" ]; then
|
||||||
|
echo "X-AppImage-Integrate=false" >> AppDir/org.citron_emu.citron.desktop
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ]; then
|
||||||
|
# Generate update information if releasing to stable
|
||||||
|
./appimagetool-x86_64.AppImage -u "gh-releases-zsync|Citron-Project|Cit|latest|citron-*.AppImage.zsync" AppDir "${APPIMAGE_NAME}"
|
||||||
|
else
|
||||||
|
./appimagetool-x86_64.AppImage AppDir "${APPIMAGE_NAME}"
|
||||||
|
fi
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Copy the AppImage and update info to the artifacts directory and avoid compressing it
|
||||||
|
cp "build/${APPIMAGE_NAME}" "${ARTIFACTS_DIR}/"
|
||||||
|
if [ -f "build/${APPIMAGE_NAME}.zsync" ]; then
|
||||||
|
cp "build/${APPIMAGE_NAME}.zsync" "${ARTIFACTS_DIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy the AppImage to the general release directory and remove git revision info
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ] || [ "${RELEASE_NAME}" = "canary" ]; then
|
||||||
|
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/citron-${RELEASE_NAME}.AppImage"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy debug symbols to artifacts
|
||||||
|
cd build/bin
|
||||||
|
tar $COMPRESSION_FLAGS "${ARTIFACTS_DIR}/${REV_NAME}-debug.tar.xz" *.debug
|
||||||
|
cd -
|
||||||
|
|
||||||
|
. .ci/scripts/common/post-upload.sh
|
|
@ -0,0 +1,19 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Apply patches that are tagged with a specific label
|
||||||
|
# Current labels include:
|
||||||
|
# "canary merge benefit"
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
org = os.getenv("PRIVATEMERGEORG", "Citron-Project")
|
||||||
|
base = os.getenv("PRIVATEMERGEBASE", "Cit")
|
||||||
|
head = os.getenv("PRIVATEMERGEBASE", "Cit-canary")
|
||||||
|
|
||||||
|
# We use different files for the 3 PR checkers.
|
||||||
|
check_label_presence_file = ".ci/scripts/merge/check-label-presence.py"
|
||||||
|
check_reviews_file = ".ci/scripts/merge/check-reviews-private.py"
|
||||||
|
|
||||||
|
# python3 python_file org repo pr# label
|
||||||
|
os.system(f"python3 .ci/scripts/merge/apply-patches-by-label.py {sys.argv[1]} {org} {base} {head} {check_label_presence_file} {check_reviews_file}")
|
|
@ -0,0 +1,60 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Apply patches that are tagged with a specific label
|
||||||
|
# Current labels include:
|
||||||
|
# "canary merge benefit"
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
from urllib import request
|
||||||
|
|
||||||
|
|
||||||
|
def get_pull_request_list(page=1):
|
||||||
|
url = f"https://api.github.com/repos/Citron-Project/Cit/pulls?page={page}"
|
||||||
|
headers = {'Accept': 'application/vnd.github.v3+json'}
|
||||||
|
token = os.environ.get('EARLY_ACCESS_TOKEN')
|
||||||
|
if token:
|
||||||
|
headers['Authorization'] = f'token {token}'
|
||||||
|
req = request.Request(url, headers=headers)
|
||||||
|
response = request.urlopen(req)
|
||||||
|
result = json.loads(response.read().decode('utf-8'))
|
||||||
|
if len(result) > 0:
|
||||||
|
return result + get_pull_request_list(page + 1)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
seen = {}
|
||||||
|
|
||||||
|
for pr in get_pull_request_list():
|
||||||
|
pn = pr['number']
|
||||||
|
if pn in seen:
|
||||||
|
continue
|
||||||
|
seen[pn] = True
|
||||||
|
print(subprocess.check_output(["git", "fetch", "https://github.com/Citron-Project/Cit.git", f"pull/{pn}/head:pr-{pn}", "-f", "--no-recurse-submodules"]))
|
||||||
|
out = subprocess.check_output(["python3", ".ci/scripts/merge/check-label-presence.py", str(pn), sys.argv[1]])
|
||||||
|
if b'true' in out:
|
||||||
|
print(f'Applying PR #{pn} matching label {sys.argv[1]}...')
|
||||||
|
try:
|
||||||
|
if b'changes requested' in subprocess.check_output(["python3", ".ci/scripts/merge/check-reviews.py", str(pn)]):
|
||||||
|
print(f'PR #{pn} has requested changes, skipping')
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print(f'PR #{pn} has approving reviews, applying')
|
||||||
|
except:
|
||||||
|
print('Could not find any valid reviews, applying anyway')
|
||||||
|
try:
|
||||||
|
print(subprocess.check_output(["git", "merge", "--squash", f"pr-{pn}", "-m", f"Merge PR #{pn} tagged with: {sys.argv[1]}"]))
|
||||||
|
except:
|
||||||
|
print("Failed to merge cleanly, are there conflicts?")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
# Apply a tag to the EA release
|
||||||
|
try:
|
||||||
|
print(subprocess.check_output(["git", "tag", "-f", f"canary/{sys.argv[1]}"]))
|
||||||
|
except:
|
||||||
|
print("Failed to apply canary tag")
|
||||||
|
exit(0)
|
|
@ -0,0 +1,27 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Check if a pull request has a specific label
|
||||||
|
# Usage: python3 check-label-presence.py <PR Number> <Label Text>
|
||||||
|
|
||||||
|
import json, sys
|
||||||
|
from urllib import request
|
||||||
|
import os
|
||||||
|
|
||||||
|
url = 'https://api.github.com/repos/Citron-Project/Cit/issues/%s' % sys.argv[1]
|
||||||
|
headers = {'Accept': 'application/vnd.github.v3+json'}
|
||||||
|
token = os.environ.get('EARLY_ACCESS_TOKEN')
|
||||||
|
if token:
|
||||||
|
headers['Authorization'] = f'token {token}'
|
||||||
|
req = request.Request(url, headers=headers)
|
||||||
|
try:
|
||||||
|
response = request.urlopen(req)
|
||||||
|
j = json.loads(response.read().decode('utf-8'))
|
||||||
|
for label in j['labels']:
|
||||||
|
if label['name'] == sys.argv[2]:
|
||||||
|
print('true')
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error: {e}')
|
||||||
|
print('false')
|
||||||
|
sys.exit(1)
|
|
@ -0,0 +1,5 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
git config --global user.email "zephyron@citron-emu.org"
|
||||||
|
git config --global user.name "Zephyron"
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2021 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
echo -e "\e[1m\e[33mBuild tools information:\e[0m"
|
||||||
|
cmake --version
|
||||||
|
gcc -v
|
||||||
|
tx --version
|
||||||
|
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DENABLE_QT_TRANSLATION=ON -DGENERATE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_SDL2=OFF -DCITRON_TESTS=OFF -DCITRON_USE_BUNDLED_VCPKG=ON
|
||||||
|
make translation
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd dist/languages
|
||||||
|
tx push -s
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#cd /citron
|
||||||
|
|
||||||
|
ccache -sv
|
||||||
|
|
||||||
|
mkdir -p build && cd build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE="${PWD}/../CMakeModules/MinGWCross.cmake" \
|
||||||
|
-DDISPLAY_VERSION="$1" \
|
||||||
|
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||||
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
|
-DUSE_CCACHE=ON \
|
||||||
|
-DCITRON_USE_BUNDLED_SDL2=OFF \
|
||||||
|
-DCITRON_USE_EXTERNAL_SDL2=OFF \
|
||||||
|
-DCITRON_TESTS=OFF \
|
||||||
|
-GNinja
|
||||||
|
ninja citron citron-cmd
|
||||||
|
|
||||||
|
ccache -sv
|
||||||
|
|
||||||
|
echo "Tests skipped"
|
||||||
|
#ctest -VV -C Release
|
||||||
|
|
||||||
|
echo 'Prepare binaries...'
|
||||||
|
cd ..
|
||||||
|
mkdir package
|
||||||
|
|
||||||
|
if [ -d "/usr/x86_64-w64-mingw32/lib/qt5/plugins/platforms/" ]; then
|
||||||
|
QT_PLUGINS_PATH='/usr/x86_64-w64-mingw32/lib/qt5/plugins'
|
||||||
|
else
|
||||||
|
#fallback to qt
|
||||||
|
QT_PLUGINS_PATH='/usr/x86_64-w64-mingw32/lib/qt/plugins'
|
||||||
|
fi
|
||||||
|
|
||||||
|
find build/ -name "citron*.exe" -exec cp {} 'package' \;
|
||||||
|
|
||||||
|
# copy Qt plugins
|
||||||
|
mkdir package/platforms
|
||||||
|
cp -v "${QT_PLUGINS_PATH}/platforms/qwindows.dll" package/platforms/
|
||||||
|
cp -rv "${QT_PLUGINS_PATH}/mediaservice/" package/
|
||||||
|
cp -rv "${QT_PLUGINS_PATH}/imageformats/" package/
|
||||||
|
cp -rv "${QT_PLUGINS_PATH}/styles/" package/
|
||||||
|
rm -f package/mediaservice/*d.dll
|
||||||
|
|
||||||
|
for i in package/*.exe; do
|
||||||
|
# we need to process pdb here, however, cv2pdb
|
||||||
|
# does not work here, so we just simply strip all the debug symbols
|
||||||
|
x86_64-w64-mingw32-strip "${i}"
|
||||||
|
done
|
||||||
|
|
||||||
|
python3 .ci/scripts/windows/scan_dll.py package/*.exe package/imageformats/*.dll "package/"
|
||||||
|
|
||||||
|
# copy FFmpeg libraries
|
||||||
|
EXTERNALS_PATH="$(pwd)/build/externals"
|
||||||
|
FFMPEG_DLL_PATH="$(find "${EXTERNALS_PATH}" -maxdepth 1 -type d | grep 'ffmpeg-')/bin"
|
||||||
|
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -nv {} package/ ';'
|
||||||
|
|
||||||
|
# copy libraries from citron.exe path
|
||||||
|
find "$(pwd)/build/bin/" -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
mkdir -p "ccache" || true
|
||||||
|
chmod a+x ./.ci/scripts/windows/docker.sh
|
||||||
|
# the UID for the container citron user is 1027
|
||||||
|
sudo chown -R 1027 ./
|
||||||
|
docker run -e CCACHE_DIR=/citron/ccache -v "$(pwd):/citron" -w /citron yuzu-emu-mirror/build-environments:linux-mingw /bin/bash -ex /citron/.ci/scripts/windows/docker.sh "$1"
|
||||||
|
sudo chown -R $UID ./
|
|
@ -0,0 +1,33 @@
|
||||||
|
# SPDX-FileCopyrightText: 2023 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$VulkanSDKVer = "1.3.250.1"
|
||||||
|
$ExeFile = "VulkanSDK-$VulkanSDKVer-Installer.exe"
|
||||||
|
$Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/windows/$ExeFile"
|
||||||
|
$Destination = "./$ExeFile"
|
||||||
|
|
||||||
|
echo "Downloading Vulkan SDK $VulkanSDKVer from $Uri"
|
||||||
|
$WebClient = New-Object System.Net.WebClient
|
||||||
|
$WebClient.DownloadFile($Uri, $Destination)
|
||||||
|
echo "Finished downloading $ExeFile"
|
||||||
|
|
||||||
|
$VULKAN_SDK = "C:/VulkanSDK/$VulkanSDKVer"
|
||||||
|
$Arguments = "--root `"$VULKAN_SDK`" --accept-licenses --default-answer --confirm-command install"
|
||||||
|
|
||||||
|
echo "Installing Vulkan SDK $VulkanSDKVer"
|
||||||
|
$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -Wait -ArgumentList $Arguments
|
||||||
|
$ExitCode = $InstallProcess.ExitCode
|
||||||
|
|
||||||
|
if ($ExitCode -ne 0) {
|
||||||
|
echo "Error installing Vulkan SDK $VulkanSDKVer (Error: $ExitCode)"
|
||||||
|
Exit $ExitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Finished installing Vulkan SDK $VulkanSDKVer"
|
||||||
|
|
||||||
|
if ("$env:GITHUB_ACTIONS" -eq "true") {
|
||||||
|
echo "VULKAN_SDK=$VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
echo "$VULKAN_SDK/Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
import pefile
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import queue
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
# constant definitions
|
||||||
|
KNOWN_SYS_DLLS = ['WINMM.DLL', 'MSVCRT.DLL', 'VERSION.DLL', 'MPR.DLL',
|
||||||
|
'DWMAPI.DLL', 'UXTHEME.DLL', 'DNSAPI.DLL', 'IPHLPAPI.DLL']
|
||||||
|
# below is for Ubuntu 18.04 with specified PPA enabled, if you are using
|
||||||
|
# other distro or different repositories, change the following accordingly
|
||||||
|
DLL_PATH = [
|
||||||
|
'/usr/x86_64-w64-mingw32/bin/',
|
||||||
|
'/usr/x86_64-w64-mingw32/lib/',
|
||||||
|
'/usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/'
|
||||||
|
]
|
||||||
|
|
||||||
|
missing = []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_imports(file_name):
|
||||||
|
results = []
|
||||||
|
pe = pefile.PE(file_name, fast_load=True)
|
||||||
|
pe.parse_data_directories()
|
||||||
|
|
||||||
|
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||||
|
current = entry.dll.decode()
|
||||||
|
current_u = current.upper() # b/c Windows is often case insensitive
|
||||||
|
# here we filter out system dlls
|
||||||
|
# dll w/ names like *32.dll are likely to be system dlls
|
||||||
|
if current_u.upper() not in KNOWN_SYS_DLLS and not re.match(string=current_u, pattern=r'.*32\.DLL'):
|
||||||
|
results.append(current)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def parse_imports_recursive(file_name, path_list=[]):
|
||||||
|
q = queue.Queue() # create a FIFO queue
|
||||||
|
# file_name can be a string or a list for the convenience
|
||||||
|
if isinstance(file_name, str):
|
||||||
|
q.put(file_name)
|
||||||
|
elif isinstance(file_name, list):
|
||||||
|
for i in file_name:
|
||||||
|
q.put(i)
|
||||||
|
full_list = []
|
||||||
|
while q.qsize():
|
||||||
|
current = q.get_nowait()
|
||||||
|
print('> %s' % current)
|
||||||
|
deps = parse_imports(current)
|
||||||
|
# if this dll does not have any import, ignore it
|
||||||
|
if not deps:
|
||||||
|
continue
|
||||||
|
for dep in deps:
|
||||||
|
# the dependency already included in the list, skip
|
||||||
|
if dep in full_list:
|
||||||
|
continue
|
||||||
|
# find the requested dll in the provided paths
|
||||||
|
full_path = find_dll(dep)
|
||||||
|
if not full_path:
|
||||||
|
missing.append(dep)
|
||||||
|
continue
|
||||||
|
full_list.append(dep)
|
||||||
|
q.put(full_path)
|
||||||
|
path_list.append(full_path)
|
||||||
|
return full_list
|
||||||
|
|
||||||
|
|
||||||
|
def find_dll(name):
|
||||||
|
for path in DLL_PATH:
|
||||||
|
for root, _, files in os.walk(path):
|
||||||
|
for f in files:
|
||||||
|
if name.lower() == f.lower():
|
||||||
|
return os.path.join(root, f)
|
||||||
|
|
||||||
|
|
||||||
|
def deploy(name, dst, dry_run=False):
|
||||||
|
dlls_path = []
|
||||||
|
parse_imports_recursive(name, dlls_path)
|
||||||
|
for dll_entry in dlls_path:
|
||||||
|
if not dry_run:
|
||||||
|
shutil.copy(dll_entry, dst)
|
||||||
|
else:
|
||||||
|
print('[Dry-Run] Copy %s to %s' % (dll_entry, dst))
|
||||||
|
print('Deploy completed.')
|
||||||
|
return dlls_path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print('Usage: %s [files to examine ...] [target deploy directory]')
|
||||||
|
return 1
|
||||||
|
to_deploy = sys.argv[1:-1]
|
||||||
|
tgt_dir = sys.argv[-1]
|
||||||
|
if not os.path.isdir(tgt_dir):
|
||||||
|
print('%s is not a directory.' % tgt_dir)
|
||||||
|
return 1
|
||||||
|
print('Scanning dependencies...')
|
||||||
|
deploy(to_deploy, tgt_dir)
|
||||||
|
if missing:
|
||||||
|
print('Following DLLs are not found: %s' % ('\n'.join(missing)))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,118 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
param($BUILD_NAME)
|
||||||
|
|
||||||
|
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-", ""
|
||||||
|
$GITREV = $(git show -s --format='%h')
|
||||||
|
|
||||||
|
if ("$BUILD_NAME" -eq "stable") {
|
||||||
|
$RELEASE_DIST = "citron-stable-msvc"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$RELEASE_DIST = "citron-windows-msvc-$BUILD_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
$MSVC_BUILD_ZIP = "citron-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
|
||||||
|
$MSVC_BUILD_PDB = "citron-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", ""
|
||||||
|
$MSVC_SEVENZIP = "citron-windows-msvc-$GITDATE-$GITREV.7z" -replace " ", ""
|
||||||
|
$MSVC_TAR = "citron-windows-msvc-$GITDATE-$GITREV.tar" -replace " ", ""
|
||||||
|
$MSVC_TARXZ = "citron-windows-msvc-$GITDATE-$GITREV.tar.xz" -replace " ", ""
|
||||||
|
$MSVC_SOURCE = "citron-windows-msvc-source-$GITDATE-$GITREV" -replace " ", ""
|
||||||
|
$MSVC_SOURCE_TAR = "$MSVC_SOURCE.tar"
|
||||||
|
$MSVC_SOURCE_TARXZ = "$MSVC_SOURCE_TAR.xz"
|
||||||
|
|
||||||
|
$env:BUILD_ZIP = $MSVC_BUILD_ZIP
|
||||||
|
$env:BUILD_SYMBOLS = $MSVC_BUILD_PDB
|
||||||
|
$env:BUILD_UPDATE = $MSVC_SEVENZIP
|
||||||
|
|
||||||
|
if (Test-Path -Path ".\build\bin\Release") {
|
||||||
|
$BUILD_DIR = ".\build\bin\Release"
|
||||||
|
} else {
|
||||||
|
$BUILD_DIR = ".\build\bin\"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup unneeded data in submodules
|
||||||
|
git submodule foreach git clean -fxd
|
||||||
|
|
||||||
|
# Upload debugging symbols
|
||||||
|
mkdir pdb
|
||||||
|
Get-ChildItem "$BUILD_DIR\" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb
|
||||||
|
7z a -tzip $MSVC_BUILD_PDB .\pdb\*.pdb
|
||||||
|
rm "$BUILD_DIR\*.pdb"
|
||||||
|
|
||||||
|
# Create artifact directories
|
||||||
|
mkdir $RELEASE_DIST
|
||||||
|
mkdir $MSVC_SOURCE
|
||||||
|
mkdir "artifacts"
|
||||||
|
|
||||||
|
$CURRENT_DIR = Convert-Path .
|
||||||
|
|
||||||
|
# Build a tar.xz for the source of the release
|
||||||
|
git clone --depth 1 file://$CURRENT_DIR $MSVC_SOURCE
|
||||||
|
7z a -r -ttar $MSVC_SOURCE_TAR $MSVC_SOURCE
|
||||||
|
7z a -r -txz $MSVC_SOURCE_TARXZ $MSVC_SOURCE_TAR
|
||||||
|
|
||||||
|
# Following section is quick hack to package artifacts differently for GitHub Actions
|
||||||
|
if ("$env:GITHUB_ACTIONS" -eq "true") {
|
||||||
|
echo "Hello GitHub Actions"
|
||||||
|
|
||||||
|
# With vcpkg we now have a few more dll files
|
||||||
|
ls .\build\bin\*.dll
|
||||||
|
cp .\build\bin\*.dll .\artifacts\
|
||||||
|
|
||||||
|
# Hopefully there is an exe in either .\build\bin or .\build\bin\Release
|
||||||
|
cp .\build\bin\citron*.exe .\artifacts\
|
||||||
|
Copy-Item "$BUILD_DIR\*" -Destination "artifacts" -Recurse
|
||||||
|
Remove-Item .\artifacts\tests.exe -ErrorAction ignore
|
||||||
|
|
||||||
|
# None of the other GHA builds are including source, so commenting out today
|
||||||
|
#Copy-Item $MSVC_SOURCE_TARXZ -Destination "artifacts"
|
||||||
|
|
||||||
|
# Debugging symbols
|
||||||
|
cp .\build\bin\citron*.pdb .\artifacts\
|
||||||
|
|
||||||
|
# Write out a tag BUILD_TAG to environment for the Upload step
|
||||||
|
# We're getting ${{ github.event.number }} as $env:PR_NUMBER"
|
||||||
|
echo "env:PR_NUMBER: $env:PR_NUMBER"
|
||||||
|
if (Test-Path env:PR_NUMBER) {
|
||||||
|
$PR_NUMBER = $env:PR_NUMBER.Substring(2) -as [int]
|
||||||
|
$PR_NUMBER_TAG = "pr"+([string]$PR_NUMBER).PadLeft(5,'0')
|
||||||
|
if ($PR_NUMBER -gt 1){
|
||||||
|
$BUILD_TAG="verify-$PR_NUMBER_TAG-$GITDATE-$GITREV"
|
||||||
|
} else {
|
||||||
|
$BUILD_TAG = "verify-$GITDATE-$GITREV"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# If env:PR_NUMBER isn't set, we should still write out a variable
|
||||||
|
$BUILD_TAG = "verify-$GITDATE-$GITREV"
|
||||||
|
}
|
||||||
|
echo "BUILD_TAG=$BUILD_TAG"
|
||||||
|
echo "BUILD_TAG=$BUILD_TAG" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
|
# For extra job, just the exe
|
||||||
|
$INDIVIDUAL_EXE = "citron-msvc-$BUILD_TAG.exe"
|
||||||
|
echo "INDIVIDUAL_EXE=$INDIVIDUAL_EXE"
|
||||||
|
echo "INDIVIDUAL_EXE=$INDIVIDUAL_EXE" >> $env:GITHUB_ENV
|
||||||
|
echo "Just the exe: $INDIVIDUAL_EXE"
|
||||||
|
cp .\artifacts\citron.exe .\$INDIVIDUAL_EXE
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
# Build the final release artifacts
|
||||||
|
Copy-Item $MSVC_SOURCE_TARXZ -Destination $RELEASE_DIST
|
||||||
|
Copy-Item "$BUILD_DIR\*" -Destination $RELEASE_DIST -Recurse
|
||||||
|
rm "$RELEASE_DIST\*.exe"
|
||||||
|
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "citron*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||||
|
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||||
|
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\*
|
||||||
|
7z a $MSVC_SEVENZIP $RELEASE_DIST
|
||||||
|
|
||||||
|
7z a -r -ttar $MSVC_TAR $RELEASE_DIST
|
||||||
|
7z a -r -txz $MSVC_TARXZ $MSVC_TAR
|
||||||
|
|
||||||
|
Get-ChildItem . -Filter "*.zip" | Copy-Item -destination "artifacts"
|
||||||
|
Get-ChildItem . -Filter "*.7z" | Copy-Item -destination "artifacts"
|
||||||
|
Get-ChildItem . -Filter "*.tar.xz" | Copy-Item -destination "artifacts"
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
. .ci/scripts/common/pre-upload.sh
|
||||||
|
|
||||||
|
REV_NAME="citron-windows-${GITDATE}-${GITREV}"
|
||||||
|
ARCHIVE_NAME="${REV_NAME}.tar.xz"
|
||||||
|
COMPRESSION_FLAGS="-cJvf"
|
||||||
|
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ]; then
|
||||||
|
DIR_NAME="${REV_NAME}"
|
||||||
|
else
|
||||||
|
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir "$DIR_NAME"
|
||||||
|
# get around the permission issues
|
||||||
|
cp -r package/* "$DIR_NAME"
|
||||||
|
|
||||||
|
if [ "${RELEASE_NAME}" = "stable" ]; then
|
||||||
|
MSVC_BUILD_ZIP="citron-stable-msvc.zip"
|
||||||
|
else
|
||||||
|
MSVC_BUILD_ZIP="${REV_NAME}-msvc.zip"
|
||||||
|
fi
|
||||||
|
|
||||||
|
. .ci/scripts/common/post-upload.sh
|
|
@ -0,0 +1,8 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- script: mkdir artifacts || echo 'X' > artifacts/T1.txt
|
||||||
|
- publish: artifacts
|
||||||
|
artifact: 'citron-$(BuildName)-mock'
|
||||||
|
displayName: 'Upload Artifacts'
|
|
@ -0,0 +1,31 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'true'
|
||||||
|
cache: 'false'
|
||||||
|
version: ''
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: Powershell@2
|
||||||
|
displayName: 'Install Vulkan SDK'
|
||||||
|
inputs:
|
||||||
|
targetType: 'filePath'
|
||||||
|
filePath: './.ci/scripts/windows/install-vulkan-sdk.ps1'
|
||||||
|
- script: refreshenv && glslangValidator --version && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DCITRON_ENABLE_LTO=ON -DCITRON_USE_BUNDLED_QT=1 -DCITRON_USE_BUNDLED_SDL2=1 -DCITRON_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCITRON_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DCITRON_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DCITRON_CRASH_DUMPS=ON .. && cd ..
|
||||||
|
displayName: 'Configure CMake'
|
||||||
|
- task: MSBuild@1
|
||||||
|
displayName: 'Build'
|
||||||
|
inputs:
|
||||||
|
solution: 'build/citron.sln'
|
||||||
|
maximumCpuCount: true
|
||||||
|
configuration: release
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: 'Package Artifacts'
|
||||||
|
inputs:
|
||||||
|
targetType: 'filePath'
|
||||||
|
filePath: './.ci/scripts/windows/upload.ps1'
|
||||||
|
arguments: '$(BuildName)'
|
||||||
|
- publish: artifacts
|
||||||
|
artifact: 'citron-$(BuildName)-windows-msvc'
|
||||||
|
displayName: 'Upload Artifacts'
|
|
@ -0,0 +1,26 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'true'
|
||||||
|
cache: 'false'
|
||||||
|
version: ''
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: DockerInstaller@0
|
||||||
|
displayName: 'Prepare Environment'
|
||||||
|
inputs:
|
||||||
|
dockerVersion: '17.09.0-ce'
|
||||||
|
- task: CacheBeta@0
|
||||||
|
displayName: 'Cache Build System'
|
||||||
|
inputs:
|
||||||
|
key: citron-v1-$(BuildName)-$(BuildSuffix)-$(CacheSuffix)
|
||||||
|
path: $(System.DefaultWorkingDirectory)/ccache
|
||||||
|
cacheHitVar: CACHE_RESTORED
|
||||||
|
- script: chmod a+x ./.ci/scripts/$(ScriptFolder)/exec.sh && ./.ci/scripts/$(ScriptFolder)/exec.sh ${{ parameters['version'] }}
|
||||||
|
displayName: 'Build'
|
||||||
|
- script: chmod a+x ./.ci/scripts/$(ScriptFolder)/upload.sh && RELEASE_NAME=$(BuildName) ./.ci/scripts/$(ScriptFolder)/upload.sh
|
||||||
|
displayName: 'Package Artifacts'
|
||||||
|
- publish: artifacts
|
||||||
|
artifact: 'citron-$(BuildName)-$(BuildSuffix)'
|
||||||
|
displayName: 'Upload Artifacts'
|
|
@ -0,0 +1,33 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
version: ''
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: build
|
||||||
|
displayName: 'standard'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
maxParallel: 10
|
||||||
|
matrix:
|
||||||
|
windows:
|
||||||
|
BuildSuffix: 'windows-mingw'
|
||||||
|
ScriptFolder: 'windows'
|
||||||
|
clang:
|
||||||
|
BuildSuffix: 'clang'
|
||||||
|
ScriptFolder: 'clang'
|
||||||
|
linux:
|
||||||
|
BuildSuffix: 'linux'
|
||||||
|
ScriptFolder: 'linux'
|
||||||
|
steps:
|
||||||
|
- template: ./sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./build-single.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: $(parameters.cache)
|
||||||
|
version: $(parameters.version)
|
|
@ -0,0 +1,40 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
version: ''
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: build_test
|
||||||
|
displayName: 'testing'
|
||||||
|
pool:
|
||||||
|
vmImage: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
maxParallel: 5
|
||||||
|
matrix:
|
||||||
|
windows:
|
||||||
|
BuildSuffix: 'windows-testing'
|
||||||
|
ScriptFolder: 'windows'
|
||||||
|
steps:
|
||||||
|
- script: sudo apt-get update && sudo apt-get --only-upgrade -y install python3-pip && pip install requests urllib3
|
||||||
|
displayName: 'Prepare Environment'
|
||||||
|
- task: PythonScript@0
|
||||||
|
condition: eq(variables['Build.Reason'], 'PullRequest')
|
||||||
|
displayName: 'Determine Testing Status'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'filePath'
|
||||||
|
scriptPath: '.ci/scripts/merge/check-label-presence.py'
|
||||||
|
arguments: '$(System.PullRequest.PullRequestNumber) create-testing-build'
|
||||||
|
- ${{ if eq(variables.enabletesting, 'true') }}:
|
||||||
|
- template: ./sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- template: ./mergebot.yml
|
||||||
|
parameters:
|
||||||
|
matchLabel: 'testing-merge'
|
||||||
|
- template: ./build-single.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'false'
|
||||||
|
cache: 'false'
|
||||||
|
version: $(parameters.version)
|
|
@ -0,0 +1,17 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'true'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- template: ./sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: $(parameters.artifactSource)
|
||||||
|
needSubmodules: 'false'
|
||||||
|
- task: DockerInstaller@0
|
||||||
|
displayName: 'Prepare Environment'
|
||||||
|
inputs:
|
||||||
|
dockerVersion: '17.09.0-ce'
|
||||||
|
- script: chmod a+x ./.ci/scripts/format/exec.sh && ./.ci/scripts/format/exec.sh
|
||||||
|
displayName: 'Verify Formatting'
|
|
@ -0,0 +1,44 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: merge
|
||||||
|
displayName: 'pull requests'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
submodules: recursive
|
||||||
|
- template: ./mergebot-private.yml
|
||||||
|
parameters:
|
||||||
|
matchLabel: '$(BuildName)-merge'
|
||||||
|
matchLabelPublic: '$(PublicBuildName)-merge'
|
||||||
|
- task: ArchiveFiles@2
|
||||||
|
displayName: 'Package Source'
|
||||||
|
inputs:
|
||||||
|
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
|
||||||
|
includeRootFolder: false
|
||||||
|
archiveType: '7z'
|
||||||
|
archiveFile: '$(Build.ArtifactStagingDirectory)/citron-$(BuildName)-source.7z'
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
displayName: 'Upload Artifacts'
|
||||||
|
inputs:
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)/citron-$(BuildName)-source.7z'
|
||||||
|
artifact: 'citron-$(BuildName)-source'
|
||||||
|
replaceExistingArchive: true
|
||||||
|
- job: upload_source
|
||||||
|
displayName: 'upload'
|
||||||
|
dependsOn: merge
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- template: ./sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'true'
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh
|
||||||
|
displayName: 'Apply Git Configuration'
|
||||||
|
- script: git remote add other $(GitRepoPushChangesURL)
|
||||||
|
displayName: 'Register Repository'
|
||||||
|
- script: git push --force other HEAD:$(GitPushBranch)
|
||||||
|
displayName: 'Update Code'
|
|
@ -0,0 +1,43 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: merge
|
||||||
|
displayName: 'pull requests'
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
submodules: recursive
|
||||||
|
- template: ./mergebot.yml
|
||||||
|
parameters:
|
||||||
|
matchLabel: '$(BuildName)-merge'
|
||||||
|
- task: ArchiveFiles@2
|
||||||
|
displayName: 'Package Source'
|
||||||
|
inputs:
|
||||||
|
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
|
||||||
|
includeRootFolder: false
|
||||||
|
archiveType: '7z'
|
||||||
|
archiveFile: '$(Build.ArtifactStagingDirectory)/citron-$(BuildName)-source.7z'
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
displayName: 'Upload Artifacts'
|
||||||
|
inputs:
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)/citron-$(BuildName)-source.7z'
|
||||||
|
artifact: 'citron-$(BuildName)-source'
|
||||||
|
replaceExistingArchive: true
|
||||||
|
- job: upload_source
|
||||||
|
displayName: 'upload'
|
||||||
|
dependsOn: merge
|
||||||
|
pool:
|
||||||
|
vmImage: 'ubuntu-latest'
|
||||||
|
steps:
|
||||||
|
- template: ./sync-source.yml
|
||||||
|
parameters:
|
||||||
|
artifactSource: 'true'
|
||||||
|
needSubmodules: 'true'
|
||||||
|
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh
|
||||||
|
displayName: 'Apply Git Configuration'
|
||||||
|
- script: git remote add other $(GitRepoPushChangesURL)
|
||||||
|
displayName: 'Register Repository'
|
||||||
|
- script: git push --force other HEAD:$(GitPushBranch)
|
||||||
|
displayName: 'Update Code'
|
|
@ -0,0 +1,41 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
matchLabel: 'dummy-merge'
|
||||||
|
matchLabelPublic: 'dummy-merge'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
fetchDepth: 1
|
||||||
|
submodules: false
|
||||||
|
- task: PythonScript@0
|
||||||
|
displayName: 'Generate Merge Config'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'inline'
|
||||||
|
script: '${{ parameters.createMergeConfigScript }}'
|
||||||
|
- task: PythonScript@0
|
||||||
|
displayName: 'Discover, Download, and Apply Patches (Stable)'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'filePath'
|
||||||
|
scriptPath: '.ci/scripts/merge/apply-patches-by-label-private.py'
|
||||||
|
arguments: $(publicLabel)
|
||||||
|
workingDirectory: '$(Build.SourcesDirectory)'
|
||||||
|
- task: PythonScript@0
|
||||||
|
displayName: 'Discover, Download, and Apply Patches (Canary Public)'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'filePath'
|
||||||
|
scriptPath: '.ci/scripts/merge/apply-patches-by-label-private.py'
|
||||||
|
arguments: $(supporterPublicLabel)
|
||||||
|
workingDirectory: '$(Build.SourcesDirectory)'
|
||||||
|
- task: PythonScript@0
|
||||||
|
displayName: 'Discover, Download, and Apply Patches (Canary Private)'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'filePath'
|
||||||
|
scriptPath: '.ci/scripts/merge/apply-patches-by-label-private.py'
|
||||||
|
arguments: $(supporterPrivateLabel)
|
||||||
|
workingDirectory: '$(Build.SourcesDirectory)'
|
||||||
|
- script: |
|
||||||
|
echo '##vso[task.setvariable variable=DisplayPrefix]$(tagPrefix)'
|
||||||
|
git rev-parse HEAD
|
||||||
|
displayName: 'Set Version Number'
|
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
matchLabel: 'dummy-merge'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- script: mkdir $(System.DefaultWorkingDirectory)/patches && pip install requests urllib3
|
||||||
|
displayName: 'Prepare Environment'
|
||||||
|
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh
|
||||||
|
displayName: 'Apply Git Configuration'
|
||||||
|
- task: PythonScript@0
|
||||||
|
displayName: 'Discover, Download, and Apply Patches'
|
||||||
|
inputs:
|
||||||
|
scriptSource: 'filePath'
|
||||||
|
scriptPath: '.ci/scripts/merge/apply-patches-by-label.py'
|
||||||
|
arguments: '${{ parameters.matchLabel }} Tagged patches'
|
||||||
|
workingDirectory: '$(System.DefaultWorkingDirectory)'
|
|
@ -0,0 +1,22 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
displayName: 'Download Windows Release'
|
||||||
|
inputs:
|
||||||
|
artifactName: 'citron-$(BuildName)-windows-msvc'
|
||||||
|
buildType: 'current'
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)'
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
displayName: 'Download Linux Release'
|
||||||
|
inputs:
|
||||||
|
artifactName: 'citron-$(BuildName)-linux'
|
||||||
|
buildType: 'current'
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)'
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
displayName: 'Download Android Release'
|
||||||
|
inputs:
|
||||||
|
artifactName: 'citron-$(BuildName)-android'
|
||||||
|
buildType: 'current'
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)'
|
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- template: ./release-download.yml
|
||||||
|
- task: GitHubRelease@0
|
||||||
|
displayName: 'GitHub Release'
|
||||||
|
inputs:
|
||||||
|
action: 'create'
|
||||||
|
title: '$(ReleasePrefix) $(DisplayVersion)'
|
||||||
|
assets: '$(Build.ArtifactStagingDirectory)/*'
|
||||||
|
gitHubConnection: CI_RELEASE_TOKEN
|
||||||
|
repositoryName: 'Citron-Project/Cit'
|
||||||
|
target: '$(Build.SourceVersion)'
|
||||||
|
tagSource: manual
|
||||||
|
tag: $(BuildName)-$(DisplayPrefix)-$(DisplayVersion)
|
||||||
|
addChangeLog: true
|
||||||
|
isDraft: false
|
|
@ -0,0 +1,12 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/citronbot-git-config.sh
|
||||||
|
displayName: 'Apply Git Configuration'
|
||||||
|
- script: git tag -a $(BuildName)-$(DisplayPrefix)-$(DisplayVersion) -m "citron $(BuildName) $(Build.BuildNumber) $(Build.DefinitionName) $(DisplayPrefix)-$(DisplayVersion)"
|
||||||
|
displayName: 'Tag Source'
|
||||||
|
- script: git remote add other $(GitRepoPushChangesURL)
|
||||||
|
displayName: 'Register Repository'
|
||||||
|
- script: git push other $(BuildName)-$(DisplayPrefix)-$(DisplayVersion)
|
||||||
|
displayName: 'Update Code'
|
|
@ -0,0 +1,13 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- template: ./release-download.yml
|
||||||
|
- task: UniversalPackages@0
|
||||||
|
displayName: Publish Artifacts
|
||||||
|
inputs:
|
||||||
|
command: publish
|
||||||
|
publishDirectory: '$(Build.ArtifactStagingDirectory)'
|
||||||
|
vstsFeedPublish: 'citron-$(BuildName)'
|
||||||
|
vstsFeedPackagePublish: 'main'
|
||||||
|
packagePublishDescription: 'Citron Windows and Linux Executable Packages'
|
|
@ -0,0 +1,19 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- checkout: none
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
displayName: 'Download Source'
|
||||||
|
inputs:
|
||||||
|
artifactName: 'citron-$(BuildName)-source'
|
||||||
|
buildType: 'current'
|
||||||
|
targetPath: '$(Build.ArtifactStagingDirectory)'
|
||||||
|
- script: rm -rf $(System.DefaultWorkingDirectory) && mkdir $(System.DefaultWorkingDirectory)
|
||||||
|
displayName: 'Clean Working Directory'
|
||||||
|
- task: ExtractFiles@1
|
||||||
|
displayName: 'Prepare Source'
|
||||||
|
inputs:
|
||||||
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/*.7z'
|
||||||
|
destinationFolder: '$(System.DefaultWorkingDirectory)'
|
||||||
|
cleanDestinationFolder: false
|
|
@ -0,0 +1,14 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
needSubmodules: 'true'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
displayName: 'Checkout Recursive'
|
||||||
|
submodules: recursive
|
||||||
|
# condition: eq(parameters.needSubmodules, 'true')
|
||||||
|
#- checkout: self
|
||||||
|
# displayName: 'Checkout Fast'
|
||||||
|
# condition: ne(parameters.needSubmodules, 'true')
|
|
@ -0,0 +1,10 @@
|
||||||
|
# SPDX-FileCopyrightText: 2019 citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- ${{ if eq(parameters.artifactSource, 'true') }}:
|
||||||
|
- template: ./retrieve-artifact-source.yml
|
||||||
|
- ${{ if ne(parameters.artifactSource, 'true') }}:
|
||||||
|
- template: ./retrieve-master-source.yml
|
||||||
|
parameters:
|
||||||
|
needSubmodules: $(parameters.needSubmodules)
|
|
@ -1,4 +1,4 @@
|
||||||
; SPDX-FileCopyrightText: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
; SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
; SPDX-License-Identifier: GPL-2.0-or-later
|
; SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
[codespell]
|
[codespell]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# CRLF -> LF
|
# CRLF -> LF
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
dist/languages/* linguist-vendored
|
dist/languages/* linguist-vendored
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
name: New Issue (Developers Only)
|
||||||
|
description: A blank issue template for developers only. If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template.
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
**If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template.**
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: "Issue"
|
|
@ -0,0 +1,64 @@
|
||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with yuzu.
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Is there an existing issue for this?
|
||||||
|
description: Please search to see if an issue already exists for the bug you encountered.
|
||||||
|
options:
|
||||||
|
- label: I have searched the existing issues
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Affected Build(s)
|
||||||
|
description: List the affected build(s) that this issue applies to.
|
||||||
|
placeholder: Mainline 1234 / Early Access 1234
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: issue-desc
|
||||||
|
attributes:
|
||||||
|
label: Description of Issue
|
||||||
|
description: A brief description of the issue encountered along with any images and/or videos.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected-behavior
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: A brief description of how it is expected to work along with any images and/or videos.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction-steps
|
||||||
|
attributes:
|
||||||
|
label: Reproduction Steps
|
||||||
|
description: A brief explanation of how to reproduce this issue. If possible, provide a save file to aid in reproducing the issue.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: log
|
||||||
|
attributes:
|
||||||
|
label: Log File
|
||||||
|
description: A log file will help our developers to better diagnose and fix the issue. Instructions can be found [here](https://yuzu-emu.org/help/reference/log-files).
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: system-config
|
||||||
|
attributes:
|
||||||
|
label: System Configuration
|
||||||
|
placeholder: |
|
||||||
|
CPU: Intel i5-10400 / AMD Ryzen 5 3600
|
||||||
|
GPU/Driver: NVIDIA GeForce GTX 1060 (Driver 512.95)
|
||||||
|
RAM: 16GB DDR4-3200
|
||||||
|
OS: Windows 11 22H2 (Build 22621.819)
|
||||||
|
value: |
|
||||||
|
CPU:
|
||||||
|
GPU/Driver:
|
||||||
|
RAM:
|
||||||
|
OS:
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1,8 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: yuzu Discord
|
||||||
|
url: https://discord.com/invite/u77vRWY
|
||||||
|
about: If you are experiencing an issue with yuzu, and you need tech support, or if you have a general question, try asking in the official yuzu Discord linked here. Piracy is not allowed.
|
||||||
|
- name: Community forums
|
||||||
|
url: https://community.citra-emu.org
|
||||||
|
about: This is an alternative place for tech support, however helpers there are not as active.
|
|
@ -0,0 +1,28 @@
|
||||||
|
name: Feature Request
|
||||||
|
description: File a feature request
|
||||||
|
labels: "request"
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: Tech support does not belong here. You should only file an issue here if you are requesting a feature you believe would make yuzu better.
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Is there an existing issue for this?
|
||||||
|
description: Please search to see if an issue already exists for the feature you are requesting.
|
||||||
|
options:
|
||||||
|
- label: I have searched the existing issues
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-feature
|
||||||
|
attributes:
|
||||||
|
label: What feature are you suggesting?
|
||||||
|
description: A brief description of the requested feature.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: why-feature
|
||||||
|
attributes:
|
||||||
|
label: Why would this feature be useful?
|
||||||
|
description: A brief description of why this feature would make yuzu better.
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1,80 @@
|
||||||
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
name: 'yuzu-android-build'
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: [ "*" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository == 'yuzu-emu/yuzu-android' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Set up cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
~/.ccache
|
||||||
|
key: ${{ runner.os }}-android-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-android-
|
||||||
|
- name: Query tag name
|
||||||
|
uses: olegtarasov/get-tag@v2.1.2
|
||||||
|
id: tagName
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
|
- name: Build
|
||||||
|
run: ./.ci/scripts/android/build.sh
|
||||||
|
env:
|
||||||
|
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
||||||
|
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||||
|
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
||||||
|
- name: Copy artifacts
|
||||||
|
run: ./.ci/scripts/android/upload.sh
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: android
|
||||||
|
path: artifacts/
|
||||||
|
# release steps
|
||||||
|
release-android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [android]
|
||||||
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
- name: Query tag name
|
||||||
|
uses: olegtarasov/get-tag@v2.1.2
|
||||||
|
id: tagName
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ steps.tagName.outputs.tag }}
|
||||||
|
release_name: ${{ steps.tagName.outputs.tag }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: alexellis/upload-assets@0.2.3
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
asset_paths: '["./**/*.apk","./**/*.aab"]'
|
|
@ -0,0 +1,66 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
name: citron-android-canary-play-release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release-track:
|
||||||
|
description: 'Play store release track (internal/alpha/beta/production)'
|
||||||
|
required: true
|
||||||
|
default: 'alpha'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository == 'Citron-Project/Cit' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
name: Checkout
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: true
|
||||||
|
token: ${{ secrets.CI_RELEASE_TOKEN }}
|
||||||
|
- run: npm install execa@5
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
name: 'Merge and publish Android Canary changes'
|
||||||
|
env:
|
||||||
|
CI_RELEASE_TOKEN: ${{ secrets.CI_RELEASE_TOKEN }}
|
||||||
|
BUILD_CANARY: true
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const execa = require("execa");
|
||||||
|
const mergebot = require('./.github/workflows/android-merge.js').mergebot;
|
||||||
|
process.chdir('${{ github.workspace }}');
|
||||||
|
mergebot(github, context, execa);
|
||||||
|
- name: Get tag name
|
||||||
|
run: echo "GIT_TAG_NAME=$(cat tag-name.txt)" >> $GITHUB_ENV
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
|
- name: Build
|
||||||
|
run: ./.ci/scripts/android/canarybuild.sh
|
||||||
|
env:
|
||||||
|
CANARY_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
|
||||||
|
PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
|
||||||
|
PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
|
||||||
|
CANARY_SERVICE_ACCOUNT_KEY_B64: ${{ secrets.CANARY_SERVICE_ACCOUNT_KEY_B64 }}
|
||||||
|
STORE_TRACK: ${{ github.event.inputs.release-track }}
|
||||||
|
AUTO_VERSIONED: true
|
||||||
|
BUILD_CANARY: true
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.CANARY_TAG_NAME }}
|
||||||
|
name: ${{ env.CANARY_TAG_NAME }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
repository: Citron-Project/citron-android
|
||||||
|
token: ${{ secrets.CI_RELEASE_TOKEN }}
|
|
@ -0,0 +1,318 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
// Note: This is a GitHub Actions script
|
||||||
|
// It is not meant to be executed directly on your machine without modifications
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
// which label to check for changes
|
||||||
|
const CHANGE_LABEL_MAINLINE = 'android-merge';
|
||||||
|
const CHANGE_LABEL_EA = 'android-ea-merge';
|
||||||
|
// how far back in time should we consider the changes are "recent"? (default: 24 hours)
|
||||||
|
const DETECTION_TIME_FRAME = (parseInt(process.env.DETECTION_TIME_FRAME)) || (24 * 3600 * 1000);
|
||||||
|
const BUILD_EA = process.env.BUILD_EA == 'true';
|
||||||
|
const MAINLINE_TAG = process.env.MAINLINE_TAG;
|
||||||
|
|
||||||
|
async function checkBaseChanges(github) {
|
||||||
|
// query the commit date of the latest commit on this branch
|
||||||
|
const query = `query($owner:String!, $name:String!, $ref:String!) {
|
||||||
|
repository(name:$name, owner:$owner) {
|
||||||
|
ref(qualifiedName:$ref) {
|
||||||
|
target {
|
||||||
|
... on Commit { id pushedDate oid }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const variables = {
|
||||||
|
owner: 'yuzu-emu',
|
||||||
|
name: 'yuzu',
|
||||||
|
ref: 'refs/heads/master',
|
||||||
|
};
|
||||||
|
const result = await github.graphql(query, variables);
|
||||||
|
const pushedAt = result.repository.ref.target.pushedDate;
|
||||||
|
console.log(`Last commit pushed at ${pushedAt}.`);
|
||||||
|
const delta = new Date() - new Date(pushedAt);
|
||||||
|
if (delta <= DETECTION_TIME_FRAME) {
|
||||||
|
console.info('New changes detected, triggering a new build.');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.info('No new changes detected.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkAndroidChanges(github) {
|
||||||
|
if (checkBaseChanges(github)) return true;
|
||||||
|
const pulls = getPulls(github, false);
|
||||||
|
for (let i = 0; i < pulls.length; i++) {
|
||||||
|
let pull = pulls[i];
|
||||||
|
if (new Date() - new Date(pull.headRepository.pushedAt) <= DETECTION_TIME_FRAME) {
|
||||||
|
console.info(`${pull.number} updated at ${pull.headRepository.pushedAt}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.info("No changes detected in any tagged pull requests.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tagAndPush(github, owner, repo, execa, commit=false) {
|
||||||
|
let altToken = process.env.ALT_GITHUB_TOKEN;
|
||||||
|
if (!altToken) {
|
||||||
|
throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`;
|
||||||
|
}
|
||||||
|
const query = `query ($owner:String!, $name:String!) {
|
||||||
|
repository(name:$name, owner:$owner) {
|
||||||
|
refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) {
|
||||||
|
nodes { name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const variables = {
|
||||||
|
owner: owner,
|
||||||
|
name: repo,
|
||||||
|
};
|
||||||
|
const tags = await github.graphql(query, variables);
|
||||||
|
const tagList = tags.repository.refs.nodes;
|
||||||
|
let lastTag = 'android-1';
|
||||||
|
for (let i = 0; i < tagList.length; ++i) {
|
||||||
|
if (tagList[i].name.includes('android-')) {
|
||||||
|
lastTag = tagList[i].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
||||||
|
const channel = repo.split('-')[1];
|
||||||
|
const newTag = `${channel}-${tagNumber + 1}`;
|
||||||
|
console.log(`New tag: ${newTag}`);
|
||||||
|
if (commit) {
|
||||||
|
let channelName = channel[0].toUpperCase() + channel.slice(1);
|
||||||
|
console.info(`Committing pending commit as ${channelName} ${tagNumber + 1}`);
|
||||||
|
await execa("git", ['commit', '-m', `${channelName} ${tagNumber + 1}`]);
|
||||||
|
}
|
||||||
|
console.info('Pushing tags to GitHub ...');
|
||||||
|
await execa("git", ['tag', newTag]);
|
||||||
|
await execa("git", ['remote', 'add', 'target', `https://${altToken}@github.com/${owner}/${repo}.git`]);
|
||||||
|
await execa("git", ['push', 'target', 'master', '-f']);
|
||||||
|
await execa("git", ['push', 'target', 'master', '--tags']);
|
||||||
|
console.info('Successfully pushed new changes.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tagAndPushEA(github, owner, repo, execa) {
|
||||||
|
let altToken = process.env.ALT_GITHUB_TOKEN;
|
||||||
|
if (!altToken) {
|
||||||
|
throw `Please set ALT_GITHUB_TOKEN environment variable. This token should have write access to ${owner}/${repo}.`;
|
||||||
|
}
|
||||||
|
const query = `query ($owner:String!, $name:String!) {
|
||||||
|
repository(name:$name, owner:$owner) {
|
||||||
|
refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 10) {
|
||||||
|
nodes { name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const variables = {
|
||||||
|
owner: owner,
|
||||||
|
name: repo,
|
||||||
|
};
|
||||||
|
const tags = await github.graphql(query, variables);
|
||||||
|
const tagList = tags.repository.refs.nodes;
|
||||||
|
let lastTag = 'ea-1';
|
||||||
|
for (let i = 0; i < tagList.length; ++i) {
|
||||||
|
if (tagList[i].name.includes('ea-')) {
|
||||||
|
lastTag = tagList[i].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tagNumber = /\w+-(\d+)/.exec(lastTag)[1] | 0;
|
||||||
|
const newTag = `ea-${tagNumber + 1}`;
|
||||||
|
console.log(`New tag: ${newTag}`);
|
||||||
|
console.info('Pushing tags to GitHub ...');
|
||||||
|
await execa("git", ["remote", "add", "android", "https://github.com/yuzu-emu/yuzu-android.git"]);
|
||||||
|
await execa("git", ["fetch", "android"]);
|
||||||
|
|
||||||
|
await execa("git", ['tag', newTag]);
|
||||||
|
await execa("git", ['push', 'android', `${newTag}`]);
|
||||||
|
|
||||||
|
fs.writeFile('tag-name.txt', newTag, (err) => {
|
||||||
|
if (err) throw 'Could not write tag name to file!'
|
||||||
|
})
|
||||||
|
|
||||||
|
console.info('Successfully pushed new changes.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateReadme(pulls, context, mergeResults, execa) {
|
||||||
|
let baseUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/`;
|
||||||
|
let output =
|
||||||
|
"| Pull Request | Commit | Title | Author | Merged? |\n|----|----|----|----|----|\n";
|
||||||
|
for (let pull of pulls) {
|
||||||
|
let pr = pull.number;
|
||||||
|
let result = mergeResults[pr];
|
||||||
|
output += `| [${pr}](${baseUrl}/pull/${pr}) | [\`${result.rev || "N/A"}\`](${baseUrl}/pull/${pr}/files) | ${pull.title} | [${pull.author.login}](https://github.com/${pull.author.login}/) | ${result.success ? "Yes" : "No"} |\n`;
|
||||||
|
}
|
||||||
|
output +=
|
||||||
|
"\n\nEnd of merge log. You can find the original README.md below the break.\n\n-----\n\n";
|
||||||
|
output += fs.readFileSync("./README.md");
|
||||||
|
fs.writeFileSync("./README.md", output);
|
||||||
|
await execa("git", ["add", "README.md"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchPullRequests(pulls, repoUrl, execa) {
|
||||||
|
console.log("::group::Fetch pull requests");
|
||||||
|
for (let pull of pulls) {
|
||||||
|
let pr = pull.number;
|
||||||
|
console.info(`Fetching PR ${pr} ...`);
|
||||||
|
await execa("git", [
|
||||||
|
"fetch",
|
||||||
|
"-f",
|
||||||
|
"--no-recurse-submodules",
|
||||||
|
repoUrl,
|
||||||
|
`pull/${pr}/head:pr-${pr}`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
console.log("::endgroup::");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mergePullRequests(pulls, execa) {
|
||||||
|
let mergeResults = {};
|
||||||
|
console.log("::group::Merge pull requests");
|
||||||
|
await execa("git", ["config", "--global", "user.name", "yuzubot"]);
|
||||||
|
await execa("git", [
|
||||||
|
"config",
|
||||||
|
"--global",
|
||||||
|
"user.email",
|
||||||
|
"yuzu\x40yuzu-emu\x2eorg", // prevent email harvesters from scraping the address
|
||||||
|
]);
|
||||||
|
let hasFailed = false;
|
||||||
|
for (let pull of pulls) {
|
||||||
|
let pr = pull.number;
|
||||||
|
console.info(`Merging PR ${pr} ...`);
|
||||||
|
try {
|
||||||
|
const process1 = execa("git", [
|
||||||
|
"merge",
|
||||||
|
"--squash",
|
||||||
|
"--no-edit",
|
||||||
|
`pr-${pr}`,
|
||||||
|
]);
|
||||||
|
process1.stdout.pipe(process.stdout);
|
||||||
|
await process1;
|
||||||
|
|
||||||
|
const process2 = execa("git", ["commit", "-m", `Merge yuzu-emu#${pr}`]);
|
||||||
|
process2.stdout.pipe(process.stdout);
|
||||||
|
await process2;
|
||||||
|
|
||||||
|
const process3 = await execa("git", ["rev-parse", "--short", `pr-${pr}`]);
|
||||||
|
mergeResults[pr] = {
|
||||||
|
success: true,
|
||||||
|
rev: process3.stdout,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log(
|
||||||
|
`::error title=#${pr} not merged::Failed to merge pull request: ${pr}: ${err}`
|
||||||
|
);
|
||||||
|
mergeResults[pr] = { success: false };
|
||||||
|
hasFailed = true;
|
||||||
|
await execa("git", ["reset", "--hard"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("::endgroup::");
|
||||||
|
if (hasFailed) {
|
||||||
|
throw 'There are merge failures. Aborting!';
|
||||||
|
}
|
||||||
|
return mergeResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resetBranch(execa) {
|
||||||
|
console.log("::group::Reset master branch");
|
||||||
|
let hasFailed = false;
|
||||||
|
try {
|
||||||
|
await execa("git", ["remote", "add", "source", "https://github.com/yuzu-emu/yuzu.git"]);
|
||||||
|
await execa("git", ["fetch", "source"]);
|
||||||
|
const process1 = await execa("git", ["rev-parse", "source/master"]);
|
||||||
|
const headCommit = process1.stdout;
|
||||||
|
|
||||||
|
await execa("git", ["reset", "--hard", headCommit]);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`::error title=Failed to reset master branch`);
|
||||||
|
hasFailed = true;
|
||||||
|
}
|
||||||
|
console.log("::endgroup::");
|
||||||
|
if (hasFailed) {
|
||||||
|
throw 'Failed to reset the master branch. Aborting!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPulls(github) {
|
||||||
|
const query = `query ($owner:String!, $name:String!, $label:String!) {
|
||||||
|
repository(name:$name, owner:$owner) {
|
||||||
|
pullRequests(labels: [$label], states: OPEN, first: 100) {
|
||||||
|
nodes {
|
||||||
|
number title author { login }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const mainlineVariables = {
|
||||||
|
owner: 'yuzu-emu',
|
||||||
|
name: 'yuzu',
|
||||||
|
label: CHANGE_LABEL_MAINLINE,
|
||||||
|
};
|
||||||
|
const mainlineResult = await github.graphql(query, mainlineVariables);
|
||||||
|
const pulls = mainlineResult.repository.pullRequests.nodes;
|
||||||
|
if (BUILD_EA) {
|
||||||
|
const eaVariables = {
|
||||||
|
owner: 'yuzu-emu',
|
||||||
|
name: 'yuzu',
|
||||||
|
label: CHANGE_LABEL_EA,
|
||||||
|
};
|
||||||
|
const eaResult = await github.graphql(query, eaVariables);
|
||||||
|
const eaPulls = eaResult.repository.pullRequests.nodes;
|
||||||
|
return pulls.concat(eaPulls);
|
||||||
|
}
|
||||||
|
return pulls;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMainlineTag(execa) {
|
||||||
|
console.log(`::group::Getting mainline tag android-${MAINLINE_TAG}`);
|
||||||
|
let hasFailed = false;
|
||||||
|
try {
|
||||||
|
await execa("git", ["remote", "add", "mainline", "https://github.com/yuzu-emu/yuzu-android.git"]);
|
||||||
|
await execa("git", ["fetch", "mainline", "--tags"]);
|
||||||
|
await execa("git", ["checkout", `tags/android-${MAINLINE_TAG}`]);
|
||||||
|
await execa("git", ["submodule", "update", "--init", "--recursive"]);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('::error title=Failed pull tag');
|
||||||
|
hasFailed = true;
|
||||||
|
}
|
||||||
|
console.log("::endgroup::");
|
||||||
|
if (hasFailed) {
|
||||||
|
throw 'Failed pull mainline tag. Aborting!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mergebot(github, context, execa) {
|
||||||
|
// Reset our local copy of master to what appears on yuzu-emu/yuzu - master
|
||||||
|
await resetBranch(execa);
|
||||||
|
|
||||||
|
const pulls = await getPulls(github);
|
||||||
|
let displayList = [];
|
||||||
|
for (let i = 0; i < pulls.length; i++) {
|
||||||
|
let pull = pulls[i];
|
||||||
|
displayList.push({ PR: pull.number, Title: pull.title });
|
||||||
|
}
|
||||||
|
console.info("The following pull requests will be merged:");
|
||||||
|
console.table(displayList);
|
||||||
|
await fetchPullRequests(pulls, "https://github.com/yuzu-emu/yuzu", execa);
|
||||||
|
const mergeResults = await mergePullRequests(pulls, execa);
|
||||||
|
|
||||||
|
if (BUILD_EA) {
|
||||||
|
await tagAndPushEA(github, 'yuzu-emu', `yuzu-android`, execa);
|
||||||
|
} else {
|
||||||
|
await generateReadme(pulls, context, mergeResults, execa);
|
||||||
|
await tagAndPush(github, 'yuzu-emu', `yuzu-android`, execa, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.mergebot = mergebot;
|
||||||
|
module.exports.checkAndroidChanges = checkAndroidChanges;
|
||||||
|
module.exports.tagAndPush = tagAndPush;
|
||||||
|
module.exports.checkBaseChanges = checkBaseChanges;
|
||||||
|
module.exports.getMainlineTag = getMainlineTag;
|
|
@ -0,0 +1,57 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
name: yuzu-android-publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '37 0 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
android:
|
||||||
|
description: 'Whether to trigger an Android build (true/false/auto)'
|
||||||
|
required: false
|
||||||
|
default: 'true'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event.inputs.android != 'false' && github.repository == 'yuzu-emu/yuzu' }}
|
||||||
|
steps:
|
||||||
|
# this checkout is required to make sure the GitHub Actions scripts are available
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
name: Pre-checkout
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
- uses: actions/github-script@v6
|
||||||
|
id: check-changes
|
||||||
|
name: 'Check for new changes'
|
||||||
|
env:
|
||||||
|
# 24 hours
|
||||||
|
DETECTION_TIME_FRAME: 86400000
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
if (context.payload.inputs && context.payload.inputs.android === 'true') return true;
|
||||||
|
const checkAndroidChanges = require('./.github/workflows/android-merge.js').checkAndroidChanges;
|
||||||
|
return checkAndroidChanges(github);
|
||||||
|
- run: npm install execa@5
|
||||||
|
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
name: Checkout
|
||||||
|
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||||
|
with:
|
||||||
|
path: 'yuzu-merge'
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: true
|
||||||
|
token: ${{ secrets.ALT_GITHUB_TOKEN }}
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
name: 'Check and merge Android changes'
|
||||||
|
if: ${{ steps.check-changes.outputs.result == 'true' }}
|
||||||
|
env:
|
||||||
|
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const execa = require("execa");
|
||||||
|
const mergebot = require('./.github/workflows/android-merge.js').mergebot;
|
||||||
|
process.chdir('${{ github.workspace }}/yuzu-merge');
|
||||||
|
mergebot(github, context, execa);
|
|
@ -0,0 +1,59 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
name: citron-android-stable-play-release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release-tag:
|
||||||
|
description: 'Tag # from citron-android that you want to build and publish'
|
||||||
|
required: true
|
||||||
|
default: '100'
|
||||||
|
release-track:
|
||||||
|
description: 'Play store release track (internal/alpha/beta/production)'
|
||||||
|
required: true
|
||||||
|
default: 'alpha'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository == 'Citron-Project/Cit' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
name: Checkout
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: true
|
||||||
|
token: ${{ secrets.CI_RELEASE_TOKEN }}
|
||||||
|
- run: npm install execa@5
|
||||||
|
- uses: actions/github-script@v5
|
||||||
|
name: 'Pull stable tag'
|
||||||
|
env:
|
||||||
|
STABLE_TAG: ${{ github.event.inputs.release-tag }}
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const execa = require("execa");
|
||||||
|
const mergebot = require('./.github/workflows/android-merge.js').getStableTag;
|
||||||
|
process.chdir('${{ github.workspace }}');
|
||||||
|
mergebot(execa);
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
echo "GIT_TAG_NAME=android-${{ github.event.inputs.releast-tag }}" >> $GITHUB_ENV
|
||||||
|
./.ci/scripts/android/stablebuild.sh
|
||||||
|
env:
|
||||||
|
STABLE_PLAY_ANDROID_KEYSTORE_B64: ${{ secrets.PLAY_ANDROID_KEYSTORE_B64 }}
|
||||||
|
PLAY_ANDROID_KEY_ALIAS: ${{ secrets.PLAY_ANDROID_KEY_ALIAS }}
|
||||||
|
PLAY_ANDROID_KEYSTORE_PASS: ${{ secrets.PLAY_ANDROID_KEYSTORE_PASS }}
|
||||||
|
STABLE_SERVICE_ACCOUNT_KEY_B64: ${{ secrets.STABLE_SERVICE_ACCOUNT_KEY_B64 }}
|
||||||
|
STORE_TRACK: ${{ github.event.inputs.release-track }}
|
||||||
|
AUTO_VERSIONED: true
|
|
@ -0,0 +1,33 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
name: citron-ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
tags: [ "*" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
transifex:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: yuzu-emu-mirror/build-environments:linux-transifex
|
||||||
|
if: ${{ github.repository == 'Citron-Project/Cit' && !github.head_ref }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Update Translation
|
||||||
|
run: ./.ci/scripts/transifex/docker.sh
|
||||||
|
env:
|
||||||
|
TX_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }}
|
||||||
|
|
||||||
|
reuse:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository == 'Citron-Project/Cit' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: fsfe/reuse-action@v1
|
|
@ -0,0 +1,17 @@
|
||||||
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
# GitHub Action to automate the identification of common misspellings in text files.
|
||||||
|
# https://github.com/codespell-project/actions-codespell
|
||||||
|
# https://github.com/codespell-project/codespell
|
||||||
|
name: codespell
|
||||||
|
on: pull_request
|
||||||
|
permissions: {}
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
name: Check for spelling errors
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: codespell-project/actions-codespell@master
|
|
@ -0,0 +1,190 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
name: 'citron verify'
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
env:
|
||||||
|
PR_NUMBER: pr${{ github.event.number }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
name: 'verify format'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
- name: set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: 'Verify Formatting'
|
||||||
|
run: bash -ex ./.ci/scripts/format/script.sh
|
||||||
|
build:
|
||||||
|
name: 'test build'
|
||||||
|
needs: format
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- type: clang
|
||||||
|
image: linux-fresh
|
||||||
|
- type: linux
|
||||||
|
image: linux-fresh
|
||||||
|
- type: windows
|
||||||
|
image: linux-mingw
|
||||||
|
container:
|
||||||
|
image: yuzu-emu-mirror/build-environments:${{ matrix.image }}
|
||||||
|
options: -u 1001
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
id: ccache-restore
|
||||||
|
with:
|
||||||
|
path: ~/.ccache
|
||||||
|
key: ${{ runner.os }}-${{ matrix.type }}-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-${{ matrix.type }}-
|
||||||
|
- name: Create ccache directory
|
||||||
|
if: steps.ccache-restore.outputs.cache-hit != 'true'
|
||||||
|
run: mkdir -p ~/.ccache
|
||||||
|
- name: Build
|
||||||
|
run: ./.ci/scripts/${{ matrix.type }}/docker.sh
|
||||||
|
env:
|
||||||
|
ENABLE_COMPATIBILITY_REPORTING: "ON"
|
||||||
|
- name: Pack
|
||||||
|
run: ./.ci/scripts/${{ matrix.type }}/upload.sh
|
||||||
|
env:
|
||||||
|
NO_SOURCE_PACK: "YES"
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.type }}
|
||||||
|
path: artifacts/
|
||||||
|
build-mac:
|
||||||
|
name: 'test build (macos)'
|
||||||
|
needs: format
|
||||||
|
runs-on: macos-14
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake"
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCITRON_USE_BUNDLED_VCPKG=OFF -DCITRON_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
|
||||||
|
ninja
|
||||||
|
build-msvc:
|
||||||
|
name: 'test build (windows, msvc)'
|
||||||
|
needs: format
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.buildcache
|
||||||
|
key: ${{ runner.os }}-msvc-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-msvc-
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$BuildCacheVer = "v0.28.4"
|
||||||
|
$File = "buildcache-windows.zip"
|
||||||
|
$Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File"
|
||||||
|
$WebClient = New-Object System.Net.WebClient
|
||||||
|
$WebClient.DownloadFile($Uri, $File)
|
||||||
|
7z x $File
|
||||||
|
$CurrentDir = Convert-Path .
|
||||||
|
echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
- name: Install Vulkan SDK
|
||||||
|
shell: pwsh
|
||||||
|
run: .\.ci\scripts\windows\install-vulkan-sdk.ps1
|
||||||
|
- name: Set up MSVC
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
- name: Configure
|
||||||
|
env:
|
||||||
|
CC: cl.exe
|
||||||
|
CXX: cl.exe
|
||||||
|
run: |
|
||||||
|
glslangValidator --version
|
||||||
|
mkdir build
|
||||||
|
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DCITRON_USE_BUNDLED_QT=1 -DCITRON_USE_BUNDLED_SDL2=1 -DCITRON_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCITRON_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DCITRON_CRASH_DUMPS=ON
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build
|
||||||
|
- name: Cache Summary
|
||||||
|
run: buildcache -s
|
||||||
|
- name: Pack
|
||||||
|
shell: pwsh
|
||||||
|
run: .\.ci\scripts\windows\upload.ps1
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: msvc
|
||||||
|
path: artifacts/
|
||||||
|
- name: Upload EXE
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ env.INDIVIDUAL_EXE }}
|
||||||
|
path: ${{ env.INDIVIDUAL_EXE }}
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: format
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Set up cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
~/.ccache
|
||||||
|
key: ${{ runner.os }}-android-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-android-
|
||||||
|
- name: Query tag name
|
||||||
|
uses: olegtarasov/get-tag@v2.1.2
|
||||||
|
id: tagName
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ccache apksigner glslang-dev glslang-tools
|
||||||
|
- name: Build
|
||||||
|
run: ./.ci/scripts/android/build.sh
|
||||||
|
env:
|
||||||
|
USE_DEBUG_KEYSTORE: "true"
|
||||||
|
- name: Copy artifacts
|
||||||
|
run: ./.ci/scripts/android/upload.sh
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: android
|
||||||
|
path: artifacts/
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2013 Citra Emulator Project & 2025 Citron Homebrew Project
|
# SPDX-FileCopyrightText: 2013 Citra Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# Build directory
|
# Build directory
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2014 Citra Emulator Project & 2025 Citron Homebrew Project
|
# SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
[submodule "enet"]
|
[submodule "enet"]
|
||||||
|
|
22
.reuse/dep5
22
.reuse/dep5
|
@ -9,7 +9,7 @@ Files: dist/english_plurals/*
|
||||||
dist/qt_themes/*/icons/48x48/sd_card.png
|
dist/qt_themes/*/icons/48x48/sd_card.png
|
||||||
dist/qt_themes/*/icons/index.theme
|
dist/qt_themes/*/icons/index.theme
|
||||||
dist/qt_themes/default/style.qss
|
dist/qt_themes/default/style.qss
|
||||||
Copyright: yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: yuzu Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: dist/qt_themes/default/icons/256x256/citron.png
|
Files: dist/qt_themes/default/icons/256x256/citron.png
|
||||||
|
@ -17,7 +17,7 @@ Files: dist/qt_themes/default/icons/256x256/citron.png
|
||||||
dist/citron.icns
|
dist/citron.icns
|
||||||
dist/citron.ico
|
dist/citron.ico
|
||||||
dist/citron.svg
|
dist/citron.svg
|
||||||
Copyright: yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: yuzu Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: dist/qt_themes/qdarkstyle*/LICENSE.*
|
Files: dist/qt_themes/qdarkstyle*/LICENSE.*
|
||||||
|
@ -109,12 +109,12 @@ Copyright: 2021 Advanced Micro Devices, Inc.
|
||||||
License: MIT
|
License: MIT
|
||||||
|
|
||||||
Files: src/citron/*.ui
|
Files: src/citron/*.ui
|
||||||
Copyright: 2018-2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2018-2022 yuzu Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: src/citron/compatdb.ui
|
Files: src/citron/compatdb.ui
|
||||||
src/citron/main.ui
|
src/citron/main.ui
|
||||||
Copyright: 2014-2017 Citra Emulator Project & 2025 Citron Homebrew Project
|
Copyright: 2014-2017 Citra Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: src/citron/loading_screen.ui
|
Files: src/citron/loading_screen.ui
|
||||||
|
@ -125,27 +125,27 @@ Files: src/citron/applets/aboutdialog.ui
|
||||||
src/citron/applets/qt_software_keyboard.ui
|
src/citron/applets/qt_software_keyboard.ui
|
||||||
src/citron/util/overlay_dialog.ui
|
src/citron/util/overlay_dialog.ui
|
||||||
Copyright: 2020-2021 Its-Rei <kupfel@gmail.com>
|
Copyright: 2020-2021 Its-Rei <kupfel@gmail.com>
|
||||||
2020-2021 yuzu Emulator Project & 2025 citron Homebrew Project
|
2020-2021 yuzu Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: vcpkg.json
|
Files: vcpkg.json
|
||||||
Copyright: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2022 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
||||||
Files: .github/ISSUE_TEMPLATE/*
|
Files: .github/ISSUE_TEMPLATE/*
|
||||||
Copyright: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2022 yuzu Emulator Project
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
|
|
||||||
Files: src/android/app/src/ea/res/*
|
Files: src/android/app/src/ea/res/*
|
||||||
Copyright: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2023 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
||||||
Files: src/android/app/src/main/res/*
|
Files: src/android/app/src/main/res/*
|
||||||
Copyright: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2023 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
||||||
Files: src/android/gradle/wrapper/*
|
Files: src/android/gradle/wrapper/*
|
||||||
Copyright: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2023 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
||||||
Files: externals/stb/*
|
Files: externals/stb/*
|
||||||
|
@ -157,5 +157,5 @@ Copyright: Copyright 2017-2019 Feral Interactive
|
||||||
License: BSD-3-Clause
|
License: BSD-3-Clause
|
||||||
|
|
||||||
Files: src/android/app/debug.keystore
|
Files: src/android/app/debug.keystore
|
||||||
Copyright: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
Copyright: 2023 yuzu Emulator Project
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
|
|
413
CMakeLists.txt
413
CMakeLists.txt
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
@ -12,11 +12,60 @@ include(DownloadExternals)
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
# Disable Warnings as Errors for MSVC
|
||||||
|
if (MSVC)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# PGO Configuration
|
||||||
|
option(CITRON_ENABLE_PGO_INSTRUMENT "Enable Profile-Guided Optimization instrumentation build" OFF)
|
||||||
|
option(CITRON_ENABLE_PGO_OPTIMIZE "Enable Profile-Guided Optimization optimization build" OFF)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
if(CITRON_ENABLE_PGO_INSTRUMENT)
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " /GL /LTCG:PGINSTRUMENT")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG:PGINSTRUMENT")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG:PGINSTRUMENT")
|
||||||
|
elseif(CITRON_ENABLE_PGO_OPTIMIZE)
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " /GL /LTCG:PGOPTIMIZE")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG:PGOPTIMIZE")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG:PGOPTIMIZE")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# GCC and Clang PGO flags
|
||||||
|
if(CITRON_ENABLE_PGO_INSTRUMENT)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-instr-generate")
|
||||||
|
else() # GCC
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-generate")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-generate")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-generate")
|
||||||
|
endif()
|
||||||
|
elseif(CITRON_ENABLE_PGO_OPTIMIZE)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-instr-use=default.profdata")
|
||||||
|
else() # GCC
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fprofile-use")
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " -fprofile-use")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " -fprofile-use")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if SDL2::SDL2 target exists; if not, create an alias
|
||||||
|
if (TARGET SDL2::SDL2-static)
|
||||||
|
add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static)
|
||||||
|
elseif (TARGET SDL2::SDL2-shared)
|
||||||
|
add_library(SDL2::SDL2 ALIAS SDL2::SDL2-shared)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set bundled sdl2/qt as dependent options.
|
# Set bundled sdl2/qt as dependent options.
|
||||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
|
||||||
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
|
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
|
||||||
CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
|
CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
|
||||||
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
|
||||||
CMAKE_DEPENDENT_OPTION(CITRON_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
|
CMAKE_DEPENDENT_OPTION(CITRON_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
|
||||||
|
|
||||||
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF)
|
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF)
|
||||||
|
@ -24,8 +73,6 @@ cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID"
|
||||||
option(ENABLE_OPENGL "Enable OpenGL" ON)
|
option(ENABLE_OPENGL "Enable OpenGL" ON)
|
||||||
mark_as_advanced(FORCE ENABLE_OPENGL)
|
mark_as_advanced(FORCE ENABLE_OPENGL)
|
||||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||||
option(ENABLE_QT6 "Allow usage of Qt6 to be attempted" OFF)
|
|
||||||
set(QT6_LOCATION "" CACHE PATH "Additional Location to search for Qt6 libraries like C:/Qt/6.3.1/msvc2019_64/")
|
|
||||||
|
|
||||||
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
||||||
CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
||||||
|
@ -66,11 +113,18 @@ option(CITRON_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
|
||||||
|
|
||||||
option(CITRON_ENABLE_PORTABLE "Allow citron to enable portable mode if a user folder is found in the CWD" ON)
|
option(CITRON_ENABLE_PORTABLE "Allow citron to enable portable mode if a user folder is found in the CWD" ON)
|
||||||
|
|
||||||
|
option(CITRON_USE_LLVM_DEMANGLE "Use LLVM Demangle" ON)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(CITRON_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
CMAKE_DEPENDENT_OPTION(CITRON_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
|
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
|
||||||
|
|
||||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
set(DEFAULT_ENABLE_OPENSSL ON)
|
||||||
|
if (ANDROID OR WIN32 OR APPLE)
|
||||||
|
set(DEFAULT_ENABLE_OPENSSL OFF)
|
||||||
|
endif()
|
||||||
|
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||||
|
|
||||||
if (ANDROID OR WIN32 OR APPLE)
|
if (ANDROID OR WIN32 OR APPLE)
|
||||||
# - Windows defaults to the Schannel backend.
|
# - Windows defaults to the Schannel backend.
|
||||||
# - macOS defaults to the SecureTransport backend.
|
# - macOS defaults to the SecureTransport backend.
|
||||||
|
@ -83,21 +137,25 @@ endif()
|
||||||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||||
|
|
||||||
if (ANDROID AND CITRON_DOWNLOAD_ANDROID_VVL)
|
if (ANDROID AND CITRON_DOWNLOAD_ANDROID_VVL)
|
||||||
set(vvl_version "sdk-1.3.261.1")
|
set(vvl_version "1.4.309.0")
|
||||||
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
|
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
|
||||||
if (NOT EXISTS "${vvl_zip_file}")
|
|
||||||
# Download and extract validation layer release to externals directory
|
|
||||||
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
|
|
||||||
file(DOWNLOAD "${vvl_base_url}/${vvl_version}/android-binaries-${vvl_version}-android.zip"
|
|
||||||
"${vvl_zip_file}" SHOW_PROGRESS)
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
|
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Copy the arm64 binary to src/android/app/main/jniLibs
|
|
||||||
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")
|
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")
|
||||||
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
|
set(vvl_final_lib "${vvl_lib_path}/libVkLayer_khronos_validation.so")
|
||||||
DESTINATION "${vvl_lib_path}")
|
|
||||||
|
if (NOT EXISTS "${vvl_final_lib}")
|
||||||
|
# Download and extract validation layer release to externals directory
|
||||||
|
if (NOT EXISTS "${vvl_zip_file}")
|
||||||
|
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
|
||||||
|
file(DOWNLOAD "${vvl_base_url}/vulkan-sdk-${vvl_version}/android-binaries-${vvl_version}.zip"
|
||||||
|
"${vvl_zip_file}" SHOW_PROGRESS)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Copy the arm64 binary to src/android/app/main/jniLibs
|
||||||
|
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
|
||||||
|
DESTINATION "${vvl_lib_path}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
|
@ -111,22 +169,39 @@ if (CITRON_USE_BUNDLED_VCPKG)
|
||||||
|
|
||||||
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
|
||||||
set(VCPKG_TARGET_TRIPLET "arm64-android")
|
set(VCPKG_TARGET_TRIPLET "arm64-android")
|
||||||
|
# Detect host system (Windows or Linux)
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(VCPKG_HOST_TRIPLET "x64-windows")
|
||||||
|
else()
|
||||||
|
set(VCPKG_HOST_TRIPLET "x64-linux")
|
||||||
|
endif()
|
||||||
# this is to avoid CMake using the host pkg-config to find the host
|
# this is to avoid CMake using the host pkg-config to find the host
|
||||||
# libraries when building for Android targets
|
# libraries when building for Android targets
|
||||||
set(PKG_CONFIG_EXECUTABLE "aarch64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
set(PKG_CONFIG_EXECUTABLE "aarch64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
||||||
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
|
elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
|
||||||
set(VCPKG_TARGET_TRIPLET "x64-android")
|
set(VCPKG_TARGET_TRIPLET "x64-android")
|
||||||
|
# Detect host system (Windows or Linux)
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(VCPKG_HOST_TRIPLET "x64-windows")
|
||||||
|
else()
|
||||||
|
set(VCPKG_HOST_TRIPLET "x64-linux")
|
||||||
|
endif()
|
||||||
set(PKG_CONFIG_EXECUTABLE "x86_64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
set(PKG_CONFIG_EXECUTABLE "x86_64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unsupported Android architecture ${CMAKE_ANDROID_ARCH_ABI}")
|
message(FATAL_ERROR "Unsupported Android architecture ${CMAKE_ANDROID_ARCH_ABI}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Add these lines to ensure proper Android toolchain setup
|
||||||
|
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${ANDROID_NDK}/build/cmake/android.toolchain.cmake")
|
||||||
|
set(VCPKG_CRT_LINKAGE "dynamic")
|
||||||
|
set(VCPKG_LIBRARY_LINKAGE "static")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
|
set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
|
||||||
set(NASM_VERSION "2.16.01")
|
set(NASM_VERSION "2.16.03")
|
||||||
set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
|
set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
|
||||||
set(NASM_DOWNLOAD_URL "https://github.com/yuzu-mirror/ext-windows-bin/raw/master/nasm/nasm-${NASM_VERSION}-win64.zip")
|
set(NASM_DOWNLOAD_URL "https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/win64/nasm-${NASM_VERSION}-win64.zip")
|
||||||
|
|
||||||
if (NOT EXISTS ${NASM_DESTINATION_PATH})
|
if (NOT EXISTS ${NASM_DESTINATION_PATH})
|
||||||
file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
|
file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
|
||||||
|
@ -213,7 +288,7 @@ endif()
|
||||||
if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
||||||
message(STATUS "Downloading compatibility list for citron...")
|
message(STATUS "Downloading compatibility list for citron...")
|
||||||
file(DOWNLOAD
|
file(DOWNLOAD
|
||||||
https://api.yuzu-mirror.org/gamedb/
|
https://api.citron-emu.org/gamedb/
|
||||||
"${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS)
|
"${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS)
|
||||||
endif()
|
endif()
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
||||||
|
@ -292,22 +367,24 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||||
find_package(Boost 1.79.0 REQUIRED context)
|
find_package(Boost REQUIRED context)
|
||||||
find_package(enet 1.3 MODULE)
|
find_package(enet MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 10 REQUIRED)
|
||||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
if (CITRON_USE_LLVM_DEMANGLE)
|
||||||
|
find_package(LLVM MODULE COMPONENTS Demangle)
|
||||||
|
endif()
|
||||||
find_package(lz4 REQUIRED)
|
find_package(lz4 REQUIRED)
|
||||||
find_package(nlohmann_json 3.8 REQUIRED)
|
find_package(nlohmann_json REQUIRED)
|
||||||
find_package(Opus 1.3 MODULE)
|
find_package(Opus MODULE)
|
||||||
find_package(RenderDoc MODULE)
|
find_package(RenderDoc MODULE)
|
||||||
find_package(SimpleIni MODULE)
|
find_package(SimpleIni MODULE)
|
||||||
find_package(stb MODULE)
|
find_package(stb MODULE)
|
||||||
find_package(VulkanMemoryAllocator CONFIG)
|
find_package(VulkanMemoryAllocator CONFIG)
|
||||||
find_package(ZLIB 1.2 REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(zstd 1.5 REQUIRED)
|
find_package(zstd REQUIRED)
|
||||||
|
|
||||||
if (NOT CITRON_USE_EXTERNAL_VULKAN_HEADERS)
|
if (NOT CITRON_USE_EXTERNAL_VULKAN_HEADERS)
|
||||||
find_package(VulkanHeaders 1.3.274 REQUIRED)
|
find_package(VulkanHeaders 1.4.313 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT CITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
if (NOT CITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||||
|
@ -315,19 +392,19 @@ if (NOT CITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_LIBUSB)
|
if (ENABLE_LIBUSB)
|
||||||
find_package(libusb 1.0.24 MODULE)
|
find_package(libusb MODULE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||||
find_package(xbyak 6 CONFIG)
|
find_package(xbyak CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_arm64)
|
if (ARCHITECTURE_arm64)
|
||||||
find_package(oaknut 2.0.1 CONFIG)
|
find_package(oaknut CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||||
find_package(dynarmic 6.4.0 CONFIG)
|
find_package(dynarmic CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_CUBEB)
|
if (ENABLE_CUBEB)
|
||||||
|
@ -339,12 +416,12 @@ if (USE_DISCORD_PRESENCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_WEB_SERVICE)
|
if (ENABLE_WEB_SERVICE)
|
||||||
find_package(cpp-jwt 1.4 CONFIG)
|
find_package(cpp-jwt CONFIG)
|
||||||
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
|
find_package(httplib MODULE COMPONENTS OpenSSL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CITRON_TESTS)
|
if (CITRON_TESTS)
|
||||||
find_package(Catch2 3.0.1 REQUIRED)
|
find_package(Catch2 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# boost:asio has functions that require AcceptEx et al
|
# boost:asio has functions that require AcceptEx et al
|
||||||
|
@ -353,11 +430,11 @@ if (MINGW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_OPENSSL)
|
if(ENABLE_OPENSSL)
|
||||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
find_package(gamemode 1.7 MODULE)
|
find_package(gamemode MODULE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Please consider this as a stub
|
# Please consider this as a stub
|
||||||
|
@ -365,171 +442,11 @@ if(ENABLE_QT6 AND Qt6_LOCATION)
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
function(set_citron_qt_components)
|
|
||||||
# Best practice is to ask for all components at once, so they are from the same version
|
|
||||||
set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent)
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
|
||||||
list(APPEND CITRON_QT_COMPONENTS2 DBus)
|
|
||||||
endif()
|
|
||||||
if (CITRON_USE_QT_MULTIMEDIA)
|
|
||||||
list(APPEND CITRON_QT_COMPONENTS2 Multimedia)
|
|
||||||
endif()
|
|
||||||
if (CITRON_USE_QT_WEB_ENGINE)
|
|
||||||
list(APPEND CITRON_QT_COMPONENTS2 WebEngineCore WebEngineWidgets)
|
|
||||||
endif()
|
|
||||||
if (ENABLE_QT_TRANSLATION)
|
|
||||||
list(APPEND CITRON_QT_COMPONENTS2 LinguistTools)
|
|
||||||
endif()
|
|
||||||
if (USE_DISCORD_PRESENCE)
|
|
||||||
list(APPEND CITRON_QT_COMPONENTS2 Network)
|
|
||||||
endif()
|
|
||||||
set(CITRON_QT_COMPONENTS ${CITRON_QT_COMPONENTS2} PARENT_SCOPE)
|
|
||||||
endfunction(set_citron_qt_components)
|
|
||||||
|
|
||||||
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
|
|
||||||
if(ENABLE_QT)
|
|
||||||
set(QT_VERSION 5.15)
|
|
||||||
# These are used to specify minimum versions
|
|
||||||
set(QT5_VERSION 5.15)
|
|
||||||
set(QT6_VERSION 6.3.1)
|
|
||||||
|
|
||||||
set_citron_qt_components()
|
|
||||||
if (ENABLE_QT6)
|
|
||||||
find_package(Qt6 ${QT6_VERSION} COMPONENTS ${CITRON_QT_COMPONENTS})
|
|
||||||
endif()
|
|
||||||
if (Qt6_FOUND)
|
|
||||||
message(STATUS "citron/CMakeLists.txt: Qt6Widgets_VERSION ${Qt6Widgets_VERSION}, setting QT_VERSION")
|
|
||||||
set(QT_VERSION ${Qt6Widgets_VERSION})
|
|
||||||
set(QT_MAJOR_VERSION 6)
|
|
||||||
# Qt6 sets cxx_std_17 and we need to undo that
|
|
||||||
set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "")
|
|
||||||
else()
|
|
||||||
message(STATUS "citron/CMakeLists.txt: Qt6 not found/not selected, trying for Qt5")
|
|
||||||
# When Qt6 partially found, need this set to use Qt5 when not specifying version
|
|
||||||
set(QT_DEFAULT_MAJOR_VERSION 5)
|
|
||||||
set(QT_MAJOR_VERSION 5)
|
|
||||||
|
|
||||||
set(CITRON_USE_QT_MULTIMEDIA ON)
|
|
||||||
# Check for system Qt on Linux, fallback to bundled Qt
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
if (NOT CITRON_USE_BUNDLED_QT)
|
|
||||||
find_package(Qt5 ${QT5_VERSION} COMPONENTS Widgets DBus Multimedia)
|
|
||||||
endif()
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR CITRON_USE_BUNDLED_QT))
|
|
||||||
# Check for dependencies, then enable bundled Qt download
|
|
||||||
|
|
||||||
# Check that the system GLIBCXX version is compatible
|
|
||||||
find_program(OBJDUMP objdump)
|
|
||||||
if (NOT OBJDUMP)
|
|
||||||
message(FATAL_ERROR "Required program `objdump` not found.")
|
|
||||||
endif()
|
|
||||||
find_library(LIBSTDCXX libstdc++.so.6)
|
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
${OBJDUMP} -T ${LIBSTDCXX}
|
|
||||||
COMMAND
|
|
||||||
grep GLIBCXX_3.4.28
|
|
||||||
COMMAND
|
|
||||||
sed "s/[0-9a-f]*.* //"
|
|
||||||
COMMAND
|
|
||||||
sed "s/ .*//"
|
|
||||||
COMMAND
|
|
||||||
sort -u
|
|
||||||
OUTPUT_VARIABLE
|
|
||||||
GLIBCXX_MET
|
|
||||||
)
|
|
||||||
if (NOT GLIBCXX_MET)
|
|
||||||
message(FATAL_ERROR "Qt too old or not found, and bundled Qt package is not \
|
|
||||||
compatible with this system. Either install Qt ${QT_VERSION}, or provide the path \
|
|
||||||
to Qt by setting the variable Qt5_ROOT.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check for headers
|
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0)
|
|
||||||
if (NOT QT_DEP_GLU_FOUND)
|
|
||||||
message(FATAL_ERROR "Qt bundled package dependency `glu` not found. \
|
|
||||||
Perhaps `libglu1-mesa-dev` needs to be installed?")
|
|
||||||
endif()
|
|
||||||
pkg_check_modules(QT_DEP_MESA QUIET dri>=20.0.8)
|
|
||||||
if (NOT QT_DEP_MESA_FOUND)
|
|
||||||
message(FATAL_ERROR "Qt bundled package dependency `dri` not found. \
|
|
||||||
Perhaps `mesa-common-dev` needs to be installed?")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check for X libraries
|
|
||||||
set(BUNDLED_QT_REQUIREMENTS
|
|
||||||
libxcb-icccm.so.4
|
|
||||||
libxcb-image.so.0
|
|
||||||
libxcb-keysyms.so.1
|
|
||||||
libxcb-randr.so.0
|
|
||||||
libxcb-render-util.so.0
|
|
||||||
libxcb-render.so.0
|
|
||||||
libxcb-shape.so.0
|
|
||||||
libxcb-shm.so.0
|
|
||||||
libxcb-sync.so.1
|
|
||||||
libxcb-xfixes.so.0
|
|
||||||
libxcb-xinerama.so.0
|
|
||||||
libxcb-xkb.so.1
|
|
||||||
libxcb.so.1
|
|
||||||
libxkbcommon-x11.so.0
|
|
||||||
libxkbcommon.so.0
|
|
||||||
)
|
|
||||||
set(UNRESOLVED_QT_DEPS "")
|
|
||||||
foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS})
|
|
||||||
find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT})
|
|
||||||
if (NOT BUNDLED_QT_${REQUIREMENT})
|
|
||||||
set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT})
|
|
||||||
endif()
|
|
||||||
unset(BUNDLED_QT_${REQUIREMENT})
|
|
||||||
endforeach()
|
|
||||||
unset(BUNDLED_QT_REQUIREMENTS)
|
|
||||||
|
|
||||||
if (NOT "${UNRESOLVED_QT_DEPS}" STREQUAL "")
|
|
||||||
message(FATAL_ERROR "Bundled Qt package missing required dependencies: ${UNRESOLVED_QT_DEPS}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CITRON_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE)
|
|
||||||
endif()
|
|
||||||
if (CITRON_USE_BUNDLED_QT)
|
|
||||||
# Binary package currently does not support Qt webengine, so make sure it's disabled
|
|
||||||
set(CITRON_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CITRON_QT_NO_CMAKE_SYSTEM_PATH)
|
|
||||||
|
|
||||||
if(CITRON_USE_BUNDLED_QT)
|
|
||||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
|
||||||
set(QT_BUILD qt-5.15.2-msvc2019_64)
|
|
||||||
elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64)
|
|
||||||
set(QT_BUILD qt5_5_15_2)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRON_USE_BUNDLED_QT and provide your own.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (DEFINED QT_BUILD)
|
|
||||||
download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
|
|
||||||
|
|
||||||
set(CITRON_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
|
|
||||||
# Binary package for Qt5 has Qt Multimedia
|
|
||||||
set(CITRON_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_citron_qt_components()
|
|
||||||
find_package(Qt5 ${QT5_VERSION} COMPONENTS ${CITRON_QT_COMPONENTS} ${QT_PREFIX_HINT} ${CITRON_QT_NO_CMAKE_SYSTEM_PATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the citron_find_package
|
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the citron_find_package
|
||||||
if (ENABLE_SDL2)
|
if (ENABLE_SDL2)
|
||||||
if (CITRON_USE_BUNDLED_SDL2)
|
if (CITRON_USE_BUNDLED_SDL2)
|
||||||
# Detect toolchain and platform
|
# Detect toolchain and platform
|
||||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
if ((MSVC_VERSION GREATER_EQUAL 1920) AND ARCHITECTURE_x86_64)
|
||||||
set(SDL2_VER "SDL2-2.28.2")
|
set(SDL2_VER "SDL2-2.28.2")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRON_USE_BUNDLED_SDL2 and provide your own.")
|
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRON_USE_BUNDLED_SDL2 and provide your own.")
|
||||||
|
@ -554,22 +471,90 @@ if (ENABLE_SDL2)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# List of all FFmpeg components required
|
add_subdirectory(externals)
|
||||||
set(FFmpeg_COMPONENTS
|
|
||||||
|
if (USE_DISCORD_PRESENCE)
|
||||||
|
target_compile_options(discord-rpc PRIVATE -fpermissive)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_QT)
|
||||||
|
if (NOT USE_SYSTEM_QT)
|
||||||
|
download_qt(6.8.2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent Network)
|
||||||
|
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS DBus)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_QT_TRANSLATION)
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT DEFINED QT_TARGET_PATH)
|
||||||
|
get_target_property(qtcore_path Qt6::Core LOCATION_Release)
|
||||||
|
string(FIND "${qtcore_path}" "/bin/" qtcore_path_bin_pos REVERSE)
|
||||||
|
string(FIND "${qtcore_path}" "/lib/" qtcore_path_lib_pos REVERSE)
|
||||||
|
if (qtcore_path_bin_pos GREATER qtcore_path_lib_pos)
|
||||||
|
string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_bin_pos} QT_TARGET_PATH)
|
||||||
|
else()
|
||||||
|
string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_lib_pos} QT_TARGET_PATH)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT DEFINED QT_HOST_PATH)
|
||||||
|
set(QT_HOST_PATH "${QT_TARGET_PATH}")
|
||||||
|
endif()
|
||||||
|
message(STATUS "Using target Qt at ${QT_TARGET_PATH}")
|
||||||
|
message(STATUS "Using host Qt at ${QT_HOST_PATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(set_citron_qt_components)
|
||||||
|
# Best practice is to ask for all components at once, so they are from the same version
|
||||||
|
set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent)
|
||||||
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
list(APPEND CITRON_QT_COMPONENTS2 DBus)
|
||||||
|
endif()
|
||||||
|
if (CITRON_USE_QT_MULTIMEDIA)
|
||||||
|
list(APPEND CITRON_QT_COMPONENTS2 Multimedia)
|
||||||
|
endif()
|
||||||
|
if (CITRON_USE_QT_WEB_ENGINE)
|
||||||
|
list(APPEND CITRON_QT_COMPONENTS2 WebEngineCore WebEngineWidgets)
|
||||||
|
endif()
|
||||||
|
if (ENABLE_QT_TRANSLATION)
|
||||||
|
list(APPEND CITRON_QT_COMPONENTS2 LinguistTools)
|
||||||
|
endif()
|
||||||
|
if (USE_DISCORD_PRESENCE)
|
||||||
|
list(APPEND CITRON_QT_COMPONENTS2 Network)
|
||||||
|
endif()
|
||||||
|
set(CITRON_QT_COMPONENTS ${CITRON_QT_COMPONENTS2} PARENT_SCOPE)
|
||||||
|
endfunction(set_citron_qt_components)
|
||||||
|
|
||||||
|
# List of all FFmpeg components required
|
||||||
|
set(FFmpeg_COMPONENTS
|
||||||
avcodec
|
avcodec
|
||||||
avfilter
|
avfilter
|
||||||
avutil
|
avutil
|
||||||
swscale)
|
swscale)
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT ANDROID)
|
if (UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(LIBVA libva)
|
pkg_check_modules(LIBVA libva)
|
||||||
endif()
|
endif()
|
||||||
if (NOT CITRON_USE_BUNDLED_FFMPEG)
|
if (NOT CITRON_USE_BUNDLED_FFMPEG)
|
||||||
# Use system installed FFmpeg
|
# Use system installed FFmpeg
|
||||||
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
find_package(FFmpeg REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_QT)
|
||||||
|
set_citron_qt_components()
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS ${CITRON_QT_COMPONENTS})
|
||||||
|
set(QT_MAJOR_VERSION 6)
|
||||||
|
# Qt6 sets cxx_std_17 and we need to undo that
|
||||||
|
set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32 AND CITRON_CRASH_DUMPS)
|
if (WIN32 AND CITRON_CRASH_DUMPS)
|
||||||
set(BREAKPAD_VER "breakpad-c89f9dd")
|
set(BREAKPAD_VER "breakpad-c89f9dd")
|
||||||
download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX)
|
download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX)
|
||||||
|
@ -700,7 +685,25 @@ if (CITRON_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(externals)
|
# Set runtime library to MD/MDd for all configurations
|
||||||
|
if(MSVC)
|
||||||
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||||
|
|
||||||
|
# Force all projects (including external dependencies) to use the same runtime
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd")
|
||||||
|
|
||||||
|
# Add this to ensure Cubeb uses the same runtime
|
||||||
|
add_compile_options(
|
||||||
|
$<$<CONFIG:Debug>:/MDd>
|
||||||
|
$<$<CONFIG:Release>:/MD>
|
||||||
|
$<$<CONFIG:RelWithDebInfo>:/MD>
|
||||||
|
$<$<CONFIG:MinSizeRel>:/MD>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
# Set citron project or citron-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
|
# Set citron project or citron-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
function(copy_citron_FFmpeg_deps target_dir)
|
function(copy_citron_FFmpeg_deps target_dir)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2016 Citra Emulator Project & 2025 Citron Homebrew Project
|
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
function(copy_citron_Qt5_deps target_dir)
|
function(copy_citron_Qt5_deps target_dir)
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project
|
||||||
|
|
||||||
|
function(copy_citron_Qt6_deps target_dir)
|
||||||
|
include(WindowsCopyFiles)
|
||||||
|
if (MSVC)
|
||||||
|
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
|
||||||
|
set(Qt6_DLL_DIR "${Qt6_DIR}/../../../bin")
|
||||||
|
else()
|
||||||
|
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/")
|
||||||
|
set(Qt6_DLL_DIR "${Qt6_DIR}/../../../lib/")
|
||||||
|
endif()
|
||||||
|
set(Qt6_PLATFORMS_DIR "${Qt6_DIR}/../../../plugins/platforms/")
|
||||||
|
set(Qt6_STYLES_DIR "${Qt6_DIR}/../../../plugins/styles/")
|
||||||
|
set(Qt6_IMAGEFORMATS_DIR "${Qt6_DIR}/../../../plugins/imageformats/")
|
||||||
|
set(Qt6_RESOURCES_DIR "${Qt6_DIR}/../../../resources/")
|
||||||
|
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
|
||||||
|
set(STYLES ${DLL_DEST}plugins/styles/)
|
||||||
|
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
|
||||||
|
Qt6Core$<$<CONFIG:Debug>:d>.*
|
||||||
|
Qt6Gui$<$<CONFIG:Debug>:d>.*
|
||||||
|
Qt6Widgets$<$<CONFIG:Debug>:d>.*
|
||||||
|
Qt6Network$<$<CONFIG:Debug>:d>.*
|
||||||
|
)
|
||||||
|
if (CITRON_USE_QT_MULTIMEDIA)
|
||||||
|
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
|
||||||
|
Qt6Multimedia$<$<CONFIG:Debug>:d>.*
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if (CITRON_USE_QT_WEB_ENGINE)
|
||||||
|
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
|
||||||
|
Qt6WebEngineCore$<$<CONFIG:Debug>:d>.*
|
||||||
|
Qt6WebEngineWidgets$<$<CONFIG:Debug>:d>.*
|
||||||
|
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
|
||||||
|
)
|
||||||
|
windows_copy_files(${target_dir} ${Qt6_RESOURCES_DIR} ${DLL_DEST}
|
||||||
|
icudtl.dat
|
||||||
|
qtwebengine_devtools_resources.pak
|
||||||
|
qtwebengine_resources.pak
|
||||||
|
qtwebengine_resources_100p.pak
|
||||||
|
qtwebengine_resources_200p.pak
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
windows_copy_files(citron ${Qt6_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
|
||||||
|
windows_copy_files(citron ${Qt6_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
|
||||||
|
windows_copy_files(citron ${Qt6_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
|
||||||
|
qjpeg$<$<CONFIG:Debug>:d>.*
|
||||||
|
qgif$<$<CONFIG:Debug>:d>.*
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# Update for non-MSVC platforms if needed
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create an empty qt.conf file
|
||||||
|
add_custom_command(TARGET citron POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
|
||||||
|
)
|
||||||
|
endfunction(copy_citron_Qt6_deps)
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2016 Citra Emulator Project & 2025 Citron Homebrew Project
|
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
function(copy_citron_SDL_deps target_dir)
|
function(copy_citron_SDL_deps target_dir)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
# SPDX-FileCopyrightText: 2017 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# This function downloads a binary library package from our external repo.
|
# This function downloads a binary library package from our external repo.
|
||||||
# Params:
|
# Params:
|
||||||
# remote_path: path to the file to download, relative to the remote repository root
|
# remote_path: path to the file to download, relative to the remote repository root
|
||||||
# prefix_var: name of a variable which will be set with the path to the extracted contents
|
# prefix_var: name of a variable which will be set with the path to the extracted contents
|
||||||
|
set(CURRENT_MODULE_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||||
function(download_bundled_external remote_path lib_name prefix_var)
|
function(download_bundled_external remote_path lib_name prefix_var)
|
||||||
|
|
||||||
set(package_base_url "https://github.com/yuzu-mirror/")
|
set(package_base_url "https://github.com/yuzu-mirror/")
|
||||||
|
@ -16,7 +17,7 @@ if (WIN32)
|
||||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(package_repo "ext-linux-bin/raw/main/")
|
set(package_repo "ext-linux-bin/raw/main/")
|
||||||
set(package_extension ".tar.xz")
|
set(package_extension ".tar.xz")
|
||||||
elseif (ANDROID)
|
elseif (ANDROID)
|
||||||
set(package_repo "ext-android-bin/raw/main/")
|
set(package_repo "ext-android-bin/raw/main/")
|
||||||
set(package_extension ".tar.xz")
|
set(package_extension ".tar.xz")
|
||||||
else()
|
else()
|
||||||
|
@ -54,3 +55,172 @@ function(download_moltenvk_external platform version)
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}")
|
list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}")
|
||||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
|
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# Determine installation parameters for OS, architecture, and compiler
|
||||||
|
function(determine_qt_parameters target host_out type_out arch_out arch_path_out host_type_out host_arch_out host_arch_path_out)
|
||||||
|
if (WIN32)
|
||||||
|
set(host "windows")
|
||||||
|
set(type "desktop")
|
||||||
|
|
||||||
|
if (NOT tool)
|
||||||
|
if (MINGW)
|
||||||
|
set(arch "win64_mingw")
|
||||||
|
set(arch_path "mingw_64")
|
||||||
|
elseif (MSVC)
|
||||||
|
if ("arm64" IN_LIST ARCHITECTURE)
|
||||||
|
set(arch_path "msvc2022_arm64")
|
||||||
|
elseif ("x86_64" IN_LIST ARCHITECTURE)
|
||||||
|
set(arch_path "msvc2022_64")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.")
|
||||||
|
endif()
|
||||||
|
set(arch "win64_${arch_path}")
|
||||||
|
|
||||||
|
if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
|
||||||
|
set(host_arch_path "msvc2022_64")
|
||||||
|
elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||||
|
set(host_arch_path "msvc2022_64")
|
||||||
|
endif()
|
||||||
|
set(host_arch "win64_${host_arch_path}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unsupported bundled Qt toolchain. Enable USE_SYSTEM_QT and provide your own.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
elseif (APPLE)
|
||||||
|
set(host "mac")
|
||||||
|
set(type "desktop")
|
||||||
|
set(arch "clang_64")
|
||||||
|
set(arch_path "macos")
|
||||||
|
else()
|
||||||
|
set(host "linux")
|
||||||
|
set(type "desktop")
|
||||||
|
set(arch "gcc_64")
|
||||||
|
set(arch_path "linux")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${host_out} "${host}" PARENT_SCOPE)
|
||||||
|
set(${type_out} "${type}" PARENT_SCOPE)
|
||||||
|
set(${arch_out} "${arch}" PARENT_SCOPE)
|
||||||
|
set(${arch_path_out} "${arch_path}" PARENT_SCOPE)
|
||||||
|
if (DEFINED host_type)
|
||||||
|
set(${host_type_out} "${host_type}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${host_type_out} "${type}" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
if (DEFINED host_arch)
|
||||||
|
set(${host_arch_out} "${host_arch}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${host_arch_out} "${arch}" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
if (DEFINED host_arch_path)
|
||||||
|
set(${host_arch_path_out} "${host_arch_path}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${host_arch_path_out} "${arch_path}" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Download Qt binaries for a specific configuration.
|
||||||
|
function(download_qt_configuration prefix_out target host type arch arch_path base_path)
|
||||||
|
if (target MATCHES "tools_.*")
|
||||||
|
set(tool ON)
|
||||||
|
else()
|
||||||
|
set(tool OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini")
|
||||||
|
if (tool)
|
||||||
|
set(prefix "${base_path}/Tools")
|
||||||
|
set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target})
|
||||||
|
else()
|
||||||
|
set(prefix "${base_path}/${target}/${arch_path}")
|
||||||
|
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch}
|
||||||
|
-m all)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT EXISTS "${prefix}")
|
||||||
|
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
|
||||||
|
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.2.0")
|
||||||
|
if (WIN32)
|
||||||
|
set(aqt_path "${base_path}/aqt.exe")
|
||||||
|
if (NOT EXISTS "${aqt_path}")
|
||||||
|
file(DOWNLOAD
|
||||||
|
${AQT_PREBUILD_BASE_URL}/aqt.exe
|
||||||
|
${aqt_path} SHOW_PROGRESS)
|
||||||
|
endif()
|
||||||
|
execute_process(COMMAND ${aqt_path} ${install_args}
|
||||||
|
WORKING_DIRECTORY ${base_path})
|
||||||
|
elseif (APPLE)
|
||||||
|
set(aqt_path "${base_path}/aqt-macos")
|
||||||
|
if (NOT EXISTS "${aqt_path}")
|
||||||
|
file(DOWNLOAD
|
||||||
|
${AQT_PREBUILD_BASE_URL}/aqt-macos
|
||||||
|
${aqt_path} SHOW_PROGRESS)
|
||||||
|
endif()
|
||||||
|
execute_process(COMMAND chmod +x ${aqt_path})
|
||||||
|
execute_process(COMMAND ${aqt_path} ${install_args}
|
||||||
|
WORKING_DIRECTORY ${base_path})
|
||||||
|
else()
|
||||||
|
set(aqt_install_path "${base_path}/aqt")
|
||||||
|
file(MAKE_DIRECTORY "${aqt_install_path}")
|
||||||
|
|
||||||
|
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall
|
||||||
|
WORKING_DIRECTORY ${base_path})
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args}
|
||||||
|
WORKING_DIRECTORY ${base_path})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${prefix_out} "${prefix}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# This function downloads Qt using aqt.
|
||||||
|
# The path of the downloaded content will be added to the CMAKE_PREFIX_PATH.
|
||||||
|
# QT_TARGET_PATH is set to the Qt for the compile target platform.
|
||||||
|
# QT_HOST_PATH is set to a host-compatible Qt, for running tools.
|
||||||
|
# Params:
|
||||||
|
# target: Qt dependency to install. Specify a version number to download Qt, or "tools_(name)" for a specific build tool.
|
||||||
|
function(download_qt target)
|
||||||
|
determine_qt_parameters("${target}" host type arch arch_path host_type host_arch host_arch_path)
|
||||||
|
|
||||||
|
get_external_prefix(qt base_path)
|
||||||
|
file(MAKE_DIRECTORY "${base_path}")
|
||||||
|
|
||||||
|
download_qt_configuration(prefix "${target}" "${host}" "${type}" "${arch}" "${arch_path}" "${base_path}")
|
||||||
|
if (DEFINED host_arch_path AND NOT "${host_arch_path}" STREQUAL "${arch_path}")
|
||||||
|
download_qt_configuration(host_prefix "${target}" "${host}" "${host_type}" "${host_arch}" "${host_arch_path}" "${base_path}")
|
||||||
|
else()
|
||||||
|
set(host_prefix "${prefix}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(QT_TARGET_PATH "${prefix}" CACHE STRING "")
|
||||||
|
set(QT_HOST_PATH "${host_prefix}" CACHE STRING "")
|
||||||
|
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "${prefix}")
|
||||||
|
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(download_moltenvk)
|
||||||
|
set(MOLTENVK_PLATFORM "macOS")
|
||||||
|
|
||||||
|
set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK")
|
||||||
|
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
|
||||||
|
if (NOT EXISTS ${MOLTENVK_DIR})
|
||||||
|
if (NOT EXISTS ${MOLTENVK_TAR})
|
||||||
|
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.10-rc2/MoltenVK-all.tar
|
||||||
|
${MOLTENVK_TAR} SHOW_PROGRESS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add the MoltenVK library path to the prefix so find_library can locate it.
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${MOLTENVK_PLATFORM}")
|
||||||
|
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(get_external_prefix lib_name prefix_var)
|
||||||
|
set(${prefix_var} "${CMAKE_BINARY_DIR}/externals/${lib_name}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2019 Citra Emulator Project & 2025 Citron Homebrew Project
|
# SPDX-FileCopyrightText: 2019 Citra Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# FindFFmpeg
|
# FindFFmpeg
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# Gets a UTC timestamp and sets the provided variable to it
|
# Gets a UTC timestamp and sets the provided variable to it
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# buildcache wrapper
|
# buildcache wrapper
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
|
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# This file provides the function windows_copy_files.
|
# This file provides the function windows_copy_files.
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project
|
||||||
|
|
||||||
|
[aqt]
|
||||||
|
concurrency: 2
|
||||||
|
|
||||||
|
[mirrors]
|
||||||
|
trusted_mirrors:
|
||||||
|
https://download.qt.io
|
||||||
|
blacklist:
|
||||||
|
https://qt.mirror.constant.com
|
||||||
|
https://mirrors.ocf.berkeley.edu
|
||||||
|
https://mirrors.ustc.edu.cn
|
||||||
|
https://mirrors.tuna.tsinghua.edu.cn
|
||||||
|
https://mirrors.geekpie.club
|
||||||
|
https://mirrors-wan.geekpie.club
|
||||||
|
https://mirrors.sjtug.sjtu.edu.cn
|
||||||
|
fallbacks:
|
||||||
|
https://qtproject.mirror.liquidtelecom.com/
|
||||||
|
https://mirrors.aliyun.com/qt/
|
||||||
|
https://ftp.jaist.ac.jp/pub/qtproject/
|
||||||
|
https://ftp.yz.yamagata-u.ac.jp/pub/qtproject/
|
||||||
|
https://qt-mirror.dannhauer.de/
|
||||||
|
https://ftp.fau.de/qtproject/
|
||||||
|
https://mirror.netcologne.de/qtproject/
|
||||||
|
https://mirrors.dotsrc.org/qtproject/
|
||||||
|
https://www.nic.funet.fi/pub/mirrors/download.qt-project.org/
|
||||||
|
https://master.qt.io/
|
||||||
|
https://mirrors.ukfast.co.uk/sites/qt.io/
|
||||||
|
https://ftp2.nluug.nl/languages/qt/
|
||||||
|
https://ftp1.nluug.nl/languages/qt/
|
|
@ -14,13 +14,14 @@ Welcome to **Citron**, a cutting-edge Nintendo Homebrew emulator designed to del
|
||||||
|
|
||||||
## Download 🚀
|
## Download 🚀
|
||||||
|
|
||||||
Ready to experience Citron? [Download the latest version](https://git.citron-emu.org/Citron/Citron/releases) and dive into your favorite Nintendo homebrew titles!
|
Ready to experience Citron? [Download the latest version](https://git.citron-emu.org/citron/emu/-/releases) and dive into your favorite Nintendo homebrew titles!
|
||||||
|
|
||||||
## Getting Started 💡
|
## Getting Started 💡
|
||||||
|
|
||||||
1. **Download and Install**: Head over to the [downloads page](https://git.citron-emu.org/Citron/Citron/releases) to grab the latest release.
|
1. **Check the System Requirements**: Head over to this link to check the requirements to run this emulator [system requirements page](https://evilperson1337.notion.site/Hardware-Requirements-1d957c2edaf680418e2bf2c7239170ce)
|
||||||
2. **Add Homebrew Games**: Citron is built to play homebrew games. Add them to your game directory and enjoy!
|
2. **Download and Install**: Head over to the [downloads page](https://git.citron-emu.org/citron/emu/-/releases) to grab the latest release.
|
||||||
3. **Configure Your Settings**: Customize your emulator settings to suit your performance needs.
|
3. **Add Homebrew Games**: Citron is built to play homebrew games. Add them to your game directory and enjoy!
|
||||||
|
4. **Configure Your Settings**: Customize your emulator settings to suit your performance needs.
|
||||||
|
|
||||||
## Source Code 🔧
|
## Source Code 🔧
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# reg_server, 2024-01-09
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# check arguments
|
||||||
|
if [[ $# != 2 ]]; then
|
||||||
|
>&2 echo "Invalid arguments!"
|
||||||
|
echo "Usage: $0 torzu|citron <build dir>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_APP="$1"
|
||||||
|
if [[ "${BUILD_APP}" != "torzu" && "${BUILD_APP}" != "citron" ]]; then
|
||||||
|
>&2 echo "Invalid arguments!"
|
||||||
|
echo "Usage: $0 torzu|citron <build dir>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_DIR=$(realpath "$2")
|
||||||
|
if [[ ! -d "${BUILD_DIR}" ]]; then
|
||||||
|
>&2 echo "Invalid arguments!"
|
||||||
|
echo "'$2' is not a directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEPLOY_LINUX_FOLDER="${BUILD_DIR}/deploy-linux"
|
||||||
|
DEPLOY_LINUX_APPDIR_FOLDER="${BUILD_DIR}/deploy-linux/AppDir"
|
||||||
|
BIN_FOLDER="${BUILD_DIR}/bin"
|
||||||
|
BIN_EXE="${BIN_FOLDER}/${BUILD_APP//torzu/yuzu}"
|
||||||
|
|
||||||
|
CPU_ARCH=$(uname -m)
|
||||||
|
|
||||||
|
#export DISPLAYVERSION="1.2.3" # before cmake
|
||||||
|
|
||||||
|
BIN_EXE_MIME_TYPE=$(file -b --mime-type "${BIN_EXE}")
|
||||||
|
if [[ "${BIN_EXE_MIME_TYPE}" != "application/x-pie-executable" && "${BIN_EXE_MIME_TYPE}" != "application/x-executable" ]]; then
|
||||||
|
>&2 echo "Invalid or missing main executable (${BIN_EXE})!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${DEPLOY_LINUX_FOLDER}"
|
||||||
|
rm -rf "${DEPLOY_LINUX_APPDIR_FOLDER}"
|
||||||
|
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
|
||||||
|
# deploy/install to deploy-linux/AppDir
|
||||||
|
DESTDIR="${DEPLOY_LINUX_APPDIR_FOLDER}" ninja install
|
||||||
|
|
||||||
|
cd "${DEPLOY_LINUX_FOLDER}"
|
||||||
|
|
||||||
|
# remove -cmd executable, not needed for AppImage
|
||||||
|
rm -fv "${DEPLOY_LINUX_APPDIR_FOLDER}"/usr/bin/"${BUILD_APP//torzu/yuzu}"-cmd
|
||||||
|
|
||||||
|
curl -fsSLo ./linuxdeploy "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${CPU_ARCH}.AppImage"
|
||||||
|
chmod +x ./linuxdeploy
|
||||||
|
|
||||||
|
curl -fsSLo ./linuxdeploy-plugin-qt "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-${CPU_ARCH}.AppImage"
|
||||||
|
chmod +x ./linuxdeploy-plugin-qt
|
||||||
|
|
||||||
|
curl -fsSLo ./linuxdeploy-plugin-checkrt.sh https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh
|
||||||
|
chmod +x ./linuxdeploy-plugin-checkrt.sh
|
||||||
|
|
||||||
|
# Add Qt 6 specific environment variables
|
||||||
|
export QT_QPA_PLATFORM="wayland;xcb"
|
||||||
|
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so;libqxcb.so"
|
||||||
|
export EXTRA_QT_PLUGINS="svg;wayland-decoration-client;wayland-graphics-integration-client;wayland-shell-integration;waylandcompositor;xcb-gl-integration;platformthemes/libqt6ct.so"
|
||||||
|
|
||||||
|
# Update linuxdeploy commands for Qt 6
|
||||||
|
export QMAKE="/usr/bin/qmake6"
|
||||||
|
export QT_SELECT=6
|
||||||
|
|
||||||
|
# remove NO_STRIP=1 if linuxdeploy is updated, see: https://github.com/linuxdeploy/linuxdeploy/issues/272
|
||||||
|
NO_STRIP=1 APPIMAGE_EXTRACT_AND_RUN=1 ./linuxdeploy --appdir ./AppDir --plugin qt --plugin checkrt
|
||||||
|
|
||||||
|
# remove libwayland-client because it has platform-dependent exports and breaks other OSes
|
||||||
|
rm -fv ./AppDir/usr/lib/libwayland-client.so*
|
||||||
|
|
||||||
|
# remove libvulkan because it causes issues with gamescope
|
||||||
|
rm -fv ./AppDir/usr/lib/libvulkan.so*
|
||||||
|
|
||||||
|
rm -rf ./linuxdeploy-squashfs-root
|
||||||
|
./linuxdeploy --appimage-extract
|
||||||
|
mv -v ./squashfs-root/ ./linuxdeploy-squashfs-root/
|
||||||
|
|
||||||
|
./linuxdeploy-squashfs-root/plugins/linuxdeploy-plugin-appimage/usr/bin/appimagetool ./AppDir -g
|
||||||
|
|
||||||
|
#APPIMAGE_SUFFIX="linux_${CPU_ARCH}"
|
||||||
|
APPIMAGE_SUFFIX="${CPU_ARCH}"
|
||||||
|
#COMM_TAG="${DISPLAYVERSION}"
|
||||||
|
COMM_COUNT="$(git rev-list --count HEAD)"
|
||||||
|
COMM_HASH="$(git rev-parse --short=9 HEAD)"
|
||||||
|
BUILD_DATE=$(date +"%Y%m%d")
|
||||||
|
#APPIMAGE_NAME="${BUILD_APP}-v${COMM_TAG}-${BUILD_DATE}-${COMM_COUNT}-${COMM_HASH}-${APPIMAGE_SUFFIX}.AppImage"
|
||||||
|
APPIMAGE_NAME="${BUILD_APP}-nightly-${BUILD_DATE}-${COMM_COUNT}-${COMM_HASH}-${APPIMAGE_SUFFIX}.AppImage"
|
||||||
|
|
||||||
|
LATEST_APPIMAGE=$(ls -1t ${BUILD_APP}*.AppImage | head -n 1) # find the most recent AppImage
|
||||||
|
if [[ -z "${LATEST_APPIMAGE}" ]]; then
|
||||||
|
>&2 echo "Error: No AppImage found for ${BUILD_APP}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv -v "${LATEST_APPIMAGE}" "${APPIMAGE_NAME}"
|
||||||
|
|
||||||
|
FILESIZE=$(stat -c %s "./${APPIMAGE_NAME}")
|
||||||
|
SHA256SUM=$(sha256sum "./${APPIMAGE_NAME}" | awk '{ print $1 }')
|
||||||
|
|
||||||
|
echo "${APPIMAGE_NAME}"
|
||||||
|
echo "${SHA256SUM};${FILESIZE}B"
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project & 2025 citron Homebrew Project
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# Allow systemd-logind to manage user access to hidraw with this file
|
# Allow systemd-logind to manage user access to hidraw with this file
|
||||||
|
@ -7,13 +8,13 @@
|
||||||
|
|
||||||
# Switch Pro Controller (USB/Bluetooth)
|
# Switch Pro Controller (USB/Bluetooth)
|
||||||
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", MODE="0660", TAG+="uaccess"
|
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", MODE="0660", TAG+="uaccess"
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2009*", MODE="0660", TAG+="uaccess"
|
KERNEL=="hidraw*", KERNELS=="*057E:2009*", MODE="0660", TAG+="uaccess"
|
||||||
|
|
||||||
# Joy-Con L (Bluetooth)
|
# Joy-Con L (Bluetooth)
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2006*", MODE="0660", TAG+="uaccess"
|
KERNEL=="hidraw*", KERNELS=="*057E:2006*", MODE="0660", TAG+="uaccess"
|
||||||
|
|
||||||
# Joy-Con R (Bluetooth)
|
# Joy-Con R (Bluetooth)
|
||||||
KERNEL=="hidraw*", KERNELS=="*057e:2007*", MODE="0660", TAG+="uaccess"
|
KERNEL=="hidraw*", KERNELS=="*057E:2007*", MODE="0660", TAG+="uaccess"
|
||||||
|
|
||||||
# Joy-Con Charging Grip (USB)
|
# Joy-Con Charging Grip (USB)
|
||||||
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="200e", MODE="0660", TAG+="uaccess"
|
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="200e", MODE="0660", TAG+="uaccess"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2020 yuzu Emulator Project & 2025 citron Homebrew Project
|
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project
|
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2020 yuzu Emulator Project & 2025 citron Homebrew Project
|
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2021 yuzu Emulator Project & 2025 citron Homebrew Project
|
SPDX-FileCopyrightText: 2021 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">موقعنا</span></a>|<a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">رماز المصدر</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">المساهمون</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">الرخصة</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">موقعنا</span></a>|<a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">رماز المصدر</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">المساهمون</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">الرخصة</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -409,7 +409,7 @@ This would ban both their forum username and their IP address.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6074,7 +6074,7 @@ Please, only use this feature to install updates and DLC.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation>Mii تحرير التطبيق الصغير</translation>
|
<translation>Mii تحرير التطبيق الصغير</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Pàgina web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Codi Font</span></a>|<a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuïdors</span></a>|<a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Llicència</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Pàgina web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Codi Font</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuïdors</span></a>|<a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Llicència</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -407,7 +407,7 @@ This would ban both their forum username and their IP address.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6111,7 +6111,7 @@ Si us plau, utilitzi aquesta funció només per a instal·lar actualitzacions i
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webové stránky</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Zdrojový kód</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Přispěvatelé</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webové stránky</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Zdrojový kód</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Přispěvatelé</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licence</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -407,7 +407,7 @@ This would ban both their forum username and their IP address.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6095,7 +6095,7 @@ Tuto funkci prosím používejte pouze k instalaci aktualizací a DLC.</translat
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/">Netsted<span style=" text-decoration: underline; color:#039be5;"></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsydere</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/">Netsted<span style=" text-decoration: underline; color:#039be5;"></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Kildekode</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Bidragsydere</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licens</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -409,7 +409,7 @@ Dette vil bandlyse både vedkommendes forum-brugernavn og IP-adresse.</translati
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6101,7 +6101,7 @@ Please, only use this feature to install updates and DLC.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webseite</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Quellcode</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Mitwirkende</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lizenz</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Webseite</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Quellcode</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Mitwirkende</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Lizenz</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -408,7 +408,7 @@ Dies würde deren Forum-Benutzernamen und deren IP-Adresse sperren.</translation
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6121,7 +6121,7 @@ Bitte nutze diese Funktion nur zum Installieren von Updates und DLC.</translatio
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation>Mii-Edit-Applet</translation>
|
<translation>Mii-Edit-Applet</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Ιστοσελίδα</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Πηγαίος Κώδικας</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Συνεργάτες</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"></span>Άδεια</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Ιστοσελίδα</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Πηγαίος Κώδικας</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Συνεργάτες</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"></span>Άδεια</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -409,7 +409,7 @@ This would ban both their forum username and their IP address.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6097,7 +6097,7 @@ Please, only use this feature to install updates and DLC.</source>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation type="unfinished"/>
|
<translation type="unfinished"/>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -35,8 +35,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="130"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Página web</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Código fuente</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencia</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Página web</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Código fuente</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contribuidores</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">Licencia</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="146"/>
|
||||||
|
@ -409,7 +409,7 @@ Esto banearía su nombre del foro y su dirección IP.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
<location filename="../../src/citron/configuration/shared_translation.cpp" line="37"/>
|
||||||
<source>Mii Edit</source>
|
<source>Mii Editor</source>
|
||||||
<translation>Editor de Mii</translation>
|
<translation>Editor de Mii</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -6167,7 +6167,7 @@ Por favor, utiliza esta función sólo para instalar actualizaciones y DLCs.</tr
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/main.cpp" line="4451"/>
|
<location filename="../../src/citron/main.cpp" line="4451"/>
|
||||||
<source>Mii Edit Applet</source>
|
<source>Mii Editor Applet</source>
|
||||||
<translation>Applet de Editor de Mii</translation>
|
<translation>Applet de Editor de Mii</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -40,8 +40,8 @@ p, li { white-space: pre-wrap; }
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="118"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="118"/>
|
||||||
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
<source><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></source>
|
||||||
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettisivu</span></a> | <a href="https://github.com/citron-emu"><span style=" text-decoration: underline; color:#039be5;">Lähdekoodi</span></a> | <a href="https://github.com/citron-emu/citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Lahjoittajat</span></a> | <a href="https://github.com/citron-emu/citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisenssi</span></a></p></body></html></translation>
|
<translation><html><head/><body><p><a href="https://citron-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Nettisivu</span></a> | <a href="https://git.citron-emu.org"><span style=" text-decoration: underline; color:#039be5;">Lähdekoodi</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Lahjoittajat</span></a> | <a href="https://git.citron-emu.org/Citron/Citron/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">Lisenssi</span></a></p></body></html></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/citron/aboutdialog.ui" line="134"/>
|
<location filename="../../src/citron/aboutdialog.ui" line="134"/>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue