Parcourir la source

Fix mingw build (#831)

* Fix mingw build errors

* Use SetThreadDescription for thread name on mingw

Mingw does not support __try and __except, so we cannot use the old
exception method for setting a thread name. We can however use
SetThreadDescription, which is the modern way of setting thread names.

* [make] Fix mingw build errors

* [cmake] Fix mingw build errors

* [ci] Add configuration for mingw cmake

* [ci] Use windows-2025 for mingw build

2022 has an old version of mingw which doesn't have SetThreadDescription

* [ui] Fix decrement on rvalue error with mingw

* [ci] Enable ui.hdll build with mingw

* [dx] Add missing cast in gamecontroller

Required by mingw compiler

* [sdl,dx] Fix include paths for mingw cross compile

* [sdl] Use system glext.h on mingw builds

glext.h is vendored for windows since that is not part of the windows
sdk. However, the vendored version is outdated and has issues on mingw,
and on mingw the header is provided by the system so that can be used
instead.

* [ci] Enable fmt, sdl, openal, directx mingw builds

* [video] Add missing cast for mingw

* [ci] Enable video.hdll build on mingw

* [ci] Use parallel build for cmake mingw

* [ci] Add mingw binaries to automated releases

---------

Co-authored-by: N3rdL0rd <[email protected]>
tobil4sk il y a 3 mois
Parent
commit
2da7ebeeab

+ 41 - 6
.github/workflows/build.yml

@@ -23,7 +23,7 @@ jobs:
       matrix:
         target: [linux, darwin, windows]
         architecture: [32, 64, arm64]
-        build_system: [make, cmake, vs2019, makegcc14]
+        build_system: [make, cmake, cmake-mingw, vs2019, makegcc14]
 
         include:
           - target: linux
@@ -46,6 +46,9 @@ jobs:
           - build_system: cmake
             cmake_configuration: RelWithDebInfo
 
+          - build_system: cmake-mingw
+            cmake_configuration: RelWithDebInfo
+
           - build_system: vs2019
             msbuild_configuration: Release
 
@@ -58,6 +61,11 @@ jobs:
             build_system: cmake
             cmake_generator: Visual Studio 17 2022
 
+          - target: windows
+            architecture: 64
+            runner: windows-2025
+            build_system: cmake-mingw
+
           - target: windows
             architecture: 32
             ffmpeg_url: https://github.com/HaxeFoundation/hashlink/files/5648055/ffmpeg-3.4.2-win32-dev.zip
@@ -100,6 +108,16 @@ jobs:
           - target: windows
             build_system: makegcc14
 
+          - target: windows
+            architecture: 32
+            build_system: cmake-mingw
+
+          - target: darwin
+            build_system: cmake-mingw
+
+          - target: linux
+            build_system: cmake-mingw
+
     steps:
     - name: "SCM Checkout"
       uses: actions/checkout@v5
@@ -143,7 +161,12 @@ jobs:
             ;;
 
           windows*)
-            curl -fsSL --retry 3 --retry-delay 5 -o /tmp/sdl.zip https://www.libsdl.org/release/SDL2-devel-2.30.2-VC.zip
+            if [[ ${{ matrix.build_system }} == cmake-mingw ]]; then
+              SDL_SUFFIX=mingw
+            else
+              SDL_SUFFIX=VC
+            fi
+            curl -fsSL --retry 3 --retry-delay 5 -o /tmp/sdl.zip https://www.libsdl.org/release/SDL2-devel-2.30.2-${SDL_SUFFIX}.zip
             curl -fsSL --retry 3 --retry-delay 5 -o /tmp/openal.zip https://github.com/kcat/openal-soft/releases/download/1.23.1/openal-soft-1.23.1-bin.zip
             curl -fsSL --retry 3 --retry-delay 5 -o /tmp/ffmpeg.zip ${{ matrix.ffmpeg_url }}
             7z x /tmp/sdl.zip    -oinclude; mv include/SDL2*   include/sdl
@@ -209,6 +232,14 @@ jobs:
             BUILD_FOLDER=build/bin
             ;;
 
+          cmake-mingw)
+            cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} \
+              -DWITH_DX12=OFF
+
+            cmake --build build --config ${{ matrix.cmake_configuration }} --parallel
+            BUILD_FOLDER=build/bin
+            ;;
+
           vs2019)
             MSBuild.exe hl.sln //nologo //m //clp:ErrorsOnly \
               //p:Configuration=${{ matrix.msbuild_configuration }} \
@@ -239,7 +270,7 @@ jobs:
         set -eux
 
         case "${{ matrix.build_system }}" in
-          cmake)
+          cmake*)
             case "${{matrix.target}}" in
               linux)
                 cmake --install build --prefix /tmp/hashlink
@@ -249,6 +280,9 @@ jobs:
                 cmake --install build --prefix /tmp/hashlink
                 if [ -f /tmp/hashlink/hl ]; then /tmp/hashlink/hl --version; fi
                 ;;
+              windows)
+                export PATH=$(pwd)/build/bin:$PATH
+                ;;
             esac
             cd build && ctest --verbose --build-config ${{ matrix.cmake_configuration }}
             ;;
@@ -301,8 +335,8 @@ jobs:
         short_commit=$(git rev-parse --short HEAD)
 
         case "${{ matrix.build_system }}" in
-          cmake)
-            dist_folder=hashlink-${short_commit}-${platform_name}-cmake
+          cmake*)
+            dist_folder=hashlink-${short_commit}-${platform_name}-${{ matrix.build_system }}
             cd build && cpack -D CPACK_PACKAGE_FILE_NAME=$dist_folder -C ${{ matrix.cmake_configuration }}
 
             echo "HASHLINK_DISTRIBUTION=build/bin/$dist_folder.${{ matrix.archive_ext }}" >> $GITHUB_ENV
@@ -391,4 +425,5 @@ jobs:
           "darwin-cmake-arm64/hashlink-${short_commit}-darwin-arm64-cmake.tar.gz#hashlink-latest-darwin-arm64.tar.gz" \
           "linux-make-64/hashlink-${short_commit}-linux-amd64.tar.gz#hashlink-latest-linux-amd64.tar.gz" \
           "windows-vs2019-32/hashlink-${short_commit}-win32.zip#hashlink-latest-win32.zip" \
-          "windows-vs2019-64/hashlink-${short_commit}-win64.zip#hashlink-latest-win64.zip"
+          "windows-vs2019-64/hashlink-${short_commit}-win64.zip#hashlink-latest-win64.zip" \
+          "windows-cmake-mingw-64/hashlink-${short_commit}-win64-cmake-mingw.zip#hashlink-latest-win64-mingw.zip"

+ 16 - 1
CMakeLists.txt

@@ -49,6 +49,11 @@ if(MSVC)
     add_definitions(-DUNICODE -D_UNICODE)
 endif()
 
+if (MINGW)
+    add_compile_options(-municode)
+    add_link_options(-municode)
+endif()
+
 list(APPEND CMAKE_MODULE_PATH
     ${CMAKE_CURRENT_SOURCE_DIR}/other/cmake
 )
@@ -170,7 +175,7 @@ set_target_properties(libhl
     PUBLIC_HEADER "${public_headers}"
 )
 
-if(WIN32)
+if(MSVC)
     set_target_properties(libhl
         PROPERTIES
         OUTPUT_NAME libhl
@@ -240,6 +245,12 @@ if(BUILD_TESTING)
         SET(HAXE_FLAGS )
     endif()
 
+    if(MINGW)
+        set(HLC_LIBRARIES dbghelp)
+    else()
+        set(HLC_LIBRARIES)
+    endif()
+
     #####################
     # hello.hl
 
@@ -300,6 +311,7 @@ if(BUILD_TESTING)
     )
     target_link_libraries(hello
         libhl
+        ${HLC_LIBRARIES}
     )
 
     #####################
@@ -323,6 +335,7 @@ if(BUILD_TESTING)
     )
     target_link_libraries(threads
         libhl
+        ${HLC_LIBRARIES}
     )
 
     #####################
@@ -347,6 +360,7 @@ if(BUILD_TESTING)
     target_link_libraries(uvsample
         libhl
         uv.hdll
+        ${HLC_LIBRARIES}
     )
 
     #####################
@@ -361,6 +375,7 @@ if(BUILD_TESTING)
     )
     target_link_libraries(header_macro_clashes
         libhl
+        ${HLC_LIBRARIES}
     )
 
     #####################

+ 15 - 4
Makefile

@@ -14,6 +14,7 @@ CFLAGS = -Wall -O3 -I src -std=c11 -D LIBHL_EXPORTS
 LFLAGS = -L. -lhl
 EXTRA_LFLAGS ?=
 LIBFLAGS =
+LIBHL_LDLIBS = -lm -lpthread
 HLFLAGS = -ldl
 LIBEXT = so
 LIBTURBOJPEG = -lturbojpeg
@@ -123,7 +124,7 @@ BOOT = src/_main.o
 
 UNAME := $(shell uname)
 
-# Cygwin
+# Cygwin / mingw
 ifeq ($(OS),Windows_NT)
 
 LIBFLAGS += -Wl,--export-all-symbols
@@ -144,6 +145,16 @@ VS_SDL_LIBRARY ?= include/sdl/lib/x64/SDL2.dll
 VS_OPENAL_LIBRARY ?= include/openal/bin/Win64/soft_oal.dll
 endif
 
+ifneq (, $(findstring MINGW64, $(UNAME)))
+LIBHL_LDLIBS += -lws2_32 -lwsock32
+SSL_LDLIBS += -lcrypt32 -lbcrypt -lws2_32
+MYSQL_LDLIBS += -lws2_32 -lwsock32
+HLC_LDLIBS = -ldbghelp
+CFLAGS += -municode
+LIBFLAGS += -municode
+HLFLAGS =
+endif
+
 else ifeq ($(UNAME),Darwin)
 
 # Mac
@@ -243,10 +254,10 @@ src/std/regexp.o: src/std/regexp.c
 	${CC} ${CFLAGS} -o $@ -c $< ${PCRE_FLAGS}
 
 libhl: ${LIB}
-	${CC} ${CFLAGS} -o libhl.$(LIBEXT) -m${MARCH} ${LIBFLAGS} ${LHL_LINK_FLAGS} -shared ${LIB} -lpthread -lm
+	${CC} ${CFLAGS} -o libhl.$(LIBEXT) -m${MARCH} ${LIBFLAGS} ${LHL_LINK_FLAGS} -shared $^ ${LIBHL_LDLIBS}
 
 hlc: ${BOOT}
-	${CC} ${CFLAGS} -o hlc ${BOOT} ${LFLAGS} ${EXTRA_LFLAGS}
+	${CC} ${CFLAGS} -o hlc ${BOOT} ${LFLAGS} ${EXTRA_LFLAGS} ${HLC_LDLIBS}
 
 hl: ${HL} libhl
 	${CC} ${CFLAGS} -o hl ${HL} ${LFLAGS} ${EXTRA_LFLAGS} ${HLFLAGS}
@@ -281,7 +292,7 @@ uv: ${UV} libhl
 	${CC} ${CFLAGS} -shared -o uv.hdll ${UV} ${LIBFLAGS} -L. -lhl -luv
 
 mysql: ${MYSQL} libhl
-	${CC} ${CFLAGS} -shared -o mysql.hdll ${MYSQL} ${LIBFLAGS} -L. -lhl
+	${CC} ${CFLAGS} -shared -o mysql.hdll ${MYSQL} ${LIBFLAGS} -L. -lhl ${MYSQL_LDLIBS}
 
 sqlite: ${SQLITE} libhl
 	${CC} ${CFLAGS} -shared -o sqlite.hdll ${SQLITE} ${LIBFLAGS} -L. -lhl -lsqlite3

+ 0 - 0
include/gl/glext.h → include/gl/GL/glext.h


+ 1 - 1
libs/directx/directx.cpp

@@ -6,7 +6,7 @@
 #include <dxgi.h>
 #include <d3dcommon.h>
 #include <d3d11.h>
-#include <D3Dcompiler.h>
+#include <d3dcompiler.h>
 #else
 #include <xbo_directx.h>
 #endif

+ 2 - 2
libs/directx/gamecontroller.c

@@ -3,7 +3,7 @@
 #include "hlsystem.h"
 
 #include <xinput.h>
-#include <InitGuid.h>
+#include <initguid.h>
 #define DIRECTINPUT_VERSION 0x0800
 #include <dinput.h>
 #include <dbt.h>
@@ -122,7 +122,7 @@ static LRESULT CALLBACK gctrl_WndProc(HWND wnd, UINT umsg, WPARAM wparam, LPARAM
 
 static void gctrl_dinput_init( varray *mappings ) {
 	if( !gctrl_dinput) {
-		DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8, &gctrl_dinput, NULL);
+		DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8, (LPVOID*)&gctrl_dinput, NULL);
 		if (gctrl_dinput) {
 			WNDCLASSEX wc;
 			memset(&wc, 0, sizeof(wc));

+ 6 - 4
libs/sdl/CMakeLists.txt

@@ -26,16 +26,18 @@ if ((NOT WIN32) AND DOWNLOAD_DEPENDENCIES)
 else()
     if(WIN32)
         set(SDL2_DIR ${INCLUDES_BASE_DIR}/sdl/cmake)
+        if(NOT MINGW)
+            target_include_directories(sdl.hdll
+                PRIVATE
+                ${INCLUDES_BASE_DIR}/gl
+            )
+        endif()
     endif()
 
     find_package(SDL2 REQUIRED)
 endif()
 
 set_as_hdll(sdl)
-target_include_directories(sdl.hdll
-    PRIVATE
-    ${INCLUDES_BASE_DIR}/gl
-)
 target_link_libraries(sdl.hdll
     libhl
     SDL2::SDL2

+ 2 - 2
libs/sdl/gl.c

@@ -15,8 +15,8 @@
 #	define glMemoryBarrier(...) hl_error("Not supported on OSX")
 #elif defined(_WIN32)
 #	include <SDL.h>
-#	include <GL/GL.h>
-#	include <glext.h>
+#	include <GL/gl.h>
+#	include <GL/glext.h>
 #elif defined(HL_CONSOLE)
 #	include <graphic/glapi.h>
 #elif defined(HL_MESA)

+ 1 - 1
libs/ssl/CMakeLists.txt

@@ -4,7 +4,7 @@ add_library(ssl.hdll
 
 if (WIN32)
     set(MBEDTLS_INCLUDE_DIRS ${INCLUDES_BASE_DIR}/mbedtls/include .)
-    set(MBEDTLS_LIBRARIES crypt32)
+    set(MBEDTLS_LIBRARIES crypt32 bcrypt)
 
     target_sources(ssl.hdll PRIVATE
         ${INCLUDES_BASE_DIR}/mbedtls/library/aes.c

+ 8 - 4
libs/ui/ui_win.c

@@ -226,12 +226,16 @@ static void sentinel_loop( vsentinel *s ) {
 				GetThreadContext(h,&regs);
 				// simulate a call
 #				ifdef HL_64
-				*--(int_val*)regs.Rsp = regs.Rip;
-				*--(int_val*)regs.Rsp = regs.Rsp;
+				int_val* rsp = (int_val*)regs.Rsp;
+				*--rsp = (int_val)regs.Rip;
+				*--rsp = (int_val)rsp;
+				regs.Rsp = (int_val)rsp;
 				regs.Rip = (int_val)s->callback;
 #				else
-				*--(int_val*)regs.Esp = regs.Eip;
-				*--(int_val*)regs.Esp = regs.Esp;
+				int_val* esp = (int_val*)regs.Esp;
+				*--esp = (int_val)regs.Eip;
+				*--esp = (int_val)esp;
+				regs.Esp = (int_val)esp;
 				regs.Eip = (int_val)s->callback;
 #				endif
 				// resume

+ 2 - 2
libs/video/video.c

@@ -94,7 +94,7 @@ HL_PRIM bool HL_NAME(video_decode_frame)( hl_video *v, vbyte *out, double *time
 		i.linesize[0] = v->codec->width * 4;
 		i.linesize[1] = v->codec->width * 4;
 		i.linesize[2] = v->codec->width * 4;
-		sws_scale(v->scale, v->frame->data, v->frame->linesize, 0, v->codec->height, i.data, i.linesize);
+		sws_scale(v->scale, (const uint8_t* const*)v->frame->data, v->frame->linesize, 0, v->codec->height, i.data, i.linesize);
 	}
 	if( time )
 		*time = (double)av_frame_get_best_effort_timestamp(v->frame) * av_q2d(v->codec->pkt_timebase);
@@ -111,4 +111,4 @@ DEFINE_PRIM(_VOID, video_init, _NO_ARG);
 DEFINE_PRIM(_VIDEO, video_open, _BYTES);
 DEFINE_PRIM(_VOID, video_get_size, _VIDEO _REF(_I32) _REF(_I32));
 DEFINE_PRIM(_BOOL, video_decode_frame, _VIDEO _BYTES _REF(_F64));
-DEFINE_PRIM(_VOID, video_close, _VIDEO);
+DEFINE_PRIM(_VOID, video_close, _VIDEO);

+ 2 - 2
src/hl.h

@@ -182,7 +182,7 @@
 #ifdef HL_64
 #	define HL_WSIZE 8
 #	define IS_64	1
-#	ifdef HL_VCC
+#	if defined(HL_VCC) || defined(HL_MINGW)
 #		define _PTR_FMT	L"%IX"
 #	else
 #		define _PTR_FMT	u"%lX"
@@ -190,7 +190,7 @@
 #else
 #	define HL_WSIZE 4
 #	define IS_64	0
-#	ifdef HL_VCC
+#	if defined(HL_VCC) || defined(HL_MINGW)
 #		define _PTR_FMT	L"%IX"
 #	else
 #		define _PTR_FMT	u"%X"

+ 4 - 0
src/jit.c

@@ -4291,7 +4291,11 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 
 				size = begin_native_call(ctx, 1);
 				set_native_arg(ctx,trap);
+#ifdef HL_MINGW
+				call_native(ctx,_setjmp,size);
+#else
 				call_native(ctx,setjmp,size);
+#endif
 				op64(ctx,TEST,PEAX,PEAX);
 				XJump_small(JZero,jenter);
 				op64(ctx,ADD,PESP,pconst(&p,trap_size));

+ 2 - 2
src/profile.c

@@ -242,12 +242,12 @@ static void read_thread_data( thread_handle *t ) {
 #else
 	int size = (int)((unsigned char*)t->inf->stack_top - (unsigned char*)stack);
 	if( size > MAX_STACK_SIZE-32 ) size = MAX_STACK_SIZE-32;
-#ifdef HL_WIN_DESKTOP
+#if defined(HL_WIN_DESKTOP) && defined(HL_VCC)
 	// it seems we rarely can't make a first read on the thread stack, let's ignore errors and wait.
 	__try {
 #endif
 		memcpy(data.tmpMemory + 2,stack,size);
-#ifdef HL_WIN_DESKTOP
+#if defined(HL_WIN_DESKTOP) && defined(HL_VCC)
 	} __except(EXCEPTION_EXECUTE_HANDLER) {
 	}
 #endif

+ 9 - 0
src/std/thread.c

@@ -919,6 +919,14 @@ HL_PRIM hl_thread *hl_thread_create( vclosure *c ) {
 }
 
 #if defined(HL_WIN) && defined(HL_THREADS)
+#ifdef HL_MINGW
+static void SetThreadName(DWORD dwThreadID, const char* threadName) {
+	SetThreadDescription(
+		OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, dwThreadID),
+		hl_to_utf16(threadName)
+	);
+}
+#else
 const DWORD MS_VC_EXCEPTION = 0x406D1388;
 #pragma pack(push,8)
 typedef struct tagTHREADNAME_INFO
@@ -945,6 +953,7 @@ void SetThreadName(DWORD dwThreadID, const char* threadName) {
 #pragma warning(pop)
 }
 #endif
+#endif
 
 HL_PRIM int hl_get_thread_id( hl_thread *t ) {
 #	if !defined(HL_THREADS)