node-libcurl
Version:
The fastest http(s) client (and much more) for Node.js - Node.js bindings for libcurl
196 lines (169 loc) • 5.76 kB
JavaScript
/**
* Copyright (c) Jonathan Cardoso Machado. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// https://github.com/nodejs/node-gyp/blob/64bb407c14149c216885a48e78df178cedaec8fd/bin/node-gyp.js#L25
if (process.platform !== 'win32') {
process.exit(0)
}
/*
* Notes about this script:
* It's a mess because of the callback hell, I could have used a promise library here,
* but adding a dependency that is going to be used only in a single script, that is executed
* only on Windows machines during install is not worth it.
*/
const { exec } = require('child_process')
const fs = require('fs')
const path = require('path')
const os = require('os')
const envPaths = require('env-paths')
const homeDir = os.homedir()
let { version } = process
let gypFolder = envPaths('node-gyp', { suffix: '' }).cache
if (process.env.npm_config_runtime === 'node-webkit') {
version = process.env.npm_config_target
gypFolder = path.resolve(homeDir, '.nw-gyp')
}
// node-gyp path from here: https://github.com/nodejs/node-gyp/blob/v5.0.3/bin/node-gyp.js#L31
const gypDir = path.resolve(gypFolder, version.replace('v', ''))
// we are renaming openssl directory
// so it does not get used when compilling.
// node-gyp default addon.gyp file adds the above folder as include, which would make
// the c++ includes for openssl/* point to that folder, instead of using the one from the openssl
// we are building. This only happens for node >= 10, probably because only there openssl started to
// to be have their symbols exported on Windows. Or for other obscure motive.
const opensslFolder = path.resolve(gypDir, 'include', 'node', 'openssl')
const opensslFolderDisabled = `${opensslFolder}.disabled`
if (fs.existsSync(opensslFolder)) {
fs.renameSync(opensslFolder, opensslFolderDisabled)
}
const execConfig = {
cwd: path.resolve(__dirname + '/..'),
}
const depsGypTarget = 'curl-for-windows/curl.gyp:libcurl'
const fileWithDepsTag = 'LIBCURL_VERSION_WIN_DEPS'
const depsRepo = 'https://github.com/JCMais/curl-for-windows.git'
const envCurlForWindowsDepsVersionTag = process.env.NODE_LIBCURL_WINDEPS_TAG
const cleanupAndExit = (code = 0) => {
process.exit(code)
}
// Check if we are on the root git dir. That is, someone is running this
// directly from the node-libcurl repo.
exec('git rev-parse --show-toplevel', execConfig, function (err, stdout) {
// Make sure we are the root git repo
// path.relative will return an empty string if both paths are equal
if (!err && path.relative(execConfig.cwd, stdout.trim()) === '') {
replaceTokensOnFiles(
path.resolve(__dirname, '..', 'deps', 'curl-for-windows'),
)
process.stdout.write('deps/' + depsGypTarget)
cleanupAndExit()
} else {
retrieveWinDeps()
}
})
function retrieveWinDeps() {
const fileExists = fs.existsSync(fileWithDepsTag)
if (!fileExists && !envCurlForWindowsDepsVersionTag) {
console.error(
'File: ',
fileWithDepsTag,
' not found, and no NODE_LIBCURL_WINDEPS_TAG environment variable found.',
)
cleanupAndExit(1)
}
const depsTag = envCurlForWindowsDepsVersionTag
? envCurlForWindowsDepsVersionTag.trim()
: fs.readFileSync(fileWithDepsTag).toString().replace(/\n|\s/g, '')
exec('git clone --branch ' + depsTag + ' ' + depsRepo, execConfig, function (
err,
) {
if (err) {
if (
err
.toString()
.indexOf('already exists and is not an empty directory') !== -1
) {
exec('rmdir curl-for-windows /S /Q', execConfig, function (err) {
if (err) {
console.error(err.toString())
cleanupAndExit(1)
}
retrieveWinDeps()
})
} else {
console.error(err.toString())
cleanupAndExit(1)
}
} else {
exec(
'cd curl-for-windows && git submodule update --init && python configure.py',
execConfig,
function (err) {
if (err) {
console.error(err.toString())
cleanupAndExit(1)
}
// Grab gyp config files and replace <(library) with static_library
replaceTokensOnFiles(
path.resolve(__dirname, '..', 'curl-for-windows'),
)
// remove git folder
exec('rmdir curl-for-windows\\.git /S /Q', execConfig, function (
err,
) {
if (err) {
console.error(err.toString())
cleanupAndExit(1)
}
process.stdout.write(depsGypTarget)
cleanupAndExit()
})
},
)
}
})
}
function replaceTokensOnFiles(dir) {
const filesToCheck = [
'libssh2.gyp',
'openssl/openssl.gyp',
'nghttp2/nghttp2.gyp',
'zlib.gyp',
'curl.gyp',
]
// const pattern = /<\(library\)/g;
const replacements = [
{
pattern: /<\(library\)/g,
replacement: 'static_library',
},
// {
// pattern: /curl_for_windows_build_openssl%': 'true'/g,
// replacement: 'curl_for_windows_build_openssl\': \'false\'',
// },
]
for (const file of filesToCheck) {
const filePath = path.resolve(dir, file)
for (const patternReplacementPair of replacements) {
replaceOnFile(
filePath,
patternReplacementPair.pattern,
patternReplacementPair.replacement,
)
}
}
}
function replaceOnFile(file, search, replacement) {
if (!fs.existsSync(file)) {
console.error('File: ', file, ' not found.')
cleanupAndExit(1)
}
const fileContent = fs
.readFileSync(file)
.toString()
.replace(search, replacement)
fs.writeFileSync(file, fileContent)
}