From 26d1a7ff656299bdd565a1a9d2922546b479a6ad Mon Sep 17 00:00:00 2001 From: maxjivi05 Date: Fri, 3 Jul 2026 15:08:31 -0400 Subject: [PATCH 1/2] FEX UnixLibs: native .so backend toggle + wiring Add a smart "Use UnixLibs" toggle (Advanced, above the FEX selectors) that runs FEX translation via the native .so unixlib backend instead of the in-c_drive PE dlls. Detects UnixLib-capable FEX versions, tracks dll/unixlibs mode per launch, and places the .so into the active wine/Proton so_dir. Includes translations for all locales and a .wcp packaging tool. --- .gitignore | 3 + app/src/main/feature/library/GameSettings.kt | 15 ++++ .../ContainerSettingsComposeDialog.kt | 4 ++ .../ShortcutSettingsComposeDialog.kt | 13 ++++ app/src/main/res/values-da/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-hi/strings.xml | 1 + app/src/main/res/values-it/strings.xml | 1 + app/src/main/res/values-ko/strings.xml | 1 + app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values-pt-rBR/strings.xml | 1 + app/src/main/res/values-ro/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-uk/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/runtime/container/Container.java | 9 +++ .../main/runtime/content/ContentsManager.java | 70 ++++++++++++++++++- .../GuestProgramLauncherComponent.java | 49 +++++++++---- tools/build_fex_unixlibs_wcp.sh | 57 +++++++++++++++ 23 files changed, 220 insertions(+), 15 deletions(-) create mode 100755 tools/build_fex_unixlibs_wcp.sh diff --git a/.gitignore b/.gitignore index 7e71a9864..ecf01c18a 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ signing.properties References/ *.hprof android_sysvshm/build64/ + +# local build artifacts (FEX/Proton wcp) +dist/ diff --git a/app/src/main/feature/library/GameSettings.kt b/app/src/main/feature/library/GameSettings.kt index 85aae8e63..08479e6c9 100644 --- a/app/src/main/feature/library/GameSettings.kt +++ b/app/src/main/feature/library/GameSettings.kt @@ -507,6 +507,9 @@ class GameSettingsStateHolder { val selectedFexcoreVersion = mutableIntStateOf(0) val fexcorePresetEntries = mutableStateOf>(emptyList()) val selectedFexcorePreset = mutableIntStateOf(0) + // Per-version flag: true when that FEX version ships native .so UnixLibs. + val fexcoreUnixLibsFlags = mutableStateOf>(emptyList()) + val useUnixLibs = mutableStateOf(true) // Advanced - System val startupSelectionEntries = mutableStateOf>(emptyList()) @@ -3554,6 +3557,18 @@ private fun AdvancedSection( // FEXCore — hidden when FEXCore isn't explicitly in either slot. if (state.showFexcoreFrame.value) { + val fexUnixCapable = state.fexcoreUnixLibsFlags.value + .getOrNull(state.selectedFexcoreVersion.intValue) ?: false + SettingGroup { + SettingSwitch( + label = stringResource(R.string.use_unix_libs), + checked = state.useUnixLibs.value && fexUnixCapable, + onCheckedChange = { state.useUnixLibs.value = it }, + enabled = fexUnixCapable + ) + } + Spacer(Modifier.height(SettingSectionGap)) + val fexcoreUsage = emulatorUsageLabel(state, setOf("fexcore")) EmulatorSectionHeader(stringResource(R.string.container_fexcore_config), fexcoreUsage) Spacer(Modifier.height(8.dp)) diff --git a/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt b/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt index c6757926b..0192754bc 100644 --- a/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt +++ b/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt @@ -422,6 +422,7 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( } state.fullscreenStretched.value = c?.isFullscreenStretched() ?: false + state.useUnixLibs.value = c?.isUseUnixLibs() ?: true // Steam fields are shortcut-only in the UI; leave any existing steam // state on the container untouched — saveSettings() skips them. @@ -799,6 +800,7 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( c.setWinComponents(wincomponents) c.setDrives(drivesString) c.setFullscreenStretched(state.fullscreenStretched.value) + c.setUseUnixLibs(state.useUnixLibs.value) c.setInputType(finalInputType) c.setExclusiveXInput(state.containerExclusiveInput.value) c.setStartupSelection(startupSelection) @@ -839,6 +841,7 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( data.put("wincomponents", wincomponents) data.put("drives", drivesString) data.put("fullscreenStretched", state.fullscreenStretched.value) + data.put("useUnixLibs", state.useUnixLibs.value) data.put("inputType", finalInputType) data.put("exclusiveXInput", state.containerExclusiveInput.value) data.put("startupSelection", startupSelection.toInt()) @@ -989,6 +992,7 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( if (firstDash >= 0) items.add(entryName.substring(firstDash + 1)) } state.fexcoreVersionEntries.value = items + state.fexcoreUnixLibsFlags.value = items.map { contentsManager.fexcoreVersionHasUnixLibs(it) } val saved = container?.getFEXCoreVersion() ?: "" selectByValue(items, saved, state.selectedFexcoreVersion) } diff --git a/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt b/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt index 0fa0f52ba..d685cf306 100644 --- a/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt +++ b/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt @@ -414,6 +414,10 @@ class ShortcutSettingsComposeDialog private constructor( if (container.isFullscreenStretched) "1" else "0" ) state.fullscreenStretched.value = fullscreenStretched == "1" + state.useUnixLibs.value = getShortcutSetting( + "useUnixLibs", + if (container.isUseUnixLibs) "1" else "0" + ) == "1" // LC_ALL state.lcAll.value = getShortcutSetting("lc_all", container.getLC_ALL()) @@ -824,6 +828,7 @@ class ShortcutSettingsComposeDialog private constructor( } state.fexcoreVersionEntries.value = items + state.fexcoreUnixLibsFlags.value = items.map { contentsManager.fexcoreVersionHasUnixLibs(it) } val savedVersion = if (shouldUseShortcutOverrides(container)) getShortcutSetting("fexcoreVersion", container.getFEXCoreVersion()) else @@ -1071,6 +1076,13 @@ class ShortcutSettingsComposeDialog private constructor( if (container.isFullscreenStretched) "1" else "0" ) + // Use UnixLibs + hasContainerOverride = hasContainerOverride or saveOverride( + "useUnixLibs", + if (state.useUnixLibs.value) "1" else "0", + if (container.isUseUnixLibs) "1" else "0" + ) + // Win components val wincomponents = buildWinComponentsString() hasContainerOverride = @@ -2160,6 +2172,7 @@ class ShortcutSettingsComposeDialog private constructor( state.lcAll.value = container.getLC_ALL() state.fullscreenStretched.value = container.isFullscreenStretched + state.useUnixLibs.value = container.isUseUnixLibs val startupEntries = state.startupSelectionEntries.value state.selectedStartupSelection.intValue = container.getStartupSelection().toInt() diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 232fde91a..4f146e6a8 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -505,6 +505,7 @@ FEXCore FEXCore-forudindstilling FEXCore-version + Brug UnixLibs Grafikdriver diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 54ef2714d..3db58b93d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -505,6 +505,7 @@ FEXCore FEXCore-Voreinstellung FEXCore-Version + UnixLibs verwenden Grafiktreiber diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d5c56ec06..f173826f6 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -505,6 +505,7 @@ FEXCore Preset de FEXCore Versión de FEXCore + Usar UnixLibs Controlador gráfico diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 52d81280e..15d7a9801 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -505,6 +505,7 @@ FEXCore Préréglage FEXCore Version de FEXCore + Utiliser les UnixLibs Pilote graphique diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index a285325bb..73340af82 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -559,6 +559,7 @@ FEXCore FEXCore प्रीसेट FEXCore संस्करण + UnixLibs का उपयोग करें ग्राफ़िक्स ड्राइवर ग्राफ़िक्स ड्राइवर कॉन्फ़िगरेशन ग्राफ़िक्स ड्राइवर संस्करण diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 21d6b2bc9..8ce77f6ba 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -505,6 +505,7 @@ FEXCore Preset FEXCore Versione FEXCore + Usa UnixLibs Driver grafico diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1d82ebedf..d3e12a025 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -505,6 +505,7 @@ FEXCore FEXCore 프리셋 FEXCore 버전 + UnixLibs 사용 그래픽 드라이버 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index cb133e128..98613951f 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -509,6 +509,7 @@ FEXCore Preset FEXCore Wersja FEXCore + Użyj UnixLibs Sterownik grafiki diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 996104f88..7bd36eee2 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -505,6 +505,7 @@ FEXCore Predefinicao FEXCore Versao do FEXCore + Usar UnixLibs Driver Grafico diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 0ec0c94c8..8411c5bc1 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -505,6 +505,7 @@ FEXCore Preset FEXCore Versiune FEXCore + Folosește UnixLibs Driver grafic diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index f64eb6a8a..392f3549a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -513,6 +513,7 @@ FEXCore Пресет FEXCore Версия FEXCore + Использовать UnixLibs Графический драйвер Конфигурация графического драйвера diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 281acaeb0..45c92c010 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -509,6 +509,7 @@ FEXCore Пресет FEXCore Версія FEXCore + Використовувати UnixLibs Графічний драйвер diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 682ac8177..20e4aec3e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -505,6 +505,7 @@ FEXCore FEXCore 预设 FEXCore 版本 + 使用 UnixLibs 图形驱动 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 1dc93cd8f..90001b4e8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -505,6 +505,7 @@ FEXCore FEXCore 預設 FEXCore 版本 + 使用 UnixLibs 圖形驅動程式 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 540cc9451..bf004118b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -585,6 +585,7 @@ FEXCore FEXCore Preset FEXCore Version + Use UnixLibs Graphics Driver diff --git a/app/src/main/runtime/container/Container.java b/app/src/main/runtime/container/Container.java index 96e6812b1..8f259419a 100644 --- a/app/src/main/runtime/container/Container.java +++ b/app/src/main/runtime/container/Container.java @@ -51,6 +51,7 @@ public class Container { private String drives = DEFAULT_DRIVES; private String wineVersion = WineInfo.MAIN_WINE_VERSION.identifier(); private boolean fullscreenStretched; + private boolean useUnixLibs = true; private byte startupSelection = STARTUP_SELECTION_ESSENTIAL; private String cpuList; private String cpuListWoW64; @@ -207,6 +208,10 @@ public void setLC_ALL(String lc_all) { public void setFullscreenStretched(boolean fullscreenStretched) { this.fullscreenStretched = fullscreenStretched; } + public boolean isUseUnixLibs() { return useUnixLibs; } + + public void setUseUnixLibs(boolean useUnixLibs) { this.useUnixLibs = useUnixLibs; } + public byte getStartupSelection() { return startupSelection; } @@ -424,6 +429,7 @@ public void saveData() { data.put("wincomponents", wincomponents); data.put("drives", drives); data.put("fullscreenStretched", fullscreenStretched); + data.put("useUnixLibs", useUnixLibs); data.put("inputType", inputType); data.put("exclusiveXInput", exclusiveXInput); data.put("startupSelection", startupSelection); @@ -508,6 +514,9 @@ public void loadData(JSONObject data) throws JSONException { case "fullscreenStretched" : setFullscreenStretched(data.getBoolean(key)); break; + case "useUnixLibs" : + setUseUnixLibs(data.getBoolean(key)); + break; case "inputType" : setInputType(data.getInt(key)); break; diff --git a/app/src/main/runtime/content/ContentsManager.java b/app/src/main/runtime/content/ContentsManager.java index 2c85adea3..0fa2e6fbc 100644 --- a/app/src/main/runtime/content/ContentsManager.java +++ b/app/src/main/runtime/content/ContentsManager.java @@ -17,6 +17,7 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; @@ -750,6 +751,72 @@ public ContentProfile getProfileByEntryName(String entryName) { return null; } + // A FEX version exposes native UnixLibs when its install dir ships any .so payload. + public boolean profileHasUnixLibs(ContentProfile profile) { + if (profile == null) return false; + return dirContainsSharedObject(getInstallDir(context, profile)); + } + + public boolean fexcoreVersionHasUnixLibs(String fexcoreVersion) { + if (fexcoreVersion == null || fexcoreVersion.isEmpty()) return false; + return profileHasUnixLibs(getProfileByEntryName("fexcore-" + fexcoreVersion)); + } + + private static boolean dirContainsSharedObject(File dir) { + if (dir == null) return false; + File[] files = dir.listFiles(); + if (files == null) return false; + for (File file : files) { + if (file.isDirectory()) { + if (dirContainsSharedObject(file)) return true; + } else if (isSharedObject(file.getName())) { + return true; + } + } + return false; + } + + private static boolean isSharedObject(String name) { + String lower = name.toLowerCase(Locale.ROOT); + return lower.endsWith(".so") || lower.contains(".so."); + } + + // Delete the .so payload a profile installs (its PE dlls are left in place). + public void removeAppliedUnixLibs(ContentProfile profile) { + if (profile == null || profile.fileList == null) return; + for (ContentProfile.ContentFile contentFile : profile.fileList) { + if (!isSharedObject(new File(contentFile.target).getName())) continue; + File targetFile = new File(getPathFromTemplate(contentFile.target)); + if (targetFile.exists() && targetFile.delete()) { + Log.i("ContentsManager", "UnixLibs: removed " + targetFile.getName()); + } + } + } + + // Copy a profile's .so payload into destDir (the active wine runtime's so_dir). + public void copyUnixLibsToDir(ContentProfile profile, File destDir) { + if (profile == null || profile.fileList == null) return; + for (ContentProfile.ContentFile contentFile : profile.fileList) { + String name = new File(contentFile.target).getName(); + if (!isSharedObject(name)) continue; + File sourceFile = new File(getInstallDir(context, profile), contentFile.source); + if (!sourceFile.exists()) continue; + File destFile = new File(destDir, name); + FileUtils.copy(sourceFile, destFile); + FileUtils.chmod(destFile, 0771); + } + } + + public void deleteUnixLibsFromDir(ContentProfile profile, File destDir) { + if (profile == null || profile.fileList == null) return; + for (ContentProfile.ContentFile contentFile : profile.fileList) { + String name = new File(contentFile.target).getName(); + if (!isSharedObject(name)) continue; + File destFile = new File(destDir, name); + if (destFile.exists()) destFile.delete(); + } + } + public boolean applyContent(ContentProfile profile) { if (profile.type != ContentProfile.ContentType.CONTENT_TYPE_WINE && profile.type != ContentProfile.ContentType.CONTENT_TYPE_PROTON) { @@ -760,7 +827,8 @@ public boolean applyContent(ContentProfile profile) { targetFile.delete(); FileUtils.copy(sourceFile, targetFile); - if (profile.type == ContentProfile.ContentType.CONTENT_TYPE_BOX64) { + if (profile.type == ContentProfile.ContentType.CONTENT_TYPE_BOX64 + || isSharedObject(targetFile.getName())) { FileUtils.chmod(targetFile, 0771); } } diff --git a/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java b/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java index 58ac5f6ae..2381fac6a 100644 --- a/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java +++ b/app/src/main/runtime/display/environment/components/GuestProgramLauncherComponent.java @@ -55,6 +55,7 @@ public class GuestProgramLauncherComponent extends EnvironmentComponent { private final Shortcut shortcut; private File workingDir; private Runnable preUnpackCallback; + private boolean fexUnixLibsActive = false; public static File ensureImageFsNativeLibrary( Context context, ImageFs imageFs, String libraryName) { @@ -371,11 +372,13 @@ private void extractEmulatorsDlls() { if (wowbox64Version == null) wowbox64Version = ""; if (fexcoreVersion == null) fexcoreVersion = ""; + boolean unixLibsPref = container.isUseUnixLibs(); if (shortcut != null) { emulator = shortcut.getSettingExtra("emulator", emulator); emulator64 = shortcut.getSettingExtra("emulator64", emulator64); wowbox64Version = shortcut.getSettingExtra("box64Version", wowbox64Version); fexcoreVersion = shortcut.getSettingExtra("fexcoreVersion", fexcoreVersion); + unixLibsPref = "1".equals(shortcut.getSettingExtra("useUnixLibs", unixLibsPref ? "1" : "0")); } boolean usesWowbox64 = emulator.equalsIgnoreCase("wowbox64"); @@ -384,6 +387,9 @@ private void extractEmulatorsDlls() { || emulator64.equalsIgnoreCase("fexcore") || !usesWowbox64; + fexUnixLibsActive = + usesFexcore && unixLibsPref && contentsManager.fexcoreVersionHasUnixLibs(fexcoreVersion); + Log.i( "GuestProgramLauncherComponent", "Launch runtime selected: emulator=" @@ -439,30 +445,45 @@ private void extractEmulatorsDlls() { "WowBox64 already loaded for launch: version=" + wowbox64Version); } - if (usesFexcore - && (fexcoreDllsMissing || !fexcoreVersion.equals(container.getExtra("fexcoreVersion")))) { - if (fexcoreVersion.isEmpty()) { - Log.w("GuestProgramLauncherComponent", "No FEXCore version selected; skipping content extraction"); - } else { - ContentProfile profile = contentsManager.getProfileByEntryName("fexcore-" + fexcoreVersion); - if (profile != null) { + if (usesFexcore) { + ContentProfile profile = + fexcoreVersion.isEmpty() ? null : contentsManager.getProfileByEntryName("fexcore-" + fexcoreVersion); + String wantMode = fexUnixLibsActive ? "unixlibs" : "dll"; + boolean modeChanged = !wantMode.equals(container.getExtra("fexcoreMode")); + boolean versionChanged = !fexcoreVersion.equals(container.getExtra("fexcoreVersion")); + boolean needsExtraction = + versionChanged || modeChanged || (!fexUnixLibsActive && fexcoreDllsMissing); + + if (needsExtraction) { + if (fexcoreVersion.isEmpty()) { + Log.w("GuestProgramLauncherComponent", "No FEXCore version selected; skipping content extraction"); + } else if (profile != null) { Log.i( "GuestProgramLauncherComponent", - "Loading FEXCore content profile: version=" + fexcoreVersion); + "Loading FEXCore content profile: version=" + fexcoreVersion + " mode=" + wantMode); contentsManager.applyContent(profile); + if (!fexUnixLibsActive) contentsManager.removeAppliedUnixLibs(profile); } else { Log.w( "GuestProgramLauncherComponent", "FEXCore content profile not installed; no bundled FEXCore archive will be loaded: version=" + fexcoreVersion); } + container.putExtra("fexcoreVersion", fexcoreVersion); + container.putExtra("fexcoreMode", wantMode); + containerDataChanged = true; + } else { + Log.i( + "GuestProgramLauncherComponent", + "FEXCore already loaded for launch: version=" + fexcoreVersion + " mode=" + wantMode); + } + + // Sync the native .so with the active wine runtime's so_dir per the toggle. + if (profile != null) { + File wineUnixDir = new File(environment.getImageFs().getWinePath(), "lib/wine/aarch64-unix"); + if (fexUnixLibsActive) contentsManager.copyUnixLibsToDir(profile, wineUnixDir); + else contentsManager.deleteUnixLibsFromDir(profile, wineUnixDir); } - container.putExtra("fexcoreVersion", fexcoreVersion); - containerDataChanged = true; - } else if (usesFexcore) { - Log.i( - "GuestProgramLauncherComponent", - "FEXCore already loaded for launch: version=" + fexcoreVersion); } if (containerDataChanged) container.saveData(); } diff --git a/tools/build_fex_unixlibs_wcp.sh b/tools/build_fex_unixlibs_wcp.sh new file mode 100755 index 000000000..70fe4c041 --- /dev/null +++ b/tools/build_fex_unixlibs_wcp.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Package a FEX UnixLibs component (.wcp) for WinNative. +# +# Payload layout (top dir -> WinNative content-path template; sub-paths are preserved): +# lib/wine/aarch64-unix/.so -> ${libdir}/wine/aarch64-unix/.so (FEX host UnixLibs) +# system32/ -> ${system32}/ (FEX PE dlls) +# syswow64/ -> ${syswow64}/ +# bin/ -> ${bindir}/ +# +# A .wcp is an xz-compressed tar of profile.json + the payload tree. +# +# Usage: +# tools/build_fex_unixlibs_wcp.sh -v -c -p -o +set -euo pipefail + +VERSION_NAME=""; VERSION_CODE="0"; PAYLOAD=""; OUT="" +while getopts "v:c:p:o:" opt; do + case "$opt" in + v) VERSION_NAME="$OPTARG" ;; + c) VERSION_CODE="$OPTARG" ;; + p) PAYLOAD="$OPTARG" ;; + o) OUT="$OPTARG" ;; + *) echo "bad option" >&2; exit 2 ;; + esac +done + +[ -n "$VERSION_NAME" ] && [ -n "$PAYLOAD" ] && [ -n "$OUT" ] || { + echo "usage: $0 -v -c -p -o " >&2; exit 2; } +[ -d "$PAYLOAD" ] || { echo "payload dir not found: $PAYLOAD" >&2; exit 1; } + +STAGE="$(mktemp -d)" +trap 'rm -rf "$STAGE"' EXIT +cp -a "$PAYLOAD/." "$STAGE/" + +python3 - "$STAGE" "$VERSION_NAME" "$VERSION_CODE" <<'PY' +import json, os, sys +stage, vname, vcode = sys.argv[1], sys.argv[2], int(sys.argv[3]) +tpl = {"lib": "${libdir}", "system32": "${system32}", "syswow64": "${syswow64}", "bin": "${bindir}"} +files = [] +for root, _, names in os.walk(stage): + for n in sorted(names): + rel = os.path.relpath(os.path.join(root, n), stage) + parts = rel.split(os.sep, 1) + top = parts[0] + if top not in tpl or len(parts) < 2: + continue + files.append({"source": rel, "target": f"{tpl[top]}/{parts[1]}"}) +files.sort(key=lambda f: f["source"]) +profile = {"type": "FEXCore", "versionName": vname, "versionCode": vcode, + "description": vname, "files": files} +with open(os.path.join(stage, "profile.json"), "w") as f: + json.dump(profile, f, indent=2) +print(json.dumps(profile, indent=2)) +PY + +tar -C "$STAGE" -cJf "$OUT" . +echo "wrote $OUT ($(du -h "$OUT" | cut -f1))" From 380b537c39d773e707ad93ac0617c41f9bd303e7 Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Fri, 3 Jul 2026 15:46:59 -0400 Subject: [PATCH 2/2] Delete tools/build_fex_unixlibs_wcp.sh --- tools/build_fex_unixlibs_wcp.sh | 57 --------------------------------- 1 file changed, 57 deletions(-) delete mode 100755 tools/build_fex_unixlibs_wcp.sh diff --git a/tools/build_fex_unixlibs_wcp.sh b/tools/build_fex_unixlibs_wcp.sh deleted file mode 100755 index 70fe4c041..000000000 --- a/tools/build_fex_unixlibs_wcp.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -# Package a FEX UnixLibs component (.wcp) for WinNative. -# -# Payload layout (top dir -> WinNative content-path template; sub-paths are preserved): -# lib/wine/aarch64-unix/.so -> ${libdir}/wine/aarch64-unix/.so (FEX host UnixLibs) -# system32/ -> ${system32}/ (FEX PE dlls) -# syswow64/ -> ${syswow64}/ -# bin/ -> ${bindir}/ -# -# A .wcp is an xz-compressed tar of profile.json + the payload tree. -# -# Usage: -# tools/build_fex_unixlibs_wcp.sh -v -c -p -o -set -euo pipefail - -VERSION_NAME=""; VERSION_CODE="0"; PAYLOAD=""; OUT="" -while getopts "v:c:p:o:" opt; do - case "$opt" in - v) VERSION_NAME="$OPTARG" ;; - c) VERSION_CODE="$OPTARG" ;; - p) PAYLOAD="$OPTARG" ;; - o) OUT="$OPTARG" ;; - *) echo "bad option" >&2; exit 2 ;; - esac -done - -[ -n "$VERSION_NAME" ] && [ -n "$PAYLOAD" ] && [ -n "$OUT" ] || { - echo "usage: $0 -v -c -p -o " >&2; exit 2; } -[ -d "$PAYLOAD" ] || { echo "payload dir not found: $PAYLOAD" >&2; exit 1; } - -STAGE="$(mktemp -d)" -trap 'rm -rf "$STAGE"' EXIT -cp -a "$PAYLOAD/." "$STAGE/" - -python3 - "$STAGE" "$VERSION_NAME" "$VERSION_CODE" <<'PY' -import json, os, sys -stage, vname, vcode = sys.argv[1], sys.argv[2], int(sys.argv[3]) -tpl = {"lib": "${libdir}", "system32": "${system32}", "syswow64": "${syswow64}", "bin": "${bindir}"} -files = [] -for root, _, names in os.walk(stage): - for n in sorted(names): - rel = os.path.relpath(os.path.join(root, n), stage) - parts = rel.split(os.sep, 1) - top = parts[0] - if top not in tpl or len(parts) < 2: - continue - files.append({"source": rel, "target": f"{tpl[top]}/{parts[1]}"}) -files.sort(key=lambda f: f["source"]) -profile = {"type": "FEXCore", "versionName": vname, "versionCode": vcode, - "description": vname, "files": files} -with open(os.path.join(stage, "profile.json"), "w") as f: - json.dump(profile, f, indent=2) -print(json.dumps(profile, indent=2)) -PY - -tar -C "$STAGE" -cJf "$OUT" . -echo "wrote $OUT ($(du -h "$OUT" | cut -f1))"