nodejs / node-gyp

Node.js native addon build tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Windows/Visual Studio build process fails on node-gyp generated vcxproj output

aldriq opened this issue · comments

I recently updated a project that uses node-gyp from Node.js 18.18.0/node-gyp 9.4.0 to Node.js 18.19.0/node-gyp 10.3.0. While the Linux project builds and runs as before, the Windows version using Visual Studio 2017 no longer builds.

After some digging through the detailed logs and intermediate files I found the reason MSBuild.exe fails now, the actions in the binding.gyp file seem to be getting additional quotes in the generated Visual Studio project file:

From my binding.gyp:

"action": [ "msbuild <(module_root_dir)/../../../../../APIs/C/c.vcxproj -p:Configuration=$(ConfigurationName) -p:Platform=x64" ]

With the older node-gyp 9.4.0 the corresponding output in the generated project file for Visual Studio was:

<Command>call call msbuild C:\Users\DevUser\Source\core\Server\testrest\svr\build\testclient\..\..\..\..\..\APIs\C\c.vcxproj -p:Configuration=$(Configuration) -p:Platform=x64&#xD;&#xA;if %errorlevel% neq 0 exit /b %errorlevel%</Command>

Whereas the current node-gyp (10.0.1 and 10.3.0) generates the additional quotes:

<Command>call call &quot;msbuild C:\Users\DevUser\Source\core\Server\testrest\svr\build\testclient\..\..\..\..\..\APIs\C\c.vcxproj -p:Configuration=$(Configuration) -p:Platform=x64&quot;&#xD;&#xA;if %errorlevel% neq 0 exit /b %errorlevel%</Command>

I found that this issue might have potentially happened before, but note sure if this is the same or a similar regresssion.

Any help/confirmation appreciated.

  • Node Version: 18.19.0
  • Platform: OS Name: Microsoft Windows Server 2019 Standard
  • OS Version: 10.0.17763 N/A Build 17763
  • System Type: x64-based PC
  • Compiler: Microsoft (R) Build Engine version 15.9.21+g9802d43bc3 for .NET Framework (15.9.21.664 )
Verbose output (from npm or node-gyp):
18>    gyp info it worked if it ends with ok
18>    gyp info using node-gyp@10.3.0
18>    gyp info using node@18.19.0 | win32 | x64
18>    gyp info find Python using Python version 3.11.4 found at "C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe"
18>
18>    gyp info find VS using VS2017 (15.9.34407.156) found at:
18>    gyp info find VS "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional"
18>    gyp info find VS run with --verbose for detailed information
...

18>    Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
18>      build_test_library
18>      The filename, directory name, or volume label syntax is incorrect.
18>    C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5): error MSB6006: "cmd.exe" exited with code 1. [C:\Users\DevUser\Source\core\Server\testrest\svr\build\testlibrary\build\libtestlibrary.vcxproj]
18>    gyp ERR! build error
18>    EXEC : gyp ERR! stack error : `C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe` failed with exit code: 1

@aldriq I am not able to reproduce the issue, the quotes work for me. Can you run with --verbose and provide us with the full log?

Sure, here's the full output for my latest run with node 20.11.1:

2>------ Build started: Project: glrest, Configuration: Release x64 ------
2>
2>Microsoft (R) Program Maintenance Utility Version 14.16.27051.0
2>Copyright (C) Microsoft Corporation.  All rights reserved.
2>
2>	set PATH=C:\Users\DevUser\source\core\Server\glrest\node-v20.11.1-win-x64;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86;C:\Program Files (x86)\Windows Kits\8.1\bin\x86;;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\tools;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\ide;C:\Program Files (x86)\HTML Help Workshop;;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin;C:\Windows\Microsoft.NET\Framework\v4.0.30319\;;C:\Users\DevUser\AppData\Local\ActiveState\StateTool\release\bin;C:\Program Files\Zulu\zulu-11\bin\;C:\Program Files\Python39\Scripts\;C:\Program Files\Python39\;C:\Users\DTopham\AppData\Roaming\ActiveState\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\ProgramData\chocolatey\bin;C:\Program Files\dotnet\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\7-Zip;C:\Users\DTopham\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files\CMake\bin;C:\Program Files\Git\cmd;C:\Program Files\PuTTY\;C:\Program Files\Microsoft VS Code\bin;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin;C:\Program Files\PowerShell\7\;C:\Users\DevUser\AppData\Local\Programs\Python\Python311\Scripts\;C:\Users\DevUser\AppData\Local\Programs\Python\Python311\;C:\Users\DevUser\AppData\Local\Microsoft\WindowsApps;;
2>	cd svr\build\gllibrary
2>	npm install --msvs-version=2017
2>
2>> gllibrary@15.19.0 install
2>> node-gyp rebuild --verbose
2>
2>gyp info it worked if it ends with ok
2>gyp verb cli [
2>gyp verb cli 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node.exe',
2>gyp verb cli 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js',
2>gyp verb cli 'rebuild',
2>gyp verb cli '--verbose'
2>gyp verb cli ]
2>gyp info using node-gyp@10.0.1
2>gyp info using node@20.11.1 | win32 | x64
2>gyp verb clean removing "build" directory
2>gyp verb find Python Python is not set from command line or npm configuration
2>gyp verb find Python Python is not set from environment variable PYTHON
2>gyp verb find Python checking if the py launcher can be used to find Python 3
2>gyp verb find Python - executing "py.exe" to get Python 3 executable path
2>gyp verb find Python - executable path is "C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe"
2>gyp verb find Python - executing "C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe" to get version
2>gyp verb find Python - version is "3.11.4"
2>gyp info find Python using Python version 3.11.4 found at "C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe"
2>gyp verb get node dir no --target version specified, falling back to host node version: 20.11.1
2>
2>gyp verb install input version string "20.11.1"
2>gyp verb install installing version: 20.11.1
2>gyp verb install --ensure was passed, so won't reinstall if already installed
2>gyp verb install version is already installed, need to check "installVersion"
2>gyp verb got "installVersion" 11
2>gyp verb needs "installVersion" 11
2>gyp verb install version is good
2>gyp verb on Windows; need to check node.lib
2>gyp verb get node dir target node version installed: 20.11.1
2>gyp verb build dir attempting to create "build" dir: C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build
2>gyp verb build dir "build" dir needed to be created? Yes
2>gyp verb find VS msvs_version was set from command line or npm config
2>gyp verb find VS - looking for Visual Studio version 2017
2>gyp verb find VS VCINSTALLDIR not set, not running in VS Command Prompt
2>gyp verb find VS checking VS2017 (15.9.34601.69) found at:
2>gyp verb find VS "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional"
2>gyp verb find VS - found "Visual Studio C++ core features"
2>gyp verb find VS - found VC++ toolset: v141
2>gyp verb find VS - found Windows SDK: 10.0.17763.0
2>gyp info find VS using VS2017 (15.9.34601.69) found at:
2>gyp info find VS "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional"
2>gyp info find VS run with --verbose for detailed information
2>gyp verb build/config.gypi creating config file
2>gyp verb build/config.gypi writing out config file: C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\config.gypi
2>gyp verb config.gypi checking for gypi file: C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\config.gypi
2>gyp verb common.gypi checking for gypi file: C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\common.gypi
2>gyp verb gyp gyp format was not specified; forcing "msvs"
2>gyp info spawn C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe
2>gyp info spawn args [
2>gyp info spawn args 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node_modules\\npm\\node_modules\\node-gyp\\gyp\\gyp_main.py',
2>gyp info spawn args 'binding.gyp',
2>gyp info spawn args '-f',
2>gyp info spawn args 'msvs',
2>gyp info spawn args '-I',
2>gyp info spawn args 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\svr\\build\\gllibrary\\build\\config.gypi',
2>gyp info spawn args '-I',
2>gyp info spawn args 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node_modules\\npm\\node_modules\\node-gyp\\addon.gypi',
2>gyp info spawn args '-I',
2>gyp info spawn args 'C:\\Users\\DevUser\\AppData\\Local\\node-gyp\\Cache\\20.11.1\\include\\node\\common.gypi',
2>gyp info spawn args '-Dlibrary=shared_library',
2>gyp info spawn args '-Dvisibility=default',
2>gyp info spawn args '-Dnode_root_dir=C:\\Users\\DevUser\\AppData\\Local\\node-gyp\\Cache\\20.11.1',
2>gyp info spawn args '-Dnode_gyp_dir=C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node_modules\\npm\\node_modules\\node-gyp',
2>gyp info spawn args '-Dnode_lib_file=C:\\\\Users\\\\DevUser\\\\AppData\\\\Local\\\\node-gyp\\\\Cache\\\\20.11.1\\\\<(target_arch)\\\\node.lib',
2>gyp info spawn args '-Dmodule_root_dir=C:\\Users\\DevUser\\source\\core\\Server\\glrest\\svr\\build\\gllibrary',
2>gyp info spawn args '-Dnode_engine=v8',
2>gyp info spawn args '--depth=.',
2>gyp info spawn args '--no-parallel',
2>gyp info spawn args '--generator-output',
2>gyp info spawn args 'C:\\Users\\DevUser\\source\\core\\Server\\glrest\\svr\\build\\gllibrary\\build',
2>gyp info spawn args '-Goutput_dir=.'
2>gyp info spawn args ]
2>gyp verb build type Release
2>gyp verb architecture x64
2>gyp verb node dev dir C:\Users\DevUser\AppData\Local\node-gyp\Cache\20.11.1
2>gyp verb python C:\Users\DevUser\AppData\Local\Programs\Python\Python311\python.exe
2>gyp verb found first Solution file build\binding.sln
2>gyp verb using MSBuild: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe
2>gyp info spawn C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe
2>gyp info spawn args [
2>gyp info spawn args 'build\\binding.sln',
2>gyp info spawn args '/nologo',
2>gyp info spawn args '/p:Configuration=Release;Platform=x64'
2>gyp info spawn args ]
2>Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
2>Build started 2/23/2024 7:08:27 AM.
2>Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\binding.sln" on node 1 (default targets).
2>ValidateSolutionConfiguration:
2>  Building solution configuration "Release|x64".
2>Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\binding.sln" (1) is building "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\gllibrary.vcxproj.metaproj" (2) on node 1 (default targets).
2>Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\gllibrary.vcxproj.metaproj" (2) is building "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\libgllibrary.vcxproj" (3) on node 1 (default targets).
2>PrepareForBuild:
2>  Creating directory "Release\obj\libgllibrary\".
2>  Creating directory "Release\obj\libgllibrary\libgllibrary.tlog\".
2>InitializeBuildStatus:
2>  Creating "Release\obj\libgllibrary\libgllibrary.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
2>CustomBuild:
2>  build_GL_library
2>  The filename, directory name, or volume label syntax is incorrect.
2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5): error MSB6006: "cmd.exe" exited with code 1. [C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\libgllibrary.vcxproj]
2>Done Building Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\libgllibrary.vcxproj" (default targets) -- FAILED.
2>Done Building Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\gllibrary.vcxproj.metaproj" (default targets) -- FAILED.
2>Done Building Project "C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\binding.sln" (default targets) -- FAILED.
2>
2>Build FAILED.
2>
2>"C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\binding.sln" (default target) (1) ->
2>"C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\gllibrary.vcxproj.metaproj" (default target) (2) ->
2>"C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\libgllibrary.vcxproj" (default target) (3) ->
2>(CustomBuild target) ->
2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\VCTargets\Microsoft.CppCommon.targets(209,5): error MSB6006: "cmd.exe" exited with code 1. [C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary\build\libgllibrary.vcxproj]
2>
2>    0 Warning(s)
2>    1 Error(s)
2>
2>Time Elapsed 00:00:00.90
2>gyp ERR! build error
2>EXEC : gyp ERR! stack error : `C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe` failed with exit code: 1
2>gyp ERR! stack at ChildProcess.<anonymous> (C:\Users\DevUser\source\core\Server\glrest\node-v20.11.1-win-x64\node_modules\npm\node_modules\node-gyp\lib\build.js:209:23)
2>gyp ERR! stack at ChildProcess.emit (node:events:518:28)
2>gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:294:12)
2>gyp ERR! System Windows_NT 10.0.17763
2>gyp ERR! command "C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node.exe" "C:\\Users\\DevUser\\source\\core\\Server\\glrest\\node-v20.11.1-win-x64\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--verbose"
2>gyp ERR! cwd C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary
2>gyp ERR! node -v v20.11.1
2>gyp ERR! node-gyp -v v10.0.1
2>gyp ERR! not ok
2>npm ERR! code 1
2>npm ERR! path C:\Users\DevUser\source\core\Server\glrest\svr\build\gllibrary
2>npm ERR! command failed
2>npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node-gyp rebuild --verbose
2>
2>npm ERR! A complete log of this run can be found in: C:\Users\DevUser\AppData\Local\npm-cache\_logs\2024-02-23T12_08_08_837Z-debug-0.log
2>NMAKE : fatal error U1077: 'C:\Users\DevUser\source\core\Server\glrest\node-v20.11.1-win-x64\npm.CMD' : return code '0x1'
2>Stop.
2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\VCTargets\Microsoft.MakeFile.Targets(44,5): error MSB3073: The command "nmake /f win.make all" exited with code 2.
2>Done building project "glrest.vcxproj" -- FAILED.

Since I'm happy with the upgrade to Node.js 20.11.1, for now I've just replaced the default "node-gyp rebuild" with separate "node-gyp configure" and "node-gyp build" so I can remove the quotes in the VS project files manually before the build stage.

@huseyinacacak-janea I wonder if the problem with mine is due to the spaces in the path, my msbuild executable is in "C:\Program Files (x86)\Microsoft Visual Studio\2017" so if those spaces were being correctly escaped before the new quotes were added, they might not be now.

Node-gyp expects its arguments to be comma-separated so that it can quote each argument. This way, it can handle spaces in the path.

@aldriq you have a single line of action, can you try separating the arguments?

"action": [ "msbuild",
            "<(module_root_dir)/../../../../../APIs/C/c.vcxproj",
            "-p:Configuration=$(ConfigurationName)",
            "-p:Platform=x64" ]

Splitting the parameters works, thanks @huseyinacacak-janea! It makes sense that every element should be quoted/escaped individually. Now looking at the Linux build action it turns out this one was split in parameters, but the Windows one wasn't for some reason. All sorted then, thanks!