diff options
| -rw-r--r-- | .github/workflows/build-arm64-layer.yml | 72 | ||||
| -rw-r--r-- | package.json | 4 | ||||
| -rw-r--r-- | py_modules/lsfg_vk/installation.py | 36 |
3 files changed, 106 insertions, 6 deletions
diff --git a/.github/workflows/build-arm64-layer.yml b/.github/workflows/build-arm64-layer.yml new file mode 100644 index 0000000..973a548 --- /dev/null +++ b/.github/workflows/build-arm64-layer.yml @@ -0,0 +1,72 @@ +name: Build ARM64 lsfg-vk layer + +on: + workflow_dispatch: + pull_request: + paths: + - .github/workflows/build-arm64-layer.yml + +permissions: + contents: read + +env: + SOURCE_REPOSITORY: https://github.com/FrankBarretta/lsfg-vk-android.git + SOURCE_COMMIT: 3e89e5439a98f55d5acb003d20039426ab24e69c + +jobs: + build: + name: Native AArch64 release build + runs-on: ubuntu-24.04-arm + + steps: + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install --yes --no-install-recommends \ + clang cmake g++ git libvulkan-dev ninja-build + + - name: Check out the pinned layer source + run: | + git init lsfg-vk-android + cd lsfg-vk-android + git remote add origin "${SOURCE_REPOSITORY}" + git fetch --depth=1 origin "${SOURCE_COMMIT}" + git checkout --detach FETCH_HEAD + git submodule update --init --recursive --depth=1 + test "$(git rev-parse HEAD)" = "${SOURCE_COMMIT}" + + - name: Build with static C++ runtimes + run: | + cmake -S lsfg-vk-android -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \ + -DCMAKE_SHARED_LINKER_FLAGS="-static-libstdc++ -static-libgcc -Wl,--exclude-libs,ALL" + cmake --build build --parallel 4 + strip --strip-unneeded build/liblsfg-vk.so + + - name: Verify and document the artifact + run: | + mkdir -p artifact + install -m 0755 build/liblsfg-vk.so artifact/liblsfg-vk-arm64.so + readelf -h artifact/liblsfg-vk-arm64.so | grep -q 'Machine:.*AArch64' + readelf -d artifact/liblsfg-vk-arm64.so | tee artifact/ELF-DYNAMIC.txt + ! grep -Eq 'libstdc\+\+\.so|libgcc_s\.so' artifact/ELF-DYNAMIC.txt + sha256sum artifact/liblsfg-vk-arm64.so | tee artifact/SHA256SUMS + { + echo "Source repository: ${SOURCE_REPOSITORY}" + echo "Source commit: ${SOURCE_COMMIT}" + echo "Runner: ubuntu-24.04-arm" + echo "Compiler: $(clang++ --version | head -n1)" + echo "CMake: $(cmake --version | head -n1)" + echo "Static runtimes: libstdc++ and libgcc" + } > artifact/SOURCE.txt + + - name: Upload ARM64 layer + uses: actions/upload-artifact@v4 + with: + name: lsfg-vk-arm64-${{ env.SOURCE_COMMIT }} + path: artifact/ + if-no-files-found: error + retention-days: 90 diff --git a/package.json b/package.json index a71b9cc..347820b 100644 --- a/package.json +++ b/package.json @@ -66,8 +66,8 @@ }, { "name": "liblsfg-vk-arm64.so", - "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/arm-test/liblsfg-vk.so", - "sha256hash": "c745893b3798eb1acb422775a43107fc3f2efb2ae2711090b90b04941d8de309" + "url": "https://github.com/Janleyx/decky-lsfg-vk-for-Ayn-Odin-2/releases/download/arm64-layer-3e89e54/liblsfg-vk-arm64.so", + "sha256hash": "2e84f8d1a1dd0344474846f6252d6f948f72caaaeab3cd316c04254be05a9949" } ], "pnpm": { diff --git a/py_modules/lsfg_vk/installation.py b/py_modules/lsfg_vk/installation.py index 4f01be1..29259f7 100644 --- a/py_modules/lsfg_vk/installation.py +++ b/py_modules/lsfg_vk/installation.py @@ -53,7 +53,7 @@ class InstallationService(BaseService): if self._is_arm_architecture(): self.log.info("Detected ARM architecture, using ARM binary") arm_so_path = plugin_dir / BIN_DIR / ARM_LIB_FILENAME - shutil.copy2(arm_so_path, self.lib_file) + self._copy_plugin_file(arm_so_path, self.lib_file) self.log.info(f"Overwrote with ARM binary: {self.lib_file}") self._create_config_file() @@ -78,7 +78,35 @@ class InstallationService(BaseService): Returns: True if running on ARM (aarch64), False otherwise """ - return platform.machine().lower() == 'aarch64' + if platform.machine().lower() in ('aarch64', 'arm64'): + return True + + # Decky runs through FEX on Armada, so Python reports x86_64 even + # though the host is AArch64. Armada exposes this native helper only + # on its ARM image, including inside Decky's FEX rootfs. + if Path('/usr/libexec/armada/device-env').is_file(): + self.log.info("Detected native AArch64 Armada host through device-env") + return True + + # Fall back to the native PID 1 ELF header. e_machine 183 is AArch64. + try: + with Path('/proc/1/exe').open('rb') as host_executable: + elf_header = host_executable.read(20) + if elf_header[:4] == b'\x7fELF' and elf_header[5] in (1, 2): + byte_order = 'little' if elf_header[5] == 1 else 'big' + if int.from_bytes(elf_header[18:20], byte_order) == 183: + self.log.info("Detected native AArch64 host through PID 1") + return True + except OSError as e: + self.log.debug(f"Could not inspect native host architecture: {e}") + + return False + + @staticmethod + def _copy_plugin_file(src_file: Path, dst_file: Path) -> None: + """Copy plugin content without preserving FEX-incompatible metadata.""" + shutil.copyfile(src_file, dst_file) + dst_file.chmod(0o644) def _extract_and_install_files(self, zip_path: Path) -> None: """Extract zip file and install files to appropriate locations @@ -117,7 +145,7 @@ class InstallationService(BaseService): if file_path.suffix == JSON_EXT and file == JSON_FILENAME: self._copy_and_fix_json_file(src_file, dst_file) else: - shutil.copy2(src_file, dst_file) + self._copy_plugin_file(src_file, dst_file) self.log.info(f"Copied {file} to {dst_file}") @@ -147,7 +175,7 @@ class InstallationService(BaseService): except (json.JSONDecodeError, KeyError, OSError) as e: self.log.error(f"Error fixing JSON file {src_file}: {e}") # Fallback to simple copy if JSON modification fails - shutil.copy2(src_file, dst_file) + self._copy_plugin_file(src_file, dst_file) def _create_config_file(self) -> None: """Create or update the TOML config file in ~/.config/lsfg-vk with default configuration and detected DLL path |
