Skip to content

Commit 8ae769f

Browse files
Merge pull request #632 from justadudewhohacks/improve_install_script
Improve install script + configure environments via package.json
2 parents 036a545 + b8fd442 commit 8ae769f

19 files changed

+255
-124
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ci/coverage-report
44
!package.json
55
!binding.gyp
66
!lib
7+
!install
78
!test
89
!cc
910
!data/got.jpg

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ script:
199199
fi
200200

201201
after_success:
202-
- if [ $BUILD_TASK = 'cover' ]; then
202+
- if [ "$BUILD_TASK" == "cover" ]; then
203203
npm install;
204204
npm run codecov -- -t $CODECOV_TOKEN;
205205
fi

README.md

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,40 @@ You can specify the Version of OpenCV you want to install via the script by sett
174174

175175
If you only want to build a subset of the OpenCV modules you can pass the *-DBUILD_LIST* cmake flag via the *OPENCV4NODEJS_AUTOBUILD_FLAGS* environment variable. For example `export OPENCV4NODEJS_AUTOBUILD_FLAGS=-DBUILD_LIST=dnn` will build only modules required for `dnn` and reduces the size and compilation time of the OpenCV package.
176176

177+
## Configuring Environments via package.json
178+
179+
It's possible to specify build environment variables by inserting them into the `package.json` as follows:
180+
181+
```json
182+
{
183+
"name": "my-project",
184+
"version": "0.0.0",
185+
"dependencies": {
186+
"opencv4nodejs": "^X.X.X"
187+
},
188+
"opencv4nodejs": {
189+
"disableAutoBuild": 1,
190+
"opencvIncludeDir": "C:\\tools\\opencv\\build\\include",
191+
"opencvLibDir": "C:\\tools\\opencv\\build\\x64\\vc14\\lib",
192+
"opencvBinDir": "C:\\tools\\opencv\\build\\x64\\vc14\\bin"
193+
}
194+
}
195+
```
196+
197+
The following environment variables can be passed:
198+
199+
- autoBuildBuildCuda
200+
- autoBuildFlags
201+
- autoBuildOpencvVersion
202+
- autoBuildWithoutContrib
203+
- disableAutoBuild
204+
- opencvIncludeDir
205+
- opencvLibDir
206+
- opencvBinDir
207+
177208
<a name="usage-with-docker"></a>
178209

179-
## Usage with Docker
210+
# Usage with Docker
180211

181212
### [opencv-express](https://github.com/justadudewhohacks/opencv-express) - example for opencv4nodejs with express.js and docker
182213

@@ -192,7 +223,7 @@ Different OpenCV 3.x base images can be found here: https://hub.docker.com/r/jus
192223

193224
<a name="usage-with-electron"></a>
194225

195-
## Usage with Electron
226+
# Usage with Electron
196227

197228
### [opencv-electron](https://github.com/justadudewhohacks/opencv-electron) - example for opencv4nodejs with electron
198229

@@ -213,7 +244,7 @@ const cv = require('opencv4nodejs');
213244

214245
<a name="usage-with-nwjs"></a>
215246

216-
## Usage with NW.js
247+
# Usage with NW.js
217248

218249
Any native modules, including opencv4nodejs, must be recompiled to be used with [NW.js](https://nwjs.io/). Instructions on how to do this are available in the **[Use Native Modules](http://docs.nwjs.io/en/latest/For%20Users/Advanced/Use%20Native%20Node%20Modules/)** section of the the NW.js documentation.
219250

appveyor.yml

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,33 @@ environment:
4343
- nodejs_version: 6
4444
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
4545
OPENCV_VERSION: "%OPENCV4_LATEST%"
46+
- nodejs_version: 12
47+
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
48+
OPENCV_VERSION: "%OPENCV4_LATEST%"
49+
BUILD_TASK: "ENVS"
4650

4751
install:
4852
- cmd: choco install OpenCV -y -version %OPENCV_VERSION%
49-
- IF EXIST c:\tools\opencv* CD c:\tools\opencv*
50-
- SET OPENCV_INCLUDE_DIR=%CD%\build\include
51-
- SET OPENCV_LIB_DIR=%CD%\build\x64\vc14\lib
52-
- SET OPENCV_BIN_DIR=%CD%\build\x64\vc14\bin
53-
- SET PATH=%PATH%;%OPENCV_BIN_DIR%;
54-
53+
- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_INCLUDE_DIR=c:\tools\opencv\build\include
54+
- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_LIB_DIR=c:\tools\opencv\build\x64\vc14\lib
55+
- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_BIN_DIR=c:\tools\opencv\build\x64\vc14\bin
56+
- if not "%BUILD_TASK%" == "ENVS" SET PATH=%PATH%;%OPENCV_BIN_DIR%;
5557
- ps: Install-Product node $env:nodejs_version x64
5658
- node --version
57-
- npm install -g node-gyp
58-
- cd c:\projects\opencv4nodejs
59-
- npm install
6059

6160
build: off
6261

6362
test_script:
6463
- node --version
65-
- cmd: cd c:\projects\opencv4nodejs\test
66-
- npm install
67-
- npm run test-appveyor
68-
- npm run test-externalMemTracking
64+
- if "%BUILD_TASK%" == "ENVS" (
65+
cd c:\projects\opencv4nodejs\ci\envs &&
66+
npm install &&
67+
npm test
68+
) else (
69+
cd c:\projects\opencv4nodejs &&
70+
npm install &&
71+
cd c:\projects\opencv4nodejs\test &&
72+
npm install &&
73+
npm run test-appveyor &&
74+
npm run test-externalMemTracking
75+
)

binding.gyp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
"targets": [{
33
"target_name": "opencv4nodejs",
44
"defines": [
5-
"<!@(node ./lib/defines.js)",
5+
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_DEFINES)",
66
],
77
"include_dirs" : [
8-
"<!@(node ./lib/includes.js)",
8+
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_INCLUDES)",
99
"cc",
1010
"cc/core",
1111
"<!(node -e \"require('nan')\")",
1212
"<!(node -e \"require('native-node-utils')\")"
1313
],
1414
"libraries": [
15-
"<!@(node ./lib/libs.js)"
15+
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_LIBRARIES)",
1616
],
1717
"sources": [
1818
"cc/opencv4nodejs.cc",

ci/cover/cover.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
image=opencv4nodejs-ci:$1-node$2-with-coverage
33
docker build -t $image -f ./Dockerfile --build-arg TAG=$1 --build-arg NODE_MAJOR_VERSION=$2 ../../
4-
docker run -v $PWD/coverage-report:/test/coverage-report $image
4+
docker run -v $PWD/coverage-report:/test/coverage-report -e OPENCV_VERSION=$OPENCV_VERSION -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image

ci/envs/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"scripts": {
3+
"test": "node ./test.js"
4+
},
5+
"dependencies": {
6+
"opencv4nodejs": "../../"
7+
},
8+
"opencv4nodejs": {
9+
"disableAutoBuild": 1,
10+
"opencvIncludeDir": "C:\\tools\\opencv\\build\\include",
11+
"opencvLibDir": "C:\\tools\\opencv\\build\\x64\\vc14\\lib",
12+
"opencvBinDir": "C:\\tools\\opencv\\build\\x64\\vc14\\bin"
13+
}
14+
}

ci/envs/test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
process.env.OPENCV4NODES_DEBUG_REQUIRE = true
2+
3+
if (!require('opencv4nodejs')) {
4+
throw new Error('failed to require opencv4nodejs')
5+
}

ci/test/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
image=opencv4nodejs-ci:$1-node$2
33
docker build -t $image -f ./Dockerfile --build-arg TAG=$1 --build-arg NODE_MAJOR_VERSION=$2 ../../
4-
docker run -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image
4+
docker run -e OPENCV_VERSION=$OPENCV_VERSION -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image

install/install.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const opencvBuild = require('opencv-build')
2+
const child_process = require('child_process')
3+
const fs = require('fs')
4+
const log = require('npmlog')
5+
const { resolvePath } = require('../lib/commons')
6+
7+
const defaultDir = '/usr/local'
8+
const defaultLibDir = `${defaultDir}/lib`
9+
const defaultIncludeDir = `${defaultDir}/include`
10+
const defaultIncludeDirOpenCV4 = `${defaultIncludeDir}/opencv4`
11+
12+
function getDefaultIncludeDirs() {
13+
log.info('install', 'OPENCV_INCLUDE_DIR is not set, looking for default include dir')
14+
if (opencvBuild.isWin()) {
15+
throw new Error('OPENCV_INCLUDE_DIR has to be defined on windows when auto build is disabled')
16+
}
17+
return [defaultIncludeDir, defaultIncludeDirOpenCV4]
18+
}
19+
20+
function getDefaultLibDir() {
21+
log.info('install', 'OPENCV_LIB_DIR is not set, looking for default lib dir')
22+
if (opencvBuild.isWin()) {
23+
throw new Error('OPENCV_LIB_DIR has to be defined on windows when auto build is disabled')
24+
}
25+
return defaultLibDir
26+
}
27+
28+
opencvBuild.applyEnvsFromPackageJson()
29+
30+
const libDir = opencvBuild.isAutoBuildDisabled()
31+
? (resolvePath(process.env.OPENCV_LIB_DIR) || getDefaultLibDir())
32+
: resolvePath(opencvBuild.opencvLibDir)
33+
34+
log.info('install', 'using lib dir: ' + libDir)
35+
36+
if (!fs.existsSync(libDir)) {
37+
throw new Error('library dir does not exist: ' + libDir)
38+
}
39+
40+
const libsFoundInDir = opencvBuild
41+
.getLibs(libDir)
42+
.filter(lib => lib.libPath)
43+
44+
if (!libsFoundInDir.length) {
45+
throw new Error('no OpenCV libraries found in lib dir: ' + libDir)
46+
}
47+
48+
log.info('install', 'found the following libs:')
49+
libsFoundInDir.forEach(lib => log.info('install', lib.opencvModule + ' : ' + lib.libPath))
50+
51+
const defines = libsFoundInDir
52+
.map(lib => `OPENCV4NODEJS_FOUND_LIBRARY_${lib.opencvModule.toUpperCase()}`)
53+
54+
const explicitIncludeDir = resolvePath(process.env.OPENCV_INCLUDE_DIR)
55+
const includes = opencvBuild.isAutoBuildDisabled()
56+
? (explicitIncludeDir ? [explicitIncludeDir] : getDefaultIncludeDirs())
57+
: [resolvePath(opencvBuild.opencvInclude), resolvePath(opencvBuild.opencv4Include)]
58+
59+
const libs = opencvBuild.isWin()
60+
? libsFoundInDir.map(lib => resolvePath(lib.libPath))
61+
// dynamically link libs if not on windows
62+
: ['-L' + libDir]
63+
.concat(libsFoundInDir.map(lib => '-lopencv_' + lib.opencvModule))
64+
.concat('-Wl,-rpath,' + libDir)
65+
66+
console.log()
67+
log.info('install', 'setting the following defines:')
68+
defines.forEach(def => log.info('defines', def))
69+
console.log()
70+
log.info('install', 'setting the following includes:')
71+
includes.forEach(inc => log.info('includes', inc))
72+
console.log()
73+
log.info('install', 'setting the following libs:')
74+
libs.forEach(lib => log.info('libs', lib))
75+
76+
process.env['OPENCV4NODEJS_DEFINES'] = defines.join('\n')
77+
process.env['OPENCV4NODEJS_INCLUDES'] = includes.join('\n')
78+
process.env['OPENCV4NODEJS_LIBRARIES'] = libs.join('\n')
79+
80+
const flags = process.env.BINDINGS_DEBUG ? '--jobs max --debug' : '--jobs max'
81+
const nodegypCmd = 'node-gyp rebuild ' + flags
82+
log.info('install', `spawning node gyp process: ${nodegypCmd}`)
83+
const child = child_process.exec(nodegypCmd, {}, function(err, stdout, stderr) {
84+
const _err = err || stderr
85+
if (_err) log.error(_err)
86+
})
87+
child.stdout.pipe(process.stdout)
88+
child.stderr.pipe(process.stderr)

install/parseEnv.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const envName = process.argv[2]
2+
3+
if (!envName) {
4+
throw new Error('no env name passed to parseEnv')
5+
}
6+
const outputs = (process.env[envName] || '').split('\n')
7+
outputs.forEach(o => console.log(o))

lib/commons.js

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,13 @@
1-
const fs = require('fs');
2-
const path = require('path');
1+
const fs = require('fs')
2+
const path = require('path')
33

44
function resolvePath(filePath, file) {
55
if (!filePath) {
6-
return undefined;
6+
return undefined
77
}
8-
return (file ? path.resolve(filePath, file) : path.resolve(filePath)).replace(/\\/g, '/');
9-
}
10-
11-
const defaultDir = '/usr/local';
12-
const defaultIncludeDir = `${defaultDir}/include`;
13-
const defaultIncludeDirOpenCV4 = `${defaultIncludeDir}/opencv4`;
14-
15-
function getLibDir() {
16-
const libPath = resolvePath(process.env.OPENCV_LIB_DIR)
17-
if (process.platform === 'win32' && !libPath) {
18-
throw new Error('OPENCV_LIB_DIR is not defined')
19-
}
20-
return libPath || `${defaultDir}/lib`;
8+
return (file ? path.resolve(filePath, file) : path.resolve(filePath)).replace(/\\/g, '/')
219
}
2210

2311
module.exports = {
24-
resolvePath,
25-
defaultDir,
26-
defaultIncludeDir,
27-
defaultIncludeDirOpenCV4,
28-
getLibDir
29-
};
12+
resolvePath
13+
}

lib/cv.js

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,60 @@ const path = require('path');
22
const opencvBuild = require('opencv-build');
33
const { resolvePath } = require('./commons');
44

5-
// ensure binaries are added to path on windows
6-
if (!opencvBuild.isAutoBuildDisabled() && process.platform === 'win32') {
7-
// append opencv binary path to node process
8-
if (!process.env.path.includes(opencvBuild.opencvBinDir)) {
9-
process.env.path = `${process.env.path};${opencvBuild.opencvBinDir};`
5+
const requirePath = path.join(__dirname, process.env.BINDINGS_DEBUG ? '../build/Debug/opencv4nodejs' : '../build/Release/opencv4nodejs')
6+
7+
const logDebug = process.env.OPENCV4NODES_DEBUG_REQUIRE ? require('npmlog').info : () => {}
8+
9+
function tryGetOpencvBinDir() {
10+
if (process.env.OPENCV_BIN_DIR) {
11+
logDebug('tryGetOpencvBinDir', 'OPENCV_BIN_DIR environment variable is set')
12+
return process.env.OPENCV_BIN_DIR
1013
}
14+
// if the auto build is not disabled via environment do not even attempt
15+
// to read package.json
16+
if (!opencvBuild.isAutoBuildDisabled()) {
17+
logDebug('tryGetOpencvBinDir', 'auto build has not been disabled via environment variable, using opencv bin dir of opencv-build')
18+
return opencvBuild.opencvBinDir
19+
}
20+
21+
logDebug('tryGetOpencvBinDir', 'auto build has not been explicitly disabled via environment variable, attempting to read envs from package.json...')
22+
const envs = opencvBuild.readEnvsFromPackageJson()
23+
24+
if (!envs.disableAutoBuild) {
25+
logDebug('tryGetOpencvBinDir', 'auto build has not been disabled via package.json, using opencv bin dir of opencv-build')
26+
return opencvBuild.opencvBinDir
27+
}
28+
29+
if (envs.opencvBinDir) {
30+
logDebug('tryGetOpencvBinDir', 'found opencv binary environment variable in package.json')
31+
return envs.opencvBinDir
32+
}
33+
logDebug('tryGetOpencvBinDir', 'failed to find opencv binary environment variable in package.json')
34+
return null
1135
}
1236

13-
let cv;
14-
if (process.env.BINDINGS_DEBUG) {
15-
cv = require(path.join(__dirname, '../build/Debug/opencv4nodejs'));
16-
} else {
17-
cv = require(path.join(__dirname, '../build/Release/opencv4nodejs'));
37+
let cv = null
38+
try {
39+
logDebug('require', 'require path is ' + requirePath)
40+
cv = require(requirePath);
41+
} catch (err) {
42+
logDebug('require', 'failed to require cv with exception: ' + err.toString())
43+
logDebug('require', 'attempting to add opencv binaries to path')
44+
45+
if (!process.env.path) {
46+
logDebug('require', 'there is no path environment variable, skipping...')
47+
throw err
48+
}
49+
50+
const opencvBinDir = tryGetOpencvBinDir()
51+
logDebug('require', 'adding opencv binary dir to path: ' + opencvBinDir)
52+
53+
// ensure binaries are added to path on windows
54+
if (!process.env.path.includes(opencvBinDir)) {
55+
process.env.path = `${process.env.path};${opencvBinDir};`
56+
}
57+
logDebug('require', 'process.env.path: ' + process.env.path)
58+
cv = require(requirePath);
1859
}
1960

2061
// resolve haarcascade files

0 commit comments

Comments
 (0)