diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c4ec43..ed55ecd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,9 @@ jobs: name: Recompiling ido ${{ matrix.ido }} for ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Ubuntu - name: Install dependencies (Ubuntu) diff --git a/Makefile b/Makefile index d520a47..bd48c4c 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,18 @@ else $(error Unsupported host OS for Makefile) endif +# check if in a git repository +ifeq ($(shell git rev-parse --is-inside-work-tree >/dev/null 2>/dev/null; echo $$?),0) + PACKAGE_VERSION := $(shell LC_ALL=C git --git-dir .git describe --tags --always --dirty) +endif + +# Get the current date and time in ISO 8601 format +DATETIME := $(shell date +'%F %T UTC%z') + +$(info Package version $(PACKAGE_VERSION)) +$(info Build date $(DATETIME)) + + RABBITIZER := tools/rabbitizer RABBITIZER_LIB := $(RABBITIZER)/build/librabbitizerpp.a @@ -110,9 +122,11 @@ LIBS := $(foreach lib,$(IDO_LIBS),$(BUILT_BIN)/$(lib)) RECOMP_ELF := $(BUILD_BASE)/recomp.elf LIBC_IMPL := libc_impl +VERSION_INFO := version_info TARGET_BINARIES := $(foreach binary,$(IDO_TC),$(BUILT_BIN)/$(binary)) -O_FILES := $(foreach binary,$(IDO_TC),$(BUILD_DIR)/$(binary).o) +# NCC is filtered out since it isn't an actual program, but a symlink to cc +O_FILES := $(foreach binary,$(filter-out NCC, $(IDO_TC)),$(BUILD_DIR)/$(binary).o) C_FILES := $(O_FILES:.o=.c) # Automatic dependency files @@ -138,6 +152,8 @@ ifeq ($(DETECTED_OS),linux) $(RECOMP_ELF): LDFLAGS += -Wl,-export-dynamic endif +CFLAGS += -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\"" -DDATETIME="\"$(DATETIME)\"" + %/$(LIBC_IMPL).o: WARNINGS += -Wno-unused-parameter -Wno-deprecated-declarations %/$(LIBC_IMPL)_53.o: WARNINGS += -Wno-unused-parameter -Wno-deprecated-declarations @@ -220,25 +236,26 @@ $(BUILT_BIN)/%: $(BUILD_DIR)/arm64-apple-macos11/% $(BUILD_DIR)/x86_64-apple-mac ### Built programs ### -$(BUILD_DIR)/arm64-apple-macos11/%: $(BUILD_DIR)/arm64-apple-macos11/%.o $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL).o | $(ERR_STRS) +$(BUILD_DIR)/arm64-apple-macos11/%: $(BUILD_DIR)/arm64-apple-macos11/%.o $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL).o $(BUILD_DIR)/arm64-apple-macos11/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -target arm64-apple-macos11 -o $@ $^ $(LDFLAGS) $(STRIP) $@ -$(BUILD_DIR)/x86_64-apple-macos10.14/%: $(BUILD_DIR)/x86_64-apple-macos10.14/%.o $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL).o | $(ERR_STRS) +$(BUILD_DIR)/x86_64-apple-macos10.14/%: $(BUILD_DIR)/x86_64-apple-macos10.14/%.o $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL).o $(BUILD_DIR)/x86_64-apple-macos10.14/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -target x86_64-apple-macos10.14 -o $@ $^ $(LDFLAGS) $(STRIP) $@ +# NCC 7.1 is just a renamed cc $(BUILD_BASE)/7.1/arm64-apple-macos11/NCC: $(BUILD_BASE)/7.1/arm64-apple-macos11/cc cp $^ $@ $(BUILD_BASE)/7.1/x86_64-apple-macos10.14/NCC: $(BUILD_BASE)/7.1/x86_64-apple-macos10.14/cc cp $^ $@ -$(BUILD_DIR)/arm64-apple-macos11/edgcpfe: $(BUILD_DIR)/arm64-apple-macos11/edgcpfe.o $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL)_53.o | $(ERR_STRS) +$(BUILD_DIR)/arm64-apple-macos11/edgcpfe: $(BUILD_DIR)/arm64-apple-macos11/edgcpfe.o $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL)_53.o $(BUILD_DIR)/arm64-apple-macos11/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -target arm64-apple-macos11 -o $@ $^ $(LDFLAGS) $(STRIP) $@ -$(BUILD_DIR)/x86_64-apple-macos10.14/edgcpfe: $(BUILD_DIR)/x86_64-apple-macos10.14/edgcpfe.o $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL)_53.o | $(ERR_STRS) +$(BUILD_DIR)/x86_64-apple-macos10.14/edgcpfe: $(BUILD_DIR)/x86_64-apple-macos10.14/edgcpfe.o $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL)_53.o $(BUILD_DIR)/x86_64-apple-macos10.14/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -target x86_64-apple-macos10.14 -o $@ $^ $(LDFLAGS) $(STRIP) $@ @@ -264,10 +281,17 @@ $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL)_53.o: $(LIBC_IMPL).c $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL)_53.o: $(LIBC_IMPL).c $(CC) -c $(CSTD) $(OPTFLAGS) $(CFLAGS) -DIDO53 $(WARNINGS) -target x86_64-apple-macos10.14 -o $@ $< +# $(VERSION_INFO).o is set to depend on every other .o file to ensure the version information is always up to date +$(BUILD_DIR)/arm64-apple-macos11/$(VERSION_INFO).o: $(VERSION_INFO).c $(O_FILES) $(BUILD_DIR)/arm64-apple-macos11/$(LIBC_IMPL).o + $(CC) -c $(CSTD) $(OPTFLAGS) $(CFLAGS) -D$(IDO_VERSION) $(WARNINGS) -target arm64-apple-macos11 -o $@ $< + +$(BUILD_DIR)/x86_64-apple-macos10.14/$(VERSION_INFO).o: $(VERSION_INFO).c $(O_FILES) $(BUILD_DIR)/x86_64-apple-macos10.14/$(LIBC_IMPL).o + $(CC) -c $(CSTD) $(OPTFLAGS) $(CFLAGS) -D$(IDO_VERSION) $(WARNINGS) -target x86_64-apple-macos10.14 -o $@ $< + else ### Built programs ### -$(BUILT_BIN)/%: $(BUILD_DIR)/%.o $(BUILD_DIR)/$(LIBC_IMPL).o | $(ERR_STRS) +$(BUILT_BIN)/%: $(BUILD_DIR)/%.o $(BUILD_DIR)/$(LIBC_IMPL).o $(BUILD_DIR)/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(STRIP) $@ @@ -276,7 +300,7 @@ $(BUILD_BASE)/7.1/out/NCC: $(BUILD_BASE)/7.1/out/cc cp $^ $@ # edgcpfe 7.1 uses libc 5.3, so we need to hack a way to link a libc_impl file with the 5.3 stuff -$(BUILT_BIN)/edgcpfe: $(BUILD_DIR)/edgcpfe.o $(BUILD_DIR)/$(LIBC_IMPL)_53.o | $(ERR_STRS) +$(BUILT_BIN)/edgcpfe: $(BUILD_DIR)/edgcpfe.o $(BUILD_DIR)/$(LIBC_IMPL)_53.o $(BUILD_DIR)/$(VERSION_INFO).o | $(ERR_STRS) $(CC) $(CSTD) $(OPTFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(STRIP) $@ @@ -292,6 +316,10 @@ $(BUILD_DIR)/$(LIBC_IMPL).o: $(LIBC_IMPL).c $(BUILD_DIR)/$(LIBC_IMPL)_53.o: $(LIBC_IMPL).c $(CC) -c $(CSTD) $(OPTFLAGS) $(CFLAGS) -DIDO53 $(WARNINGS) -o $@ $< + +# $(VERSION_INFO).o is set to depend on every other .o file to ensure the version information is always up to date +$(BUILD_DIR)/$(VERSION_INFO).o: $(VERSION_INFO).c $(O_FILES) $(BUILD_DIR)/$(LIBC_IMPL).o $(BUILD_DIR)/$(LIBC_IMPL)_53.o + $(CC) -c $(CSTD) $(OPTFLAGS) $(CFLAGS) -D$(IDO_VERSION) $(WARNINGS) -o $@ $< endif # Remove built-in rules, to improve performance diff --git a/libc_impl.c b/libc_impl.c index a0837bb..363115c 100644 --- a/libc_impl.c +++ b/libc_impl.c @@ -42,8 +42,8 @@ #define STRING(param) \ size_t param##_len = wrapper_strlen(mem, param##_addr); \ char param[param##_len + 1]; \ - for (size_t i = 0; i <= param##_len; i++) { \ - param[i] = MEM_S8(param##_addr + i); \ + for (size_t __i = 0; __i <= param##_len; __i++) { \ + param[__i] = MEM_S8(param##_addr + __i); \ } #if !defined(IDO53) && !defined(IDO71) && !defined(IDO72) @@ -399,7 +399,7 @@ static void destroy_global_args(void) { static char** make_argv_from_mem(uint8_t* mem, int argc, uint32_t argv_addr) { char** argv = malloc((argc + 1) * sizeof(char*)); - for (uint32_t i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { uint32_t str_addr = MEM_U32(argv_addr + i * sizeof(uint32_t)); uint32_t len = wrapper_strlen(mem, str_addr) + 1; @@ -417,7 +417,7 @@ static char** make_argv_from_mem(uint8_t* mem, int argc, uint32_t argv_addr) { } static void free_argv(int argc, char** argv) { - for (uint32_t i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { free(argv[i]); } @@ -432,12 +432,20 @@ void final_cleanup(uint8_t* mem) { destroy_global_args(); } +void print_version_info(void); const char* progname; int main(int argc, char* argv[]) { int ret; progname = argv[0]; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--version") == 0) { + print_version_info(); + return 0; + } + } + init_redirect_paths(); #ifdef RUNTIME_PAGESIZE g_Pagesize = sysconf(_SC_PAGESIZE); diff --git a/version_info.c b/version_info.c new file mode 100644 index 0000000..b811b4c --- /dev/null +++ b/version_info.c @@ -0,0 +1,64 @@ +/** + * Function that prints version info. This file should be compiled with the following defined: + * - PACKAGE_VERSION, e.g. with `-DPACKAGE_VERSION="\"$(LC_ALL=C git --git-dir .git describe --tags --dirty)\""` + * - DATETIME, e.g. with `-DDATETIME="\"$(date +'%F %T UTC%z')\""` + * + * The code in this file is mostly taken from + * - CPython: https://github.com/python/cpython/, licensed under the PSF, available here: https://docs.python.org/3/license.html + * - The Ocarina of Time practice rom, gz: https://github.com/glankk/gz/ + */ +#include +#include +#include +#include + +#if defined(IDO53) +#define IDO_VERSION "IDO 5.3" +#elif defined(IDO71) +#define IDO_VERSION "IDO 7.1" +#else +#define IDO_VERSION "" +#endif + +#ifndef COMPILER + +// Note the __clang__ conditional has to come before the __GNUC__ one because +// clang pretends to be GCC. +#if defined(__clang__) +#define COMPILER "Clang " __clang_version__ +#elif defined(__GNUC__) +#define COMPILER "GCC " __VERSION__ +// Generic fallbacks. +#elif defined(__cplusplus) +#define COMPILER "C++" +#else +#define COMPILER "C" +#endif + +#endif /* !COMPILER */ + +/* git */ +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "Unknown version" +#endif + +/* Date and time */ +#ifndef DATETIME +#define DATETIME "Unknown date" +#endif + +extern char* progname; + +void print_version_info(void) { + char* buf = malloc(strlen(progname) + 1); + strcpy(buf, progname); + char* name = basename(buf); + + printf("%s `%s` static recompilation, Decompals version\n", IDO_VERSION, name); + printf("Source: https://github.com/decompals/ido-static-recomp\n"); + printf("Version: %s\n", PACKAGE_VERSION); + printf("Build date: %s\n", DATETIME); + printf("Compiler: %s\n", COMPILER); + + free(buf); +}