Skip to content

Commit

Permalink
Merge pull request #632 from justadudewhohacks/improve_install_script
Browse files Browse the repository at this point in the history
Improve install script + configure environments via package.json
  • Loading branch information
justadudewhohacks committed Sep 22, 2019
2 parents 036a545 + b8fd442 commit 8ae769f
Show file tree
Hide file tree
Showing 19 changed files with 255 additions and 124 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Expand Up @@ -4,6 +4,7 @@ ci/coverage-report
!package.json
!binding.gyp
!lib
!install
!test
!cc
!data/got.jpg
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -199,7 +199,7 @@ script:
fi

after_success:
- if [ $BUILD_TASK = 'cover' ]; then
- if [ "$BUILD_TASK" == "cover" ]; then
npm install;
npm run codecov -- -t $CODECOV_TOKEN;
fi
37 changes: 34 additions & 3 deletions README.md
Expand Up @@ -174,9 +174,40 @@ You can specify the Version of OpenCV you want to install via the script by sett

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.

## Configuring Environments via package.json

It's possible to specify build environment variables by inserting them into the `package.json` as follows:

```json
{
"name": "my-project",
"version": "0.0.0",
"dependencies": {
"opencv4nodejs": "^X.X.X"
},
"opencv4nodejs": {
"disableAutoBuild": 1,
"opencvIncludeDir": "C:\\tools\\opencv\\build\\include",
"opencvLibDir": "C:\\tools\\opencv\\build\\x64\\vc14\\lib",
"opencvBinDir": "C:\\tools\\opencv\\build\\x64\\vc14\\bin"
}
}
```

The following environment variables can be passed:

- autoBuildBuildCuda
- autoBuildFlags
- autoBuildOpencvVersion
- autoBuildWithoutContrib
- disableAutoBuild
- opencvIncludeDir
- opencvLibDir
- opencvBinDir

<a name="usage-with-docker"></a>

## Usage with Docker
# Usage with Docker

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

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

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

## Usage with Electron
# Usage with Electron

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

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

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

## Usage with NW.js
# Usage with NW.js

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.

Expand Down
33 changes: 20 additions & 13 deletions appveyor.yml
Expand Up @@ -43,26 +43,33 @@ environment:
- nodejs_version: 6
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
OPENCV_VERSION: "%OPENCV4_LATEST%"
- nodejs_version: 12
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
OPENCV_VERSION: "%OPENCV4_LATEST%"
BUILD_TASK: "ENVS"

install:
- cmd: choco install OpenCV -y -version %OPENCV_VERSION%
- IF EXIST c:\tools\opencv* CD c:\tools\opencv*
- SET OPENCV_INCLUDE_DIR=%CD%\build\include
- SET OPENCV_LIB_DIR=%CD%\build\x64\vc14\lib
- SET OPENCV_BIN_DIR=%CD%\build\x64\vc14\bin
- SET PATH=%PATH%;%OPENCV_BIN_DIR%;

- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_INCLUDE_DIR=c:\tools\opencv\build\include
- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_LIB_DIR=c:\tools\opencv\build\x64\vc14\lib
- if not "%BUILD_TASK%" == "ENVS" SET OPENCV_BIN_DIR=c:\tools\opencv\build\x64\vc14\bin
- if not "%BUILD_TASK%" == "ENVS" SET PATH=%PATH%;%OPENCV_BIN_DIR%;
- ps: Install-Product node $env:nodejs_version x64
- node --version
- npm install -g node-gyp
- cd c:\projects\opencv4nodejs
- npm install

build: off

test_script:
- node --version
- cmd: cd c:\projects\opencv4nodejs\test
- npm install
- npm run test-appveyor
- npm run test-externalMemTracking
- if "%BUILD_TASK%" == "ENVS" (
cd c:\projects\opencv4nodejs\ci\envs &&
npm install &&
npm test
) else (
cd c:\projects\opencv4nodejs &&
npm install &&
cd c:\projects\opencv4nodejs\test &&
npm install &&
npm run test-appveyor &&
npm run test-externalMemTracking
)
6 changes: 3 additions & 3 deletions binding.gyp
Expand Up @@ -2,17 +2,17 @@
"targets": [{
"target_name": "opencv4nodejs",
"defines": [
"<!@(node ./lib/defines.js)",
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_DEFINES)",
],
"include_dirs" : [
"<!@(node ./lib/includes.js)",
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_INCLUDES)",
"cc",
"cc/core",
"<!(node -e \"require('nan')\")",
"<!(node -e \"require('native-node-utils')\")"
],
"libraries": [
"<!@(node ./lib/libs.js)"
"<!@(node ./install/parseEnv.js OPENCV4NODEJS_LIBRARIES)",
],
"sources": [
"cc/opencv4nodejs.cc",
Expand Down
2 changes: 1 addition & 1 deletion ci/cover/cover.sh
@@ -1,4 +1,4 @@
#!/bin/sh
image=opencv4nodejs-ci:$1-node$2-with-coverage
docker build -t $image -f ./Dockerfile --build-arg TAG=$1 --build-arg NODE_MAJOR_VERSION=$2 ../../
docker run -v $PWD/coverage-report:/test/coverage-report $image
docker run -v $PWD/coverage-report:/test/coverage-report -e OPENCV_VERSION=$OPENCV_VERSION -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image
14 changes: 14 additions & 0 deletions ci/envs/package.json
@@ -0,0 +1,14 @@
{
"scripts": {
"test": "node ./test.js"
},
"dependencies": {
"opencv4nodejs": "../../"
},
"opencv4nodejs": {
"disableAutoBuild": 1,
"opencvIncludeDir": "C:\\tools\\opencv\\build\\include",
"opencvLibDir": "C:\\tools\\opencv\\build\\x64\\vc14\\lib",
"opencvBinDir": "C:\\tools\\opencv\\build\\x64\\vc14\\bin"
}
}
5 changes: 5 additions & 0 deletions ci/envs/test.js
@@ -0,0 +1,5 @@
process.env.OPENCV4NODES_DEBUG_REQUIRE = true

if (!require('opencv4nodejs')) {
throw new Error('failed to require opencv4nodejs')
}
2 changes: 1 addition & 1 deletion ci/test/test.sh
@@ -1,4 +1,4 @@
#!/bin/sh
image=opencv4nodejs-ci:$1-node$2
docker build -t $image -f ./Dockerfile --build-arg TAG=$1 --build-arg NODE_MAJOR_VERSION=$2 ../../
docker run -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image
docker run -e OPENCV_VERSION=$OPENCV_VERSION -e TEST_MODULE_LIST=$TEST_MODULE_LIST $image
88 changes: 88 additions & 0 deletions install/install.js
@@ -0,0 +1,88 @@
const opencvBuild = require('opencv-build')
const child_process = require('child_process')
const fs = require('fs')
const log = require('npmlog')
const { resolvePath } = require('../lib/commons')

const defaultDir = '/usr/local'
const defaultLibDir = `${defaultDir}/lib`
const defaultIncludeDir = `${defaultDir}/include`
const defaultIncludeDirOpenCV4 = `${defaultIncludeDir}/opencv4`

function getDefaultIncludeDirs() {
log.info('install', 'OPENCV_INCLUDE_DIR is not set, looking for default include dir')
if (opencvBuild.isWin()) {
throw new Error('OPENCV_INCLUDE_DIR has to be defined on windows when auto build is disabled')
}
return [defaultIncludeDir, defaultIncludeDirOpenCV4]
}

function getDefaultLibDir() {
log.info('install', 'OPENCV_LIB_DIR is not set, looking for default lib dir')
if (opencvBuild.isWin()) {
throw new Error('OPENCV_LIB_DIR has to be defined on windows when auto build is disabled')
}
return defaultLibDir
}

opencvBuild.applyEnvsFromPackageJson()

const libDir = opencvBuild.isAutoBuildDisabled()
? (resolvePath(process.env.OPENCV_LIB_DIR) || getDefaultLibDir())
: resolvePath(opencvBuild.opencvLibDir)

log.info('install', 'using lib dir: ' + libDir)

if (!fs.existsSync(libDir)) {
throw new Error('library dir does not exist: ' + libDir)
}

const libsFoundInDir = opencvBuild
.getLibs(libDir)
.filter(lib => lib.libPath)

if (!libsFoundInDir.length) {
throw new Error('no OpenCV libraries found in lib dir: ' + libDir)
}

log.info('install', 'found the following libs:')
libsFoundInDir.forEach(lib => log.info('install', lib.opencvModule + ' : ' + lib.libPath))

const defines = libsFoundInDir
.map(lib => `OPENCV4NODEJS_FOUND_LIBRARY_${lib.opencvModule.toUpperCase()}`)

const explicitIncludeDir = resolvePath(process.env.OPENCV_INCLUDE_DIR)
const includes = opencvBuild.isAutoBuildDisabled()
? (explicitIncludeDir ? [explicitIncludeDir] : getDefaultIncludeDirs())
: [resolvePath(opencvBuild.opencvInclude), resolvePath(opencvBuild.opencv4Include)]

const libs = opencvBuild.isWin()
? libsFoundInDir.map(lib => resolvePath(lib.libPath))
// dynamically link libs if not on windows
: ['-L' + libDir]
.concat(libsFoundInDir.map(lib => '-lopencv_' + lib.opencvModule))
.concat('-Wl,-rpath,' + libDir)

console.log()
log.info('install', 'setting the following defines:')
defines.forEach(def => log.info('defines', def))
console.log()
log.info('install', 'setting the following includes:')
includes.forEach(inc => log.info('includes', inc))
console.log()
log.info('install', 'setting the following libs:')
libs.forEach(lib => log.info('libs', lib))

process.env['OPENCV4NODEJS_DEFINES'] = defines.join('\n')
process.env['OPENCV4NODEJS_INCLUDES'] = includes.join('\n')
process.env['OPENCV4NODEJS_LIBRARIES'] = libs.join('\n')

const flags = process.env.BINDINGS_DEBUG ? '--jobs max --debug' : '--jobs max'
const nodegypCmd = 'node-gyp rebuild ' + flags
log.info('install', `spawning node gyp process: ${nodegypCmd}`)
const child = child_process.exec(nodegypCmd, {}, function(err, stdout, stderr) {
const _err = err || stderr
if (_err) log.error(_err)
})
child.stdout.pipe(process.stdout)
child.stderr.pipe(process.stderr)
7 changes: 7 additions & 0 deletions install/parseEnv.js
@@ -0,0 +1,7 @@
const envName = process.argv[2]

if (!envName) {
throw new Error('no env name passed to parseEnv')
}
const outputs = (process.env[envName] || '').split('\n')
outputs.forEach(o => console.log(o))
28 changes: 6 additions & 22 deletions lib/commons.js
@@ -1,29 +1,13 @@
const fs = require('fs');
const path = require('path');
const fs = require('fs')
const path = require('path')

function resolvePath(filePath, file) {
if (!filePath) {
return undefined;
return undefined
}
return (file ? path.resolve(filePath, file) : path.resolve(filePath)).replace(/\\/g, '/');
}

const defaultDir = '/usr/local';
const defaultIncludeDir = `${defaultDir}/include`;
const defaultIncludeDirOpenCV4 = `${defaultIncludeDir}/opencv4`;

function getLibDir() {
const libPath = resolvePath(process.env.OPENCV_LIB_DIR)
if (process.platform === 'win32' && !libPath) {
throw new Error('OPENCV_LIB_DIR is not defined')
}
return libPath || `${defaultDir}/lib`;
return (file ? path.resolve(filePath, file) : path.resolve(filePath)).replace(/\\/g, '/')
}

module.exports = {
resolvePath,
defaultDir,
defaultIncludeDir,
defaultIncludeDirOpenCV4,
getLibDir
};
resolvePath
}
61 changes: 51 additions & 10 deletions lib/cv.js
Expand Up @@ -2,19 +2,60 @@ const path = require('path');
const opencvBuild = require('opencv-build');
const { resolvePath } = require('./commons');

// ensure binaries are added to path on windows
if (!opencvBuild.isAutoBuildDisabled() && process.platform === 'win32') {
// append opencv binary path to node process
if (!process.env.path.includes(opencvBuild.opencvBinDir)) {
process.env.path = `${process.env.path};${opencvBuild.opencvBinDir};`
const requirePath = path.join(__dirname, process.env.BINDINGS_DEBUG ? '../build/Debug/opencv4nodejs' : '../build/Release/opencv4nodejs')

const logDebug = process.env.OPENCV4NODES_DEBUG_REQUIRE ? require('npmlog').info : () => {}

function tryGetOpencvBinDir() {
if (process.env.OPENCV_BIN_DIR) {
logDebug('tryGetOpencvBinDir', 'OPENCV_BIN_DIR environment variable is set')
return process.env.OPENCV_BIN_DIR
}
// if the auto build is not disabled via environment do not even attempt
// to read package.json
if (!opencvBuild.isAutoBuildDisabled()) {
logDebug('tryGetOpencvBinDir', 'auto build has not been disabled via environment variable, using opencv bin dir of opencv-build')
return opencvBuild.opencvBinDir
}

logDebug('tryGetOpencvBinDir', 'auto build has not been explicitly disabled via environment variable, attempting to read envs from package.json...')
const envs = opencvBuild.readEnvsFromPackageJson()

if (!envs.disableAutoBuild) {
logDebug('tryGetOpencvBinDir', 'auto build has not been disabled via package.json, using opencv bin dir of opencv-build')
return opencvBuild.opencvBinDir
}

if (envs.opencvBinDir) {
logDebug('tryGetOpencvBinDir', 'found opencv binary environment variable in package.json')
return envs.opencvBinDir
}
logDebug('tryGetOpencvBinDir', 'failed to find opencv binary environment variable in package.json')
return null
}

let cv;
if (process.env.BINDINGS_DEBUG) {
cv = require(path.join(__dirname, '../build/Debug/opencv4nodejs'));
} else {
cv = require(path.join(__dirname, '../build/Release/opencv4nodejs'));
let cv = null
try {
logDebug('require', 'require path is ' + requirePath)
cv = require(requirePath);
} catch (err) {
logDebug('require', 'failed to require cv with exception: ' + err.toString())
logDebug('require', 'attempting to add opencv binaries to path')

if (!process.env.path) {
logDebug('require', 'there is no path environment variable, skipping...')
throw err
}

const opencvBinDir = tryGetOpencvBinDir()
logDebug('require', 'adding opencv binary dir to path: ' + opencvBinDir)

// ensure binaries are added to path on windows
if (!process.env.path.includes(opencvBinDir)) {
process.env.path = `${process.env.path};${opencvBinDir};`
}
logDebug('require', 'process.env.path: ' + process.env.path)
cv = require(requirePath);
}

// resolve haarcascade files
Expand Down

0 comments on commit 8ae769f

Please sign in to comment.