Imported from probonopd/theunarchiver-gnustep (
AGENTS.md). Install upstream withnpx skills add probonopd/theunarchiver-gnustep. Copyright stays with the author.
AGENTS.md
GNUstep (Objective-C, AppKit) port of the upstream The Unarchiver app (mapache-soft/Unarchiver). The GUI comes from the upstream nib files, not from code. System GNUstep lives in /System; source the environment with source /System/Library/Makefiles/GNUstep.sh before any make/clang work.
Layout
The upstream repository is a git submodule at upstream/ (pinned commit), kept pristine. Our changes to upstream files are .patch files in patches/, replayed onto the submodule working tree by patches/apply.sh:
upstream/- git submodule (mapache-soft/Unarchiver, pinned). Do not commit inside it; it is expected to be dirty from the applied patches.Unarchiver/,XADMaster/,UniversalDetector/,Extra/- tracked symlinks intoupstream/so the build sees upstream's sibling layout and the GNUmakefile paths stay short.patches/*.patch+patches/apply.sh- our portability changes against the pristine upstream, applied withgit applyinside the submodule.vendor/XADMaster/GNUmakefile,vendor/UniversalDetector/GNUmakefile- our gnustep-make wrappers that build the upstream library sources (referenced throughXADSRC/UDSRCsymlinks) into the shared libraries.Compat/- our own additions that are not patches:GSCompatibility.h/.m(injected via-include),CSLaunchServicesStub.h/.m, and the app iconunarchiver.png(copied into the bundle byafter-all).TheUnarchiverInfo.plist- the app plist gnustep-make merges into the bundle'sInfo-gnustep.plist.
Setup (after a fresh clone)
The GNUmakefile's submodule-preflight step runs patches/apply.sh automatically
on the first build (it initializes the submodule and is skipped when the
submodule is already checked out and patched), so a plain make is enough.
To prepare the submodule without building:
git submodule update --init --recursive
./patches/apply.sh
The build does not work on a pristine submodule (e.g. XADPath's -encoding methods only compile once the __APPLE__ guards are removed by the patches).
Build
The app GNUmakefile declares the two library wrappers (vendor/UniversalDetector, vendor/XADMaster) as subprojects, so a single make in the repo root builds them (in order) and then the app.
- Keep the ObjC/Link flags for native exceptions (
-fobjc-exceptions -D_NATIVE_OBJC_EXCEPTIONS,-fexceptions). ADDITIONAL_OBJCFLAGS += -include Compat/GSCompatibility.hforce-injects the Mac-only API compatibility categories into every app source so the upstream files stay byte-identical.
The repo is git-tracked on branch main (the previous code-built reimplementation is kept on without-nib); .gitignore excludes obj/, *.app/, compiled object/library artifacts, .DS_Store, and __MACOSX/.
Run
The app is self-contained: after-all copies libXADMaster.so.0 and libUniversalDetector.so.0 into TheUnarchiver.app/Frameworks/, and the binary is linked with -Wl,-rpath,$ORIGIN/Frameworks. Run it directly, no LD_LIBRARY_PATH needed (a stale copy of these libs in /System/Library/Libraries would shadow the bundle ones via LD_LIBRARY_PATH - remove such stale installs). If you build the libs to a new obj dir or rename them, ldd shows "not found" - check the after-all copy step and the -Wl,-rpath flag.
Conventions
- Upstream sources are kept byte-identical to mapache-soft/Unarchiver; the submodule stays pristine. Any change to an upstream file belongs in
patches/(regenerate from the modified submodule working tree withgit diffinsideupstream/, or withdiff -u --label a/<path> --label b/<path>against a fresh checkout). - Mac-only APIs used by upstream (e.g.
NSApplication -dockTile, security-scopedNSURL,NSScriptCommand) are provided as no-op/inert categories inCompat/GSCompatibility.h/.m, injected via-include. - The GUI is the upstream nib files (
MainMenu.nib,ProgressView.nib,WaitView.nib,EncodingView.nib, ...) plus the localized.lprojresources; strings are localized via.stringsfiles, not hardcoded. - File associations / document types (double-clicking an archive opens The Unarchiver) come from the
NSTypesentries (withNSUnixExtensions) inTheUnarchiverInfo.plist, which gnustep-make merges into the bundle'sInfo-gnustep.plist. - Archive parsing uses the XADMaster API (
XADArchiveParser,XADSimpleUnarchiver); headers come from the submodule'sXADMaster/via theXADMastersymlink. - Known issue (not in app code): a flaky SIGSEGV in the system Eau theme's progress-bezel drawing (a freed
NSGraphicsContext) can be triggered by small/fast archives; reproducible without DriveUI.