Skip to content

npm_install requires external build tools for installing native modules #506

Description

@guytt

🐞 bug report

Affected Rule

The issue is caused by the rule: npm_install

Is this a regression?

Not that I have noticed.

Description

When I use npm_install on a package.json that includes, in its list of dependencies, a native node module, the run of the rule attempts to use build tools external to bazel (e.g. **make**) and fails when such build tools are not present in the linux environment where bazel is being run.

After installing the required tools (i.e. running apt-get install build-essential), running the rule succeeds. This violates bazel's proclaimed hermeticity to some extent.

🔬 Minimal Reproduction

Partial content of WORKSPACE file:

load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "npm_install")

node_repositories(
    package_json = ["//:package.json"],
    node_version = "10.13.0",
)

npm_install(
    name = "node_modules",
    package_json = "//:package.json",
)

Content of pacakge.json:

{
  "name": "mymodule",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "native-module": "^0.11.3"
  }
}

🔥 Exception or Error


gyp ERR! build error
gyp ERR! stack Error: not found: make
gyp ERR! stack     at getNotFoundError (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp ERR! stack     at F (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp ERR! stack     at E (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/isexe/index.js:42:5
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/isexe/mode.js:8:5
gyp ERR! stack     at FSReqWrap.oncomplete (fs.js:154:21)
gyp ERR! System Linux 4.9.125-linuxkit
gyp ERR! command "/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/bin/node" "/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/cloud-host-worker-deps/node_modules/native-module
gyp ERR! node -v v10.13.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm WARN @wix/wix-express-newrelic-parameters@1.0.481 requires a peer of newrelic@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @wix/cloud-host-worker@1.0.920 No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! native-module@0.11.3 install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the native-module@0.11.3 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/bazel/.npm/_logs/2019-01-18T19_55_56_115Z-debug.log

🌍 Your Environment

Operating System:

  
4.9.125-linuxkit
  

Output of bazel version:

  
Build label: 0.20.0
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Fri Nov 30 14:39:01 2018 (1543588741)
Build timestamp: 1543588741
Build timestamp as int: 1543588741
  

Rules version (SHA):

  
0.16.4 (d6fcfaf1380e81ace932b534c4ea99166008f0b6)
  

Encountered as part of using Bazel at Wix.com @ittaiz

Activity

  1. mgechev commented on Jan 18, 2019

    @mgechev
    Collaborator

    Do you hit this issue by running npm outside of Bazel? I suppose no?

    I understand that this violates the hermeticity but it might be a reasonable compromise so that we do not couple rules_nodejs with the external tooling involved in building native node modules.

    cc @alexeagle @gregmagolan

  2. ittaiz commented on Jan 19, 2019

    @ittaiz
  3. guytt commented on Jan 20, 2019

    @guytt
    Author

    @mgechev
    I hit this issue whenever running npm install in an environment where this external tooling is not installed.
    As most installations of node/npm install this additional tooling, I don't hit the issue.

  4. ittaiz commented on Jan 27, 2019

    @ittaiz

    @gregmagolan can you update about the toolchain approach we discussed? Thanks!

  5. gregmagolan commented on Jan 28, 2019

    @gregmagolan
    Collaborator

    Yes. @ittaiz @alexeagle and I discussed this at the bazel rules summit last week. The thinking is that we should be able to resolve this with bazel toolchains. We're planning to migrate nodejs to bazel toolchains in the next month so we'll look at this at that point.

  6. rohansingh commented on Mar 3, 2019

    @rohansingh

    Doesn't this break determinism as well? The npm process for building native modules seems to break caching for me.

  7. ittaiz commented on Mar 3, 2019

    @ittaiz
  8. Toxicable commented on Sep 8, 2020

    @Toxicable

    Flyby comment: I think the long term solution for this one is getting projects that publish native code to instead publish WASM

  9. added 2 commits that reference this issue on Oct 17, 2020
    46b7fd6
    8bd9734
  10. vpanta commented on May 4, 2021

    @vpanta
    Contributor

    Is there any planned next-steps on this? Or is it just a big question-mark still?

    We have similar issues where we can't use npm_install due to failures with modules installing themselves via node-gyp. We live in a weird mixed world at the moment (we have hacked around to get the BUILD file generation but leave module installation outside of bazel), but we'd much prefer to get to the standard patterns expected by the library.

  11. vpanta commented on May 4, 2021

    @vpanta
    Contributor

    *clarification, our issue with node modules and node-gyp is explicitly when executing in our Linux docker container on CI, however it works fine on our local MacOS machines.

  12. xvzf commented on May 3, 2022

    @xvzf

    @vpanta did you manage to find a solution?

  13. vpanta commented on May 10, 2022

    @vpanta
    Contributor

    @xvzf No, although we're diving back into looking more at it now.

  14. vpanta commented on May 10, 2022

    @vpanta
    Contributor

    for now, I think we've found a workaround with using npm_command = "install", as it's only when bazel runs npm ci in these environments that it seems to fail to install node-gyp-build appropriately (?)

    *edit: that only worked due to symlink_node_modules being set to True, however we'll probably want to use the default once we can update rules_nodejs (now False). That sets us back to the same issue as before :/

  15. vpanta commented on May 12, 2022

    @vpanta
    Contributor

    Ok, so our issue isn't purely with node-gyp-build but rather that, when it executes, it can't find node-gyp. Which shouldn't be a thing seeing that node-gyp is a pack-in with npm itself.

    So, if I get onto the machine and use npm outside of bazel to globally install node-gyp (shouldn't be needed, as node-gyp is a pack-in with node), then we get past this as bazel is finding that secondary installed node-gyp.

    Poking deeper, I patched our version of the _npm.sh generated here to include a call npm ls -g node-gyp immediately before the call to npm ci. It returned:

    `-- npm@8.1.0
      +-- @npmcli/run-script@2.0.0
      | `-- node-gyp@8.2.0 deduped
      `-- node-gyp@8.2.0
    

    yet still failed on the very next line with:

    npm ERR! command failed
    npm ERR! command sh -c node-gyp-build
    npm ERR! node:events:368
    npm ERR!       throw er; // Unhandled 'error' event
    npm ERR!       ^
    npm ERR! 
    npm ERR! Error: spawn node-gyp ENOENT
    npm ERR!     at Process.ChildProcess._handle.onexit (node:internal/child_process:282:19)
    

    which has me extra flummoxed...

  16. vpanta commented on May 13, 2022

    @vpanta
    Contributor

    I was hoping this was maybe due to something with symlinked paths, assuming it was executing the node-gyp from within utf-8-validate's build (that's who's using node-gyp-build), and during that install the cwd is a different place, but various attempts to get --preserve-symlinks for node and/or --scripts-prepend-node-path=true for npm into the command line have also failed to produce any results.

    At the moment, we're solving this with a forced global install of node-gyp (i.e. npm i -g node-gyp), so that when the other modules get installed it can find node-gyp without issue. This isn't great though.

  17. vpanta commented on May 13, 2022

    @vpanta
    Contributor

    Ok, one last update: this isn't Linux specific. We're seeing the same issue on our MacOS containers as well.

  18. vpanta commented on May 13, 2022

    @vpanta
    Contributor

    phooey, the "globally install" trick isn't working on our MacOS containers :/

  19. Shusanta commented on Mar 4, 2024

    @Shusanta

    @vpanta what was the solution?

  20. vpanta commented on Mar 4, 2024

    @vpanta
    Contributor

    We never found a solution under the old versions of rules_nodejs. We now use the latest version of rules_nodejs along with aspect-build/rules_js and don't have this specific issue.

    We did however recently run into an issue with node-gyp-build, which was solved by apnpm.packageExtensions block in our package.json (forcing node-gyp as a dependency of packages which depended on node-gyp-build).

  21. gregmagolan commented on Jun 8, 2024

    @gregmagolan
    Collaborator

    No longer in scope for rules_nodejs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions