Node-gyp: OS X 10.9: node-gyp links to libstdc++ instead of libc++

Created on 30 Jun 2014  路  3Comments  路  Source: nodejs/node-gyp

In OS X 10.9, Apple switched from gcc to clang which results in a change in the name of the standard library name from libstdc++ (gcc) to libc++ (clang).

However, it seems all modules compiled with node-gyp are linked against libstdc++ on OS X 10.9 . (For example, https://github.com/tbonelaforge/jinac/blob/master/binding.gyp ) Because dynamic libraries that node modules may link against are compiled on 10.9 with clang, there are issues resolving symbols in the standard library.

node-gyp -v
v0.13.1

I realize I can manually set the stdlib to be what it should be with "OTHER_CFLAGS": ["-stdlib=libc++"] but this will cause issues on OS X < 10.9.

macOS

Most helpful comment

In OS X 10.9, Apple switched from gcc to clang which results in a change in the name of the standard library name from libstdc++ (gcc) to libc++ (clang).

Apple switched to clang well before. But, yes what switched in 10.9 is that the bundled clang++ version started defaulting to linking to libc++ rather than libstdc++.

However, it seems all modules compiled with node-gyp are linked against libstdc++ on OS X 10.9

Correct. This behavior results from this MACOSX_DEPLOYMENT_TARGET setting inside Node's common.gypi: https://github.com/joyent/node/blob/912b5e05811fd24f09f9d65200a1561a4482f166/common.gypi#L216

Because dynamic libraries that node modules may link against are compiled on 10.9 with clang, there are issues resolving symbols in the standard library.

Would be useful to see the exact errors you are seeing. Generally having Node C++ addons linked to libstdc++ works fine on 10.9 (and of course previous OS X versions). What breaks is when an addon also depends on an external c++ library and that library is linked against libc++ - that condition will lead to odd linking errors when common C++ symbols like std::string cannot be resolved. Or odder things might result like the runtime symbol errors as seen at https://github.com/mapbox/mapbox-studio/issues/73

I realize I can manually set the stdlib to be what it should be with "OTHER_CFLAGS": ["-stdlib=libc++"] but this will cause issues on OS X < 10.9.

Right, don't do that. Instead the best fix in my opinion is to override MACOSX_DEPLOYMENT_TARGET and do it only for users that are building on 10.9. Basically what you want is for 10.9 users to end up with node c++ addons linked to libc++ and users on older systems to continue to link against libstdc++. My approach to this can be seen at:

https://github.com/mapnik/node-mapnik/blob/e0041df852720f389ed6a4bd2e761f989d6368c1/common.gypi#L2-L14

Note: Users running node binaries or those who source compile and do not also override this option will end up with node binaries linked against libstdc++. Theoretically having node linked against libstdc++ and an addon linked against libc++ is not a very good idea and could lead to crashes or undefined behavior. In practice however I've not yet seen any problems. That said, if you are targeting >= 10.9 then recommending your users compile their own node that links against libc++ is a good idea. You can do this like:

export CXXFLAGS="-mmacosx-version-min=10.9"
export LDFLAGS="-mmacosx-version-min=10.9"
cd node
./configure && make && make install

All 3 comments

In OS X 10.9, Apple switched from gcc to clang which results in a change in the name of the standard library name from libstdc++ (gcc) to libc++ (clang).

Apple switched to clang well before. But, yes what switched in 10.9 is that the bundled clang++ version started defaulting to linking to libc++ rather than libstdc++.

However, it seems all modules compiled with node-gyp are linked against libstdc++ on OS X 10.9

Correct. This behavior results from this MACOSX_DEPLOYMENT_TARGET setting inside Node's common.gypi: https://github.com/joyent/node/blob/912b5e05811fd24f09f9d65200a1561a4482f166/common.gypi#L216

Because dynamic libraries that node modules may link against are compiled on 10.9 with clang, there are issues resolving symbols in the standard library.

Would be useful to see the exact errors you are seeing. Generally having Node C++ addons linked to libstdc++ works fine on 10.9 (and of course previous OS X versions). What breaks is when an addon also depends on an external c++ library and that library is linked against libc++ - that condition will lead to odd linking errors when common C++ symbols like std::string cannot be resolved. Or odder things might result like the runtime symbol errors as seen at https://github.com/mapbox/mapbox-studio/issues/73

I realize I can manually set the stdlib to be what it should be with "OTHER_CFLAGS": ["-stdlib=libc++"] but this will cause issues on OS X < 10.9.

Right, don't do that. Instead the best fix in my opinion is to override MACOSX_DEPLOYMENT_TARGET and do it only for users that are building on 10.9. Basically what you want is for 10.9 users to end up with node c++ addons linked to libc++ and users on older systems to continue to link against libstdc++. My approach to this can be seen at:

https://github.com/mapnik/node-mapnik/blob/e0041df852720f389ed6a4bd2e761f989d6368c1/common.gypi#L2-L14

Note: Users running node binaries or those who source compile and do not also override this option will end up with node binaries linked against libstdc++. Theoretically having node linked against libstdc++ and an addon linked against libc++ is not a very good idea and could lead to crashes or undefined behavior. In practice however I've not yet seen any problems. That said, if you are targeting >= 10.9 then recommending your users compile their own node that links against libc++ is a good idea. You can do this like:

export CXXFLAGS="-mmacosx-version-min=10.9"
export LDFLAGS="-mmacosx-version-min=10.9"
cd node
./configure && make && make install

Node.js 7 onwards specifies linking against libc++:
https://github.com/nodejs/node/blob/09b85e2b04e560066df584fe3cc9acda822b0d18/common.gypi#L404
For supported versions of Node.js, this should only still be an issue for Node.js 6 (which doesn't specify the library to link against and uses the default). Node.js 6 will be end-of-life in April.

There's a lot of "noise" on this page - for those who hit this via Google, the solution is simple - update to a newer version of Node.

Was this page helpful?
0 / 5 - 0 ratings