diff --git a/README.md b/README.md index 3bc59c12..42fb958a 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,8 @@ Options: -T, --target only build the specified target [string] -C, --prefer-clang use Clang compiler instead of default CMake compiler, if available (Posix) [boolean] + --cc use the specified C compiler [string] + --cxx use the specified C++ compiler [string] -r, --runtime the runtime to use [string] -v, --runtime-version the runtime version to use [string] -a, --arch the architecture to build in [string] @@ -143,7 +145,6 @@ Options: -i, --silent Prevents CMake.js to print to the stdio [boolean] -O, --out Specify the output directory to compile to, default is projectRoot/build [string] - projectRoot/build [string] ``` **Requirements:** diff --git a/bin/cmake-js b/bin/cmake-js index 7a210128..96a840f4 100755 --- a/bin/cmake-js +++ b/bin/cmake-js @@ -114,6 +114,16 @@ var yargs = require("yargs") describe: "use Clang compiler instead of default CMake compiler, if available (Posix)", type: "boolean" }, + cc: { + demand: false, + describe: "use the specified C compiler", + type: "string" + }, + cxx: { + demand: false, + describe: "use the specified C++ compiler", + type: "string" + }, r: { alias: "runtime", demand: false, @@ -188,6 +198,8 @@ var options = { preferXcode: argv.x, preferGnu: argv.g, preferClang: argv.C, + cCompilerPath: argv.cc, + cppCompilerPath: argv.cxx, runtime: argv.r, runtimeVersion: argv.v, arch: argv.a, diff --git a/lib/es5/toolset.js b/lib/es5/toolset.js index edf8c5c7..bd0a6b25 100644 --- a/lib/es5/toolset.js +++ b/lib/es5/toolset.js @@ -15,8 +15,8 @@ function Toolset(options) { this.generator = options.generator; this.toolset = options.toolset; this.target = options.target; - this.cCompilerPath = null; - this.cppCompilerPath = null; + this.cCompilerPath = options.cCompilerPath; + this.cppCompilerPath = options.cppCompilerPath; this.compilerFlags = []; this.linkerFlags = []; this.makePath = null; @@ -54,25 +54,27 @@ Toolset.prototype.initialize = async($traceurRuntime.initGeneratorFunction(funct }, $__8, this); })); Toolset.prototype.initializePosix = function(install) { - if (!environment.isGPPAvailable && !environment.isClangAvailable) { - if (environment.isOSX) { - throw new Error("C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'."); - } else { - throw new Error("C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'."); - } - } - if (this.options.preferClang && environment.isClangAvailable) { - if (install) { - this.log.info("TOOL", "Using clang++ compiler, because preferClang option is set, and clang++ is available."); + if (!this.cCompilerPath || !this.cppCompilerPath) { + if (!environment.isGPPAvailable && !environment.isClangAvailable) { + if (environment.isOSX) { + throw new Error("C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'."); + } else { + throw new Error("C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'."); + } } - this.cppCompilerPath = "clang++"; - this.cCompilerPath = "clang"; - } else if (this.options.preferGnu && environment.isGPPAvailable) { - if (install) { - this.log.info("TOOL", "Using g++ compiler, because preferGnu option is set, and g++ is available."); + if (this.options.preferClang && environment.isClangAvailable) { + if (install) { + this.log.info("TOOL", "Using clang++ compiler, because preferClang option is set, and clang++ is available."); + } + this.cppCompilerPath = this.cppCompilerPath || "clang++"; + this.cCompilerPath = this.cCompilerPath || "clang"; + } else if (this.options.preferGnu && environment.isGPPAvailable) { + if (install) { + this.log.info("TOOL", "Using g++ compiler, because preferGnu option is set, and g++ is available."); + } + this.cppCompilerPath = this.cppCompilerPath || "g++"; + this.cCompilerPath = this.cCompilerPath || "gcc"; } - this.cppCompilerPath = "g++"; - this.cCompilerPath = "gcc"; } if (this.generator) { if (install) { diff --git a/lib/es5/toolset.js.map b/lib/es5/toolset.js.map index ad57dfeb..d5a37526 100644 --- a/lib/es5/toolset.js.map +++ b/lib/es5/toolset.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["toolset.js"],"sourcesContent":["\"use strict\";\nlet Promise = require(\"bluebird\");\nlet async = Promise.coroutine;\nlet _ = require(\"lodash\");\nlet TargetOptions = require(\"./targetOptions\");\nlet environment = require(\"./environment\");\nlet assert = require(\"assert\");\nlet vsDetect = require(\"./vsDetect\");\nlet path = require(\"path\");\nlet CMLog = require(\"./cmLog\");\nlet processHelpers = require(\"./processHelpers\");\n\nfunction Toolset(options) {\n this.options = options || {};\n this.targetOptions = new TargetOptions(this.options);\n this.generator = options.generator;\n this.toolset = options.toolset;\n this.target = options.target;\n this.cCompilerPath = null;\n this.cppCompilerPath = null;\n this.compilerFlags = [];\n this.linkerFlags = [];\n this.makePath = null;\n this.log = new CMLog(this.options);\n this._initialized = false;\n}\n\nToolset.prototype.initialize = async(function*(install) {\n if (!this._initialized) {\n if (environment.isWin) {\n yield this.initializeWin(install);\n }\n else {\n this.initializePosix(install);\n }\n this._initialized = true;\n }\n});\n\nToolset.prototype.initializePosix = function (install) {\n // 1: Compiler\n if (!environment.isGPPAvailable && !environment.isClangAvailable) {\n if (environment.isOSX) {\n throw new Error(\"C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'.\");\n }\n else {\n throw new Error(\"C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'.\");\n }\n }\n\n if (this.options.preferClang && environment.isClangAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using clang++ compiler, because preferClang option is set, and clang++ is available.\");\n }\n this.cppCompilerPath = \"clang++\";\n this.cCompilerPath = \"clang\";\n }\n else if (this.options.preferGnu && environment.isGPPAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using g++ compiler, because preferGnu option is set, and g++ is available.\");\n }\n this.cppCompilerPath = \"g++\";\n this.cCompilerPath = \"gcc\";\n }\n // if it's already set because of options...\n if (this.generator) {\n if (install) {\n this.log.info(\"TOOL\", \"Using \" + this.options.generator + \" generator, as specified from commandline.\");\n }\n }\n // 2: Generator\n else if (environment.isOSX) {\n if (this.options.preferXcode) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Xcode generator, because preferXcode option is set.\");\n }\n this.generator = \"Xcode\";\n }\n else if (this.options.preferMake && environment.isMakeAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator, because preferMake option is set, and make is available.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n else if (environment.isNinjaAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Ninja generator, because ninja is available.\");\n }\n this.generator = \"Ninja\";\n }\n else {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n }\n else {\n if (this.options.preferMake && environment.isMakeAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator, because preferMake option is set, and make is available.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n else if (environment.isNinjaAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Ninja generator, because ninja is available.\");\n }\n this.generator = \"Ninja\";\n }\n else {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n }\n\n // 3: Flags\n if (environment.isOSX) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting default OSX compiler flags.\");\n }\n\n this.compilerFlags.push(\"-D_DARWIN_USE_64_BIT_INODE=1\");\n this.compilerFlags.push(\"-D_LARGEFILE_SOURCE\");\n this.compilerFlags.push(\"-D_FILE_OFFSET_BITS=64\");\n this.compilerFlags.push(\"-DBUILDING_NODE_EXTENSION\");\n this.linkerFlags.push(\"-undefined dynamic_lookup\");\n }\n\n // 4: Build target\n if (this.options.target) {\n this.log.info(\"TOOL\", \"Building only the \" + this.options.target + \" target, as specified from the command line.\");\n }\n};\n\nToolset.prototype.initializeWin = async(function*(install) {\n // Visual Studio:\n // if it's already set because of options...\n if (this.generator) {\n if (install) {\n this.log.info(\"TOOL\", \"Using \" + this.options.generator + \" generator, as specified from commandline.\");\n }\n\n this.linkerFlags.push(\"/DELAYLOAD:NODE.EXE\");\n\n if (this.targetOptions.isX86) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting SAFESEH:NO linker flag.\");\n }\n this.linkerFlags.push(\"/SAFESEH:NO\");\n }\n return;\n }\n let topVS = yield this._getTopSupportedVisualStudioGenerator();\n if (topVS) {\n if (install) {\n this.log.info(\"TOOL\", `Using ${topVS} generator.`);\n }\n this.generator = topVS;\n\n this.linkerFlags.push(\"/DELAYLOAD:NODE.EXE\");\n\n if (this.targetOptions.isX86) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting SAFESEH:NO linker flag.\");\n }\n this.linkerFlags.push(\"/SAFESEH:NO\");\n }\n }\n else {\n throw new Error(\"There is no Visual C++ compiler installed. Install Visual C++ Build Toolset or Visual Studio.\");\n }\n});\n\nToolset.prototype._getTopSupportedVisualStudioGenerator = async(function*() {\n let CMake = require(\"./cMake\");\n assert(environment.isWin);\n\n let vswhereVersion = yield this._getVersionFromVSWhere();\n\n let list = yield CMake.getGenerators(this.options);\n let maxVer = 0;\n let result = null;\n for (let gen of list) {\n let found = /^visual studio (\\d+)/i.exec(gen);\n if (!found) {\n continue;\n }\n\n let ver = parseInt(found[1]);\n if (ver <= maxVer) {\n continue;\n }\n\n // unlike previous versions \"Visual Studio 16 2019\" doesn't end with arch name\n const isAboveVS16 = ver >= 16;\n if (!isAboveVS16) {\n const is64Bit = gen.endsWith(\"Win64\");\n if ((this.targetOptions.isX86 && is64Bit) || (this.targetOptions.isX64 && !is64Bit)) {\n continue;\n }\n }\n\n if (ver === vswhereVersion || (yield vsDetect.isInstalled(ver + \".0\"))) {\n result = gen;\n maxVer = ver;\n }\n }\n return result;\n});\n\nToolset.prototype._getVersionFromVSWhere = async(function*() {\n let programFilesPath = _.get(process.env, \"ProgramFiles(x86)\", _.get(process.env, \"ProgramFiles\"));\n let vswhereCommand = path.resolve(programFilesPath, \"Microsoft Visual Studio\", \"Installer\", \"vswhere.exe\");\n let vswhereOutput = null;\n\n try {\n this.log.verbose(\"TOOL\", `Looking for vswhere.exe at '${vswhereCommand}'.`);\n vswhereOutput = yield processHelpers.exec(`\"${vswhereCommand}\" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion`);\n }\n catch (e) {\n this.log.verbose(\"TOOL\", \"Could not find vswhere.exe (VS installation is probably older than 15.2).\");\n return null;\n }\n\n if (!vswhereOutput) {\n return null;\n }\n\n let version = vswhereOutput.trim();\n version = version.substring(0, version.indexOf(\".\"));\n\n return Number(version);\n});\n\nmodule.exports = Toolset;\n"],"file":"toolset.js"} \ No newline at end of file +{"version":3,"names":[],"mappings":"","sources":["toolset.js"],"sourcesContent":["\"use strict\";\nlet Promise = require(\"bluebird\");\nlet async = Promise.coroutine;\nlet _ = require(\"lodash\");\nlet TargetOptions = require(\"./targetOptions\");\nlet environment = require(\"./environment\");\nlet assert = require(\"assert\");\nlet vsDetect = require(\"./vsDetect\");\nlet path = require(\"path\");\nlet CMLog = require(\"./cmLog\");\nlet processHelpers = require(\"./processHelpers\");\n\nfunction Toolset(options) {\n this.options = options || {};\n this.targetOptions = new TargetOptions(this.options);\n this.generator = options.generator;\n this.toolset = options.toolset;\n this.target = options.target;\n this.cCompilerPath = options.cCompilerPath;\n this.cppCompilerPath = options.cppCompilerPath;\n this.compilerFlags = [];\n this.linkerFlags = [];\n this.makePath = null;\n this.log = new CMLog(this.options);\n this._initialized = false;\n}\n\nToolset.prototype.initialize = async(function*(install) {\n if (!this._initialized) {\n if (environment.isWin) {\n yield this.initializeWin(install);\n }\n else {\n this.initializePosix(install);\n }\n this._initialized = true;\n }\n});\n\nToolset.prototype.initializePosix = function (install) {\n if (!this.cCompilerPath || !this.cppCompilerPath) {\n // 1: Compiler\n if (!environment.isGPPAvailable && !environment.isClangAvailable) {\n if (environment.isOSX) {\n throw new Error(\"C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'.\");\n }\n else {\n throw new Error(\"C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'.\");\n }\n }\n\n if (this.options.preferClang && environment.isClangAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using clang++ compiler, because preferClang option is set, and clang++ is available.\");\n }\n this.cppCompilerPath = this.cppCompilerPath || \"clang++\";\n this.cCompilerPath = this.cCompilerPath || \"clang\";\n }\n else if (this.options.preferGnu && environment.isGPPAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using g++ compiler, because preferGnu option is set, and g++ is available.\");\n }\n this.cppCompilerPath = this.cppCompilerPath || \"g++\";\n this.cCompilerPath = this.cCompilerPath || \"gcc\";\n }\n }\n // if it's already set because of options...\n if (this.generator) {\n if (install) {\n this.log.info(\"TOOL\", \"Using \" + this.options.generator + \" generator, as specified from commandline.\");\n }\n }\n // 2: Generator\n else if (environment.isOSX) {\n if (this.options.preferXcode) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Xcode generator, because preferXcode option is set.\");\n }\n this.generator = \"Xcode\";\n }\n else if (this.options.preferMake && environment.isMakeAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator, because preferMake option is set, and make is available.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n else if (environment.isNinjaAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Ninja generator, because ninja is available.\");\n }\n this.generator = \"Ninja\";\n }\n else {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n }\n else {\n if (this.options.preferMake && environment.isMakeAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator, because preferMake option is set, and make is available.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n else if (environment.isNinjaAvailable) {\n if (install) {\n this.log.info(\"TOOL\", \"Using Ninja generator, because ninja is available.\");\n }\n this.generator = \"Ninja\";\n }\n else {\n if (install) {\n this.log.info(\"TOOL\", \"Using Unix Makefiles generator.\");\n }\n this.generator = \"Unix Makefiles\";\n }\n }\n\n // 3: Flags\n if (environment.isOSX) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting default OSX compiler flags.\");\n }\n\n this.compilerFlags.push(\"-D_DARWIN_USE_64_BIT_INODE=1\");\n this.compilerFlags.push(\"-D_LARGEFILE_SOURCE\");\n this.compilerFlags.push(\"-D_FILE_OFFSET_BITS=64\");\n this.compilerFlags.push(\"-DBUILDING_NODE_EXTENSION\");\n this.linkerFlags.push(\"-undefined dynamic_lookup\");\n }\n\n // 4: Build target\n if (this.options.target) {\n this.log.info(\"TOOL\", \"Building only the \" + this.options.target + \" target, as specified from the command line.\");\n }\n};\n\nToolset.prototype.initializeWin = async(function*(install) {\n // Visual Studio:\n // if it's already set because of options...\n if (this.generator) {\n if (install) {\n this.log.info(\"TOOL\", \"Using \" + this.options.generator + \" generator, as specified from commandline.\");\n }\n\n this.linkerFlags.push(\"/DELAYLOAD:NODE.EXE\");\n\n if (this.targetOptions.isX86) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting SAFESEH:NO linker flag.\");\n }\n this.linkerFlags.push(\"/SAFESEH:NO\");\n }\n return;\n }\n let topVS = yield this._getTopSupportedVisualStudioGenerator();\n if (topVS) {\n if (install) {\n this.log.info(\"TOOL\", `Using ${topVS} generator.`);\n }\n this.generator = topVS;\n\n this.linkerFlags.push(\"/DELAYLOAD:NODE.EXE\");\n\n if (this.targetOptions.isX86) {\n if (install) {\n this.log.verbose(\"TOOL\", \"Setting SAFESEH:NO linker flag.\");\n }\n this.linkerFlags.push(\"/SAFESEH:NO\");\n }\n }\n else {\n throw new Error(\"There is no Visual C++ compiler installed. Install Visual C++ Build Toolset or Visual Studio.\");\n }\n});\n\nToolset.prototype._getTopSupportedVisualStudioGenerator = async(function*() {\n let CMake = require(\"./cMake\");\n assert(environment.isWin);\n\n let vswhereVersion = yield this._getVersionFromVSWhere();\n\n let list = yield CMake.getGenerators(this.options);\n let maxVer = 0;\n let result = null;\n for (let gen of list) {\n let found = /^visual studio (\\d+)/i.exec(gen);\n if (!found) {\n continue;\n }\n\n let ver = parseInt(found[1]);\n if (ver <= maxVer) {\n continue;\n }\n\n // unlike previous versions \"Visual Studio 16 2019\" doesn't end with arch name\n const isAboveVS16 = ver >= 16;\n if (!isAboveVS16) {\n const is64Bit = gen.endsWith(\"Win64\");\n if ((this.targetOptions.isX86 && is64Bit) || (this.targetOptions.isX64 && !is64Bit)) {\n continue;\n }\n }\n\n if (ver === vswhereVersion || (yield vsDetect.isInstalled(ver + \".0\"))) {\n result = gen;\n maxVer = ver;\n }\n }\n return result;\n});\n\nToolset.prototype._getVersionFromVSWhere = async(function*() {\n let programFilesPath = _.get(process.env, \"ProgramFiles(x86)\", _.get(process.env, \"ProgramFiles\"));\n let vswhereCommand = path.resolve(programFilesPath, \"Microsoft Visual Studio\", \"Installer\", \"vswhere.exe\");\n let vswhereOutput = null;\n\n try {\n this.log.verbose(\"TOOL\", `Looking for vswhere.exe at '${vswhereCommand}'.`);\n vswhereOutput = yield processHelpers.exec(`\"${vswhereCommand}\" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion`);\n }\n catch (e) {\n this.log.verbose(\"TOOL\", \"Could not find vswhere.exe (VS installation is probably older than 15.2).\");\n return null;\n }\n\n if (!vswhereOutput) {\n return null;\n }\n\n let version = vswhereOutput.trim();\n version = version.substring(0, version.indexOf(\".\"));\n\n return Number(version);\n});\n\nmodule.exports = Toolset;\n"],"file":"toolset.js"} \ No newline at end of file diff --git a/lib/es6/toolset.js b/lib/es6/toolset.js index 8735460e..7642dc1e 100644 --- a/lib/es6/toolset.js +++ b/lib/es6/toolset.js @@ -16,8 +16,8 @@ function Toolset(options) { this.generator = options.generator; this.toolset = options.toolset; this.target = options.target; - this.cCompilerPath = null; - this.cppCompilerPath = null; + this.cCompilerPath = options.cCompilerPath; + this.cppCompilerPath = options.cppCompilerPath; this.compilerFlags = []; this.linkerFlags = []; this.makePath = null; @@ -38,29 +38,31 @@ Toolset.prototype.initialize = async(function*(install) { }); Toolset.prototype.initializePosix = function (install) { - // 1: Compiler - if (!environment.isGPPAvailable && !environment.isClangAvailable) { - if (environment.isOSX) { - throw new Error("C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'."); - } - else { - throw new Error("C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'."); + if (!this.cCompilerPath || !this.cppCompilerPath) { + // 1: Compiler + if (!environment.isGPPAvailable && !environment.isClangAvailable) { + if (environment.isOSX) { + throw new Error("C++ Compiler toolset is not available. Install Xcode Commandline Tools from Apple Dev Center, or install Clang with homebrew by invoking: 'brew install llvm --with-clang --with-asan'."); + } + else { + throw new Error("C++ Compiler toolset is not available. Install proper compiler toolset with your package manager, eg. 'sudo apt-get install g++'."); + } } - } - if (this.options.preferClang && environment.isClangAvailable) { - if (install) { - this.log.info("TOOL", "Using clang++ compiler, because preferClang option is set, and clang++ is available."); + if (this.options.preferClang && environment.isClangAvailable) { + if (install) { + this.log.info("TOOL", "Using clang++ compiler, because preferClang option is set, and clang++ is available."); + } + this.cppCompilerPath = this.cppCompilerPath || "clang++"; + this.cCompilerPath = this.cCompilerPath || "clang"; } - this.cppCompilerPath = "clang++"; - this.cCompilerPath = "clang"; - } - else if (this.options.preferGnu && environment.isGPPAvailable) { - if (install) { - this.log.info("TOOL", "Using g++ compiler, because preferGnu option is set, and g++ is available."); + else if (this.options.preferGnu && environment.isGPPAvailable) { + if (install) { + this.log.info("TOOL", "Using g++ compiler, because preferGnu option is set, and g++ is available."); + } + this.cppCompilerPath = this.cppCompilerPath || "g++"; + this.cCompilerPath = this.cCompilerPath || "gcc"; } - this.cppCompilerPath = "g++"; - this.cCompilerPath = "gcc"; } // if it's already set because of options... if (this.generator) {