diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 145da176..23be64f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,3 +42,38 @@ jobs: - name: Prebuild shell: bash run: npm run prebuild + + test-mingw: + name: Test MinGW (MSYS2 MINGW64) on Windows + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up MSYS2 with MINGW64 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: >- + mingw-w64-x86_64-nodejs + mingw-w64-x86_64-python + mingw-w64-x86_64-gcc + make + + - name: Verify MinGW Node.js is active + shell: msys2 {0} + run: node -e "const os = require('os'); console.log('os.type():', os.type()); if (!os.type().startsWith('MINGW')) process.exit(1)" + + - name: Install dependencies + shell: msys2 {0} + run: npm install + + - name: Build native tests + shell: msys2 {0} + run: npm run build + + - name: Run tests + shell: msys2 {0} + run: npm test diff --git a/deps/libffi/libffi.gyp b/deps/libffi/libffi.gyp index 5d495728..ec0afcba 100644 --- a/deps/libffi/libffi.gyp +++ b/deps/libffi/libffi.gyp @@ -9,6 +9,14 @@ { 'variables': { 'target_arch%': 'ia32', # built for a 32-bit CPU by default + # Distinguish MSVC from MinGW/MSYS2 on Windows. MinGW-compiled Node reports + # an OS type starting with "MINGW", but MSYS2 subsystems like UCRT64 ship a + # Windows-native Node where os.type() returns "Windows_NT". Real MSYS2 sets + # MSYSTEM_PREFIX (e.g. /mingw64, /ucrt64); Git for Windows also sets MSYSTEM + # but does NOT set MSYSTEM_PREFIX, so we use that to avoid false positives + # in Git Bash environments. Either signal means GCC is the toolchain, so .S + # files compile directly without the MSVC preprocess_asm.cmd step. + 'target_platform%': ' .asm -> .obj. + # MinGW uses GCC and compiles .S files directly without these rules. 'conditions': [ - ['OS=="win"', { + ['OS=="win" and target_platform=="msvc"', { 'target_defaults': { 'conditions': [ ['target_arch=="ia32"', { @@ -151,38 +160,51 @@ ['OS=="linux" or OS=="mac"', { 'sources': [ 'src/aarch64/sysv.S' ] }], - ['OS=="win"', { + ['OS=="win" and target_platform=="msvc"', { 'sources': [ 'src/aarch64/win64_armasm.preasm' ] }], + ['OS=="win" and target_platform=="mingw"', { + 'sources': [ 'src/aarch64/sysv.S' ] + }], ] }, { # ia32 or x64 'conditions': [ ['target_arch=="ia32"', { 'sources': [ 'src/x86/ffi.c' ], 'conditions': [ - ['OS=="win"', { + ['OS=="win" and target_platform=="msvc"', { 'sources': [ 'src/x86/sysv_intel.preasm' ], - }, { + }], + ['OS=="win" and target_platform=="mingw"', { + 'sources': [ 'src/x86/sysv.S' ], + }], + ['OS!="win"', { 'sources': [ 'src/x86/sysv.S' ], }], ], }], ['target_arch=="x64"', { - 'sources': [ - 'src/x86/ffiw64.c', - ], 'conditions': [ - ['OS=="win"', { + ['OS=="win" and target_platform=="msvc"', { 'sources': [ + 'src/x86/ffiw64.c', 'src/x86/win64_intel.preasm', ], - }, { + 'msvs_disabled_warnings': [ 4267 ], + }], + ['OS=="win" and target_platform=="mingw"', { + 'sources': [ + 'src/x86/ffiw64.c', + 'src/x86/win64.S', + ], + }], + ['OS!="win"', { 'sources': [ 'src/x86/ffi64.c', 'src/x86/unix64.S', 'src/x86/win64.S', ], - }] + }], ], }], ['target_arch=="s390x"', { @@ -191,11 +213,6 @@ 'src/s390/sysv.S', ], }], - ['OS=="win"', { - # the libffi dlmalloc.c file has a bunch of implicit conversion - # warnings, and the main ffi.c file contains one, so silence them - 'msvs_disabled_warnings': [ 4267 ], - }], ] }], ] diff --git a/package-lock.json b/package-lock.json index 36e8bb48..feb200b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@napi-ffi/ffi-napi", - "version": "4.0.4", + "version": "4.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@napi-ffi/ffi-napi", - "version": "4.0.4", + "version": "4.0.5", "hasInstallScript": true, "license": "MIT", "dependencies": { "@napi-ffi/get-uv-event-loop-napi-h": "^1.0.6", - "@napi-ffi/ref-napi": "^3.0.6", + "@napi-ffi/ref-napi": "^3.0.7", "@napi-ffi/ref-struct-di": "^1.1.1", "debug": "^4.3.7", "node-addon-api": "^8.2.1", @@ -446,9 +446,9 @@ } }, "node_modules/@napi-ffi/ref-napi": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@napi-ffi/ref-napi/-/ref-napi-3.0.6.tgz", - "integrity": "sha512-xR+sxG/DzV+g/xbSHlrjAQkzJoR/+uL6RGde5SR2cGQqj/WO9A93gBypYtcdfnsnUOgNOeyfiUU9TRKatxD9cA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@napi-ffi/ref-napi/-/ref-napi-3.0.7.tgz", + "integrity": "sha512-oCaKehZERf2mEnqTJnxv/2hNDT5CpCH3s4jqncbi8jfSp40ydjhWk/xkuBz3GuSoCWeMW2y3EvFQS+sNDrfnug==", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 6ece4cdd..e27fff99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@napi-ffi/ffi-napi", - "version": "4.0.4", + "version": "4.0.5", "license": "MIT", "author": "Anna Henningsen ", "contributors": [ @@ -33,7 +33,7 @@ "@napi-ffi/get-uv-event-loop-napi-h": "^1.0.6", "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2", - "@napi-ffi/ref-napi": "^3.0.6", + "@napi-ffi/ref-napi": "^3.0.7", "@napi-ffi/ref-struct-di": "^1.1.1" }, "devDependencies": { diff --git a/test/library.js b/test/library.js index 84528ebb..a19c06e8 100644 --- a/test/library.js +++ b/test/library.js @@ -21,19 +21,22 @@ describe('Library', function () { }); it('should accept `null` as a first argument', function () { - if (process.platform == 'win32') { - // On Windows, null refers to just the main executable (e.g. node.exe). - // Windows never searches for symbols across multiple DLL's. - // Note: Exporting symbols from an executable is unusual on Windows. - // Normally you only see exports from DLL's. It happens that node.exe - // does export symbols, so null as a first argument can be tested. - // This is an implementation detail of node, and could potentially - // change in the future (e.g. if node gets broken up into DLL's - // rather than being one large static linked executable). + if (process.platform == 'win32' && !process.env.MSYSTEM_PREFIX) { + // On Windows (MSVC builds), null refers to just the main executable + // (e.g. node.exe). Windows never searches for symbols across DLLs. + // node.exe happens to export uv_fs_open, so null can be tested here. + // This is an implementation detail of node that does not hold for + // MSYS2/MinGW builds where libuv may be a separate DLL or symbols + // are not re-exported from the node binary. const winFuncs = new Library(null, { 'uv_fs_open': [ 'void', [ charPtr ] ] }); assert(typeof winFuncs.uv_fs_open === 'function'); + } else if (process.platform == 'win32') { + // MinGW/MSYS2: null is supported but uv_fs_open is not guaranteed + // to be exported from the node binary, skip the symbol check. + const l = new Library(null, {}); + assert(typeof l === 'object'); } else { // On POSIX, null refers to the global symbol table, and lets you use // symbols in the main executable and loaded shared libaries.