Skip to content

feat: rework lib #325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ node_modules
build
package-lock.json
yarn.lock
rewrite/dist

# Users Environment Variables
.lock-wscript
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package.json
142 changes: 142 additions & 0 deletions Lib.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
cmake_minimum_required(VERSION 3.15)

# setup some cmake required config
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_definitions("-DBUILDING_NODE_EXTENSION")

# In some configurations MD builds will crash upon attempting to free memory.
# This tries to encourage MT builds which are larger but less likely to have this crash.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

# Setup some variables
if(NOT CMAKE_BUILD_TYPE)
SET (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
endif()

set(NODE_PATH "node") # TODO - allow setting externally

# Find versions info
execute_process(COMMAND ${NODE_PATH} "${CMAKE_CURRENT_LIST_DIR}/bin/cmake-js-versions"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE CMAKE_JS_VERSIONS
)
if (NOT DEFINED CMAKE_JS_VERSIONS OR "${CMAKE_JS_VERSIONS}" STREQUAL "")
message(FATAL_ERROR "Failed to find cmake-js and nodejs versions!")
endif()
string(REGEX MATCH "CMAKEJS_VERSION ([0-9a-zA-Z\.]+)" _ ${CMAKE_JS_VERSIONS})
set(CMAKE_JS_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "NODE_RUNTIME ([0-9a-zA-Z\.]+)" _ ${CMAKE_JS_VERSIONS})
set(NODE_RUNTIME ${CMAKE_MATCH_1})
string(REGEX MATCH "NODE_RUNTIMEVERSION ([0-9a-zA-Z\.]+)" _ ${CMAKE_JS_VERSIONS})
set(NODE_RUNTIMEVERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "NODE_ARCH ([0-9a-zA-Z\.]+)" _ ${CMAKE_JS_VERSIONS})
set(NODE_ARCH ${CMAKE_MATCH_1})

set(CMAKE_JS_PATH ${CMAKE_CURRENT_LIST_DIR}) # cache value of CMAKE_CURRENT_LIST_DIR, as it changes inside function calls

# cmake-js version of CMake `add_library` specifically for node addons
FUNCTION (cmake_js_add_node_addon PROJECT_NAME)
cmake_parse_arguments(
PARSED_ARGS # prefix of output variables
"OLD_ADDON_API" # list of names of the boolean arguments (only defined ones will be true)
"" # list of names of mono-valued arguments
"SOURCES" # list of names of multi-valued arguments (output variables are lists)
${ARGN} # arguments of the function to parse, here we take the all original ones
)

# windows delay hook
set(CMAKE_JS_SRC "")
if (MSVC)
list (APPEND CMAKE_JS_SRC "${CMAKE_JS_PATH}/lib/cpp/win_delay_load_hook.cc")
endif()

# Setup the library and some default config
add_library(${PROJECT_NAME} SHARED ${PARSED_ARGS_SOURCES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")

if (OLD_ADDON_API)
# # Try finding nan
# execute_process(COMMAND ${NODE_PATH} -p "require('nan').include"
# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
# OUTPUT_VARIABLE NODE_NAN_DIR
# OUTPUT_STRIP_TRAILING_WHITESPACE
# )
# if (DEFINED NODE_ADDON_API_DIR AND NOT "${NODE_NAN_DIR}" STREQUAL "")
# string(REGEX REPLACE "[\"]" "" NODE_NAN_DIR ${NODE_NAN_DIR})
# message("Found nan: ${NODE_NAN_DIR}")
# target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_NAN_DIR})
# endif()

# TODO nan and headers

# include headers
set (NODE_HEADERS_DIR "") # TODO
target_include_directories(${PROJECT_NAME} PRIVATE
# some runtimes provide tidy headers
"${NODE_HEADERS_DIR}/include/node"
# some runtimes provide a lot more stuff
"${NODE_HEADERS_DIR}/src"
"${NODE_HEADERS_DIR}/deps/v8/include"
"${NODE_HEADERS_DIR}/deps/uv/include"
)

else()
# Find node-addon-api
execute_process(COMMAND ${NODE_PATH} -p "require('node-api-headers').include_dir"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_API_HEADERS_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (DEFINED NODE_API_HEADERS_DIR AND NOT "${NODE_API_HEADERS_DIR}" STREQUAL "")
message("Found node-api-headers: ${NODE_API_HEADERS_DIR}")
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_API_HEADERS_DIR})
else()
message(FATAL_ERROR "Failed to find node-api-headers!")
endif()

# Try finding node-addon-api
execute_process(COMMAND ${NODE_PATH} -p "require('node-addon-api').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_ADDON_API_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (DEFINED NODE_ADDON_API_DIR AND NOT "${NODE_ADDON_API_DIR}" STREQUAL "")
string(REGEX REPLACE "[\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
message("Found node-addon-api: ${NODE_ADDON_API_DIR}")
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
endif()

# Generate node.lib if needed
if(MSVC)
# Find node-addon-api
execute_process(COMMAND ${NODE_PATH} -p "require('node-api-headers').def_paths.node_api_def"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_API_DEF_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (DEFINED NODE_API_DEF_PATH AND NOT "${NODE_API_DEF_PATH}" STREQUAL "")
# Generate node.lib
set(CMAKE_JS_NODELIB_TARGET "${CMAKE_BINARY_DIR}/node.lib")
execute_process(COMMAND ${CMAKE_AR} /def:${NODE_API_DEF_PATH} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_NODELIB_TARGET})
else()
message(FATAL_ERROR "Failed to find node-api-headers node_api_def!")
endif()

endif()
endif()

if (MSVC)
# setup delayload
target_link_options(${PROJECT_NAME} PRIVATE "/DELAYLOAD:NODE.EXE")
target_link_libraries(${PROJECT_NAME} PRIVATE delayimp)

if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)")
target_link_options(${PROJECT_NAME} PUBLIC "/SAFESEH:NO")
endif()
endif()

ENDFUNCTION ()
15 changes: 15 additions & 0 deletions bin/cmake-js-cmake.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env node

/**
* This script is intended to be a minimal helper script which makes for easy invocation of `cmake`,
* utilising the same logic to locate cmake and potentially fill in some parameters
*/

// TODO - a helper to replace #GENERATOR# with autoselected generator, to simplify windows

import { runCommand } from '../rewrite/dist/processHelpers.js'
import { findCmake } from '../rewrite/dist/toolchain.js'

const cmakePath = await findCmake()

await runCommand([cmakePath, ...process.argv.slice(2)])
9 changes: 9 additions & 0 deletions bin/cmake-js-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env node
'use strict'

const version = require('../package').version

console.log(`CMAKEJS_VERSION ${version}`)
console.log(`NODE_RUNTIME node`)
console.log(`NODE_RUNTIMEVERSION ${process.version.slice(1)}`)
console.log(`NODE_ARCH ${process.arch}`)
15 changes: 15 additions & 0 deletions lib/import/find-visualstudio.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export interface FoundVisualStudio {
version: string
versionMajor: number
versionMinor: number
versionYear: number

path: string
msBuild: string
toolset: string
sdk: string
}

export class FindVisualStudio {
static findVisualStudio(nodeSemver: string, configMsvsVersion?: string): Promise<FoundVisualStudio | null>
}
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"url": "git://github.com/cmake-js/cmake-js.git"
},
"bin": {
"cmake-js": "./bin/cmake-js"
"cmake-js": "./bin/cmake-js",
"cmake-js-cmake": "./bin/cmake-js-cmake.mjs"
},
"engines": {
"node": ">= 14.15.0"
Expand All @@ -55,12 +56,16 @@
"yargs": "^17.7.2"
},
"devDependencies": {
"@tsconfig/node14": "^14.1.0",
"@types/node": "^14.18.63",
"@types/which": "^2.0.2",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"mocha": "*",
"nan": "^2.18.0",
"node-addon-api": "^6.1.0",
"prettier": "^3.2.2"
"prettier": "^3.2.2",
"typescript": "^5.3.3"
},
"scripts": {
"test": "mocha tests",
Expand Down
96 changes: 96 additions & 0 deletions rewrite/old/buildSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict'
const CMake = require('./cMake')
const Dist = require('./dist')
const CMLog = require('./cmLog')
const appCMakeJSConfig = require('./appCMakeJSConfig')
const npmConfig = require('./npmConfig')
const path = require('path')
const Toolset = require('./toolset')

class BuildSystem {
constructor(options) {
this.options = options || {}
this.options.directory = path.resolve(this.options.directory || process.cwd())
this.options.out = path.resolve(this.options.out || path.join(this.options.directory, 'build'))
this.log = new CMLog(this.options)
const npmOptions = npmConfig(this.log)

if (npmOptions && typeof npmOptions === 'object' && Object.keys(npmOptions).length) {
this.options.runtimeDirectory = npmOptions['nodedir']
this.options.msvsVersion = npmOptions['msvs_version']
}

this.log.verbose('CFG', 'Build system options:')
this.log.verbose('CFG', JSON.stringify(this.options))
this.cmake = new CMake(this.options)
this.dist = new Dist(this.options)
this.toolset = new Toolset(this.options)
}
async _ensureInstalled() {
try {
await this.toolset.initialize(true)
if (!this.options.isNodeApi) {
await this.dist.ensureDownloaded()
}
} catch (e) {
this._showError(e)
throw e
}
}
_showError(e) {
if (this.log === undefined) {
// handle internal errors (init failed)
console.error('OMG', e.stack)
return
}
if (this.log.level === 'verbose' || this.log.level === 'silly') {
this.log.error('OMG', e.stack)
} else {
this.log.error('OMG', e.message)
}
}
install() {
return this._ensureInstalled()
}
async _invokeCMake(method) {
try {
await this._ensureInstalled()
return await this.cmake[method]()
} catch (e) {
this._showError(e)
throw e
}
}
getConfigureCommand() {
return this._invokeCMake('getConfigureCommand')
}
getCmakeJsLibString() {
return this._invokeCMake('getCmakeJsLibString')
}
configure() {
return this._invokeCMake('configure')
}
getBuildCommand() {
return this._invokeCMake('getBuildCommand')
}
build() {
return this._invokeCMake('build')
}
getCleanCommand() {
return this._invokeCMake('getCleanCommand')
}
clean() {
return this._invokeCMake('clean')
}
reconfigure() {
return this._invokeCMake('reconfigure')
}
rebuild() {
return this._invokeCMake('rebuild')
}
compile() {
return this._invokeCMake('compile')
}
}

module.exports = BuildSystem
Loading