From d961e3cf279580a53fb91e8307c00543883fea95 Mon Sep 17 00:00:00 2001 From: Rosalie Wanders Date: Sat, 11 Nov 2023 15:38:22 +0100 Subject: [PATCH] ci: build mingw version of SporeModManager & SporeModLoader --- .github/workflows/build.yml | 35 ++++++- Makefile | 89 ++++-------------- SporeModLoader/Makefile | 57 ++++++++++++ SporeModLoader/SporeModLoader.cpp | 2 +- SporeModLoader/SporeModLoaderHelpers.cpp | 5 +- SporeModLoader/dllmain.cpp | 8 +- SporeModManager/Makefile | 111 +++++++++++++++++++++++ 7 files changed, 226 insertions(+), 81 deletions(-) create mode 100644 SporeModLoader/Makefile create mode 100644 SporeModManager/Makefile diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 254c0db..73a8baa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,7 @@ name: SporeModLoader on: [push, pull_request] jobs: - build: + msvc-build: runs-on: windows-2022 steps: - uses: actions/checkout@v4 @@ -50,6 +50,14 @@ jobs: with: name: SporeModLoader-${{ env.GIT_REVISION }} path: bin/* + # the modapi dlls cannot be compiled using mingw + # due to needing to keep ABI compatability with + # existing mods compiled with msvc + - name: Upload SporeModLoader (for mingw) + uses: actions/upload-artifact@v3 + with: + name: SporeModLoader-mingw-${{ env.GIT_REVISION }} + path: bin/* linux-build: runs-on: ubuntu-20.04 steps: @@ -61,9 +69,32 @@ jobs: echo "GIT_REVISION=$(git describe --tags --always)" >> $GITHUB_ENV - name: Build SporeModManager (Linux) run: | - make BINARY_DIR=bin/SporeModLoader/SporeModManager -j$(nproc) + make SporeModManager -j$(nproc) - name: Upload SporeModLoader (Linux) uses: actions/upload-artifact@v3 with: name: SporeModLoader-${{ env.GIT_REVISION }} path: bin/* + mingw-build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + - name: Install Packages + run: | + sudo apt-get -y install gcc-mingw-w64-i686 g++-mingw-w64-i686 + - name: Prepare Environment + run: | + echo "GIT_REVISION=$(git describe --tags --always)" >> $GITHUB_ENV + - name: Build SporeModLoader (mingw) + run: | + make SporeModLoader -j$(nproc) + - name: Build SporeModManager (mingw) + run: | + make SporeModManager.exe -j$(nproc) + - name: Upload SporeModLoader (mingw) + uses: actions/upload-artifact@v3 + with: + name: SporeModLoader-mingw-${{ env.GIT_REVISION }} + path: bin/* diff --git a/Makefile b/Makefile index c973453..20750a9 100644 --- a/Makefile +++ b/Makefile @@ -1,85 +1,30 @@ # # SporeModManager Makefile # -THIRDPARTY_DIR := 3rdParty -BINARY_DIR := bin -SOURCE_DIR := SporeModManager -EXE_FILE := SporeModManager -VERBOSE := 0 +SOURCE_DIR := $(CURDIR) +THIRDPARTY_DIR := $(SOURCE_DIR)/3rdParty -PKG_CONFIG := pkg-config CC := gcc CXX := g++ -CFLAGS := \ - -I$(THIRDPARTY_DIR)/zlib \ - -I$(THIRDPARTY_DIR)/zlib/contrib/minizip -CXXFLAGS := -std=c++17 \ - -I$(SOURCE_DIR) \ - -I$(THIRDPARTY_DIR)/tinyxml2 \ - -I$(THIRDPARTY_DIR)/zlib \ - -I$(THIRDPARTY_DIR)/zlib/contrib/minizip -OPTFLAGS := -Os -flto -LDFLAGS := -flto -s +MINGW_CC := i686-w64-mingw32-gcc +MINGW_CXX := i686-w64-mingw32-g++ -OBJECT_FILES := \ - $(SOURCE_DIR)/SporeModManagerHelpers/FileVersion.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/Path.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/SporeMod.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/SporeModXml.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/String.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/UI.o \ - $(SOURCE_DIR)/SporeModManagerHelpers/Zip.o \ - $(SOURCE_DIR)/SporeModManager.o \ - $(SOURCE_DIR)/main.o +export THIRDPARTY_DIR CC CXX MINGW_CC MINGW_CXX -HEADER_FILES := \ - $(SOURCE_DIR)/SporeModManager.hpp \ - $(SOURCE_DIR)/SporeModManagerHelpers.hpp +all: SporeModLoader SporeModManager SporeModManager.exe +clean: + $(MAKE) -C SporeModLoader clean BINARY_DIR=$(SOURCE_DIR)/bin/SporebinEP1 + $(MAKE) -C SporeModManager clean BINARY_DIR=$(SOURCE_DIR)/bin/SporeModLoader/SporeModManager + $(MAKE) -C SporeModManager clean MINGW=1 BINARY_DIR=$(SOURCE_DIR)/bin/SporeModLoader/SporeModManager -THIRDPARTY_OBJECT_FILES := \ - $(THIRDPARTY_DIR)/tinyxml2/tinyxml2.o \ - $(THIRDPARTY_DIR)/zlib/adler32.o \ - $(THIRDPARTY_DIR)/zlib/crc32.o \ - $(THIRDPARTY_DIR)/zlib/inflate.o \ - $(THIRDPARTY_DIR)/zlib/inffast.o \ - $(THIRDPARTY_DIR)/zlib/inftrees.o \ - $(THIRDPARTY_DIR)/zlib/zutil.o \ - $(THIRDPARTY_DIR)/zlib/contrib/minizip/unzip.o \ - $(THIRDPARTY_DIR)/zlib/contrib/minizip/ioapi.o - -THIRDPARTY_HEADER_FILES := \ - $(THIRDPARTY_DIR)/zlib/zconf.h - - -ifeq ($(VERBOSE), 0) - QUIET := @ -else - QUIET := -endif - -%.o: %.c $(THIRDPARTY_HEADER_FILES) - @echo "CC $<" - $(QUIET)$(CC) -c $< -o $@ $(OPTFLAGS) $(CFLAGS) - -%.o: %.cpp $(HEADER_FILES) $(THIRDPARTY_HEADER_FILES) - @echo "CXX $<" - $(QUIET)$(CXX) -c $< -o $@ $(OPTFLAGS) $(CXXFLAGS) - -all: $(BINARY_DIR)/$(EXE_FILE) - -$(BINARY_DIR): - $(QUIET)mkdir -p $@ - -$(THIRDPARTY_DIR)/zlib/zconf.h: - @echo "GEN $@" - $(QUIET)cp $@.in $@ +SporeModLoader: + $(MAKE) -C $@ SOURCE_DIR=$(SOURCE_DIR)/$@ BINARY_DIR=$(SOURCE_DIR)/bin/SporebinEP1 -$(BINARY_DIR)/$(EXE_FILE): $(BINARY_DIR) $(THIRDPARTY_OBJECT_FILES) $(OBJECT_FILES) - @echo "LD $@" - $(QUIET)$(CXX) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) -o $@ $(LDFLAGS) +SporeModManager: + $(MAKE) -C $@ SOURCE_DIR=$(SOURCE_DIR)/$@ BINARY_DIR=$(SOURCE_DIR)/bin/SporeModLoader/SporeModManager -clean: - rm -f $(BINARY_DIR)/$(EXE_FILE) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) $(THIRDPARTY_HEADER_FILES) +SporeModManager.exe: + $(MAKE) -C $(basename $@) SOURCE_DIR=$(SOURCE_DIR)/$(basename $@) BINARY_DIR=$(SOURCE_DIR)/bin/SporeModLoader/SporeModManager MINGW=1 -.PHONY: all clean +.PHONY: SporeModLoader SporeModManager SporeModManager.exe all clean diff --git a/SporeModLoader/Makefile b/SporeModLoader/Makefile new file mode 100644 index 0000000..999ec21 --- /dev/null +++ b/SporeModLoader/Makefile @@ -0,0 +1,57 @@ +# +# SporeModLoader Makefile +# +THIRDPARTY_DIR ?= ../3rdParty +BINARY_DIR ?= bin +SOURCE_DIR ?= . +DLL_FILE ?= dinput8.dll +VERBOSE ?= 0 + +MINGW_CXX ?= i686-w64-mingw32-g++ +CXXFLAGS := -std=c++17 \ + -I$(SOURCE_DIR) \ + -I$(THIRDPARTY_DIR)/Detours/src \ + -Wno-attributes -Wp,-w +OPTFLAGS := -Os -flto +LDFLAGS := -s -flto + +OBJECT_FILES := \ + $(SOURCE_DIR)/SporeModLoaderHelpers.obj \ + $(SOURCE_DIR)/SporeModLoader.obj \ + $(SOURCE_DIR)/dllmain.obj + +HEADER_FILES := \ + $(SOURCE_DIR)/SporeModLoaderHelpers.hpp \ + $(SOURCE_DIR)/SporeModLoader.hpp + +THIRDPARTY_OBJECT_FILES := \ + $(THIRDPARTY_DIR)/Detours/src/detours.obj \ + $(THIRDPARTY_DIR)/Detours/src/modules.obj \ + $(THIRDPARTY_DIR)/Detours/src/disasm.obj \ + $(THIRDPARTY_DIR)/Detours/src/image.obj \ + $(THIRDPARTY_DIR)/Detours/src/creatwth.obj \ + $(THIRDPARTY_DIR)/Detours/src/disolx86.obj + +ifeq ($(VERBOSE), 0) + QUIET := @ +else + QUIET := +endif + +%.obj: %.cpp $(HEADER_FILES) + @echo "MINGW_CXX $<" + $(QUIET)$(MINGW_CXX) -c $< -o $@ $(OPTFLAGS) $(CXXFLAGS) + +all: $(BINARY_DIR)/$(DLL_FILE) + +$(BINARY_DIR): + $(QUIET)mkdir -p $@ + +$(BINARY_DIR)/$(DLL_FILE): $(BINARY_DIR) $(THIRDPARTY_OBJECT_FILES) $(OBJECT_FILES) + @echo "MINGW_LD $@" + $(QUIET)$(MINGW_CXX) $(THIRDPARTY_OBJECT_FILES) $(OBJECT_FILES) -static -shared $(SOURCE_DIR)/dllmain.def -o $@ $(LDFLAGS) + +clean: + rm -f $(BINARY_DIR)/$(DLL_FILE) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) $(THIRDPARTY_HEADER_FILES) + +.PHONY: all clean \ No newline at end of file diff --git a/SporeModLoader/SporeModLoader.cpp b/SporeModLoader/SporeModLoader.cpp index 6e05d5c..e2ec859 100644 --- a/SporeModLoader/SporeModLoader.cpp +++ b/SporeModLoader/SporeModLoader.cpp @@ -7,7 +7,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include "SporeModLoader.hpp" #include "SporeModLoaderHelpers.hpp" diff --git a/SporeModLoader/SporeModLoaderHelpers.cpp b/SporeModLoader/SporeModLoaderHelpers.cpp index 996c056..5ccaf0e 100644 --- a/SporeModLoader/SporeModLoaderHelpers.cpp +++ b/SporeModLoader/SporeModLoaderHelpers.cpp @@ -7,7 +7,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include @@ -145,7 +145,8 @@ std::vector Path::GetModLibsPaths(void) std::wstring filename = entry.path().filename().wstring(); for (const auto& postfix : excludePostfixes) { - if (filename.ends_with(postfix)) + // HACK: TODO: rewrite ends_with in C++17 + if (filename.find(postfix) != std::wstring::npos) { skipLib = true; break; diff --git a/SporeModLoader/dllmain.cpp b/SporeModLoader/dllmain.cpp index 3bc4c5b..dae9b59 100644 --- a/SporeModLoader/dllmain.cpp +++ b/SporeModLoader/dllmain.cpp @@ -7,7 +7,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include "detours.h" #include "SporeModLoader.hpp" @@ -46,7 +46,7 @@ static int SporeAppEntry_detoured(void) // The game calls this function but ignores the result, // so just return E_FAIL. -HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID* ppvOut, LPUNKNOWN punkOuter) +extern "C" HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID* ppvOut, LPUNKNOWN punkOuter) { return E_FAIL; } @@ -68,7 +68,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); - DetourAttach(&(PVOID&)SporeAppEntry_real, SporeAppEntry_detoured); + DetourAttach(&(PVOID&)SporeAppEntry_real, (PVOID)SporeAppEntry_detoured); DetourTransactionCommit(); } else if (dwReason == DLL_PROCESS_DETACH) @@ -77,7 +77,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) DetourUpdateThread(GetCurrentThread()); if (SporeAppEntry_real != nullptr) { - DetourDetach(&(PVOID&)SporeAppEntry_real, SporeAppEntry_detoured); + DetourDetach(&(PVOID&)SporeAppEntry_real, (PVOID)SporeAppEntry_detoured); } DetourTransactionCommit(); } diff --git a/SporeModManager/Makefile b/SporeModManager/Makefile new file mode 100644 index 0000000..519654e --- /dev/null +++ b/SporeModManager/Makefile @@ -0,0 +1,111 @@ +# +# SporeModManager Makefile +# +THIRDPARTY_DIR ?= ../3rdParty +BINARY_DIR ?= bin +SOURCE_DIR ?= . +EXE_FILE ?= SporeModManager +VERBOSE ?= 0 +MINGW ?= 0 + +CC ?= gcc +CXX ?= g++ +MINGW_CC ?= i686-w64-mingw32-gcc +MINGW_CXX ?= i686-w64-mingw32-g++ + +ifeq ($(MINGW), 0) +LDFLAGS := -flto -s +OPTFLAGS := -Os -flto +OBJ := o +EXE_EXT := +else +# mingw doesn't like LTO +# and we need to statically link +LDFLAGS := -s -municode -static +OPTFLAGS := -Os +OBJ := obj +EXE_EXT := .exe +endif +CFLAGS := \ + -I$(THIRDPARTY_DIR)/zlib \ + -I$(THIRDPARTY_DIR)/zlib/contrib/minizip +CXXFLAGS := -std=c++17 \ + -I$(SOURCE_DIR) \ + -I$(THIRDPARTY_DIR)/tinyxml2 \ + -I$(THIRDPARTY_DIR)/zlib \ + -I$(THIRDPARTY_DIR)/zlib/contrib/minizip + +OBJECT_FILES := \ + $(SOURCE_DIR)/SporeModManagerHelpers/FileVersion.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/Path.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/SporeMod.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/SporeModXml.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/String.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/UI.$(OBJ) \ + $(SOURCE_DIR)/SporeModManagerHelpers/Zip.$(OBJ) \ + $(SOURCE_DIR)/SporeModManager.$(OBJ) \ + $(SOURCE_DIR)/main.$(OBJ) + +HEADER_FILES := \ + $(SOURCE_DIR)/SporeModManager.hpp \ + $(SOURCE_DIR)/SporeModManagerHelpers.hpp + + +THIRDPARTY_OBJECT_FILES := \ + $(THIRDPARTY_DIR)/tinyxml2/tinyxml2.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/adler32.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/crc32.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/inflate.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/inffast.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/inftrees.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/zutil.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/contrib/minizip/unzip.$(OBJ) \ + $(THIRDPARTY_DIR)/zlib/contrib/minizip/ioapi.$(OBJ) + +THIRDPARTY_HEADER_FILES := \ + $(THIRDPARTY_DIR)/zlib/zconf.h + + +ifeq ($(VERBOSE), 0) + QUIET := @ +else + QUIET := +endif + +%.o: %.c $(THIRDPARTY_HEADER_FILES) + @echo "CC $<" + $(QUIET)$(CC) -c $< -o $@ $(OPTFLAGS) $(CFLAGS) + +%.o: %.cpp $(HEADER_FILES) $(THIRDPARTY_HEADER_FILES) + @echo "CXX $<" + $(QUIET)$(CXX) -c $< -o $@ $(OPTFLAGS) $(CXXFLAGS) + +%.obj: %.c $(THIRDPARTY_HEADER_FILES) + @echo "MINGW_CC $<" + $(QUIET)$(MINGW_CC) -c $< -o $@ $(OPTFLAGS) $(CFLAGS) + +%.obj: %.cpp $(HEADER_FILES) $(THIRDPARTY_HEADER_FILES) + @echo "MINGW_CXX $<" + $(QUIET)$(MINGW_CXX) -c $< -o $@ $(OPTFLAGS) $(CXXFLAGS) + +all: $(BINARY_DIR)/$(EXE_FILE)$(EXE_EXT) + +$(BINARY_DIR): + $(QUIET)mkdir -p $@ + +$(THIRDPARTY_DIR)/zlib/zconf.h: + @echo "GEN $@" + $(QUIET)cp -f $@.in $@ + +$(BINARY_DIR)/$(EXE_FILE): $(BINARY_DIR) $(THIRDPARTY_OBJECT_FILES) $(OBJECT_FILES) + @echo "LD $@" + $(QUIET)$(CXX) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) -o $@ $(LDFLAGS) + +$(BINARY_DIR)/$(EXE_FILE).exe: $(BINARY_DIR) $(THIRDPARTY_OBJECT_FILES) $(OBJECT_FILES) + @echo "MINGW_LD $@" + $(QUIET)$(MINGW_CXX) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) -o $@ $(LDFLAGS) + +clean: + rm -f $(BINARY_DIR)/$(EXE_FILE)$(EXE_EXT) $(OBJECT_FILES) $(THIRDPARTY_OBJECT_FILES) $(THIRDPARTY_HEADER_FILES) + +.PHONY: all clean