Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix building with wine wrapped MSVC #24

Merged
merged 1 commit into from
Aug 23, 2024
Merged

Conversation

Edremon
Copy link

@Edremon Edremon commented Aug 19, 2024

Those changes allow to build gbe_fork for Windows on Linux with MinGW. There is also some change needed ingame_overlay:

--- a/deps/System/include/System/SystemExports.h
+++ b/deps/System/include/System/SystemExports.h
@@ -89,7 +89,7 @@ Copy/Paste this code in some source file if you want to call a function when the
 
 #define VC_EXTRALEAN
 #define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
+#include <windows.h>
 
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
diff --git a/deps/System/src/Filesystem.cpp b/deps/System/src/Filesystem.cpp
index 068d45a..20fd50b 100755
--- a/deps/System/src/Filesystem.cpp
+++ b/deps/System/src/Filesystem.cpp
@@ -25,7 +25,7 @@
     #define WIN32_LEAN_AND_MEAN
     #define VC_EXTRALEAN
     #define NOMINMAX
-    #include <Windows.h>
+    #include <windows.h>
 
     #ifdef CreateDirectory
     #undef CreateDirectory
diff --git a/deps/System/src/Library.cpp b/deps/System/src/Library.cpp
index 5033384..da1ccda 100755
--- a/deps/System/src/Library.cpp
+++ b/deps/System/src/Library.cpp
@@ -26,7 +26,7 @@
     #define WIN32_LEAN_AND_MEAN
     #define VC_EXTRALEAN
     #define NOMINMAX
-    #include <Windows.h>
+    #include <windows.h>
 
     constexpr char library_suffix[] = ".dll";
 
diff --git a/deps/System/src/System.cpp b/deps/System/src/System.cpp
index 8b00a8f..3c94650 100755
--- a/deps/System/src/System.cpp
+++ b/deps/System/src/System.cpp
@@ -26,8 +26,8 @@
     #define WIN32_LEAN_AND_MEAN
     #define VC_EXTRALEAN
     #define NOMINMAX
-    #include <Windows.h>
-    #include <TlHelp32.h>
+    #include <windows.h>
+    #include <tlhelp32.h>
     #include <shellapi.h>
     #include <shlobj.h>   // (shell32.lib) Infos about current user folders
 
diff --git a/deps/System/src/System_internals.cpp b/deps/System/src/System_internals.cpp
index 55f58d5..eb0a5c3 100755
--- a/deps/System/src/System_internals.cpp
+++ b/deps/System/src/System_internals.cpp
@@ -23,7 +23,7 @@
 #define WIN32_LEAN_AND_MEAN
 #define VC_EXTRALEAN
 #define NOMINMAX
-#include <Windows.h>
+#include <windows.h>
 
 namespace System {
 
diff --git a/deps/System/tests/shared_main.cpp b/deps/System/tests/shared_main.cpp
index e3f44f5..b60a641 100755
--- a/deps/System/tests/shared_main.cpp
+++ b/deps/System/tests/shared_main.cpp
@@ -38,7 +38,7 @@ SYSTEM_EXPORT_API(SYSTEM_EXTERN_C, result_wrapper, SYSTEM_MODE_EXPORT, SYSTEM_CA
 
 #define VC_EXTRALEAN
 #define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
+#include <windows.h>
 
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
diff --git a/deps/mini_detour/src/mini_detour_windows.h b/deps/mini_detour/src/mini_detour_windows.h
index dff21a9..d9c2942 100755
--- a/deps/mini_detour/src/mini_detour_windows.h
+++ b/deps/mini_detour/src/mini_detour_windows.h
@@ -4,7 +4,7 @@
 #define WIN32_LEAN_AND_MEAN
 #define VC_EXTRALEAN
 #define NOMINMAX
-#include <Windows.h>
+#include <windows.h>
 
 namespace MemoryManipulation {
 #if defined(MINIDETOUR_ARCH_X64) || defined(MINIDETOUR_ARCH_ARM64)
diff --git a/src/Windows/RendererDetector.cpp b/src/Windows/RendererDetector.cpp
index 2804769..ea893e0 100755
--- a/src/Windows/RendererDetector.cpp
+++ b/src/Windows/RendererDetector.cpp
@@ -854,7 +854,7 @@ private:
     ATOM _DummyWindowAtom;
 
     RendererDetector_t() :
-        _RendererHook(false),
+        _RendererHook(nullptr),
         _DetectionStarted(false),
         _DetectionDone(false),
         _DetectionCount(0),
@@ -1594,4 +1594,4 @@ RendererHook_t* CreateRendererHook(RendererHookType_t hookType, bool preferSyste
     return rendererHook;
 }
 
-}// namespace InGameOverlay
\ No newline at end of file
+}// namespace InGameOverlay
diff --git a/tests/common/glfw/include/GLFW/glfw3.h b/tests/common/glfw/include/GLFW/glfw3.h
index 43b4ea8..ee7b172 100755
--- a/tests/common/glfw/include/GLFW/glfw3.h
+++ b/tests/common/glfw/include/GLFW/glfw3.h
@@ -5907,7 +5907,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
  *  GLFW_PLATFORM_ERROR.
  *
- *  @remark @win32 The clipboard on Windows has a single global lock for reading and
+ *  @remark @win32 The clipboard on windows.has a single global lock for reading and
  *  writing.  GLFW tries to acquire it a few times, which is almost always enough.  If it
  *  cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
  *  It is safe to try this multiple times.
@@ -5940,7 +5940,7 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
  *  GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
  *
- *  @remark @win32 The clipboard on Windows has a single global lock for reading and
+ *  @remark @win32 The clipboard on windows.has a single global lock for reading and
  *  writing.  GLFW tries to acquire it a few times, which is almost always enough.  If it
  *  cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
  *  It is safe to try this multiple times.
diff --git a/tests/overlay_example/library_main.cpp b/tests/overlay_example/library_main.cpp
index 534c1f1..f9f6493 100755
--- a/tests/overlay_example/library_main.cpp
+++ b/tests/overlay_example/library_main.cpp
@@ -218,7 +218,7 @@ void shared_library_unload(void* hmodule)
 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) ||\
     defined(_WIN64) || defined(WIN64) || defined(__MINGW64__)
 
-#include <Windows.h>
+#include <windows.h>
 
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
diff --git a/tests/test_overlay/library_main.cpp b/tests/test_overlay/library_main.cpp
index 2da2b9a..af80586 100755
--- a/tests/test_overlay/library_main.cpp
+++ b/tests/test_overlay/library_main.cpp
@@ -117,7 +117,7 @@ void shared_library_unload(void* hmodule)
 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) ||\
     defined(_WIN64) || defined(WIN64) || defined(__MINGW64__)
 
-#include <Windows.h>
+#include <windows.h>
 
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
 {

I only tested building on x64. The resulting .dll fail make my game crash for some reason. With a debug build, I don't see anything wrong in the STEAM_LOG.txt generated by the emu. The crash is a simple Unhandled exception: page fault on read access to 0xffffffffffffffff in 64-bit code (0x00000140e8d11f). while the game is loading. The backtrace doesn't tell anything useful, only game/kernel/ntdll in it, nothing about steam.

@otavepto
Copy link

msvc and gcc/clang have different ABI, a function returning a trivial class instance for example (class containing only numerics for example) is flattened directly into RAX register on x64 with gcc/clang for Windows, while msvc will always change the signature of the function to be void and the 1st arg will be an out param with same type as the desired (old) return type, and the caller will get the result via an allocated local.

MyClass get()

// becomes
void get(MyClass *ret)

check this API via an assembly debugger as an example

CSteamID Steam_User::GetSteamID()

Valve did this manually in some of the old interfaces versions and later ditched the idea.

STEAMWORKS_STRUCT_RETURN_2(CSteamID, GetFriendByIndex, int, iFriend, EFriendFlags, eFriendFlags) /*virtual CSteamID GetFriendByIndex( int iFriend, EFriendFlags eFriendFlags ) = 0;*/

#define STEAMWORKS_STRUCT_RETURN_2(returnType, functionName, arg1Type, arg1Name, arg2Type, arg2Name) \

and the implementation

void Steam_Friends::GetFriendByIndex(CSteamID& res, int iFriend, int iFriendFlags )

this won't work, the original API library and the client library on Windows are both using msvc's ABI.
this is why you're getting weird crashes, attach a debugger to see it in action.
the original SDK doesn't even support anything other than Visual Studio.
forget about this whole idea, trust me it's an absolute waste of time with 0 gain, if you hate Visual Studio that much use Build Tools from Microsoft or use Gihub's runner, it takes less than 10 min to build everything.

@otavepto
Copy link

some similar cases
https://stackoverflow.com/questions/71711846/segfault-on-some-steam-api-dll-calls-from-executable-compiled-with-mingw-gcc-an/76582160#76582160

if you search the web can i use mingw for steam sdk you'll get plenty more from people trying that with the original SDK.
this is my genuine search query, not being sarcastic.

remember all apps/games out there are linked against the original API library (steam_api.dll), you can't change that

@Edremon
Copy link
Author

Edremon commented Aug 20, 2024

How does DXVK, vkd3d, wine libs and proton steam api bridge work then? They all use mingw gcc as far as I know and they work nicely with existing programs.

I would like to build gbe fork with FOSS tools and libs.

@otavepto
Copy link

otavepto commented Aug 20, 2024

are they returning class instances or trivial types ?
also note that Dx11 and Dx12 even have manual vftable which you can hook, making it compatible with C code

I don't know what is proton steam api bridge, but in case it does the magic I'm interested as well, didn't find any workflow though so I can't tell what's the purpose or the output, it could be just an implementation/hooking for Win32 APIs which are all flat C functions.

ping me if you found more about this.
if you can check the API I mentioned earlier with an assembly debugger see how it returns the user id, in RAX or in a local stack var.

@Edremon
Copy link
Author

Edremon commented Aug 20, 2024

I don't understand how they do it. There is not that much information from my search other that it's not possible but wine or mingw must have something to make it work.

Another possibility is to build using either MSVC in wine (like goldberg originally did in his CI) or use clang-cl with MSVC but that still make the build reliant on proprietary stuff.

@otavepto
Copy link

otavepto commented Aug 20, 2024

I looked now at the gitlab workflow of the original repo, it seems to have 2 build types.

The first one is build_windows, it indeed runs on fedora, it uses Wine and eventually calls python generate_build_win_bat.py at line 75.

- python generate_build_win_bat.py

Looking into the .py script, it generates a .bat file, but it uses cl.exe as a compiler (the compiler used by Visual Studio & Microsoft's build tools)
These are the relevant lines:
Line 97 will write the line that links all objects in the generated .bat file

out = ""
out += cl_line_obj(normal_build_args + release_build_args + include_arch + all_deps, deps_folder)
out += cl_line_link(normal_build_args + release_build_args + include_arch + steam_deps + sc_different_deps + ["deps/net.pb.obj"] + linker_arch + normal_linker_libs, ["/debug:none", "/OUT:release\\{}".format(steam_api_name)])

And the function cl_line_link is defined above as

def cl_line_link(arguments, linker_arguments):
    return "cl /LD {} /link {}\n".format(' '.join(arguments), ' '.join(linker_arguments))

The function above it creates the object files

def cl_line_obj(arguments, out_dir):
    return "rmdir /S /Q {0}\nmkdir {0}\ncl /Fo:{0}/ /c {1}\n".format(out_dir, ' '.join(arguments))

This is the string formatted (replacing \n with actual lines for readability)

"rmdir /S /Q {0}"
"mkdir {0}"
"cl /Fo:{0}/ /c {1}"

The last line is also another call to cl.exe

It eventually dumps the output to build_win_release_test.bat here

with open("build_win_release_test.bat", "w") as f:
    f.write(out)

And wine will run this batch script here

- python generate_build_win_bat.py
- export WINEDEBUG=-all
- wine cmd /c build_win_release_test.bat

This way the CI run/build time is as minimum as possible (all repos providers charge/consume from your minutes way less on Linux runners), and the build is done through a Microsoft compiler ensuring correct ABI in the output binaries. This is a clever idea indeed but github (and I assume also gitlab) gives you unlimited build times for non-private repos, still the build time is always way less on Linux.

Looking at the pipeline of the last commit: SDK 1.56 and 1.57 you can see it runs the above workflow job build_windows
In the job log, starting from this line the Microsoft compiler is invoked and the usual output is displayed

Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24245 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.
steam_apps.cpp
steam_gameserver.cpp
steam_parental.cpp
steam_screenshots.cpp
local_storage.cpp
settings_parser.cpp
steam_applist.cpp
...
...
...
Microsoft (R) Incremental Linker Version 14.00.24245.0
Copyright (C) Microsoft Corporation.  All rights reserved.
/out:steam_apps.dll 
/dll 
/implib:steam_apps.lib
...
...
...
rtlgenrandom.lib 
Shell32.lib 
   Creating library steam_apps.lib and object steam_apps.exp
Success.

The second one is build_cmake_windows which you can see is always skipped in the CI pipeline, it creates a batch script which calls set_vars64.bat to set the path for cl.exe

...
...
- 7za x sdk_standalone.7z -osdk_standalone
...
...
- wine cmd /c
- mkdir cmake-builds && cd cmake-builds
- mkdir x64-release && cd x64-release
- echo call .\\..\\..\\sdk_standalone\\set_vars64.bat >> cmake-build.bat
- echo .\\..\\..\\cmake-3.15.0-rc1-win64-x64\\bin\\cmake.exe ..\\.. -G \"NMake Makefiles\" -DCMAKE_BUILD_TYPE:STRING="RelWithDebInfo" -DCMAKE_PREFIX_PATH="protobuf_x64-windows-static" -DProtobuf_PROTOC_EXECUTABLE:STRING="./../../protobuf_x64-windows-static/tools/protobuf/protoc.exe" >> cmake-build.bat
- echo nmake.exe >> cmake-build.bat
- wine cmd /c cmake-build.bat

You can download the sdk_standalone archive from its link mentioned here: https://gitlab.com/Mr_Goldberg/goldberg_emulator/-/blob/master/.gitlab-ci.yml?ref_type=heads#L114
It's a 112MB .7z archive.
Here's the entire set_vars64.bat

batch script
SET VSINSTALLDIR=%~dp0Microsoft Visual Studio 14.0\
SET VCINSTALLDIR=%VSINSTALLDIR%VC\
SET VS140COMNTOOLS=%VSINSTALLDIR%Common7\Tools\
SET UCRTVersion=10.0.17763.0
SET WindowsSdkDir=%~dp0Windows Kits\10\
SET UniversalCRTSdkDir=%WindowsSdkDir%
SET WindowsSDKVersion=10.0.17763.0\
SET WindowsSDKLibVersion=10.0.17763.0\
SET WindowsSDK_ExecutablePath_x64=%~dp0Windows Kits\10\bin\%WindowsSDKVersion%x64\

SET LIB=
SET INCLUDE=
SET LIBPATH=

@if exist "%VSINSTALLDIR%Common7\Tools" set PATH=%VSINSTALLDIR%Common7\Tools;%PATH%
@if exist "%VSINSTALLDIR%Common7\IDE" set PATH=%VSINSTALLDIR%Common7\IDE;%PATH%
@if exist "%VCINSTALLDIR%VCPackages" set PATH=%VCINSTALLDIR%VCPackages;%PATH%
@if exist "%VCINSTALLDIR%BIN\amd64" set PATH=%VCINSTALLDIR%BIN\amd64;%PATH%

@if not "%UCRTVersion%" == "" @set INCLUDE=%UniversalCRTSdkDir%include\%UCRTVersion%\ucrt;%INCLUDE%
@if not "%UCRTVersion%" == "" @set LIB=%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64;%LIB%

@if not "%WindowsSdkDir%" == "" @set PATH=%WindowsSdkDir%bin\x64;%WindowsSdkDir%bin\x86;%PATH%
@if not "%WindowsSdkDir%" == "" @set INCLUDE=%WindowsSdkDir%include\%WindowsSDKVersion%shared;%WindowsSdkDir%include\%WindowsSDKVersion%um;%WindowsSdkDir%include\%WindowsSDKVersion%winrt;%INCLUDE%
@if not "%WindowsSdkDir%" == "" @set LIB=%WindowsSdkDir%lib\%WindowsSDKLibVersion%um\x64;%LIB%
@if not "%WindowsSdkDir%" == "" @set LIBPATH=%WindowsLibPath%;%ExtensionSDKDir%\Microsoft.VCLibs\14.0\References\CommonConfiguration\neutral;%LIBPATH%

@if not "%WindowsSDK_ExecutablePath_x64%" == "" @set PATH=%WindowsSDK_ExecutablePath_x64%;%PATH%

@if exist "%VCINSTALLDIR%LIB\store\amd64" set LIB=%VCINSTALLDIR%LIB\store\amd64;%LIB%

@if exist "%VCINSTALLDIR%ATLMFC\INCLUDE" set INCLUDE=%VCINSTALLDIR%ATLMFC\INCLUDE;%INCLUDE%
@if exist "%VCINSTALLDIR%INCLUDE" set INCLUDE=%VCINSTALLDIR%INCLUDE;%INCLUDE%

@if exist "%VCINSTALLDIR%ATLMFC\LIB\amd64" set LIB=%VCINSTALLDIR%ATLMFC\LIB\amd64;%LIB%
@if exist "%VCINSTALLDIR%LIB\amd64" set LIB=%VCINSTALLDIR%LIB\amd64;%LIB%

@if exist "%VCINSTALLDIR%ATLMFC\LIB\amd64" set LIBPATH=%VCINSTALLDIR%ATLMFC\LIB\amd64;%LIBPATH%
@if exist "%VCINSTALLDIR%LIB\amd64" set LIBPATH=%VCINSTALLDIR%LIB\amd64;%LIBPATH%

@if exist "%VCINSTALLDIR%LIB\store\amd64" set LIBPATH=%VCINSTALLDIR%LIB\store\amd64;%VCINSTALLDIR%LIB\store\references;%LIBPATH%

It is setting every env var used by Microsoft's build tools, and accordingly Visual Studio, manually.

And finally calls cmake as seen above. It looks more or less the same as the first job, except the build files are generated and ran by cmake.
I'm not sure how or why nmake is used there, but you can completely ignore this job since the CI never runs it.

The summary of it is that the entire project was always being built with a Microsoft compiler for Windows OS, except it was done through wine, not MinGW.

Some things you can also see in the workflow is that the original author did the same and cached the deps as public archives in the repo, they are the equivalent to the branches third-party/**** here on Github, the idea is to avoid depending on the original links since they may get taken down for one reason or another.

I still remember the 1st issue discussing how crap and hacky the 2 build scripts I made for myself back then, but it seems no one bothered to look into the original project's CI workflow (I'm still salty about it 😄 ).

Anyway, this is my deep dive into the gitlab workflows, I'm looking forward to the future of how this develops, compiler/linker challenges are always intriguing to me.

Edit: Looking into the archive more, it turned to be the entire Microsoft Build tools compressed, when extracted it is 1.52GB.

@Edremon
Copy link
Author

Edremon commented Aug 20, 2024

I always used the same way to build as Goldberg, always build it locally with wine and MSVC, but with the whole rewrite thought we could go leaner.

I currently managed to build it with wine and MSVC cl, the resulting dll worked correctly. I'm now trying with clang-cl (and x86_64-windows-msvc target), but I'm struggling. The deps part worked correctly, but the problem is with gbe fork. premake with the deps is just using cmake so it generate correct makefile, but premake with gbe fork will either generate a visual studio solution which I can't use or makefile in normal gcc/ld format.

@otavepto
Copy link

According to their docs it can generate GNU make files including Cygwin & MinGW using the gmake2 action

premake5 --file=premake5.lua --genproto --os=windows gmake2

I don't have any VM but did the above line not work on wine?

@Edremon
Copy link
Author

Edremon commented Aug 20, 2024

I just don't think that it is possible to currently use clang-cl with premake. Would have to rewrite it to use CMake or another build system that support clang-cl. I'm too lazy for that, and it will still use most of the proprietary MSVC stuff anyway.

According to their docs it can generate GNU make files including Cygwin & MinGW using the gmake2 action

That not the problem, the problem is those makefiles use GNU-like command options instead of MSVC-like command options. CMake auto detect which compiler options should those makefile use, premake have hardcoded GNU-like options.

I don't have any VM but did the above line not work on wine?

Those command are not being run in wine, I never run premake under wine in either wine msvc build or clang-cl, wine is only used to call the compiler (and msbuild in msvc case). Also the whole goal of using clang-cl is to not use wine at all.

I added a commit to support building with msvc on wine, I'm using msvc-wine to simplify the task. It is running on a single thread because it errors otherwise (at least on my machine), you can run it on more if you want to build faster but would have to relaunch it a few times.

Here basically how I build it:

premake5 --file=premake5-deps.lua --32-build --all-ext --all-build --custom-cmake=cmake --cmake-toolchain=/opt/msvc/cmake/toolchain-x86.cmake --custom-extractor=7z --j=$(nproc) --os=windows vs2022
premake5 --file=premake5-deps.lua --64-build --all-ext --all-build --custom-cmake=cmake --cmake-toolchain=/opt/msvc/cmake/toolchain-x64.cmake --custom-extractor=7z --j=$(nproc) --os=windows vs2022
premake5 --file=premake5.lua --genproto --os=windows vs2022
cd build/project/vs2022/win
/opt/msvc/bin/x86/msbuild '/nologo' '/v:n' '/p:Configuration=release,Platform=Win32' gbe.sln
/opt/msvc/bin/x64/msbuild '/nologo' '/v:n' '/p:Configuration=release,Platform=x64' gbe.sln

@Edremon
Copy link
Author

Edremon commented Aug 21, 2024

So, what should be the future of this PR?

I propose to merge those two commits into a single "Allow building with wine wrapped MSVC", keeping only the relevant change to make it able to be built with MSVC wrapped in wine. Keeping custom-extractor, cmake-toolchain options and calling executable with wine. We could do without cmake-toolchain by using a wrapper like this for cmake:

if echo -- "$@" | grep -Ewq "(--build|--install|-E|--system-information)" ; then
    cmake "$@"
else
    cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake  "$@"
fi

But that is a bit annoying, same for extractor, could just wrap it with wine or use linux extractor binaries. But overall, I'm really not a fan of using binaries, I understand that on windows it might be annoying to fetch those, but on linux it's just another simple dependencies to install (premake, cmake, 7z), at least giving user an option to not use those bundled binaries is great, but would be even better if they weren't shipped and used at all.

@Edremon
Copy link
Author

Edremon commented Aug 22, 2024

I did what I talked about in my previous post.

Here a PKGBUILD that I use to build a package on Arch Linux that build windows .dll, linux .so and tools:

pkgbase=gbe-fork-git
pkgname=('gbe-fork-common-git' 'gbe-fork-linux-git' 'gbe-fork-windows-git' 'gbe-fork-tools-git')
pkgver=r1785.be2a8eeb
pkgrel=1
pkgdesc="GBE Fork (Git version)"
arch=('x86_64')
license=('GPL-3.0')
makedepends=('git' 'premake' 'wine' 'cmake' 'p7zip' 'python' 'msvc-wine-git')
source=("git+https://github.com/Detanup01/gbe_fork.git")
sha256sums=('SKIP')

pkgver() {
  cd "${srcdir}/gbe_fork"
  printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}

prepare() {
  cd "${srcdir}/gbe_fork"
  git -c protocol.file.allow=always submodule update --init --recursive

  cd "${srcdir}/gbe_fork/tools/generate_emu_config"
  python -m venv .env-linux
  chmod +x rebuild_linux.sh

  cd "${srcdir}/gbe_fork/tools/migrate_gse"
  python -m venv .env-linux
  chmod +x rebuild_linux.sh
}

build() {
  cd "${srcdir}/gbe_fork"

  # Build for Linux
  premake5 --file=premake5-deps.lua --64-build --32-build --all-ext --all-build --custom-cmake=cmake --custom-extractor=7z --j=8 --os=linux gmake2
  premake5 --file=premake5.lua --genproto --os=linux gmake2
  cd build/project/gmake2/linux

  make config=release_x32 -j8 all
  make config=release_x64 -j8 all
  cd "${srcdir}/gbe_fork"

  # Build for Windows
  wine_env() {
    (
      export WINEESYNC=1
      export WINEFSYNC=1
      unset CFLAGS CXXFLAGS LDFLAGS LTOFLAGS
      "$@"
    )
  }

  wine_env premake5 --file=premake5-deps.lua --32-build --all-ext --all-build --custom-cmake=cmake --cmake-toolchain=/opt/msvc/cmake/toolchain-x86.cmake --custom-extractor=7z --j=8 --os=windows vs2022
  wine_env premake5 --file=premake5-deps.lua --64-build --all-ext --all-build --custom-cmake=cmake --cmake-toolchain=/opt/msvc/cmake/toolchain-x64.cmake --custom-extractor=7z --j=8 --os=windows vs2022
  wine_env premake5 --file=premake5.lua --genproto --os=windows vs2022

  cd build/project/vs2022/win
  wine_env /opt/msvc/bin/x86/msbuild '/nologo' '/v:n' '/p:Configuration=release,Platform=Win32' gbe.sln
  wine_env /opt/msvc/bin/x64/msbuild '/nologo' '/v:n' '/p:Configuration=release,Platform=x64' gbe.sln

  # Build tools
  cd "${srcdir}/gbe_fork/tools/generate_emu_config"
  source .env-linux/bin/activate
  pip install -r requirements.txt
  ./rebuild_linux.sh
  deactivate

  cd "${srcdir}/gbe_fork/tools/migrate_gse"
  source .env-linux/bin/activate
  pip install -r requirements.txt
  ./rebuild_linux.sh
  deactivate
}

package_gbe-fork-common-git() {
  pkgdesc="GBE Fork - Common files (Git version)"
  conflicts=('gbe-fork-common')

  cd "${srcdir}/gbe_fork"

  package_dir="${pkgdir}/opt/gbe-fork"
  mkdir -p "$package_dir"

  cp -r "post_build/steam_settings.EXAMPLE/" "$package_dir/"
  cp "post_build/README.release.md" "$package_dir/"
  cp "CHANGELOG.md" "$package_dir/"
  cp "CREDITS.md" "$package_dir/"
  mkdir "$package_dir/tools"
  mkdir "$package_dir/tools/generate_interfaces"
  mkdir "$package_dir/tools/lobby_connect"
  cp "post_build/README.generate_interfaces.md" "$package_dir/tools/generate_interfaces/"
  cp "post_build/README.lobby_connect.md" "$package_dir/tools/lobby_connect/"
}

package_gbe-fork-linux-git() {
  pkgdesc="GBE Fork - Linux files (Git version)"
  depends=('gbe-fork-common-git')
  conflicts=('gbe-fork-linux')

  cd "${srcdir}/gbe_fork"

  package_dir="${pkgdir}/opt/gbe-fork"
  mkdir -p "$package_dir"

  cp -r build/linux/gmake2/release/experimental "$package_dir"
  cp -r build/linux/gmake2/release/regular "$package_dir"
  cp -r build/linux/gmake2/release/tools "$package_dir"
  cp "post_build/README.experimental_linux.md" "$package_dir/experimental/"
}

package_gbe-fork-windows-git() {
  pkgdesc="GBE Fork - Windows files (Git version)"
  depends=('gbe-fork-common-git')
  conflicts=('gbe-fork-windows')

  cd "${srcdir}/gbe_fork"

  package_dir="${pkgdir}/opt/gbe-fork"
  mkdir -p "$package_dir"

  cp -r build/win/vs2022/release/experimental "$package_dir"
  cp -r build/win/vs2022/release/regular "$package_dir"
  cp -r build/win/vs2022/release/steamclient_experimental "$package_dir"
  cp -r build/win/vs2022/release/tools "$package_dir"
  cp "post_build/README.experimental.md" "$package_dir/experimental/README.experimental_windows.md"
  cp "post_build/README.experimental_steamclient.md" "$package_dir/steamclient_experimental"
}

package_gbe-fork-tools-git() {
  pkgdesc="GBE Fork - Tools (Git version)"
  depends=('gbe-fork-common-git')
  conflicts=('gbe-fork-tools')

  cd "${srcdir}/gbe_fork"

  package_dir="${pkgdir}/opt/gbe-fork"
  mkdir -p "$package_dir/tools"

  cp -r tools/steamclient_loader/linux "$package_dir/tools/steamclient_loader"
  cp -r tools/generate_emu_config/bin/linux/* "$package_dir/tools/"
  cp -r tools/migrate_gse/bin/linux/migrate_gse "$package_dir/tools/"
}

@Edremon Edremon changed the title Allow building with MinGW on Linux Fix building with wine wrapped MSVC Aug 22, 2024
@Detanup01
Copy link
Owner

I don't think I want to change ingame_overlay.
Head over to source and make a pr there.

@Edremon
Copy link
Author

Edremon commented Aug 22, 2024

Please read the PR history. The scope was changed from building with mingw which resulted in an ABI incompatible dll to building with wine wrapped msvc. The change to ingame_overlay was for building with mingw.

I should have fixed the case where CMAKE_GENERATOR was not explicitly set on windows (like CI).

@Detanup01 Detanup01 merged commit 0684fa0 into Detanup01:dev Aug 23, 2024
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants