node-gyp ignores (c++17) cflag

2.3k Views Asked by At

I try to configure & build a node.js C++ addon with this binding.gyp file:

{ 
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "addon.cpp" ],
      "cflags": [
        "-std=c++17"
      ]          
    }
  ]
}

But when I run node-gyp configure and node-gype rebuild I always get messages like

warning: ‘if constexpr’ only available with -std=c++17 or -std=gnu++17

The build also fails, because I really depend on these c++17 features. What am I doing wrong?

3

There are 3 best solutions below

0
On BEST ANSWER

Using "cflags_cc" (instead of "cflags") works.

This solved the problem.

0
On

cflags cflags_cc was not working for me, but with the setting in VCCLCompilerTool it works (on Windows):

{
  'targets': [
    {
      'target_name': 'test-napi-native',
      'sources': [ 'src/test_napi.cc' ],
      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],
      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
      'cflags': [ '-fno-exceptions' ],
      'cflags_cc': [ '-fno-exceptions' ],
      'xcode_settings': {
        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
        'CLANG_CXX_LIBRARY': 'libc++',
        'MACOSX_DEPLOYMENT_TARGET': '10.7'
      },
      'msvs_settings': {
        'VCCLCompilerTool': { "ExceptionHandling": 1, 'AdditionalOptions': [ '-std:c++17' ] }
      }
    }
  ]
}
0
On

The default is against your will

node-gyp has default settings.

argv.push('-I', addonGypi)
argv.push('-I', commonGypi)
argv.push('-Dlibrary=shared_library')
argv.push('-Dvisibility=default')
argv.push('-Dnode_root_dir=' + nodeDir)
if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
  argv.push('-Dnode_exp_file=' + nodeExpFile)
  if (process.platform === 'os390' && zoslibIncDir) {
    argv.push('-Dzoslib_include_dir=' + zoslibIncDir)
  }
}
argv.push('-Dnode_gyp_dir=' + nodeGypDir)

// Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
// resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
if (win) {
  nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
}
argv.push('-Dnode_lib_file=' + nodeLibFile)
argv.push('-Dmodule_root_dir=' + process.cwd())
argv.push('-Dnode_engine=' +
  (gyp.opts.node_engine || process.jsEngine || 'v8'))

You need to override the default settings described in node-gyp/addon.gypi and node/common.gypi’s cflags (C & C++), cflags_cc (C++), ldflags (Linux), msvs_settings (Windows), and xcode_settings (OS X). All of them.

In your case, you only set the cflags. So, other default settings were left not overridden and thus in effect.

Specifically, you’d want to override the default settings about:

  • the C++ standard to conform,
    • cflags_cc
    • msvs_settings.VCCLCompilerTool.AdditionalOptions
    • xcode_settings.CLANG_CXX_LANGUAGE_STANDARD
  • floating point arithmetics,
    • msvs_settings.VCCLCompilerTool.FloatingPointModel
  • exceptions,
    • cflags_cc
    • msvs_settings.VCCLCompilerTool.ExceptionHandling
    • xcode_settings.GCC_ENABLE_CPP_EXCEPTIONS
    • xcode_settings.GCC_ENABLE_CPP_RTTI
  • optimization,
  • the warning level,
  • et cetera.

If you don’t, unintented default settings might be applied.


Why it defaults to this

Because the Node.js executable is built with the settings and node-gyp adopted the settings for the default settings for unknown reasons.

From the nodejs/node-gyp issue #26 — “Overriding default flags:

edhemphill: Does anyone know why -fno-rtti was used as a default? Any particular reason?

TooTallNate: @edhemphill node-gyp uses the same configuration as when node itself it built, so the answer is because node itself doesn’t need rtti.