node-gyp ignores (c++17) cflag - node.js

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?

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' ] }
}
}
]
}

Using "cflags_cc" (instead of "cflags") works.
This solved the problem.

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.

Related

Webpack error after upgrading Node: "Module parse failed: Unexpected token"

I'm troubleshooting a webpack error.
Command: bin/webpack --colors --progress
Produces this error:
ERROR in ./node_modules/#flatfile/sdk/dist/index.js 351:361
Module parse failed: Unexpected token (351:361)
File was processed with these loaders:
* ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| class v extends i {
| constructor(e, t) {
> super(e), r(this, "code", "FF-UA-00"), r(this, "name", "UnauthorizedError"), r(this, "debug", "The JWT was not signed with a recognized private key or you did not provide the necessary information to identify the end user"), r(this, "userMessage", "There was an issue establishing a secure import session."), e && (this.debug = e), this.code = t ?? "FF-UA-00";
| }
| }
# ./app/javascript/src/app/pages/content_assets/Index.vue?vue&type=script&lang=ts& (./node_modules/babel-loader/lib??ref--8-0!./node_modules/vue-loader/lib??vue-loader-options!./app/javascript/src/app/pages/content_assets/Index.vue?vue&type=script&lang=ts&) 22:0-41 125:6-14
# ./app/javascript/src/app/pages/content_assets/Index.vue?vue&type=script&lang=ts&
# ./app/javascript/src/app/pages/content_assets/Index.vue
# ./app/javascript/packs/app.js
NOTES
I found what appears to be an identical issue reported in the Flatfile project: https://github.com/FlatFilers/sdk/issues/83
Looks like ES2020 was emitted to the /dist folder so my cra babel loader is not able to parse it, in order to fix it I need to include the path on my webpack config.
Node v16.13.1
We're using webpack with a Rails project via the webpacker package (#rails/webpacker": "5.4.3") which is depending on webpack#4.46.0.
When I change to Node v14x and rebuild node_modules (yarn install) webpack compiles successfully.
The line referenced in the error (351:361) does not exist when I go check the file in node_modules/
We have a yarn.lock file, which I delete and recreate before running yarn install. I also delete the node_modules directory to ensure a "fresh" download of the correct packages.
We have a babel.config.js file...
module.exports = function(api) {
var validEnv = ['development', 'test', 'production']
var currentEnv = api.env()
var isDevelopmentEnv = api.env('development')
var isProductionEnv = api.env('production')
var isTestEnv = api.env('test')
if (!validEnv.includes(currentEnv)) {
throw new Error(
'Please specify a valid `NODE_ENV` or ' +
'`BABEL_ENV` environment variables. Valid values are "development", ' +
'"test", and "production". Instead, received: ' +
JSON.stringify(currentEnv) +
'.'
)
}
return {
presets: [
isTestEnv && [
'#babel/preset-env',
{
targets: {
node: 'current'
}
}
],
(isProductionEnv || isDevelopmentEnv) && [
'#babel/preset-env',
{
forceAllTransforms: true,
useBuiltIns: 'entry',
corejs: 3,
modules: false,
exclude: ['transform-typeof-symbol']
}
],
["babel-preset-typescript-vue", { "allExtensions": true, "isTSX": true }]
].filter(Boolean),
plugins: [
'babel-plugin-macros',
'#babel/plugin-syntax-dynamic-import',
isTestEnv && 'babel-plugin-dynamic-import-node',
'#babel/plugin-transform-destructuring',
[
'#babel/plugin-proposal-class-properties',
{
loose: true
}
],
[
'#babel/plugin-proposal-object-rest-spread',
{
useBuiltIns: true
}
],
[
'#babel/plugin-transform-runtime',
{
helpers: false,
regenerator: true,
corejs: false
}
],
[
'#babel/plugin-transform-regenerator',
{
async: false
}
]
].filter(Boolean)
}
}
Ultimately I want to get webpack to compile. If you had advice about any of the following questions, it would help a lot.
Why would changing the Node version (only) cause different webpack behavior? We aren't changing the the webpack version or the version of the #flatfile package that's causing the error.
Why is the error pointing to a line that doesn't exist in the package? Is this evidence of some kind of caching problem?
Does the workaround mentioned in the linked GitHub issue shed light on my problem?
I'll take a stab at this.
I believe your issue is that webpack 4 does not support the nullish coalescing operator due to it's dependency on acorn 6. See this webpack issue and this PR comment.
You haven't specified the exact minor version of Node.js 14x that worked for you. I will assume it was a version that did not fully support the nullish coalescing operator, or at least a version that #babel/preset-env's target option understood to not support ??, so it was transpiled by babel and thus webpack didn't complain. You can see what versions of node support nullish coalescing on node.green.
I don't fully understand the point you are making here, so not focusing on this in the proposed solution.
I'm not sure what the proposed workaround is in the linked issue, maybe the comment about "include the path on my webpack config", but yes the issue does seem relevant as it is pointing out the nullish coalescing operator as the source of the issue.
You can try to solve this by
adding #babel/plugin-proposal-nullish-coalescing-operator to your babel config's plugins
updating your webpack config to run #flatfile/sdk through babel-loader to transpile the nullish coalescing operator:
{
test: /\.jsx?$/,
exclude: filename => {
return /node_modules/.test(filename) && !/#flatfile\/sdk\/dist/.test(filename)
},
use: ['babel-loader']
}
Another possibility is to upgrade webpacker to a version that depends upon webpack v5.
One final remark, when you say
We have a yarn.lock file, which I delete and recreate before running yarn install.
you probably should not be deleting the lock file before each install, as it negates the purpose of a lock file altogether.

ESlint override rule by nested directory

I want to disable rule for all files inside nested directory. I found examples only for exact path or by file extension. But it is not what I want.
We use it for shared config and don't know where this directory will be. We have many of them.
I'm trying config like this:
{
overrides: [
{
files: [
'**/test/**/*',
],
rules: {
"import/no-extraneous-dependencies": "off"
}
},
],
}
But glob like **/test/**/* and many others didn't not work.
Can someone help to reach this goal?
The above code should work.
How were you testing this? If it's an extension like VSCode you may need to refresh things to see latest definitions loaded.
If you are using a eslint service like esprint you will also need to restart it to grab latest definitions.
Caching
Make sure that eslint is not configured to cache results to avoid having to cache bust when debugging things. eslint docs
Here's an example for a react-native app with multiple overrides
module.exports = {
...baseConfig,
overrides: [
typescriptOverrides,
e2eOverrides,
themeOverrides,
{
files: ['**/*.style.js'],
rules: {
'sort-keys': [
'error',
'asc',
{
caseSensitive: true,
natural: true,
},
],
},
},
{
files: ['**/*.test.js'],
rules: {
'arrow-body-style': 'off',
},
},
],
};
Debugging the glob matcher
Run eslint in debug mode and see all the files being run example DEBUG=eslint:cli-engine npx eslint src/**/*.test.js
You can test your glob patterns by running a ls command. Example: ls ./src/**/*.test.js will either return all the files or 'no matches found'.

How do you automatically download external (C++) libraries when using native Node addons?

I'd like to include libpng in my native Node addon. How can I include it, so that when my library is installed, it will automatically download a specified version of libpng? Is it possible to use npm's package.json for this? If this is not possible, what is the accepted way of including an external library's source code in your repository?
I recommend that you create a gyp file to build the dependency library and add a script to your package.json to download it for you.
I often use my own native addon modules to demonstrate the answers I give to these questions. My own native addon module, node-dvbtee, demonstrates this.
You will notice the following inside package.json:
"scripts": {
"preinstall": "npm install mkdirp && scripts/prepare-build.sh && node scripts/configure-build.js",
"install": "node-gyp rebuild -j 8",
"test": "mocha"
},
What matters here is the preinstall section of the scripts section. It calls scripts/prepare-build.sh, which contains the following:
#!/bin/sh
cd "$(dirname "$0")"/..
if [ -e libdvbtee ]; then
echo libdvbtee sources present
else
git clone git://github.com/mkrufky/libdvbtee.git
fi
cd libdvbtee
if [ -e libdvbpsi/bootstrap ]; then
echo libdvbpsi sources present
else
rm -rf libdvbpsi
git clone git://github.com/mkrufky/libdvbpsi.git
cd libdvbpsi
touch .dont_del
cd ..
fi
As you can see, the above script checks to see if the libdvbtee directory is present. If not, it will clone it from github. After that, it checks to see if the full libdvbpsi sources are present. If not, it will clone them from github.
Now, for the gyp files:
My project has the gyp files stored in the deps directory.
libdvbpsi.gyp looks like this:
{
'target_defaults': {
'default_configuration': 'Debug',
'configurations': {
'Debug': {
'defines': [ 'DEBUG', '_DEBUG' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 1, # static debug
},
},
},
'Release': {
'defines': [ 'NDEBUG' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 0, # static release
},
},
}
},
'msvs_settings': {
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
},
},
'include_dirs': [
'../libdvbtee/libdvbpsi/src',
'../libdvbtee/libdvbpsi/src/tables',
'../libdvbtee/libdvbpsi/src/descriptors',
'../libdvbtee/libdvbpsi'
],
'defines': [
'PIC',
'HAVE_CONFIG_H'
],
},
'targets': [
# libdvbpsi
{
'target_name': 'dvbpsi',
'product_prefix': 'lib',
'type': 'static_library',
'sources': [
'../libdvbtee/libdvbpsi/src/dvbpsi.c',
'../libdvbtee/libdvbpsi/src/psi.c',
'../libdvbtee/libdvbpsi/src/demux.c',
'../libdvbtee/libdvbpsi/src/descriptor.c',
'../libdvbtee/libdvbpsi/src/tables/pat.c',
'../libdvbtee/libdvbpsi/src/tables/pmt.c',
'../libdvbtee/libdvbpsi/src/tables/sdt.c',
'../libdvbtee/libdvbpsi/src/tables/eit.c',
# '../libdvbtee/libdvbpsi/src/tables/cat.c',
'../libdvbtee/libdvbpsi/src/tables/nit.c',
'../libdvbtee/libdvbpsi/src/tables/tot.c',
# '../libdvbtee/libdvbpsi/src/tables/sis.c',
# '../libdvbtee/libdvbpsi/src/tables/bat.c',
# '../libdvbtee/libdvbpsi/src/tables/rst.c',
'../libdvbtee/libdvbpsi/src/tables/atsc_vct.c',
'../libdvbtee/libdvbpsi/src/tables/atsc_stt.c',
'../libdvbtee/libdvbpsi/src/tables/atsc_eit.c',
'../libdvbtee/libdvbpsi/src/tables/atsc_ett.c',
'../libdvbtee/libdvbpsi/src/tables/atsc_mgt.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_02.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_03.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_04.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_05.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_06.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_07.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_08.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_09.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_0a.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_0b.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_0c.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_0d.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_0e.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_0f.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_10.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_11.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_12.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_13.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_14.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_1b.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_1c.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_24.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_40.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_41.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_42.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_43.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_44.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_45.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_47.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_48.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_49.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_4a.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_4b.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_4c.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_4d.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_4e.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_4f.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_50.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_52.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_53.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_54.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_55.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_56.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_58.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_59.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_5a.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_62.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_66.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_69.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_73.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_76.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_7c.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_81.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_83.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_86.c',
# '../libdvbtee/libdvbpsi/src/descriptors/dr_8a.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_a0.c',
'../libdvbtee/libdvbpsi/src/descriptors/dr_a1.c',
],
'conditions': [
['OS=="mac"',
{
'xcode_settings': {
'WARNING_CFLAGS': [
'-Wno-deprecated-declarations'
]
}
}
]
],
'cflags!': ['-Wdeprecated-declarations','-Wimplicit-function-declaration'],
'cflags+': ['-Wno-deprecated-declarations','-Wno-implicit-function-declaration','-std=c99'],
},
]
}
Of course, there are a lot of specifics in this gyp file that are specific to libdvbpsi and my use case. As such, you will notice that quite a few of the source files in the library are not actually needed for the version of it that we're going to build for my node.js addon module. The source files that we are not going to build are commented out by preceding that line with a hash # character.
We link this library to the node module we're currently building by including it in the dependency section of the node.js addon modules bindings.gyp. Here is the one used in my addon module:
{
"targets": [
{
"target_name": "dvbtee",
"sources": [
"src/node-dvbtee.cc",
"src/dvbtee-parser.cc"
],
"dependencies": [
'deps/libdvbtee.gyp:dvbtee_parser'
],
"include_dirs": [
"libdvbtee/usr/include",
"libdvbtee/libdvbtee",
"libdvbtee/libdvbtee/decode",
"libdvbtee/libdvbtee/decode/table",
"libdvbtee/libdvbtee/decode/descriptor",
"<!(node -e \"require('nan')\")"
],
'cflags': [ '-DDEBUG_CONSOLE=1' ],
'cflags_cc': [ '-DDEBUG_CONSOLE=1', '-Wno-deprecated-declarations' ],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions', '-Wdeprecated-declarations' ],
'conditions': [
['OS=="mac"', {
'xcode_settings': {
'WARNING_CFLAGS': [
'-Wno-deprecated-declarations'
],
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
}
}]
]
}
]
}
As you can see, deps/libdvbtee.gyp:dvbtee_parser is listed in the dependencies section, above. deps/libdvbtee.gyp:dvbtee_parser itself contains its own dependencies section:
"dependencies": [
'libdvbpsi.gyp:dvbpsi'
],
So, when npm install is executed, npm will run the preinstall script to fetch the sources, then it will build the custom libdvbpsi library based on libdvbpsi.gyp, then build the custom libdvbtee based on libdvbtee.gyp which depends on that custom libdvbpsi library, and finally it will build and link the node.js addon module that depends on the libdvbtee library build.
In my specific case, the libraries need to be configured before we attempt to build them. This step is required to write the config.h header file that these libraries depend on. I handle that step within the scripts/configure-build.js script which is run after downloading the sources. In most cases, you will want to simply run ./configure for each library, but that depends on the libraries that you're including.
This is a cross-platform solution, provided that the libraries you're building are themselves cross-platform.
You can add it in scrips section in package.json. But you have to be careful about which all devices your application will be executed. Such as ARM, Intel 32 bit or Intel 64 bit, or so. You have options, I am just adding some hints here and you can put your code accordingly. Here script will get executed during npm install command.
1. In script, you have to check the machine type and do download library accordingly.
//package.json
{
"scripts": {
"preinstall": ""
,"install": ""
,"test" : ""
}
}
In script, you have to check the machine type and do download library accordingly, something like using wget abc.so in install section of script. You have to do some scripting to take right lib for machine and put in right place.
In other way if you want, you can add build script, which will do download the source code and build in the system on the fly.
git clone git://xyz/abc.git
cd abc
./configure
make
make install.
You can also look for babel cli for source compilation. https://babeljs.io/docs/usage/cli/
And all these within scripts section, within preinstall or install or test.
In your case, you would prefer to go for 1st way.

Unable to use helper classes within unit tests of a bundled aurelia app. RequireJS Configuration?

Summary
Using the aurelia cli and the default tasks that are included, I am unable to leverage helper classes that are located within the test folder in my unit tests.
Details
Starting with the sample app created with au new, I have a contrived helper class located within 'test/util/helper.ts':
export class Helper {
Property : string;
}
This class is imported by the test/unit/app.spec.ts file:
import {App} from '../../src/app';
import {Helper} from "../util/helper";
describe('the app', () => {
it('says hello', () => {
let h = new Helper();
h.Property = "Testing";
expect(h.Property).toBe("Testing");
expect(new App().message).toBe('Hello World!');
});
});
Approach #1 - Bundling
I have modified the aurelia.json file in a few places:
Change the source of the typescript compiler to include files under the test folder
"transpiler": {
"id": "typescript",
"displayName": "TypeScript",
"fileExtension": ".ts",
"dtsSource": [
"./typings/**/*.d.ts",
"./custom_typings/**/*.d.ts"
],
"source": ["src\\**\\*.ts","test\\**\\*.ts"]
},
Modify the app-bundle to exclude any file from the test folder
{
"name": "app-bundle.js",
"source": {
"include": [
"[**/*.js]",
"**/*.{css,html}"
],
"exclude": [
"**/test/**/*"
]
}
},
Add a new bundle (test-util-bundle), which includes files from the test\util folder and excludes files within the src and test/unit folders
{
"name": "test-util-bundle.js",
"source": {
"include": [
"[**/*.js]"
],
"exclude": [
"**/src/**/*",
"**/test/unit/**/*"
]
}
},
After bundling the app with 'au build', I have three bundles (app/vendor/test-util), with the test-util-bundle.js bundle defining the helper class like this:
define('../test/util/helper',["require", "exports"], function (require, exports) {
"use strict";
var Helper = (function () {
function Helper() {
}
return Helper;
}());
exports.Helper = Helper;
});
I suspect this is the root of the problem, but not that familiar with RequireJS.
When I do run 'au test' the test fails with the following error:
11 10 2016 12:05:24.606:DEBUG [middleware:source-files]: Fetching C:/git/aurelia-cli-testing/test/test/util/helper
11 10 2016 12:05:24.608:WARN [web-server]: 404: /base/test/test/util/helper
Chrome 53.0.2785 (Windows 7 0.0.0) ERROR
Uncaught Error: Script error for "C:/git/aurelia-cli-testing/test/test/util/helper", needed by: C:/git/aurelia-cli-testing/test/util/helper
http://requirejs.org/docs/errors.html#scripterror
at C:/git/aurelia-cli-testing/scripts/vendor-bundle.js:3763
Note:
This works fine if I move the helper.ts file under the src tree (as done here). This is all available here if you would like to see the behavior.
Approach #2 - Without Bundling of utility class
Modify karma.conf.js
let testSrc = [
{ pattern: project.unitTestRunner.source, included: false },
{ pattern: "test/util/**/*.ts", included: false },
'test/aurelia-karma.js'
];
...
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id],
["test/util/**/*.ts"]: [project.transpiler.id]
},
With this modification (no bundling of the utility class) karma produces the following error:
18 10 2016 16:56:59.151:DEBUG [middleware:source-files]: Fetching C:/git/aurelia-cli-testing/test/util/helper
18 10 2016 16:56:59.152:WARN [web-server]: 404: /base/test/util/helper
Chrome 53.0.2785 (Windows 7 0.0.0) ERROR
Uncaught Error: Script error for "C:/git/aurelia-cli-testing/test/util/helper", needed by: C:/git/aurelia-cli-testing/test/unit/app.spec.js
http://requirejs.org/docs/errors.html#scripterror
at C:/git/aurelia-cli-testing/scripts/vendor-bundle.js:3763
Thanks for reading, any help would be greatly appreciated!
With the help of an Aurelia team member, a small modification to the aurelia-karma.js file that is distributed with the aurelia cli fixes the issue:
The normalizePath function should be modified to append '.js' where applicable:
function normalizePath(path) {
var normalized = []
var parts = path
.split('?')[0] // cut off GET params, used by noext requirejs plugin
.split('/')
for (var i = 0; i < parts.length; i++) {
if (parts[i] === '.') {
continue
}
if (parts[i] === '..' && normalized.length && normalized[normalized.length - 1] !== '..') {
normalized.pop()
continue
}
normalized.push(parts[i])
}
//Use case of testing source code. RequireJS doesn't add .js extension to files asked via sibling selector
//If normalized path doesn't include some type of extension, add the .js to it
if(normalized.length > 0 && normalized[normalized.length-1].indexOf('.') < 0){
normalized[normalized.length-1] = normalized[normalized.length-1] + '.js';
}
return normalized.join('/')
}
I had to do the following:
1. update the aurelia-project/aurelia.json file. add this
"unitTestRunnerUtils": {
"id": "karmaUtils",
"displayName": "Karma",
"source": "test\\utils\\**\\*.js" },
Then in the karma.conf.js file updated these two places.
let testSrc = [ { pattern: project.unitTestRunner.source, included:
false }, { pattern: project.unitTestRunnerUtils.source, included:
false}, 'test/aurelia-karma.js' ];
and
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id],
[project.unitTestRunnerUtils.source]: [project.transpiler.id]
},
And then it worked...
Here is the example project on github.
https://github.com/duranmg/demo-aurelia-testing

Electron native addon failing on windows

I have a native addon that uses openSSL library on a unpacked electron app.
On a windows 10 it works and on a windows 7 it's not working , I am receiving this:
Error: The specified module could not be found.
\\?\C:\Program Files (x86)\AppX Player\resources\app\src\addon\foo.node
at Error (native)
at process.module.(anonymous function) [as dlopen] (ELECTRON_ASAR.js:167:20)
at Object.Module._extensions..node (module.js:568:18)
at Object.module.(anonymous function) [as .node] (ELECTRON_ASAR.js:167:20)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (C:\Program Files (x86)\AppX Player\resources\app\s
rc\addon\index.js:11:3)
I am targeting a windows ia32 architecture for electron and I rebuild it like the following:
node-gyp rebuild --target=1.3.1 --arch=ia32 --dist-url=https://atom.io/download/atom-shell --verbose
The binding-gyp of the file looks like this and is based on this. It uses the openSSL static library
{
"targets": [
{
"target_name": "addon",
"sources": [
"./src/encryptor.cpp" ,
"./src/EncryptorHandler.cpp",
"./src/SetupHandler.cpp",
"./src/RC4Handler.cpp",
"./src/HardwareInfoHandler.cpp",
"../Encryptions/RC4.cpp",
"../Encryptions/AES.cpp",
"../Encryptions/utils.cpp",
"../oggEncDec/src/FileHandler.cpp",
"../oggEncDec/src/OGGSelectiveEncryptor.cpp",
"../machineIdentification/common.cpp"
],
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
'cflags': ['-fexceptions'],
'cflags_cc': ['-fexceptions -Wall -Wextra -Wconversion'],
"include_dirs": [
"<!(node -e \"require('nan')\")",
"../"
],
'conditions': [
['OS=="linux"', {
"sources": [
"../machineIdentification/linuxHardwareInfo.cpp"
],
'libraries': [
'-lcrypto',
],
}
],
['OS=="mac"', {
"sources": [
"../machineIdentification/macHardwareInfo.cpp"
],
'libraries': [
'-lcrypto',
],
}],
['OS=="win"', {
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [ '/EHsc' ],
'ExceptionHandling': 1
}
},
"sources": [
"../machineIdentification/windowsHardwareInfo.cpp"
],
'conditions': [
# "openssl_root" is the directory on Windows of the OpenSSL files.
# Check the "target_arch" variable to set good default values for
# both 64-bit and 32-bit builds of the module.
['target_arch=="x64"', {
'variables': {
'openssl_root%': 'C:/OpenSSL-Win64'
},
}, {
'variables': {
'openssl_root%': 'C:/OpenSSL-Win32'
},
}],
],
'libraries': [
'-l<(openssl_root)/lib/libeay32.lib',
],
'include_dirs': [
'<(openssl_root)/include',
],
}]
]
}
]
}
Just in case it was a dll missing (it should not be as I was linking the static library) I added the openSSL dll on the same level of the exe. What else may be causing this behaviour?
Edit
Installing OpenSSL binaries make it works, i thought the static linking would take care of that so I wouldn't depend on external dll's
Edit 2
Everything would be solved if I could pack the static library and bundle it on the ".node" file. Using dependency walker on the .node file shows me that it is requiring the dll and what I need is for it to have the dll code on it.
Turns out the lib on http://slproweb.com/products/Win32OpenSSL.html seems to be just a wrapper around the dll that still uses it.
I misguided thought that node-gyp was just compiling the thing without the dependency which is not true.
I found another precompiled openssl lib here that did the trick.
So to wrap up:
I needed to ship something with OpenSSL under electron but electron does not expose OpenSSL like node does and switchs it for borinSSL.
I followed tooTallNate article that recommended a static library and assumed the static library was right and I was somehow needing the DLL and I assumed node-gyp was not bundling the used static library.
Switching the lib for another one (or better yet compiling it myself) did the trick.

Resources