Files
LisherSong--ps5-web-file-ma…/Makefile
T
Songlx516 3f80eb4692 release: v1.9.2 -- re-cut the release so tag = source = binary
The v1.9.1 tag was a lightweight tag sitting on 9a36c3c, four commits BEHIND
the tree that produced the released ELF, so `git clone --branch v1.9.1` could
not rebuild the published artifact. v1.9.2 is that same tree with the version
literal bumped, which puts the tag back on the commit the binary came from.

Source delta vs the v1.9.1 tag (all of it already shipped inside the v1.9.1
binary -- the tag was just wrong, nothing was missing from the download):

  - src/demangle_stub.c + -Wl,--icf=all: 1,034,328 -> 870,488 B (-15.8%)
    The demangler was only reachable from the uncaught-exception path.
  - upload entry: single-click file/folder pick, plus drag-and-drop upload
  - docs: language switcher in both READMEs

Artifact
  web-file-mgr-v1.9.2.elf
  870,488 B
  sha256 177e90fecf93a0251e83f67884fba4551051be248330b0d70fda8ea732f88e84
  e_machine 0x003e (x86-64 / PS5)

Verification
  - 163 checks (ZIP 108 + RAR 27 + 7z 28), 0 failures; `aeshe` remains the
    known -mhe=on gap
  - the build is reproducible: reverting the two version literals and
    rebuilding reproduces the v1.9.1 ELF byte for byte, and re-applying them
    reproduces this one. That is what pins the byte-level difference between
    the two artifacts down to the version string alone
  - docs/SIZE-OPTIMIZATION.md gains appendix A (artifact-consistency
    verification, incl. the 55,280-byte raw diff explained as linker string
    pool relayout) and appendix B (per-symbol accounting: 628 symbols
    removed, 0 added, 76 ICF fold groups)

Not yet validated on retail hardware.
2026-09-20 17:33:32 +08:00

211 lines
11 KiB
Makefile

ifneq ($(filter-out linux linux-deps clean,$(MAKECMDGOALS)),)
ifdef PS5_PAYLOAD_SDK
include $(PS5_PAYLOAD_SDK)/toolchain/prospero.mk
else
$(error PS5_PAYLOAD_SDK is undefined)
endif
endif
ifeq ($(MAKECMDGOALS),)
ifdef PS5_PAYLOAD_SDK
include $(PS5_PAYLOAD_SDK)/toolchain/prospero.mk
else
$(error PS5_PAYLOAD_SDK is undefined)
endif
endif
# Bump this together with the git tag -- it is baked into the binary (the PS5
# notification and `--version` print it) AND into the output filename, so a
# stale value silently mislabels everything. Override per-build with:
# make VERSION_TAG=v1.9.2
VERSION_TAG ?= v1.9.2
TITLE_ID := FMGR88888
PYTHON ?= python3
STRIP ?= $(PS5_PAYLOAD_SDK)/bin/prospero-strip
PKG_CONFIG ?= $(PS5_PAYLOAD_SDK)/bin/prospero-pkg-config
HOST_CC ?= cc
HOST_STRIP ?= strip
HOST_PKG_CONFIG ?= pkg-config
# Output filename carries the version so two builds never overwrite each other
# and you can tell at a glance which ELF is on the USB stick.
BIN := web-file-mgr-$(VERSION_TAG).elf
LINUX_BIN := web-file-mgr-linux-$(VERSION_TAG)
COMMON_SRCS := src/main.c src/websrv.c src/filemgr.c src/file_response.c src/task.c src/upload.c src/download.c src/text.c src/list.c src/space.c src/version.c src/fs_util.c src/json_util.c src/path_util.c src/asset.c src/mime.c src/notify.c src/pkg_installer.c src/pkg_info.c src/extract.c src/zip_extract.c src/rar_extract.c src/zipx_volume.c src/zipx_volstream.c src/zipx_common.c src/sevenz_extract.c src/sevenz_chain.c src/sevenz_volstream.c src/sevenz_mt.c src/demangle_stub.c
PS5_SRCS := $(COMMON_SRCS) src/app_installer.c src/cpu_support_stub.c
LINUX_SRCS := $(COMMON_SRCS)
BASE_ASSETS := $(filter-out %.dds,$(wildcard assets/*))
ifneq ($(filter linux,$(MAKECMDGOALS)),)
ASSETS := $(BASE_ASSETS)
else
ASSETS := $(filter-out assets/icon0.png,$(BASE_ASSETS))
endif
GEN_SRCS := $(patsubst assets/%,gen/%, $(ASSETS:=.c))
# Vendored third-party: zlib + minizip-ng (ZIP, C) and unrar 7.20.1 (RAR,
# C++). unrar sources are compiled as a static library in RARDLL mode (no
# main()); the project talks to it through the extern "C" DLL API in
# third_party/unrar7/unrar_c_api.h. Compiled with relaxed warnings (-w) —
# these are not our code and we do not want to chase upstream style updates.
#
# C++ compilers: PS5 uses prospero-clang++ (FreeBSD-style sysroot; the
# toolchain defaults to -stdlib=libc++, driver links libc++ automatically);
# host builds use the plain host C++ compiler (libstdc++).
CXX ?= $(dir $(CC))prospero-clang++
HOST_CXX ?= c++
# Source set mirrors UnRARDll.vcxproj's ClCompile list (49 files) MINUS the
# Windows-only isnt.cpp / motw.cpp (they need windows.h; the official unrar
# UNIX makefile omits them, and PS5/linux both use the _UNIX branch where
# their symbols are #ifdef'd out).
UNRAR7_SRCS := \
third_party/unrar7/archive.cpp third_party/unrar7/arcread.cpp third_party/unrar7/blake2s.cpp \
third_party/unrar7/cmddata.cpp third_party/unrar7/consio.cpp third_party/unrar7/crc.cpp \
third_party/unrar7/crypt.cpp third_party/unrar7/dll.cpp third_party/unrar7/encname.cpp \
third_party/unrar7/errhnd.cpp third_party/unrar7/extinfo.cpp third_party/unrar7/extract.cpp \
third_party/unrar7/filcreat.cpp third_party/unrar7/file.cpp third_party/unrar7/filefn.cpp \
third_party/unrar7/filestr.cpp third_party/unrar7/find.cpp third_party/unrar7/getbits.cpp \
third_party/unrar7/global.cpp third_party/unrar7/hash.cpp third_party/unrar7/headers.cpp \
third_party/unrar7/largepage.cpp third_party/unrar7/match.cpp \
third_party/unrar7/options.cpp third_party/unrar7/pathfn.cpp \
third_party/unrar7/qopen.cpp third_party/unrar7/rar.cpp third_party/unrar7/rarpch.cpp \
third_party/unrar7/rarvm.cpp third_party/unrar7/rawread.cpp third_party/unrar7/rdwrfn.cpp \
third_party/unrar7/rijndael.cpp third_party/unrar7/rs.cpp third_party/unrar7/rs16.cpp \
third_party/unrar7/scantree.cpp third_party/unrar7/secpassword.cpp third_party/unrar7/sha1.cpp \
third_party/unrar7/sha256.cpp third_party/unrar7/smallfn.cpp third_party/unrar7/strfn.cpp \
third_party/unrar7/strlist.cpp third_party/unrar7/system.cpp third_party/unrar7/threadpool.cpp \
third_party/unrar7/timefn.cpp third_party/unrar7/ui.cpp third_party/unrar7/unicode.cpp \
third_party/unrar7/unpack.cpp third_party/unrar7/volume.cpp
THIRD_PARTY_C_SRCS := $(wildcard third_party/zlib/src/*.c) $(wildcard third_party/minizip-ng/src/*.c) $(wildcard third_party/7z/*.c)
# AesOpt.c hard-codes x86 AES-NI / AVX / VAES intrinsics and guards them with
# a compiler-version check that lets clang 18 in unconditionally. The plain
# intrinsics (`_mm256_aesenc_epi128`) live behind <wmmintrin_aes.h>, which
# clang only declares after `+mvaes +mavx2` (or higher). PS5 is Zen 2 and has
# every one of these, so we just enable them for the 7z TU family instead of
# dropping AesOpt.c (Aes.c references those HW symbol names via AesGenTables).
SEVENZ_C_FLAGS := -maes -mavx2 -mvaes
THIRD_PARTY_C_FLAGS := -O2 -w -Ithird_party/zlib/include -Ithird_party/minizip-ng/include -Ithird_party/7z \
-DHAVE_ZLIB -DZLIB_COMPAT -DHAVE_UNISTD_H=1 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \
-DHAVE_FSEEKO -DZ7_PPMD_SUPPORT
THIRD_PARTY_C_FLAGS_7Z := $(THIRD_PARTY_C_FLAGS) $(SEVENZ_C_FLAGS)
# Assembly-optimised LZMA decoder (optional, on when jwasm is present).
#
# LzmaDec.c carries a compile-time switch: with Z7_LZMA_DEC_OPT it calls an
# external LzmaDec_DecodeReal_3() and drops its own C implementation; without
# it, the C version is used. The asm version is measurably faster -- on a
# 330 MiB LZMA2 archive, 1.10 s vs 1.39 s, i.e. most of the gap to the
# official 7-Zip binary, which builds with this switch on.
#
# LzmaDecOpt.asm is MASM syntax, so it needs a MASM-compatible assembler
# (jwasm). That is not something we can assume the host has, so the whole
# optimisation is conditional: no jwasm, no asm, and the build still works.
# ABI_LINUX is load-bearing -- 7zAsm.asm keys its calling convention off it
# (SysV rdi/rsi/rdx vs Win64 rcx/rdx/r8); assembling without it links cleanly
# and then segfaults on the first call.
JWASM ?= jwasm
LZMA_DEC_ASM_DIR := third_party/7z/Asm/x86
LZMA_DEC_ASM_SRC := $(LZMA_DEC_ASM_DIR)/LzmaDecOpt.asm
ifneq ($(shell command -v $(JWASM) 2>/dev/null),)
LZMA_DEC_OPT_FLAG := -DZ7_LZMA_DEC_OPT
PS5_ASM_OBJS := ps5-obj/$(LZMA_DEC_ASM_DIR)/LzmaDecOpt.o
LINUX_ASM_OBJS := linux-obj/$(LZMA_DEC_ASM_DIR)/LzmaDecOpt.o
endif
UNRAR7_CXX_FLAGS := -O2 -w -std=c++17 -DRARDLL -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
# prospero-clang++ defaults to -stdlib=libc++; state it explicitly for clarity.
UNRAR7_CXX_FLAGS_PS5 := $(UNRAR7_CXX_FLAGS) -stdlib=libc++
UNRAR7_CXX_FLAGS_HOST:= $(UNRAR7_CXX_FLAGS)
PS5_TP_OBJS := $(patsubst %.c,ps5-obj/%.o,$(THIRD_PARTY_C_SRCS)) \
$(patsubst %.cpp,ps5-obj/%.o,$(UNRAR7_SRCS))
LINUX_TP_OBJS := $(patsubst %.c,linux-obj/%.o,$(THIRD_PARTY_C_SRCS)) \
$(patsubst %.cpp,linux-obj/%.o,$(UNRAR7_SRCS))
CFLAGS := -Oz -fno-asynchronous-unwind-tables -fno-unwind-tables -Wall -Werror -ffunction-sections -fdata-sections -Isrc -Ithird_party/minizip-ng/include -Ithird_party/unrar7 -Ithird_party/7z -DVERSION_TAG=\"$(VERSION_TAG)\" -DTITLE_ID=\"$(TITLE_ID)\"
CFLAGS += `$(PKG_CONFIG) libmicrohttpd --cflags`
# --icf=all: fold byte-identical functions. LLD-only (GNU ld's --icf is
# incomplete), so it stays on the PS5 line -- the linux target never uses
# LDFLAGS. Paired with src/demangle_stub.c this takes the ELF from ~1010 to
# ~850 KiB; see docs/SIZE-OPTIMIZATION.md.
LDFLAGS := -Wl,--gc-sections -Wl,--icf=all
LDADD := `$(PKG_CONFIG) libmicrohttpd --libs`
LDADD += -lSceIpmi -lSceAppInstUtil -lSceUserService
LINUX_CFLAGS := -O2 -flto -Wall -Werror -Isrc -Ithird_party/minizip-ng/include -Ithird_party/unrar7 -Ithird_party/7z -DVERSION_TAG=\"$(VERSION_TAG)\" -DTITLE_ID=\"$(TITLE_ID)\"
LINUX_CFLAGS += `$(HOST_PKG_CONFIG) libmicrohttpd --cflags`
LINUX_LDADD := `$(HOST_PKG_CONFIG) libmicrohttpd --libs` -pthread
.PHONY: all linux deps linux-deps clean
all: deps $(BIN)
linux: linux-deps $(LINUX_BIN)
deps:
@$(PKG_CONFIG) --exists libmicrohttpd || ./install-libmicrohttpd.sh
linux-deps:
@$(HOST_PKG_CONFIG) --exists libmicrohttpd || \
(echo "libmicrohttpd development package is required for make linux" >&2; exit 1)
gen:
mkdir gen
clean:
rm -rf $(BIN) $(LINUX_BIN) gen ps5-obj linux-obj
gen/%.c: assets/% gen-asset-module.py | gen
$(PYTHON) gen-asset-module.py --path $* $< > $@
# Only LzmaDec.c changes behaviour under the switch: it stops defining its own
# decoder and declares the external symbol instead. Everything else in the 7z
# TU family is unaffected.
ifneq ($(LZMA_DEC_OPT_FLAG),)
ps5-obj/third_party/7z/LzmaDec.o: THIRD_PARTY_C_FLAGS_7Z += $(LZMA_DEC_OPT_FLAG)
linux-obj/third_party/7z/LzmaDec.o: THIRD_PARTY_C_FLAGS_7Z += $(LZMA_DEC_OPT_FLAG)
endif
# make does not track flag changes, and installing or removing jwasm flips the
# switch above. Without this, an existing LzmaDec.o silently keeps the old
# decoder and the asm object just sits in the link line unreferenced (the
# binary comes out byte-identical, which is how the problem was noticed).
ps5-obj/third_party/7z/LzmaDec.o: Makefile
linux-obj/third_party/7z/LzmaDec.o: Makefile
ps5-obj/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(if $(findstring third_party/7z,$<),$(THIRD_PARTY_C_FLAGS_7Z),$(THIRD_PARTY_C_FLAGS)) -c -o $@ $<
linux-obj/%.o: %.c
@mkdir -p $(dir $@)
$(HOST_CC) $(if $(findstring third_party/7z,$<),$(THIRD_PARTY_C_FLAGS_7Z),$(THIRD_PARTY_C_FLAGS)) -c -o $@ $<
# The assembler emits a plain ELF64 relocatable object, which both linkers
# (prospero-clang++ for PS5, cc for linux) accept as-is.
ps5-obj/$(LZMA_DEC_ASM_DIR)/LzmaDecOpt.o: $(LZMA_DEC_ASM_SRC)
@mkdir -p $(dir $@)
$(JWASM) -elf64 -q -DABI_LINUX -I$(LZMA_DEC_ASM_DIR) -Fo$@ $<
linux-obj/$(LZMA_DEC_ASM_DIR)/LzmaDecOpt.o: $(LZMA_DEC_ASM_SRC)
@mkdir -p $(dir $@)
$(JWASM) -elf64 -q -DABI_LINUX -I$(LZMA_DEC_ASM_DIR) -Fo$@ $<
ps5-obj/%.o: %.cpp
@mkdir -p $(dir $@)
$(CXX) $(UNRAR7_CXX_FLAGS_PS5) -c -o $@ $<
linux-obj/%.o: %.cpp
@mkdir -p $(dir $@)
$(HOST_CXX) $(UNRAR7_CXX_FLAGS_HOST) -c -o $@ $<
# Link with the C++ driver so libc++ (PS5) / libstdc++ (host) is pulled in
# automatically for the unrar objects. The project's own C sources are passed
# through -x c (clang++ would otherwise compile .c files as C++ and trip
# -Wdeprecated); -x none restores extension-based handling for the .o files.
$(BIN): $(PS5_SRCS) $(GEN_SRCS) $(PS5_TP_OBJS) $(PS5_ASM_OBJS)
$(CXX) $(CFLAGS) $(LDFLAGS) -o $@ -x c $(filter %.c,$^) -x none $(PS5_TP_OBJS) $(PS5_ASM_OBJS) $(LDADD)
$(STRIP) $@
$(LINUX_BIN): $(LINUX_SRCS) $(GEN_SRCS) $(LINUX_TP_OBJS) $(LINUX_ASM_OBJS)
$(HOST_CXX) $(LINUX_CFLAGS) -o $@ -x c $(filter %.c,$^) -x none $(LINUX_TP_OBJS) $(LINUX_ASM_OBJS) $(LINUX_LDADD)
$(HOST_STRIP) $@