Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefix build targets with /t: on Windows #1164

Closed
wants to merge 3 commits into from

Conversation

NatalieWolfe
Copy link
Contributor

Currently, on non-Windows platforms, it is possible to have a multi-target native module and specify building just some of the targets using node-gyp build my_target. On Windows, however, specifying the target(s) to build requires the /t: or /target: flag. Without this change you will get the error MSB1008 because MSBuild things you are trying to specify multiple solutions.

Currently, on non-Windows platforms, it is possible to have a multi-target native module and specify building just some of the targets using `node-gyp build my_target`. On Windows, however, specifying the target(s) to build requires the [`/t:` or `/target:` flag](https://msdn.microsoft.com/en-us/library/ms164311.aspx). Without this change you will get the error `MSB1008` because MSBuild things you are trying to specify multiple solutions.
@bnoordhuis
Copy link
Member

I will admit to not exactly understanding what this does. Is this for a binding.gyp that produces multiple .node files?

In any case, it would be nice to have a regression test.

@NatalieWolfe
Copy link
Contributor Author

Yes, for example take the binding file below:

{
  "targets": [{
    "target_name": "my_module",
    "sources": [
      "src/my_module.cpp",
    ],
    "include_dirs": [
      "src",
      "<!(node -e \"require('nan')\")"
    ]
  }, {
    "target_name": "tests",
    "sources": [
      "src/tests/my_tests.cpp"
    ],
    "include_dirs": [
      "src",
      "<!(node -e \"require('nan')\")"
    ]
  }]
}

I have a native module similar to this that has some tests written in C++ for native-only classes. There is no reason for this test module to build when installed from npm so I have in my package.json "install": "node-gyp configure build -j4 my_module" which will only build the my_module target but it fails when run on windows machines.

I will see if I can add a test for this.

@NatalieWolfe
Copy link
Contributor Author

I've added a test for specifying the module. If you'd like to add a case that tests a multi-target gyp file just let me know.

test('build specific addon', function (t) {
t.plan(4)

var cmd = [nodeGyp, 'clean', 'configure', '-C', addonPath, '--loglevel=verbose']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd isn't used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, cruft from before moving it into the exec function. Removed.

Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but...

If you'd like to add a case that tests a multi-target gyp file just let me know.

...would be nice. CI: https://ci.nodejs.org/job/nodegyp-test-pull-request/5/

@NatalieWolfe
Copy link
Contributor Author

@bnoordhuis If I'm reading that output correct, it looks like the tests failed to download the node headers for 4.8.1?

gyp WARN install got an error, rolling back install
gyp verb command remove [ '4.8.1' ]
gyp verb remove using node-gyp dir: C:\Users\Administrator\.node-gyp
gyp verb remove removing target version: 4.8.1
gyp verb remove removing development files for version: 4.8.1
gyp ERR! configure error 
gyp ERR! stack Error: win-x64/node.lib local checksum 1e48457fb9468bc7c7f2d01f6002b2c5ee31807cff972a21578178ed6b6757da not match remote 8626f6758318e88e8a8641d4f7b75560fa207c35ea9d80e5e4f43066b5a7f714
gyp ERR! stack     at deref (c:\workspace\nodegyp-test-commit\nodes\win2012r2\lib\install.js:266:20)
gyp ERR! stack     at Request.<anonymous> (c:\workspace\nodegyp-test-commit\nodes\win2012r2\lib\install.js:384:24)
gyp ERR! stack     at emitOne (events.js:82:20)
gyp ERR! stack     at Request.emit (events.js:169:7)
gyp ERR! stack     at IncomingMessage.<anonymous> (c:\workspace\nodegyp-test-commit\nodes\win2012r2\node_modules\request\request.js:1091:12)
gyp ERR! stack     at IncomingMessage.g (events.js:260:16)
gyp ERR! stack     at emitNone (events.js:72:20)
gyp ERR! stack     at IncomingMessage.emit (events.js:166:7)
gyp ERR! stack     at endReadableNT (_stream_readable.js:923:12)
gyp ERR! stack     at nextTickCallbackWith2Args (node.js:511:9)

That doesn't seem like the kind of thing my changes would cause. Do these tests ever flap, or am I not reading this correctly?

@bnoordhuis
Copy link
Member

Probably a hiccup. New run: https://ci.nodejs.org/job/nodegyp-test-pull-request/7/

@NatalieWolfe
Copy link
Contributor Author

NatalieWolfe commented Apr 11, 2017

Ugh, looks like tape runs all of the tests in the same process, meaning the world module I added is still in the require.cache from test-addon. Any suggestions?


Here's if you run both tests in the same go with tape test/test-*addon.js:

$ tape test/test-*addon.js
TAP version 13
# build simple addon
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js clean rebuild -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose
ok 1 should be equal
ok 2 should end in ok
ok 3 should be equal
ok 4 should be equal
# build specific addon
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js clean configure -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose
ok 5 clean build
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js build -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose hello
ok 6 should be equal
ok 7 should end in ok
ok 8 should be equal
{ world: [Function] }
not ok 9 should not have loaded unbuilt module
  ---
    operator: fail
    at: maybeClose (internal/child_process.js:854:16)
  ...

1..9
# tests 9
# pass  8
# fail  1

And this is running tape test/test-addon.js and then tape test/test-specific-addon.js:

$ tape test/test-addon.js
TAP version 13
# build simple addon
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js clean rebuild -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose
ok 1 should be equal
ok 2 should end in ok
ok 3 should be equal
ok 4 should be equal

1..4
# tests 4
# pass  4

# ok

$ tape test/test-specific-addon.js
TAP version 13
# build specific addon
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js clean configure -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose
ok 1 clean build
# /Users/nwolfe/work/ext/node-gyp/bin/node-gyp.js build -C /Users/nwolfe/work/ext/node-gyp/test/node_modules/hello_world --loglevel=verbose hello
ok 2 should be equal
ok 3 should end in ok
ok 4 should be equal
ok 5 should not build world

1..5
# tests 5
# pass  5

# ok

@bnoordhuis
Copy link
Member

That's issue #1123, it's on my todo list for when I have a spare afternoon. Would some judicious delete require.cache[...] statements work in the interim?

@bnoordhuis
Copy link
Member

@NatalieWolfe Are you still working on this? As a workaround you could make the test do child_process.spawn(process.execPath, [__dirname + '/helper.js']) to load the add-on in a separate process.

@refack
Copy link
Contributor

refack commented May 15, 2017

@NatalieWolfe I had a much simpler idea: split your .gyp file

If you run npm i only the my_module target is built.
If you run node-gyp rebuild test.gyp both targets are built.

binding.gyp

{
  "targets": [{
    "target_name": "my_module",
    "sources": [
      "hello.cc",
    ],
  }]
}

test.gyp

{
  "targets": [{
    "include_dirs" : [
        "<!(node -e \"require('nan')\")"
    ],
    "dependencies": [
       "./binding.gyp:my_module"
    ],
    "target_name": "tests",
    "sources": [
      "tests/hello-test.cc"
    ],
  }]
}

bnoordhuis pushed a commit that referenced this pull request Jun 8, 2018
Currently, on non-Windows platforms, it is possible to have
a multi-target native module and specify building just some
of the targets using `node-gyp build my_target`.

On Windows, however, specifying the targets to build requires the `/t:`
or `/target:` flag. Without this change you will get an `MSB1008` error
because MSBuild thinks you are trying to specify multiple solutions.

PR-URL: #1164
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@bnoordhuis
Copy link
Member

Landed in 4379c47. I left out the tests because of conflicts.

@NatalieWolfe Can you open a new pull request if you want to see those merged? Cheers.

@bnoordhuis bnoordhuis closed this Jun 8, 2018
ilatypov added a commit to ilatypov/node-pre-gyp that referenced this pull request Sep 12, 2018
..until fixing command line processing in Windows broken by a change making multi-target invokation possible in Windows, just like in other OSes,

nodejs/node-gyp#1164

The change did not account for the special case of passing a define on command line.
SuibianP added a commit to SuibianP/llnode that referenced this pull request Sep 25, 2024
nodejs/node-gyp#1164 interprets additional node-gyp build parameters as
target names, which breaks the current way CL configs are passed to
msbuild in install.js.

Move the detection logic into configuration phase and pass CL configs as
gyp variables.

Fixes nodejs#321, fixes nodejs#377
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants