From c88029eee9d71aad261e5af461326441f3b3a5d0 Mon Sep 17 00:00:00 2001 From: Aleksander Czajczynski Date: Thu, 17 Oct 2024 15:04:53 +0200 Subject: [PATCH] 2024-10-17 15:04 UTC+0200 Aleksander Czajczynski (hb fki.pl) * .github/workflows/windows-ci.yml * update windows MSYS2 integration runner set of requested packages. PGSQL, Firebird and MariaDB libs are no longer available in the 32-bit environment + add clang x86_64 compiler for testing under this CI * include/harbour.hbx * include/hbapi.h * src/common/hbver.c * src/harbour.def * src/rtl/version.c ! fixed Windows 11 detection, by vendor likings it has NT Kernel Version stamped with 10.0, so now Build Number is more significant as a recognition factor. + new C helper functions hb_winisbuild(), hb_iswin11() + added PRG function hb_osIsWin11() * also try to detect new Windows Server versions * config/win/clang.mk * utils/hbmk2/hbmk2.prg * ChangeLog.txt ! recursion happening in the Makefiles rendered recently introduced compatibility option unreliable. Changed to use separate variable: HB_USER_FIXES=--mingw-script You don't need it, the problem shouldn't exist, but anyway... --- .github/workflows/windows-ci.yml | 31 +++++++-- ChangeLog.txt | 34 +++++++++- config/win/clang.mk | 6 +- include/harbour.hbx | 1 + include/hbapi.h | 2 + src/common/hbver.c | 106 +++++++++++++++++++++++++++++-- src/harbour.def | 2 + src/rtl/version.c | 5 ++ utils/hbmk2/hbmk2.prg | 4 +- 9 files changed, 176 insertions(+), 15 deletions(-) diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 56ca20d17d..e015e7ff28 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -14,12 +14,15 @@ jobs: compiler: - bcc - mingw64 + - clang cpu: - x86 - x86_64 exclude: - compiler: bcc cpu: x86_64 + - compiler: clang + cpu: x86 strictness: - "normal" - "strict" @@ -37,6 +40,9 @@ jobs: (x86_64) echo MINGWxx="MINGW64" echo "msys_cpu=${{matrix.cpu}}" ;; esac + case ${{matrix.compiler}} in + (clang) echo MINGWxx="CLANG64" ;; + esac } >> $GITHUB_ENV - name: Install packages @@ -44,6 +50,7 @@ jobs: with: msystem: ${{ env.MINGWxx }} location: d:/ + update: true install: > mingw-w64-${{ env.msys_cpu }}-ccache mingw-w64-${{ env.msys_cpu }}-gcc @@ -52,17 +59,22 @@ jobs: mingw-w64-${{ env.msys_cpu }}-bzip2 mingw-w64-${{ env.msys_cpu }}-cairo mingw-w64-${{ env.msys_cpu }}-curl - mingw-w64-${{ env.msys_cpu }}-firebird2-git mingw-w64-${{ env.msys_cpu }}-libgd mingw-w64-${{ env.msys_cpu }}-ghostscript - mingw-w64-${{ env.msys_cpu }}-libmariadbclient mingw-w64-${{ env.msys_cpu }}-openssl - mingw-w64-${{ env.msys_cpu }}-postgresql mingw-w64-${{ env.msys_cpu }}-qt5-base # Dependencies for disabled contribs: # mingw-w64-${{ env.msys_cpu }}-freeimage + - name: 'Add packages available on 64-bit hosts only' + if: matrix.cpu != 'x86' + shell: msys2 {0} + run: | + pacman -S --noconfirm mingw-w64-${{ env.msys_cpu }}-postgresql + pacman -S --noconfirm mingw-w64-${{ env.msys_cpu }}-libmariadbclient + pacman -S --noconfirm mingw-w64-${{ env.msys_cpu }}-firebird + - name: Checkout code uses: actions/checkout@v3 with: @@ -87,6 +99,17 @@ jobs: set -ex HB_USER_CFLAGS="" HB_USER_LDFLAGS="" + + case ${{matrix.compiler}} in + (clang) + pacman -S --noconfirm mingw-w64-${{ env.msys_cpu }}-clang + PATH="$PATH:/mingw64/bin/" + tee ./.bashrc <> __dyn__.tmp + endef TMPSPEC := __dyn__.tmp endif diff --git a/include/harbour.hbx b/include/harbour.hbx index 60af6bb701..562f6892c5 100644 --- a/include/harbour.hbx +++ b/include/harbour.hbx @@ -731,6 +731,7 @@ DYNAMIC hb_osDriveSeparator DYNAMIC hb_osError DYNAMIC hb_osFileMask DYNAMIC hb_osIs64bit +DYNAMIC hb_osIsWin11 DYNAMIC hb_osIsWin10 DYNAMIC hb_osIsWin2K DYNAMIC hb_osIsWin7 diff --git a/include/hbapi.h b/include/hbapi.h index 34fcf421d8..c72a7f6aa8 100644 --- a/include/hbapi.h +++ b/include/hbapi.h @@ -1213,9 +1213,11 @@ extern HB_EXPORT HB_BOOL hb_iswin7( void ); /* return HB_TRUE if OS == Windo extern HB_EXPORT HB_BOOL hb_iswin8( void ); /* return HB_TRUE if OS == Windows 8 or newer */ extern HB_EXPORT HB_BOOL hb_iswin81( void ); /* return HB_TRUE if OS == Windows 8.1 or newer */ extern HB_EXPORT HB_BOOL hb_iswin10( void ); /* return HB_TRUE if OS == Windows 10 or newer */ +extern HB_EXPORT HB_BOOL hb_iswin11( void ); /* return HB_TRUE if OS == Windows 11 or newer */ extern HB_EXPORT HB_BOOL hb_iswince( void ); /* return HB_TRUE if OS is Windows CE or Windows Mobile */ extern HB_EXPORT HB_BOOL hb_iswinver( int iMajor, int iMinor, int iType, HB_BOOL fOrUpper ); extern HB_EXPORT HB_BOOL hb_iswinsp( int iServicePackMajor, HB_BOOL fOrUpper ); +extern HB_EXPORT HB_BOOL hb_iswinbuild( int iBuildNum, HB_BOOL fOrUpper ); extern HB_EXPORT HB_BOOL hb_printerIsReady( const char * pszPrinterName ); diff --git a/src/common/hbver.c b/src/common/hbver.c index 441d99b087..82c5ac3d16 100644 --- a/src/common/hbver.c +++ b/src/common/hbver.c @@ -279,6 +279,7 @@ const char * hb_verPlatformMacro( void ) static HB_BOOL s_fWinVerInit = HB_FALSE; +static HB_BOOL s_fWin11 = HB_FALSE; static HB_BOOL s_fWin10 = HB_FALSE; static HB_BOOL s_fWin81 = HB_FALSE; static HB_BOOL s_fWin8 = HB_FALSE; @@ -340,6 +341,8 @@ static void s_hb_winVerInit( void ) { #if ! defined( HB_OS_WIN_CE ) s_fWin10 = hb_iswinver( 10, 0, 0, HB_TRUE ); + if( s_fWin10 ) + s_fWin11 = hb_iswinbuild( 22000, HB_TRUE ); s_fWin81 = hb_iswinver( 6, 3, 0, HB_TRUE ); s_fWin8 = hb_iswinver( 6, 2, 0, HB_TRUE ); s_fWin7 = hb_iswinver( 6, 1, 0, HB_TRUE ); @@ -347,6 +350,7 @@ static void s_hb_winVerInit( void ) s_fWin2K3 = hb_iswinver( 5, 2, VER_NT_SERVER, HB_TRUE ) || hb_iswinver( 5, 2, VER_NT_DOMAIN_CONTROLLER, HB_TRUE ); s_fWin2K = hb_iswinver( 5, 0, 0, HB_TRUE ); + #if !( defined( HB_OS_WIN_64 ) || ( defined( _MSC_VER ) && _MSC_VER > 1310 ) ) { OSVERSIONINFO osvi; @@ -370,7 +374,7 @@ static void s_hb_winVerInit( void ) else if( osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0 ) s_iWinNT = 4; /* 4.0 */ else - s_iWinNT = 5; /* newer */ + s_iWinNT = 5; /* 2000/XP/2003 */ } } #endif @@ -383,7 +387,45 @@ static void s_hb_winVerInit( void ) s_iWine = 1; } - if( s_fWin2K ) + if( s_fWin10 && ! s_iWine ) + { + /* reusing s_iWinNT to store build number on Win10+ */ + +#if 0 + typedef LONG NTSTATUS, * PNTSTATUS; + #define STATUS_SUCCESS (0x00000000) + typedef NTSTATUS ( WINAPI * _HB_RTLGETVERSION )( LPOSVERSIONINFOW ); + HMODULE hntdll = GetModuleHandle( TEXT( "ntdll.dll" ) ); + + _HB_RTLGETVERSION pRtlGetVersion; + if( hntdll ) + { + pRtlGetVersion := ( _HB_RTLGETVERSION ) HB_WINAPI_GETPROCADDRESS( hntdll, "RtlGetVersion" ) ) + OSVERSIONINFOW ovi = { 0 }; + ovi.dwOSVersionInfoSize = sizeof( ovi ); + if( STATUS_SUCCESS == pRtlGetVersion( &ovi ) ) + { + s_iWinNT = ( int ) ovi.dwBuildNumber; + } + } +#endif + + /* NOTE: NT system version is always mapped into process (user-mode) + memory, though build number is there only on Win10 and up. + https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm */ + + s_iWinNT = ( int ) * ( PULONG ) ( 0x7FFE0000 + 0x0260 ); + + /* COMPAT: this seems much simpler than dyn-calling GetVersionEx + or WDK RtlGetVersion (having in mind deprecation warnings, + regressions from obscure compilers with conflicting headers) + If this ever causes a GPF on memory read, please revert, + or migrate to APIs. Mem-addr is correct for AMD64, ARM64 too. + WINE is intentionally excluded for reason, where an unknown + build may not support this. */ + + } + else if( s_fWin2K ) s_iWinNT = 5; #endif @@ -394,6 +436,7 @@ static void s_hb_winVerInit( void ) static HB_BOOL s_fWinVerInit = HB_FALSE; +static HB_BOOL s_fWin11 = HB_FALSE; static HB_BOOL s_fWin10 = HB_FALSE; static HB_BOOL s_fWin81 = HB_FALSE; static HB_BOOL s_fWin8 = HB_FALSE; @@ -410,6 +453,7 @@ static void s_hb_winVerInit( void ) union REGS regs; /* TODO */ + s_fWin11 = HB_FALSE; s_fWin10 = HB_FALSE; s_fWin81 = HB_FALSE; s_fWin8 = HB_FALSE; @@ -578,11 +622,16 @@ char * hb_verPlatform( void ) #if defined( HB_OS_WIN_CE ) pszName = " CE"; #else - if( hb_iswinver( 11, 0, 0, HB_TRUE ) ) + if( hb_iswin11() ) { - osvi.dwMajorVersion = 11; + osvi.dwMajorVersion = 10; osvi.dwMinorVersion = 0; - pszName = " 11 or newer"; + if( hb_iswinver( 10, 0, VER_NT_WORKSTATION, HB_FALSE ) ) + pszName = " 11 or newer"; + else if( hb_iswinbuild( 26040, HB_TRUE ) ) + pszName = " Server 2025"; + else + pszName = " Server 23H2"; } else if( hb_iswin10() ) { @@ -590,6 +639,10 @@ char * hb_verPlatform( void ) osvi.dwMinorVersion = 0; if( hb_iswinver( 10, 0, VER_NT_WORKSTATION, HB_FALSE ) ) pszName = " 10"; + else if( hb_iswinbuild( 20348, HB_TRUE ) ) + pszName = " Server 2022"; + else if( hb_iswinbuild( 17763, HB_TRUE ) ) + pszName = " Server 2019"; else pszName = " Server 2016"; } @@ -668,7 +721,14 @@ char * hb_verPlatform( void ) /* Add service pack/other info */ - if( hb_iswin2k() ) + if( hb_iswin10() && ! s_iWine ) + { + /* On Win10+ build number is more significant than Major Minor */ + char szBuild[ 8 ]; + hb_snprintf( szBuild, sizeof( szBuild ), ".%lu", ( DWORD ) s_iWinNT ); + hb_strncat( pszPlatform, szBuild, PLATFORM_BUF_SIZE ); + } + else if( hb_iswin2k() ) { int tmp; @@ -814,6 +874,29 @@ HB_BOOL hb_iswinsp( int iServicePackMajor, HB_BOOL fOrUpper ) return HB_FALSE; } +HB_BOOL hb_iswinbuild( int iBuildNum, HB_BOOL fOrUpper ) +{ +#if defined( HB_OS_WIN ) && ! defined( HB_OS_WIN_CE ) + if( s_hb_winVerifyVersionInit() ) + { + OSVERSIONINFOEXW ver; + DWORDLONG dwlConditionMask = 0; + + memset( &ver, 0, sizeof( ver ) ); + ver.dwOSVersionInfoSize = sizeof( ver ); + ver.dwBuildNumber = ( DWORD ) iBuildNum; + + dwlConditionMask = s_pVerSetConditionMask( dwlConditionMask, VER_BUILDNUMBER, fOrUpper ? VER_GREATER_EQUAL : VER_EQUAL ); + + return ( HB_BOOL ) s_pVerifyVersionInfo( &ver, VER_BUILDNUMBER, dwlConditionMask ); + } +#else + HB_SYMBOL_UNUSED( iBuildNum ); + HB_SYMBOL_UNUSED( fOrUpper ); +#endif + return HB_FALSE; +} + int hb_iswine( void ) { #if defined( HB_OS_WIN ) || defined( HB_OS_DOS ) @@ -825,6 +908,17 @@ int hb_iswine( void ) #endif } +HB_BOOL hb_iswin11( void ) +{ +#if defined( HB_OS_WIN ) || defined( HB_OS_DOS ) + if( ! s_fWinVerInit ) + s_hb_winVerInit(); + return s_fWin11; +#else + return HB_FALSE; +#endif +} + HB_BOOL hb_iswin10( void ) { #if defined( HB_OS_WIN ) || defined( HB_OS_DOS ) diff --git a/src/harbour.def b/src/harbour.def index 52e66cfb89..e25f0cfda5 100644 --- a/src/harbour.def +++ b/src/harbour.def @@ -924,6 +924,7 @@ HB_FUN_HB_OSDRIVESEPARATOR HB_FUN_HB_OSERROR HB_FUN_HB_OSFILEMASK HB_FUN_HB_OSIS64BIT +HB_FUN_HB_OSISWIN11 HB_FUN_HB_OSISWIN10 HB_FUN_HB_OSISWIN2K HB_FUN_HB_OSISWIN7 @@ -2778,6 +2779,7 @@ hb_inkeyPut hb_inkeyReset hb_inkeySetLast hb_inkeySetText +hb_iswin11 hb_iswin10 hb_iswin2k hb_iswin2k3 diff --git a/src/rtl/version.c b/src/rtl/version.c index 39fce93131..ab619daa95 100644 --- a/src/rtl/version.c +++ b/src/rtl/version.c @@ -234,6 +234,11 @@ HB_FUNC( HB_OSISWIN10 ) hb_retl( hb_iswin10() ); } +HB_FUNC( HB_OSISWIN11 ) +{ + hb_retl( hb_iswin11() ); +} + HB_FUNC( HB_OSISWINCE ) { hb_retl( hb_iswince() ); diff --git a/utils/hbmk2/hbmk2.prg b/utils/hbmk2/hbmk2.prg index 84bd1bcdf7..5146f141fc 100644 --- a/utils/hbmk2/hbmk2.prg +++ b/utils/hbmk2/hbmk2.prg @@ -4440,7 +4440,9 @@ STATIC FUNCTION __hbmk( aArgs, nArgTarget, nLevel, /* @ */ lPause, /* @ */ lExit AAddNotEmpty( hbmk[ _HBMK_aOPTCPPX ], gcc_opt_lngcpp_fill( hbmk ) ) cBin_Dyn := cBin_CompC cOpt_Dyn := "-shared -o {OD} {LO} {FD} {IM} {DL} {LS}" - IF hbmk[ _HBMK_cCOMP ] == "clang" + IF "--script-mingw" $ GetEnv("HB_USER_FIXES") + cOpt_Dyn += "{SCRIPT_MINGW}" + ELSEIF hbmk[ _HBMK_cCOMP ] == "clang" cOpt_Dyn += "{SCRIPT}{ESCAPE_BS}" ELSEIF ! hbmk[ _HBMK_cCOMP ] == "tcc" cOpt_Dyn += "{SCRIPT_MINGW}"