serialport / node-serialport

Access serial ports with JavaScript. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them!
https://serialport.io
MIT License
5.81k stars 1.01k forks source link

Unable to sign prebuilt arm and linux files for a Windows release #2515

Open chbonser opened 2 years ago

chbonser commented 2 years ago

SerialPort Version

10.0.2 and greater

Node Version

14.19.3

Electron Version

19.0.0

Platform

Microsoft Windows NT 10.0.22000.0 x64

Architecture

No response

Hardware or chipset of serialport

No response

What steps will reproduce the bug?

electron-forge make

What happens?

Error

The following error is thrown: System.AggregateException: One or more errors occurred. ---> System.Exception: Failed to sign, command invoked was: 'C:\...\electron-app\node_modules\electron-winstaller\vendor\signtool.exe sign /a /f "C:\...\cert.pfx" /p "..." C:\...\AppData\Local\SquirrelTemp\tempa\lib\net45\resources\app\node_modules\@serialport\bindings-cpp\prebuilds\android-arm\node.napi.armv7.node'

Full Stack Trace

An unhandled error has occurred inside Forge: An error occured while making for target: squirrel Failed with exit code: 4294967295 Output: Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\ffmpeg.dll Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\libEGL.dll Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\libGLESv2.dll Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\Meet Maestro.exe Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\Meet Maestro_ExecutionStub.exe Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\squirrel.exe Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\vk_swiftshader.dll Done Adding Additional Store Successfully signed: C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\vulkan-1.dll System.AggregateException: One or more errors occurred. ---> System.Exception: Failed to sign, command invoked was: 'C:...\electron-app\node_modules\electron-winstaller\vendor\signtool.exe sign /a /f "C:...\cert.pfx" /p "..." C:...\AppData\Local\SquirrelTemp\tempa\lib\net45\resources\app\node_modules\@serialport\bindings-cpp\prebuilds\android-arm\node.napi.armv7.node' at Squirrel.Update.Program.d17.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Squirrel.Update.Program.<>cDisplayClass10_0.<b14>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Squirrel.Utility.<>cDisplayClass13_11.<<ForEachAsync>b__1>d.MoveNext() --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at Squirrel.Update.Program.<>c__DisplayClass10_0.<Releasify>b__7(String pkgPath) at Squirrel.ReleasePackage.CreateReleasePackage(String outputFile, String packagesRootDir, Func2 releaseNotesProcessor, Action1 contentsPostProcessHook) at Squirrel.Update.Program.Releasify(String package, String targetDir, String packagesDir, String bootstrapperExe, String backgroundGif, String signingOpts, String baseUrl, String setupIcon, Boolean generateMsi, Boolean packageAs64Bit, String frameworkVersion, Boolean generateDeltas) at Squirrel.Update.Program.executeCommandLine(String[] args) at Squirrel.Update.Program.main(String[] args) at Squirrel.Update.Program.Main(String[] args) ---> (Inner Exception #0) System.Exception: Failed to sign, command invoked was: 'C:\...\electron-app\node_modules\electron-winstaller\vendor\signtool.exe sign /a /f "C:\...\cert.pfx" /p "..." C:\...\AppData\Local\SquirrelTemp\tempa\lib\net45\resources\app\node_modules\@serialport\bindings-cpp\prebuilds\android-arm\node.napi.armv7.node' at Squirrel.Update.Program.<signPEFile>d__17.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Squirrel.Update.Program.<>c__DisplayClass10_0.<<Releasify>b__14>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Squirrel.Utility.<>c__DisplayClass13_11.<b__1>d.MoveNext()<---

What should have happened?

The make command should have been successful.

Additional information

My exact same setup worked successfully with 10.0.1 it fails with 10.0.2. Clearly the PR Introduce Prebuildify is the root cause.

chbonser commented 2 years ago

Hi @thegecko @GazHank @robertsLando @reconbot, I'm pinging y'all since you all worked on or participated in discussion on https://github.com/serialport/node-serialport/pull/2368. Since that PR has merged I am not able to sign a windows release of our Electron app. Please see the notes above. Any advice? Thank you!

robertsLando commented 2 years ago

Sorry, no clue

thegecko commented 2 years ago

It may be due to the architecture of the other binaries shipped in the prebuildify folder. Perhaps run a pre-signing task to delete all the *.node files from node_modules you don't need?

chbonser commented 2 years ago

Thanks @thegecko. I have attempted to delete the prebuild architecture binaries before signing. I was able to complete the signing step but I then ran into import errors when running the application. Thoughts on how to address that?

I have also started a thread on the windows-installer library asking for a way to filter specified files from being signed. See https://github.com/electron/windows-installer/issues/358.

thegecko commented 2 years ago

I then ran into import errors when running the application

Keep the ones you need

chbonser commented 2 years ago

Keep the ones you need

As in edit imports in addition to deleting the architecture files that I did not need? I can experiment with that but it starts to feel like a lot of hackery post build.

neilyio commented 1 year ago

I just ran into this, and can confirm it requires post-build hackery.

This worked for me, using Electron Forge. After everything has been copied into the build folder, I loop through the non-Windows prebuild folders and delete them. You can confirm the names of the prebuild folders by looking at your node_modules/@serialport/bindings_cpp/prebuilds.

The packageAfterCopy hook exposed by Electron Forge (which is just the underlying Electron Packager's afterCopy hook) was the perfect place to do this. I've attached the snippet from my forge.config.js below.

It would be nice if this wasn't necessary, but making sure that Windows couldn't find the problematic prebuilds did indeed work.

module.exports {
  // ...
  hooks: {
    packageAfterCopy: async (config, buildPath, electronVersion, platform, arch) => {
      const fs = require("fs/promises")
      const path = require("path");

      // The Windows signtool will fail if it sees prebuilds for other platforms.
      // serialport insists on including these files no matter what platform
      // you're building on. We need to manually go through and delete them if we're
      // going to get our windows code-signing to work.
      if (platform !== "win32") return;

      const prebuildsThatFailOnWindows = [
        "android-arm",
        "android-arm64",
        "darwin-x64+arm64",
        "linux-arm",
        "linux-arm64",
        "linux-x64"
      ]

      for (const name of prebuildsThatFailOnWindows) {
        const fullPath = path.join(
          buildPath, "node_modules", "@serialport", "bindings-cpp", "prebuilds", name
        )
        await fs.rm(fullPath, { recursive: true, force: true });
      }
    }
  }
}