microsoft / node-uwp

Enables Universal Windows Platform (UWP) API access for Node.js (Chakra build) on Windows 10.
MIT License
152 stars 26 forks source link

build: missing libs in LINK command line #20

Closed jianchun closed 8 years ago

jianchun commented 8 years ago

Reported by @RReverser in #12. We should have a list of libs on LINK command line.

Those libs are supposed to be brought in by C:\Program Files\NodejsUwp\Console\node_modules\npm\node_modules\node-gyp\addon.gypi:

          ['node_win_onecore=="false"', {
            'libraries': [
              '-lkernel32.lib',
              '-luser32.lib',
              '-lgdi32.lib',
              '-lwinspool.lib',
              '-lcomdlg32.lib',
              '-ladvapi32.lib',
              '-lshell32.lib',
              '-lole32.lib',
              '-loleaut32.lib',
              '-luuid.lib',
              '-lodbc32.lib',
              '-lDelayImp.lib',
              '-l"<(node_lib_file)"',
            ],
          }],

But @RReverser only has 2:

Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\Ingvar\Documents\Projects\Web\uwp-filesystem-shim\node_modules\u
  wp\build\Release\uwp.node" /INCREMENTAL:NO /NOLOGO /LIBPATH:"C:\Program Files\NodejsUwp\Console\sdk\x64" chakrart.lib Delayimp.lib /DELAYLOAD:iojs.exe /DELAYLOAD:node.exe /
  MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /Debug /PDB:"C:\Users\Ingvar\Documents\Projects\Web\uwp-filesystem-shim\node_modules\uwp\build\Re
  lease\uwp.pdb" /MAP /MAPINFO:EXPORTS /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /ignore:4199 /DLL Release\obj\uwp\uwp.obj
  Release\obj\uwp\win_delay_load_hook.obj
     Creating library C:\Users\Ingvar\Documents\Projects\Web\uwp-filesystem-shim\node_modules\uwp\build\Release\uwp.lib and object C:\Users\Ingvar\Documents\Projects\Web\uwp-
  filesystem-shim\node_modules\uwp\build\Release\uwp.exp
uwp.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: void * __cdecl v8::External::Value(void)const " (__imp_?Value@External@v8@@QEBAPEAXXZ) [C:\ Users\Ingvar\Documents\Projects\Web\uwp-filesystem-shim\node_modules\uwp\build\uwp.vcxproj]
...
jianchun commented 8 years ago

@munyirik Do you see any clue? Any possibility node_win_onecore != false?

munyirik commented 8 years ago

Right. --node_win_onecore=false should be used. I should fix it so that it's the default behavior.

jianchun commented 8 years ago

I assume the default is indeed false? Don't know how to make it false on command line. npm i uwp --node_win_onecore=false then reproes this issue for me.

munyirik commented 8 years ago

Actually yes. I just tried to repro but I don't see that error (with just "npm i uwp"). Which version did you use? (I used this). I also see another issue where PATH isn't update to use the most recent Node.js (Chakra) install. Or maybe this should be by design.

munyirik commented 8 years ago

If I run npm i uwp node_win_onecore is 'false' and my build passes. If I run npm i uwp --node_win_onecore=false, node_win_onecore is empty and I can repro this problem. If I define node_win_onecore in C:\Program Files\NodejsUwp\Console\node_modules\npm\node_modules\node-gyp\addon.gypi then it provides a workaround for using npm i uwp --node_win_onecore=false ... 'target_defaults': { 'variables': { 'node_win_onecore': 'false', }, ... Still not sure why npm i uwp is working for me. So far I can't see where it's defined.

RReverser commented 8 years ago

Actually yes. I just tried to repro but I don't see that error (with just "npm i uwp"). Which version did you use? (I used this).

I'm using the same (and you can see in my logs in mentioned comment that Node.js reports the same version, so it's not PATH neither).

So what is the workaround? Should I do smth like npm i uwp --node_win_onecore=false or the opposite?

munyirik commented 8 years ago

Modify C:\Program Files\NodejsUwp\Console\node_modules\npm\node_modules\node-gyp\addon.gypi to set node_win_onecore=false. So at the beginning of the file you'll have this: ... 'target_defaults': { 'variables': { 'node_win_onecore': 'false', }, ... Then run npm i uwp --node-win-onecore=false

RReverser commented 8 years ago

Umm... okay, thanks, I'll try that in the evening on my home laptop. Although it looks like, if it works, it's just a temporary solution that still needs to be backported to Node.js (chakra)?

jianchun commented 8 years ago

With that default to 'false', "npm i uwp" should work.

Yes, we'll need to fix Node.js (chakra). Haven't figured out how it worked on our boxes yet.

jianchun commented 8 years ago

Ok, I figured out how it was supposed to work.

The log had:

gyp info spawn args   '-I',
gyp info spawn args   'C:\\Users\\Ingvar\\Documents\\Projects\\Web\\uwp-filesystem-shim\\node_modules\\uwp\\build\\config.gypi',

That config.gypi is generated by node-gyp during configure. Its content is supposed to be:

# Do not edit. File was generated by node-gyp's "configure" step
{
  "target_defaults": {
    "cflags": [],
    "default_configuration": "Release",
    "defines": [],
    "include_dirs": [],
    "libraries": []
  },
  "variables": {
    "asan": 0,
    "host_arch": "x64",
    "icu_small": "false",
    "node_byteorder": "little",
    "node_enable_v8_vtunejit": "false",
    "node_engine": "chakra",
    "node_install_npm": "true",
    "node_prefix": "/usr/local",
    "node_release_urlbase": "",
    "node_shared_http_parser": "false",
    "node_shared_libuv": "false",
    "node_shared_openssl": "false",
    "node_shared_zlib": "false",
    "node_tag": "-1",
    "node_use_dtrace": "false",
    "node_use_etw": "true",
    "node_use_lttng": "false",
    "node_use_openssl": "true",
    "node_use_perfctr": "true",
    "node_uwp_dll": "false",
    "node_win_onecore": "false",
    "openssl_fips": "",
    "openssl_no_asm": 0,
    "target_arch": "ia32",
    "v8_enable_gdbjit": 0,
    "v8_enable_i18n_support": 0,
    "v8_no_strict_aliasing": 1,
    "v8_optimized_debug": 0,
    "v8_random_seed": 0,
    "v8_use_snapshot": "true",
    "want_separate_host_toolset": 1,
    "nodedir": "C:\\Program Files (x86)\\NodejsUwp\\Console\\sdk",
    "copy_dev_lib": "false",
    "standalone_static_library": 1
  }
}

The variables section contains "node_win_onecore": "false". That section content comes from node.exe process.config.

PS D:\uwp> node -pe "process.config"
{ target_defaults:
   { cflags: [],
     default_configuration: 'Release',
     defines: [],
     include_dirs: [],
     libraries: [] },
  variables:
   { asan: 0,
     host_arch: 'x64',
     icu_small: false,
     node_byteorder: 'little',
     node_enable_v8_vtunejit: false,
     node_engine: 'chakra',
     node_install_npm: true,
     node_prefix: '/usr/local',
     node_release_urlbase: '',
     node_shared_http_parser: false,
     node_shared_libuv: false,
     node_shared_openssl: false,
     node_shared_zlib: false,
     node_tag: '-1',
     node_use_dtrace: false,
     node_use_etw: true,
     node_use_lttng: false,
     node_use_openssl: true,
     node_use_perfctr: true,
     node_uwp_dll: false,
     node_win_onecore: false,
     openssl_fips: '',
     openssl_no_asm: 0,
     target_arch: 'ia32',
     v8_enable_gdbjit: 0,
     v8_enable_i18n_support: 0,
     v8_no_strict_aliasing: 1,
     v8_optimized_debug: 0,
     v8_random_seed: 0,
     v8_use_snapshot: true,
     want_separate_host_toolset: 1 } }

@RReverser Could you please help us do a little debugging? Try git clone this repo to a local dir. Then with Node.js (chakra), run "npm install" in that dir. If it fails, see what you have in .\build\config.gypi.

RReverser commented 8 years ago

Okay, first of all - trick with node-win-onecore=false worked, thanks! Trying the repo now.

RReverser commented 8 years ago

@jianchun So with npm i inside of this repo results are the same - works when node-win-onecore is added in C:\Program Files\NodejsUwp\Console\node_modules\npm\node_modules\node-gyp\addon.gypi and doesn't when it's not present there (default).

This is the contents of build\config.gypi when it fails:

# Do not edit. File was generated by node-gyp's "configure" step
{
  "target_defaults": {
    "cflags": [],
    "default_configuration": "Release",
    "defines": [],
    "include_dirs": [],
    "libraries": []
  },
  "variables": {
    "asan": 0,
    "host_arch": "x64",
    "icu_small": "false",
    "node_byteorder": "little",
    "node_enable_v8_vtunejit": "false",
    "node_engine": "chakra",
    "node_install_npm": "true",
    "node_prefix": "/usr/local",
    "node_release_urlbase": "",
    "node_shared_http_parser": "false",
    "node_shared_libuv": "false",
    "node_shared_openssl": "false",
    "node_shared_zlib": "false",
    "node_tag": "-0",
    "node_use_dtrace": "false",
    "node_use_etw": "true",
    "node_use_lttng": "false",
    "node_use_openssl": "true",
    "node_use_perfctr": "true",
    "node_uwp_dll": "false",
    "node_win_onecore": "",
    "openssl_fips": "",
    "openssl_no_asm": 0,
    "python": "D:\\Python27\\python.exe",
    "target_arch": "x64",
    "v8_enable_gdbjit": 0,
    "v8_enable_i18n_support": 0,
    "v8_no_strict_aliasing": 1,
    "v8_optimized_debug": 0,
    "v8_random_seed": 0,
    "v8_use_snapshot": "true",
    "want_separate_host_toolset": 0,
    "nodedir": "C:\\Program Files\\NodejsUwp\\Console\\sdk",
    "copy_dev_lib": "false",
    "standalone_static_library": 1,
    "access": "",
    "also": "",
    "always_auth": "",
    "bin_links": "true",
    "browser": "",
    "ca": "",
    "cache": "C:\\Users\\Ingvar\\AppData\\Roaming\\npm-cache",
    "cache_lock_retries": "10",
    "cache_lock_stale": "60000",
    "cache_lock_wait": "10000",
    "cache_max": "Infinity",
    "cache_min": "10",
    "cafile": "",
    "cert": "",
    "color": "always",
    "depth": "3",
    "description": "true",
    "dev": "",
    "dry_run": "",
    "editor": "notepad.exe",
    "email": "me@rreverser.com",
    "engine_strict": "",
    "fetch_retries": "2",
    "fetch_retry_factor": "10",
    "fetch_retry_maxtimeout": "60000",
    "fetch_retry_mintimeout": "10000",
    "force": "",
    "git": "git",
    "git_tag_version": "true",
    "global": "",
    "globalconfig": "C:\\Users\\Ingvar\\AppData\\Roaming\\npm\\etc\\npmrc",
    "globalignorefile": "C:\\Users\\Ingvar\\AppData\\Roaming\\npm\\etc\\npmignore",
    "global_style": "",
    "group": "",
    "heading": "npm",
    "https_proxy": "",
    "if_present": "",
    "ignore_scripts": "",
    "init_author_email": "",
    "init_author_name": "",
    "init_author_url": "",
    "init_license": "ISC",
    "init_module": "C:\\Users\\Ingvar\\.npm-init.js",
    "init_version": "1.0.0",
    "json": "",
    "key": "",
    "legacy_bundling": "",
    "link": "",
    "local_address": "",
    "long": "",
    "message": "%s",
    "node_gyp": "C:\\Program Files\\NodejsUwp\\Console\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js",
    "node_version": "5.6.0-0",
    "npat": "",
    "onload_script": "",
    "only": "",
    "optional": "true",
    "parseable": "",
    "prefix": "C:\\Users\\Ingvar\\AppData\\Roaming\\npm",
    "production": "",
    "progress": "",
    "proprietary_attribs": "true",
    "rebuild_bundle": "true",
    "registry": "https://registry.npmjs.org/",
    "rollback": "true",
    "save": "",
    "save_bundle": "",
    "save_dev": "",
    "save_exact": "",
    "save_optional": "",
    "save_prefix": "^",
    "save_range": "~",
    "scope": "",
    "searchexclude": "",
    "searchopts": "",
    "searchsort": "name",
    "shell": "C:\\WINDOWS\\system32\\cmd.exe",
    "shrinkwrap": "true",
    "sign_git_tag": "",
    "strict_ssl": "true",
    "tag": "latest",
    "tag_version_prefix": "v",
    "tmp": "C:\\Users\\Ingvar\\AppData\\Local\\Temp",
    "umask": "0000",
    "unicode": "",
    "unsafe_perm": "true",
    "usage": "",
    "user": "",
    "userconfig": "C:\\Users\\Ingvar\\.npmrc",
    "user_agent": "npm/3.6.0 node/v5.6.0-0 win32 x64",
    "version": "",
    "versions": "",
    "viewer": "browser",
    "__registry_npmjs_org__always_auth": "",
    "__registry_npmjs_org__email": "me@rreverser.com",
    "__registry_npmjs_org__username": "rreverser"
  }
}

So it looks like by default node-win-onecore is an empty string and not "false".

Although process.config returns node_win_onecore: false:

> process.config
{ target_defaults:
   { cflags: [],
     default_configuration: 'Release',
     defines: [],
     include_dirs: [],
     libraries: [] },
  variables:
   { asan: 0,
     host_arch: 'x64',
     icu_small: false,
     node_byteorder: 'little',
     node_enable_v8_vtunejit: false,
     node_engine: 'chakra',
     node_install_npm: true,
     node_prefix: '/usr/local',
     node_release_urlbase: '',
     node_shared_http_parser: false,
     node_shared_libuv: false,
     node_shared_openssl: false,
     node_shared_zlib: false,
     node_tag: '-0',
     node_use_dtrace: false,
     node_use_etw: true,
     node_use_lttng: false,
     node_use_openssl: true,
     node_use_perfctr: true,
     node_uwp_dll: false,
     node_win_onecore: false,
     openssl_fips: '',
     openssl_no_asm: 0,
     python: 'D:\\Python27\\python.exe',
     target_arch: 'x64',
     v8_enable_gdbjit: 0,
     v8_enable_i18n_support: 0,
     v8_no_strict_aliasing: 1,
     v8_optimized_debug: 0,
     v8_random_seed: 0,
     v8_use_snapshot: true,
     want_separate_host_toolset: 0 } }

Hopefully this helps.

jianchun commented 8 years ago

@RReverser Thanks for spending time on this. This is very weird. I wish I could debug on a repro machine.

In our code "node_win_onecore" and "node_uwp_dll" usages are exactly the same. No reason for following to appear in build/config.gypi:

    "node_uwp_dll": "false",
    "node_win_onecore": "",

They should both either take defaults from process.config, or overrides from npm/command line. Possibilities of it being empty string that I can imagine:

@RReverser Could you check if you have this env variable? If not, with a clean Node.js (Chakra) install (undo addon.gypi customization), launch Node.js (Chakra) command prompt, node-gyp rebuild in local uwp git clone dir -- I'd be crazy if result build/config.gypi has "node_win_onecore": "".

RReverser commented 8 years ago
  1. This is done by npm code. I don't know why but that code converts false to empty string and sets an env variable affecting node-gyp.

    As far as I understand, it doesn't (false is a string, so it's not converted to an empty string)? In fact, after I patched addon.gypi, npm i worked even without --node_win_onecore=false for me (as it already defaulted to false from addon.gypi code).

  2. I don't have env variable like that.
  3. I installed fresh Node.js (Chakra) couple of days ago, just before trying to install uwp for the Nth time, but I can recheck to be sure.
jianchun commented 8 years ago

As far as I understand, it doesn't (false is a string, so it's not converted to an empty string)? In fact, after I patched addon.gypi, npm i worked even without --node_win_onecore=false for me (as it already defaulted to false from addon.gypi code).

I stepped that code in debugger. NPM command line parser already converts value to a boolean false, no longer a string. To verify, you can npm i --node_win_onecore=false in uwp git clone dir, then check build/config.gypi to see if it ends up an empty string.

I suspect that patch will make node_win_onecore always false, as it has higher priority than the included build/config.gypi. To verify, try npm i --node_win_onecore=true --verbose, see which link libs branch it picked -- many libs for false, or a few libs for true.

RReverser commented 8 years ago

I stepped that code in debugger. NPM command line parser already converts value to a boolean false, no longer a string.

Oh ok, then my assumption was wrong, sorry.

So... I removed all the Node.js versions I had to be sure I have clean env. reinstalled Node.js (chakra) 5.6.0 x64, and still getting same results :disappointed:

RReverser commented 8 years ago

I stepped that code in debugger. NPM command line parser already converts value to a boolean false, no longer a string.

Interesting that when I do smth like --node_win_onecore=0 (just for the sake of experiment) it doesn't get converted to a boolean/integer, but in fact results in "node_win_onecore": "0" (actual string) in common.gypi.

jianchun commented 8 years ago

True, npm does some magic conversions.

# npm i --abc=0 --abd=1 --abe=true --abf=false
   "abc": "0",
   "abd": "1",
   "abe": "true",
   "abf": "",

I am lost on why you have "node_win_onecore": "".

Anyway, next Node.js (chakra) release will have a fix for this. We'll no longer compare with 'false'. Only compare with 'true'. That's should make it work on your box...

RReverser commented 8 years ago

Okay, nevermind, I found the source where that variable was taken from. Although I'm still surprised as I don't remember adding it manually, but maybe I just added it for whatever reason and forgot... weird anyway.

The npm code you mentioned contained call to npm.config.get(i) so I decided to check output of npm config list, and yes, I had node_win_onecore = false.

It's still unclear to me how this option got there, or why false is being converted to an empty string by that lifecycle code, but at least removing this line from ; globalconfig C:\Users\Ingvar\AppData\Roaming\npm\etc\npmrc helped, and npm i uwp just works, so I guess this issue can be closed.

Sorry for the taken time.

jianchun commented 8 years ago

Oh! Great! Thanks, didn't realize there is another store for npm config. That config option is weird. @munyirik

munyirik commented 8 years ago

Great! So just to be clear, @RReverser you added that line manually? just want to be sure it wasn't automatic :-)

RReverser commented 8 years ago

@munyirik That's what I'm wondering, too. If I added it manually, then it was a rather long time ago and for a good reason, but I can't recall it :smile:

munyirik commented 8 years ago

Ok, thanks and let us know if you run into any other issues.

@jianchun I'll still make the change you mention so we don't compare to false.

jianchun commented 8 years ago

@RReverser Thanks a lot for helping us resolving this mystery!

@munyirik Sure.

RReverser commented 8 years ago

@jianchun Thank you for your time!