diff --git a/.ci/android.sh b/.ci/android.sh index 6c22922061..3cfa902fed 100755 --- a/.ci/android.sh +++ b/.ci/android.sh @@ -15,7 +15,7 @@ chmod +x ./gradlew ./gradlew assemble${BUILD_FLAVOR}Release ./gradlew bundle${BUILD_FLAVOR}Release -ccache -s +ccache -s -v if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then rm "${ANDROID_KEYSTORE_FILE}" diff --git a/.ci/ios.sh b/.ci/ios.sh index d6b4195f1a..92e1776c87 100755 --- a/.ci/ios.sh +++ b/.ci/ios.sh @@ -12,4 +12,4 @@ cmake .. -GNinja \ -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON ninja -ccache -s +ccache -s -v diff --git a/.ci/linux.sh b/.ci/linux.sh index dff7f55317..3870d08bea 100755 --- a/.ci/linux.sh +++ b/.ci/linux.sh @@ -13,8 +13,10 @@ ninja if [ "$TARGET" = "appimage" ]; then ninja bundle + # TODO: Our AppImage environment currently uses an older ccache version without the verbose flag. + ccache -s +else + ccache -s -v fi -ccache -s - ctest -VV -C Release diff --git a/.ci/macos.sh b/.ci/macos.sh index 5933b6f89a..c4e2a284b1 100755 --- a/.ci/macos.sh +++ b/.ci/macos.sh @@ -13,7 +13,7 @@ cmake .. -GNinja \ ninja ninja bundle -ccache -s +ccache -s -v CURRENT_ARCH=`arch` if [ "$TARGET" = "$CURRENT_ARCH" ]; then diff --git a/.ci/pack.sh b/.ci/pack.sh index 2aedbd4df1..dda6be33be 100755 --- a/.ci/pack.sh +++ b/.ci/pack.sh @@ -1,41 +1,72 @@ #!/bin/bash -ex +# Determine the full revision name. GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`" GITREV="`git show -s --format='%h'`" -REV_NAME="citra-${OS}-${TARGET}-${GITDATE}-${GITREV}" +REV_NAME="citra-$OS-$TARGET-$GITDATE-$GITREV" -# Find out what release we are building +# Determine the name of the release being built. if [[ "$GITHUB_REF_NAME" =~ ^canary- ]] || [[ "$GITHUB_REF_NAME" =~ ^nightly- ]]; then RELEASE_NAME=$(echo $GITHUB_REF_NAME | cut -d- -f1) else RELEASE_NAME=head fi -mkdir -p artifacts +# Archive and upload the artifacts. +mkdir artifacts -if [ -z "${UPLOAD_RAW}" ]; then - # Archive and upload the artifacts. +function pack_artifacts() { + ARTIFACTS_PATH="$1" + + # Set up root directory for archive. mkdir "$REV_NAME" - mv build/bundle/* "$REV_NAME" + if [ -f "$ARTIFACTS_PATH" ]; then + mv "$ARTIFACTS_PATH" "$REV_NAME" - if [ "$OS" = "windows" ]; then - ARCHIVE_NAME="${REV_NAME}.zip" - powershell Compress-Archive "$REV_NAME" "$ARCHIVE_NAME" - else - ARCHIVE_NAME="${REV_NAME}.tar.gz" - tar czvf "$ARCHIVE_NAME" "$REV_NAME" - fi - - mv "$REV_NAME" $RELEASE_NAME - 7z a "$REV_NAME.7z" $RELEASE_NAME - - mv "$ARCHIVE_NAME" artifacts/ - mv "$REV_NAME.7z" artifacts/ -else - # Directly upload the raw artifacts, renamed with the revision. - for ARTIFACT in build/bundle/*; do + # Use file extension to differentiate archives. FILENAME=$(basename "$ARTIFACT") EXTENSION="${FILENAME##*.}" - mv "$ARTIFACT" "artifacts/$REV_NAME.$EXTENSION" + ARCHIVE_NAME="$REV_NAME.$EXTENSION" + else + mv "$ARTIFACTS_PATH"/* "$REV_NAME" + + ARCHIVE_NAME="$REV_NAME" + fi + + # Create .zip/.tar.gz + if [ "$OS" = "windows" ]; then + ARCHIVE_FULL_NAME="$ARCHIVE_NAME.zip" + powershell Compress-Archive "$REV_NAME" "$ARCHIVE_FULL_NAME" + elif [ "$OS" = "android" ]; then + ARCHIVE_FULL_NAME="$ARCHIVE_NAME.zip" + zip -r "$ARCHIVE_FULL_NAME" "$REV_NAME" + else + ARCHIVE_FULL_NAME="$ARCHIVE_NAME.tar.gz" + tar czvf "$ARCHIVE_FULL_NAME" "$REV_NAME" + fi + mv "$ARCHIVE_FULL_NAME" artifacts/ + + if [ -z "$SKIP_7Z" ]; then + # Create .7z + ARCHIVE_FULL_NAME="$ARCHIVE_NAME.7z" + mv "$REV_NAME" "$RELEASE_NAME" + 7z a "$ARCHIVE_FULL_NAME" "$RELEASE_NAME" + mv "$ARCHIVE_FULL_NAME" artifacts/ + + # Clean up created release artifacts directory. + rm -rf "$RELEASE_NAME" + else + # Clean up created rev artifacts directory. + rm -rf "$REV_NAME" + fi +} + +if [ -z "$PACK_INDIVIDUALLY" ]; then + # Pack all of the artifacts at once. + pack_artifacts build/bundle +else + # Pack and upload the artifacts one-by-one. + for ARTIFACT in build/bundle/*; do + pack_artifacts "$ARTIFACT" done fi diff --git a/.ci/windows.sh b/.ci/windows.sh index 2dc94d5d3d..825f6ca4e7 100644 --- a/.ci/windows.sh +++ b/.ci/windows.sh @@ -12,6 +12,6 @@ cmake .. -G Ninja \ ninja ninja bundle -ccache -s +ccache -s -v ctest -VV -C Release || echo "::error ::Test error occurred on Windows build" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ea69b80195..8dd30f6c5b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,8 @@ jobs: options: -u 1001 env: CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPILERCHECK: content + CCACHE_SLOPPINESS: pch_defines,time_macros OS: linux TARGET: ${{ matrix.target }} steps: @@ -62,9 +64,9 @@ jobs: matrix: target: ["x86_64", "arm64"] env: - CCACHE_CPP2: yes - CCACHE_SLOPPINESS: time_macros CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPILERCHECK: content + CCACHE_SLOPPINESS: pch_defines,time_macros OS: macos TARGET: ${{ matrix.target }} steps: @@ -97,8 +99,6 @@ jobs: TARGET: universal steps: - uses: actions/checkout@v3 - with: - submodules: recursive - name: Download x86_64 build from cache uses: actions/cache/restore@v3 with: @@ -132,6 +132,8 @@ jobs: shell: ${{ (matrix.target == 'msys2' && 'msys2') || 'bash' }} {0} env: CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPILERCHECK: content + CCACHE_SLOPPINESS: pch_defines,time_macros OS: windows TARGET: ${{ matrix.target }} steps: @@ -184,6 +186,9 @@ jobs: android: runs-on: ubuntu-latest env: + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPILERCHECK: content + CCACHE_SLOPPINESS: pch_defines,time_macros OS: android TARGET: universal steps: @@ -196,7 +201,7 @@ jobs: path: | ~/.gradle/caches ~/.gradle/wrapper - ~/.ccache + ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-android-${{ github.sha }} restore-keys: | ${{ runner.os }}-android- @@ -221,7 +226,8 @@ jobs: run: ../../../.ci/pack.sh working-directory: src/android/app env: - UPLOAD_RAW: 1 + PACK_INDIVIDUALLY: 1 + SKIP_7Z: 1 - name: Upload uses: actions/upload-artifact@v3 with: @@ -231,9 +237,9 @@ jobs: runs-on: macos-latest if: ${{ !startsWith(github.ref, 'refs/tags/') }} env: - CCACHE_CPP2: yes - CCACHE_SLOPPINESS: time_macros CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_COMPILERCHECK: content + CCACHE_SLOPPINESS: pch_defines,time_macros OS: ios TARGET: arm64 steps: diff --git a/CMakeLists.txt b/CMakeLists.txt index bf1fdb1b88..0136af3118 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,11 @@ option(USE_SYSTEM_FMT "Use the system fmt (instead of the bundled one)" OFF) if (CITRA_USE_PRECOMPILED_HEADERS) message(STATUS "Using Precompiled Headers.") set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) + + # This ensures that pre-compiled headers won't invalidate build caches for every fresh checkout. + if(NOT MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list(APPEND CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH -Xclang -fno-pch-timestamp) + endif() endif() if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 53fb777eab..1f69d4fa70 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -97,6 +97,7 @@ if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) else() set(DYNARMIC_TESTS OFF CACHE BOOL "") set(DYNARMIC_FRONTENDS "A32" CACHE STRING "") + set(DYNARMIC_USE_PRECOMPILED_HEADERS ${CITRA_USE_PRECOMPILED_HEADERS} CACHE BOOL "") add_subdirectory(dynarmic EXCLUDE_FROM_ALL) endif() endif() @@ -293,6 +294,6 @@ if (APPLE) endif() # adrenotools -if (ANDROID) +if (ANDROID AND "arm64" IN_LIST ARCHITECTURE) add_subdirectory(libadrenotools) endif() diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index f92ce0301d..36f2154335 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -2,20 +2,24 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -import android.databinding.tool.ext.capitalizeUS - plugins { id("com.android.application") id("org.jetbrains.kotlin.android") + id("de.undercouch.download") version "5.5.0" } +import android.databinding.tool.ext.capitalizeUS +import de.undercouch.gradle.tasks.download.Download + /** * Use the number of seconds/10 since Jan 1 2016 as the versionCode. * This lets us upload a new build at most every 10 seconds for the * next 680 years. */ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toInt() -val abiFilter = listOf("arm64-v8a"/*, "x86", "x86_64"*/) +val abiFilter = listOf("arm64-v8a", "x86_64") + +val downloadedJniLibsPath = "${buildDir}/downloadedJniLibs" @Suppress("UnstableApiUsage") android { @@ -131,6 +135,13 @@ android { path = file("../../../CMakeLists.txt") } } + + sourceSets { + named("main") { + // Set up path for downloaded native libraries + jniLibs.srcDir(downloadedJniLibsPath) + } + } } dependencies { @@ -158,6 +169,30 @@ dependencies { implementation("com.android.billingclient:billing:2.0.3") } +// Download Vulkan Validation Layers from the KhronosGroup GitHub. +val downloadVulkanValidationLayers = tasks.register("downloadVulkanValidationLayers") { + src("https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download/sdk-1.3.261.1/android-binaries-sdk-1.3.261.1-android.zip") + dest(file("${buildDir}/tmp/Vulkan-ValidationLayers.zip")) + onlyIfModified(true) +} + +// Extract Vulkan Validation Layers into the downloaded native libraries directory. +val unzipVulkanValidationLayers = tasks.register("unzipVulkanValidationLayers") { + dependsOn(downloadVulkanValidationLayers) + from(zipTree(downloadVulkanValidationLayers.get().dest)) { + // Exclude the top level directory in the zip as it violates the expected jniLibs directory structure. + eachFile { + relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) + } + includeEmptyDirs = false + } + into(downloadedJniLibsPath) +} + +tasks.named("preBuild") { + dependsOn(unzipVulkanValidationLayers) +} + fun getGitVersion(): String { var versionName = "0.0" diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 7cc6304c1c..6668f9f0d8 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -34,7 +34,11 @@ add_library(citra-android SHARED ndk_motion.h ) -target_link_libraries(citra-android PRIVATE audio_core citra_common citra_core input_common network adrenotools) +target_link_libraries(citra-android PRIVATE audio_core citra_common citra_core input_common network) target_link_libraries(citra-android PRIVATE android camera2ndk EGL glad inih jnigraphics log mediandk yuv) +if ("arm64" IN_LIST ARCHITECTURE) + target_link_libraries(citra-android PRIVATE adrenotools) +endif() + set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} citra-android) diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 220151d117..1ce3b4a33e 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -10,8 +10,12 @@ #include #include "audio_core/dsp_interface.h" -#include "common/aarch64/cpu_detect.h" #include "common/arch.h" +#if CITRA_ARCH(arm64) +#include "common/aarch64/cpu_detect.h" +#elif CITRA_ARCH(x86_64) +#include "common/x64/cpu_detect.h" +#endif #include "common/common_paths.h" #include "common/dynamic_library/dynamic_library.h" #include "common/file_util.h" diff --git a/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so b/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so deleted file mode 100644 index b999455c4f..0000000000 Binary files a/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so and /dev/null differ diff --git a/src/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so b/src/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so deleted file mode 100644 index 65ac529d1d..0000000000 Binary files a/src/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so and /dev/null differ