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

Missing symbols in node.lib #7104

Closed
ermod opened this issue Jul 5, 2019 · 23 comments
Closed

Missing symbols in node.lib #7104

ermod opened this issue Jul 5, 2019 · 23 comments
Assignees

Comments

@ermod
Copy link

ermod commented Jul 5, 2019

NWJS Version : 0.39.2
Operating System : Windows 10

node.lib is missing the following symbols:

?IsCacheable@ExternalStringResourceBase@String@v8@@UEBA_NXZ (public: virtual bool __cdecl v8::String::ExternalStringResourceBase::IsCacheable(void)const )
?Lock@ExternalStringResourceBase@String@v8@@MEBAXXZ (protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Lock(void)const )
?Unlock@ExternalStringResourceBase@String@v8@@MEBAXXZ (protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Unlock(void)const )

These symbols exists in the 12.4.0 node-gyp version of node.lib

>cd .node-gyp\12.4.0\x64
>dumpbin  /EXPORTS node.lib | findstr v8::String::ExternalStringResourceBase::
                  ??0ExternalStringResourceBase@String@v8@@IEAA@XZ (protected: __cdecl v8::String::ExternalStringResourceBase::ExternalStringResourceBase(void))
                  ??1ExternalStringResourceBase@String@v8@@UEAA@XZ (public: virtual __cdecl v8::String::ExternalStringResourceBase::~ExternalStringResourceBase(void))
                  ??_7ExternalStringResourceBase@String@v8@@6B@ (const v8::String::ExternalStringResourceBase::`vftable')
                  ?Dispose@ExternalStringResourceBase@String@v8@@MEAAXXZ (protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Dispose(void))
                  ?IsCacheable@ExternalStringResourceBase@String@v8@@UEBA_NXZ (public: virtual bool __cdecl v8::String::ExternalStringResourceBase::IsCacheable(void)const )
                  ?Lock@ExternalStringResourceBase@String@v8@@MEBAXXZ (protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Lock(void)const )
                  ?Unlock@ExternalStringResourceBase@String@v8@@MEBAXXZ (protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Unlock(void)const )
>

But not in the 0.39.2 nw-gyp version of node.lib

>cd .nw-gyp\0.39.2\x64
>dumpbin  /EXPORTS node.lib | findstr v8::String::ExternalStringResourceBase::

>

An other way to see this fault and the consequences of it is to create a project that is dependent of node-lmdb version 0.7.0 and the try to rebuild it with nw-gyp

set npm_config_arch=x64
set npm_config_build_from_source=true
set npm_config_node_gyp=c:\\Users\\xxxxxxxxx\\AppData\\Roaming\\npm\\node_modules\\nw-gyp\\bin\\nw-gyp.js
set npm_config_runtime=node-webkit
set npm_config_target=0.39.2
>npm rebuild --verbose --msvs_version=2015 node-lmdb

The build will fail with the following error:

(Link target) ->
  misc.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl v8::String::ExternalStringResourceBase::IsCacheable(void)const " (?IsCacheable@ ExternalStringResourceBase@String@v8@@UEBA_NXZ) 
  misc.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Lock(void)const " (?Lock@ExternalStr ingResourceBase@String@v8@@MEBAXXZ) 
  misc.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Unlock(void)const " (?Unlock@Externa lStringResourceBase@String@v8@@MEBAXXZ) 
@rogerwang
Copy link
Member

They should be in nw.lib, which should be included in the linking. And that's one of the reasons we provide nw-gyp. Could you please check if nw.lib is included in the linking?

@ermod
Copy link
Author

ermod commented Jul 9, 2019

No they are not in nw.lib

>cd .nw-gyp\0.39.2\x64
>dumpbin  /EXPORTS nw.lib  | findstr v8::String::ExternalStringResourceBase::
                  ??_7ExternalStringResourceBase@String@v8@@6B@ (const v8::String::ExternalStringResourceBase::`vftable')

>

And nw.lib is passed to the linker.

Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\Release\node-lmdb.node" /NOLOGO kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib user32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib credui.lib dbghelp.lib shlwapi.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib DelayImp.lib "C:\Users\xxxxxxxxx\.nw-gyp\0.39.2\x64\nw.lib" "C:\Users\xxxxxxxxx\.nw-gyp\0.39.2\x64\node.lib" ntdll.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\Release\node-lmdb.pdb" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /maxilksize:0x7ff00000 /fastfail /maxilksize:0x7ff00000 /fastfail /DLL "Release\obj\node-lmdb\mdb.obj"
  "Release\obj\node-lmdb\midl.obj"
  "Release\obj\node-lmdb\node-lmdb.obj"
  "Release\obj\node-lmdb\env.obj"
  "Release\obj\node-lmdb\misc.obj"
  "Release\obj\node-lmdb\txn.obj"
  "Release\obj\node-lmdb\dbi.obj"
  "Release\obj\node-lmdb\cursor.obj"
     Creating library C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\Release\node-lmdb.lib and object C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\Release\node-lmdb.exp
misc.obj : error LNK2001: unresolved external symbol "public: virtual bool __cdecl v8::String::ExternalStringResourceBase::IsCacheable(void)const " (?IsCacheable@Ex ternalStringResourceBase@String@v8@@UEBA_NXZ) [C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\node-lmdb.vcxproj]
misc.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Lock(void)const " (?Lock@ExternalStrin gResourceBase@String@v8@@MEBAXXZ) [C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\node-lmdb.vcxproj]
misc.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl v8::String::ExternalStringResourceBase::Unlock(void)const " (?Unlock@ExternalS tringResourceBase@String@v8@@MEBAXXZ) [C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\node-lmdb.vcxproj]
C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\Release\node-lmdb.node : fatal error LNK1120: 3 unresolved external s [C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\node-lmdb.vcxproj]
Done Building Project "C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\node-lmdb.vcxproj" (default targets) -- FAIL ED.

Done Building Project "C:\Users\xxxxxxxxx\proj\NWJS-Test04\node_modules\node-lmdb\build\binding.sln" (default targets) -- FAILED.

@rogerwang
Copy link
Member

Looks like those 3 functions are inlined when NW is built since their definitions are in the v8 header. But they are not inlined when the native module is built...

@ermod
Copy link
Author

ermod commented Jul 10, 2019

If I remember correctly you need to tell Microsoft Visual Studio to explicitly to export inlined functions as symbols.

@ermod
Copy link
Author

ermod commented Jul 10, 2019

From v8.h
class V8_EXPORT ExternalStringResourceBase {

From v8config.h

#ifdef BUILDING_V8_SHARED
# define V8_EXPORT  __declspec(dllexport)
#elif USING_V8_SHARED
# define V8_EXPORT __declspec(dllimport)
#else
# define V8_EXPORT
#endif  // BUILDING_V8_SHARED

So all member functions in that class should be exported when building a DLL.

From node-lmdb compile verbose output
/D USING_V8_SHARED=1
So import should also work.

If the DLL:s are correctly built with /D BUILDING_V8_SHARED=1 the symbols should be in node.lib or nw.lib

See:
Importing and exporting inline functions
Can you dllexport/dllimport an inline function?

@rogerwang
Copy link
Member

NW is built with clang with different flags following chromium project, while native modules are built with msvc. Will look into it.

@rogerwang
Copy link
Member

PS, NW is built with BUILDING_V8_SHARED, or other v8 symbols won't be visible.

@ermod
Copy link
Author

ermod commented Jul 11, 2019

Could it be that you are building with this flag?
The /Zc:dllexportInlines- Option

@rogerwang
Copy link
Member

The switch is needed or there will be build error when build v8. It conficts with BUILDING_V8_SHARED defined. In previous major versions this doesn't happen. The reason could be the compiler upgrade across major versions. Will investigate more.

btw, upstream is also using this switch under component build: https://cs.chromium.org/chromium/src/build/config/win/BUILD.gn?q=is_component_build&dr=C&l=118

@jtg-gg
Copy link
Member

jtg-gg commented Jul 15, 2019

@ermod try to use clang when building node

@jiangjianping
Copy link

I think I encounter the same problem when I try to build node.dll (both x86 and x64) after built nwjs successfully. the version is nw40 branch(I tried 0.39 also).

[1/1] LINK_EMBED(DLL) node.dll
FAILED: node.dll node.dll.lib node.dll.pdb
C:\Python27\python.exe gyp-win-tool link-with-manifests environment.x86 True node.dll "C:\Python27\python.exe gyp-win-tool link-wrapper environment.x86 False ....\third_party/llvm-build/Release+Asserts/bin/lld-link.exe /nologo /IMPLIB:node.dll.lib /DLL /OUT:node.dll @node.dll.rsp" 2 mt.exe rc.exe "obj\third_party\node-nw\node.node.dll.intermediate.manifest" obj\third_party\node-nw\node.node.dll.generated.manifest
lld-link: error: undefined symbol: __declspec(dllimport) public: void * __thiscall v8::ArrayBuffer::Contents::Data(void) const

referenced by f:\all\src\third_party\node-nw\src\env.cc:311
obj\third_party\node-nw\src\node.env.obj:(public: __thiscall node::Environment::Environment(class node::IsolateData *, class v8::Local, class std::vector<class std::basic_string<char, struct std::char_traits, class std::allocator>, class std::allocator<class std::basic_string<char, struct std::char_traits, class std::allocator>>> const &, class std::vector<class std::basic_string<char, struct std::char_traits, class std::allocator>, class std::allocator<class std::basic_string<char, struct std::char_traits, class std::allocator>>> const &, enum node::Environment::Flags, unsigned __int64))

lld-link: error: undefined symbol: public: virtual enum v8::OutputStream::WriteResult __thiscall v8::OutputStream::WriteHeapStatsChunk(struct v8::HeapStatsUpdate *, int)

referenced by obj\third_party\node-nw\src\node.heap_utils.obj:(const node::heap::anonymous namespace'::FileOutputStream::vftable')
referenced by obj\third_party\node-nw\src\node.heap_utils.obj:(const node::heap::anonymous namespace'::HeapSnapshotStream::vftable'{for `v8::OutputStream'})

lld-link: error: undefined symbol: __declspec(dllimport) protected: __thiscall v8::String::ExternalOneByteStringResource::ExternalOneByteStringResource(void)

referenced by f:\all\src\third_party\node-nw\src\node_http2.cc:1364
obj\third_party\node-nw\src\node.node_http2.obj:(private: void __thiscall node::http2::Http2Session::HandleHeadersFrame(union nghttp2_frame const *))
referenced by f:\all\src\third_party\node-nw\src\node_http2.cc:1366
obj\third_party\node-nw\src\node.node_http2.obj:(private: void __thiscall node::http2::Http2Session::HandleHeadersFrame(union nghttp2_frame const *))

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Dispose(void)

referenced by obj\third_party\node-nw\src\node.node_http2.obj:(const node::http2::ExternalHeader::`vftable')

lld-link: error: undefined symbol: public: virtual bool __thiscall v8::String::ExternalStringResourceBase::IsCacheable(void) const

referenced by obj\third_party\node-nw\src\node.node_http2.obj:(const node::http2::ExternalHeader::`vftable')

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Lock(void) const

referenced by obj\third_party\node-nw\src\node.node_http2.obj:(const node::http2::ExternalHeader::`vftable')

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Unlock(void) const

referenced by obj\third_party\node-nw\src\node.node_http2.obj:(const node::http2::ExternalHeader::`vftable')

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Dispose(void)

referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalOneByteStringResource, char>::vftable')
referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalStringResource, unsigned short>::vftable')

lld-link: error: undefined symbol: public: virtual bool __thiscall v8::String::ExternalStringResourceBase::IsCacheable(void) const

referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalOneByteStringResource, char>::vftable')
referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalStringResource, unsigned short>::vftable')

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Lock(void) const

referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalOneByteStringResource, char>::vftable')
referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalStringResource, unsigned short>::vftable')

lld-link: error: undefined symbol: protected: virtual void __thiscall v8::String::ExternalStringResourceBase::Unlock(void) const

referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalOneByteStringResource, char>::vftable')
referenced by obj\third_party\node-nw\src\node.string_bytes.obj:(const node::anonymous namespace'::ExternString<class v8::String::ExternalStringResource, unsigned short>::vftable')

@jiangjianping
Copy link

I think the real problem is in the nwjs v8 module. The current version of nwjs v8 seemed to missing this symbols.

@gpetrov
Copy link

gpetrov commented Sep 11, 2019

I really hope @rogerwang will fix this asap as currently we are unable to compile any native modules in 0.39+, even not on 0.41-beta1 - all due to the error above of missing symbols. At least not on Windows

@gpetrov
Copy link

gpetrov commented Sep 11, 2019

Maybe this is all also related to the many compiler warnings we get:

cl : Command line warning D9002: ignoring unknown option '/Zc:dllexportInlines-'

all about using the new dllexportsinlines option in the CL compiler. And that option is not yet implemented on the older MSVS toolchain 2015/2017

It is coming up thought:
http://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html

@gpetrov
Copy link

gpetrov commented Sep 12, 2019

@rogerwang after further investigation it seems that V8 and Chrome building switched to clang-cl compiler on windows, so that is why the building process fails with missing externals. see:
nodejs/node#27257
nodejs/node#19630

The MS CL compiler doesn't support the '/Zc:dllexportInlines-' option while the clang replacement clang-cl does. The LLVM clang-cl tools can be installed from: https://llvm.org/builds/

So nw-gyp and the building instructions should be tweaked to support clang-cl
Seems node-gyp already supports it and has no problem compiling.

@jiangjianping
Copy link

@rogerwang @gpetrov,

I succeeded to compile the node.dll (windows 10 version) finally (both 0.40 and 0.41). I remove the V8_SHARED and USING_V8_SHARED from node.ninja, and I also remove the '/Zc:dllexportInlines-' flag (decrease the warning). I think when is_compont_build=false with clang, the BUILDING_V8_SHARED has no sense to nw/nw.dll. Hope this give you some hints.

@gpetrov
Copy link

gpetrov commented Sep 15, 2019

great news @jiangjianping ! I knew it will be something easy like this.

Now we just have to figure out what needs to be changed in nw-gyp so we can also build the native node modules for nwjs. Hope @rogerwang can give some light to this soon.

@rogerwang
Copy link
Member

@jiangjianping another v8 will be compiled into node DLL if it's built in this way and it would be problematic since there will be 2 copies of v8 instances (e.g. different static local variables etc)

@jiangjianping
Copy link

@rogerwang,
Thanks. I have no idea to resolve the node compile issue without this modification. What should I do?

@rogerwang
Copy link
Member

I can confirm that modules with this issue can be built successfully with clang-cl.exe and lld-link.exe. Will push an update of nw-gyp soon.

@panther7
Copy link

panther7 commented Sep 18, 2019

@rogerwang
Copy link
Member

nw-gyp 3.6.5 is published for the complete fix. Thanks.

@jiangjianping
Copy link

Thanks!

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

No branches or pull requests

6 participants