From bdb4d9b274c99d0bd19950e00ed72fa348020d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 20 Apr 2018 16:40:17 +0300 Subject: [node] allow building all ABIs at once --- Makefile | 16 +- cmake/NodeJS.cmake | 600 -------------------------------------------- cmake/loop-uv.cmake | 14 ++ cmake/mbgl.cmake | 31 ++- cmake/node.cmake | 121 ++++----- package.json | 2 +- platform/macos/config.cmake | 4 +- platform/node/index.js | 3 +- 8 files changed, 122 insertions(+), 669 deletions(-) delete mode 100644 cmake/NodeJS.cmake create mode 100644 cmake/loop-uv.cmake diff --git a/Makefile b/Makefile index 576312cabf..e54fe6313b 100644 --- a/Makefile +++ b/Makefile @@ -111,8 +111,7 @@ run-benchmark-%: benchmark $(MACOS_OUTPUT_PATH)/$(BUILDTYPE)/mbgl-benchmark --benchmark_filter=$* ${BENCHMARK_ARGS} .PHONY: node-benchmark -node-benchmark: $(MACOS_PROJ_PATH) - set -o pipefail && $(MACOS_XCODEBUILD) -scheme 'node-benchmark' build $(XCPRETTY) +node-benchmark: node .PHONY: run-node-benchmark run-node-benchmark: node-benchmark @@ -136,7 +135,11 @@ offline: $(MACOS_PROJ_PATH) .PHONY: node node: $(MACOS_PROJ_PATH) - set -o pipefail && $(MACOS_XCODEBUILD) -scheme 'mbgl-node' build $(XCPRETTY) + set -o pipefail && $(MACOS_XCODEBUILD) -scheme 'mbgl-node (Active ABI)' build $(XCPRETTY) + +.PHONY: node-all +node-all: $(MACOS_PROJ_PATH) + set -o pipefail && $(MACOS_XCODEBUILD) -scheme 'mbgl-node (All ABIs)' build $(XCPRETTY) .PHONY: macos-test macos-test: $(MACOS_PROJ_PATH) @@ -362,7 +365,11 @@ run-glfw-app: glfw-app .PHONY: node node: $(LINUX_BUILD) - $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-node + $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-node.active + +.PHONY: node-all +node-all: $(LINUX_BUILD) + $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-node.all .PHONY: compdb compdb: $(LINUX_BUILD) @@ -706,6 +713,7 @@ codestyle: .PHONY: clean clean: -rm -rf ./build \ + ./lib/*.node \ ./platform/android/gradle/configuration.gradle \ ./platform/android/MapboxGLAndroidSDK/build \ ./platform/android/MapboxGLAndroidSDK/.externalNativeBuild \ diff --git a/cmake/NodeJS.cmake b/cmake/NodeJS.cmake deleted file mode 100644 index 8e0ec56982..0000000000 --- a/cmake/NodeJS.cmake +++ /dev/null @@ -1,600 +0,0 @@ -# NOTE: We're using a patched version of the original https://github.com/cjntaylor/node-cmake - -# Our version is in https://github.com/mapbox/node-cmake/blob/mapbox-gl-native/NodeJS.cmake and -# contains these patches: -# - https://github.com/cjntaylor/node-cmake/pull/20 -# - https://github.com/cjntaylor/node-cmake/pull/22 -# - https://github.com/cjntaylor/node-cmake/pull/23 - -# Defaults for standard Node.js builds -set(NODEJS_DEFAULT_URL https://nodejs.org/download/release) -set(NODEJS_DEFAULT_VERSION installed) -set(NODEJS_VERSION_FALLBACK latest) -set(NODEJS_DEFAULT_NAME node) -set(NODEJS_DEFAULT_CHECKSUM SHASUMS256.txt) -set(NODEJS_DEFAULT_CHECKTYPE SHA256) - -include(CMakeParseArguments) - -# Find a path by walking upward from a base directory until the path is -# found. Sets the variable ${PATH} to False if the path can't -# be determined -function(find_path_parent NAME BASE PATH) - set(ROOT ${BASE}) - set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE) - set(DRIVE "^[A-Za-z]?:?/$") - while(NOT ROOT MATCHES ${DRIVE} AND NOT EXISTS ${ROOT}/${NAME}) - get_filename_component(ROOT ${ROOT} DIRECTORY) - set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE) - endwhile() - if(ROOT MATCHES ${DRIVE}) - set(${PATH} False PARENT_SCOPE) - endif() -endfunction() - -# Shortcut for finding standard node module locations -macro(find_nodejs_module NAME BASE PATH) - find_path_parent(node_modules/${NAME} ${BASE} ${PATH}) -endmacro() - -# Download with a bit of nice output (without spewing progress) -function(download_file DESCRIPTION URL FILE) - message(STATUS "Downloading: ${URL}") - file(DOWNLOAD - ${URL} - ${FILE}.tmp - ${ARGN} - STATUS RESULT - ) - list(GET RESULT 0 STATUS) - if(STATUS) - list(GET result 1 MESSAGE) - message(FATAL_ERROR "Unable to download ${DESCRIPTION} from ${URL}: ${MESSAGE}") - else() - file(RENAME ${FILE}.tmp ${FILE}) - endif() -endfunction() - -# Embedded win_delay_load_hook file so that this file can be copied -# into projects directly (recommended practice) -function(nodejs_generate_delayload_hook OUTPUT) - file(WRITE ${OUTPUT} "") - file(APPEND ${OUTPUT} "/*\n") - file(APPEND ${OUTPUT} " * When this file is linked to a DLL, it sets up a delay-load hook that\n") - file(APPEND ${OUTPUT} " * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe'\n") - file(APPEND ${OUTPUT} " * dynamically. Instead of trying to locate the .exe file it'll just return\n") - file(APPEND ${OUTPUT} " * a handle to the process image.\n") - file(APPEND ${OUTPUT} " *\n") - file(APPEND ${OUTPUT} " * This allows compiled addons to work when node.exe or iojs.exe is renamed.\n") - file(APPEND ${OUTPUT} " */\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "#ifdef _MSC_VER\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "#ifndef DELAYIMP_INSECURE_WRITABLE_HOOKS\n") - file(APPEND ${OUTPUT} "#define DELAYIMP_INSECURE_WRITABLE_HOOKS\n") - file(APPEND ${OUTPUT} "#endif\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "#ifndef WIN32_LEAN_AND_MEAN\n") - file(APPEND ${OUTPUT} "#define WIN32_LEAN_AND_MEAN\n") - file(APPEND ${OUTPUT} "#endif\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "#include \n") - file(APPEND ${OUTPUT} "#include \n") - file(APPEND ${OUTPUT} "#include \n") - file(APPEND ${OUTPUT} "#include \n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) {\n") - file(APPEND ${OUTPUT} " if (event != dliNotePreLoadLibrary) return NULL;\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " if (_stricmp(info->szDll, \"iojs.exe\") != 0 &&\n") - file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.exe\") != 0 &&\n") - file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.dll\") != 0)\n") - file(APPEND ${OUTPUT} " return NULL;\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // Get a handle to the current process executable.\n") - file(APPEND ${OUTPUT} " HMODULE processModule = GetModuleHandle(NULL);\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // Get the path to the executable.\n") - file(APPEND ${OUTPUT} " TCHAR processPath[_MAX_PATH];\n") - file(APPEND ${OUTPUT} " GetModuleFileName(processModule, processPath, _MAX_PATH);\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // Get the name of the current executable.\n") - file(APPEND ${OUTPUT} " LPSTR processName = PathFindFileName(processPath);\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // If the current process is node or iojs, then just return the proccess \n") - file(APPEND ${OUTPUT} " // module.\n") - file(APPEND ${OUTPUT} " if (_stricmp(processName, \"node.exe\") == 0 ||\n") - file(APPEND ${OUTPUT} " _stricmp(processName, \"iojs.exe\") == 0) {\n") - file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n") - file(APPEND ${OUTPUT} " }\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // If it is another process, attempt to load 'node.dll' from the same \n") - file(APPEND ${OUTPUT} " // directory.\n") - file(APPEND ${OUTPUT} " PathRemoveFileSpec(processPath);\n") - file(APPEND ${OUTPUT} " PathAppend(processPath, \"node.dll\");\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " HMODULE nodeDllModule = GetModuleHandle(processPath);\n") - file(APPEND ${OUTPUT} " if(nodeDllModule != NULL) {\n") - file(APPEND ${OUTPUT} " // This application has a node.dll in the same directory as the executable,\n") - file(APPEND ${OUTPUT} " // use that.\n") - file(APPEND ${OUTPUT} " return (FARPROC) nodeDllModule;\n") - file(APPEND ${OUTPUT} " }\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} " // Fallback to the current executable, which must statically link to \n") - file(APPEND ${OUTPUT} " // node.lib\n") - file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n") - file(APPEND ${OUTPUT} "}\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;\n") - file(APPEND ${OUTPUT} "\n") - file(APPEND ${OUTPUT} "#endif\n") -endfunction() - -# Sets up a project to build Node.js native modules -# - Downloads required dependencies and unpacks them to the build directory. -# Internet access is required the first invocation but not after ( -# provided the download is successful) -# - Sets up several variables for building against the downloaded -# dependencies -# - Guarded to prevent multiple executions, so a single project hierarchy -# will only call this once -function(nodejs_init) - # Prevents this function from executing more than once - if(NODEJS_INIT) - return() - endif() - - # Regex patterns used by the init function for component extraction - set(HEADERS_MATCH "^([A-Fa-f0-9]+)[ \t]+([^-]+)-(headers|v?[0-9.]+)-(headers|v?[0-9.]+)([.]tar[.]gz)$") - set(LIB32_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-x86)?(/)?([^/]*)(.lib)$") - set(LIB64_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-)?(x64/)(.*)(.lib)$") - - # Parse function arguments - cmake_parse_arguments(nodejs_init - "" "URL;NAME;VERSION;CHECKSUM;CHECKTYPE" "" ${ARGN} - ) - - # Allow the download URL to be overridden by command line argument - # NODEJS_URL - if(NODEJS_URL) - set(URL ${NODEJS_URL}) - else() - # Use the argument if specified, falling back to the default - set(URL ${NODEJS_DEFAULT_URL}) - if(nodejs_init_URL) - set(URL ${nodejs_init_URL}) - endif() - endif() - - # Allow name to be overridden by command line argument NODEJS_NAME - if(NODEJS_NAME) - set(NAME ${NODEJS_NAME}) - else() - # Use the argument if specified, falling back to the default - set(NAME ${NODEJS_DEFAULT_NAME}) - if(nodejs_init_NAME) - set(NAME ${nodejs_init_NAME}) - endif() - endif() - - # Allow the checksum file to be overridden by command line argument - # NODEJS_CHECKSUM - if(NODEJS_CHECKSUM) - set(CHECKSUM ${NODEJS_CHECKSUM}) - else() - # Use the argument if specified, falling back to the default - set(CHECKSUM ${NODEJS_DEFAULT_CHECKSUM}) - if(nodejs_init_CHECKSUM) - set(CHECKSUM ${nodejs_init_CHECKSUM}) - endif() - endif() - - # Allow the checksum type to be overriden by the command line argument - # NODEJS_CHECKTYPE - if(NODEJS_CHECKTYPE) - set(CHECKTYPE ${NODEJS_CHECKTYPE}) - else() - # Use the argument if specified, falling back to the default - set(CHECKTYPE ${NODEJS_DEFAULT_CHECKTYPE}) - if(nodejs_init_CHECKTYPE) - set(CHECKTYPE ${nodejs_init_CHECKTYPE}) - endif() - endif() - - # Allow the version to be overridden by the command line argument - # NODEJS_VERSION - if(NODEJS_VERSION) - set(VERSION ${NODEJS_VERSION}) - else() - # Use the argument if specified, falling back to the default - set(VERSION ${NODEJS_DEFAULT_VERSION}) - if(nodejs_init_VERSION) - set(VERSION ${nodejs_init_VERSION}) - endif() - endif() - - # "installed" is a special version that tries to use the currently - # installed version (determined by running node) - set(NODEJS_INSTALLED False CACHE BOOL "Node.js install status" FORCE) - if(VERSION STREQUAL "installed") - if(NOT NAME STREQUAL ${NODEJS_DEFAULT_NAME}) - message(FATAL_ERROR - "'Installed' version identifier can only be used with" - "the core Node.js library" - ) - endif() - # Fall back to the "latest" version if node isn't installed - set(VERSION ${NODEJS_VERSION_FALLBACK}) - find_program(NODEJS_BINARY NAMES nodejs node) - if(NODEJS_BINARY) - execute_process( - COMMAND ${NODEJS_BINARY} --version - RESULT_VARIABLE INSTALLED_VERSION_RESULT - OUTPUT_VARIABLE INSTALLED_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(INSTALLED_VERSION_RESULT STREQUAL "0") - set(NODEJS_INSTALLED True CACHE BOOL - "Node.js install status" FORCE - ) - set(VERSION ${INSTALLED_VERSION}) - endif() - endif() - endif() - - # Create a temporary download directory - set(TEMP ${CMAKE_CURRENT_BINARY_DIR}/temp) - file(MAKE_DIRECTORY ${TEMP}) - - # Unless the target is special version "latest", the parameters - # necessary to construct the root path are known - if(NOT VERSION STREQUAL "latest") - set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION}) - # Extract checksums from the existing checksum file - set(CHECKSUM_TARGET ${ROOT}/CHECKSUM) - endif() - - # If we're trying to determine the version or we haven't saved the - # checksum file for this version, download it from the specified server - if(VERSION STREQUAL "latest" OR - (DEFINED ROOT AND NOT EXISTS ${ROOT}/CHECKSUM)) - if(DEFINED ROOT) - # Clear away the old checksum in case the new one is different - # and/or it fails to download - file(REMOVE ${ROOT}/CHECKSUM) - endif() - file(REMOVE ${TEMP}/CHECKSUM) - download_file( - "checksum file" - ${URL}/${VERSION}/${CHECKSUM} - ${TEMP}/CHECKSUM - INACTIVITY_TIMEOUT 10 - ) - # Extract checksums from the temporary file - set(CHECKSUM_TARGET ${TEMP}/CHECKSUM) - endif() - - # Extract the version, name, header archive and archive checksum - # from the file. This first extract is what defines / specifies the - # actual version number and name. - file(STRINGS - ${CHECKSUM_TARGET} HEADERS_CHECKSUM - REGEX ${HEADERS_MATCH} - LIMIT_COUNT 1 - ) - if(NOT HEADERS_CHECKSUM) - file(REMOVE ${TEMP}/CHECKSUM) - if(DEFINED ROOT) - file(REMOVE ${ROOT}/CHECKSUM) - endif() - message(FATAL_ERROR "Unable to extract header archive checksum") - endif() - string(REGEX MATCH ${HEADERS_MATCH} HEADERS_CHECKSUM ${HEADERS_CHECKSUM}) - set(HEADERS_CHECKSUM ${CMAKE_MATCH_1}) - set(NAME ${CMAKE_MATCH_2}) - if(CMAKE_MATCH_3 STREQUAL "headers") - set(VERSION ${CMAKE_MATCH_4}) - else() - set(VERSION ${CMAKE_MATCH_3}) - endif() - set(HEADERS_ARCHIVE - ${CMAKE_MATCH_2}-${CMAKE_MATCH_3}-${CMAKE_MATCH_4}${CMAKE_MATCH_5} - ) - # Make sure that the root directory exists, and that the checksum - # file has been moved over from temp - if(DEFINED ROOT) - set(OLD_ROOT ${ROOT}) - endif() - set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION}) - if(DEFINED OLD_ROOT AND NOT ROOT STREQUAL "${OLD_ROOT}") - file(REMOVE ${TEMP}/CHECKSUM) - file(REMOVE ${ROOT}/CHECKSUM) - message(FATAL_ERROR "Version/Name mismatch") - endif() - file(MAKE_DIRECTORY ${ROOT}) - if(EXISTS ${TEMP}/CHECKSUM) - file(REMOVE ${ROOT}/CHECKSUM) - file(RENAME ${TEMP}/CHECKSUM ${ROOT}/CHECKSUM) - endif() - - # Now that its fully resolved, report the name and version of Node.js being - # used - message(STATUS "NodeJS: Using ${NAME}, version ${VERSION}") - - # Download the headers for the version being used - # Theoretically, these could be found by searching the installed - # system, but in practice, this can be error prone. They're provided - # on the download servers, so just use the ones there. - if(NOT EXISTS ${ROOT}/include) - file(REMOVE ${TEMP}/${HEADERS_ARCHIVE}) - download_file( - "Node.js headers" - ${URL}/${VERSION}/${HEADERS_ARCHIVE} - ${TEMP}/${HEADERS_ARCHIVE} - INACTIVITY_TIMEOUT 10 - EXPECTED_HASH ${CHECKTYPE}=${HEADERS_CHECKSUM} - ) - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xfz ${TEMP}/${HEADERS_ARCHIVE} - WORKING_DIRECTORY ${TEMP} - ) - - # This adapts the header extraction to support a number of different - # header archive contents in addition to the one used by the - # default Node.js library - unset(NODEJS_HEADERS_PATH CACHE) - find_path(NODEJS_HEADERS_PATH - NAMES src include - PATHS - ${TEMP}/${NAME}-${VERSION}-headers - ${TEMP}/${NAME}-${VERSION} - ${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}-headers - ${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION} - ${TEMP}/${NODEJS_DEFAULT_NAME} - ${TEMP} - NO_DEFAULT_PATH - ) - if(NOT NODEJS_HEADERS_PATH) - message(FATAL_ERROR "Unable to find extracted headers folder") - endif() - - # Move the headers into a standard location with a standard layout - file(REMOVE ${TEMP}/${HEADERS_ARCHIVE}) - file(REMOVE_RECURSE ${ROOT}/include) - if(EXISTS ${NODEJS_HEADERS_PATH}/include/node) - file(RENAME ${NODEJS_HEADERS_PATH}/include/node ${ROOT}/include) - elseif(EXISTS ${NODEJS_HEADERS_PATH}/src) - file(MAKE_DIRECTORY ${ROOT}/include) - if(NOT EXISTS ${NODEJS_HEADERS_PATH}/src) - file(REMOVE_RECURSE ${ROOT}/include) - message(FATAL_ERROR "Unable to find core headers") - endif() - file(COPY ${NODEJS_HEADERS_PATH}/src/ - DESTINATION ${ROOT}/include - ) - if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/uv/include) - file(REMOVE_RECURSE ${ROOT}/include) - message(FATAL_ERROR "Unable to find libuv headers") - endif() - file(COPY ${NODEJS_HEADERS_PATH}/deps/uv/include/ - DESTINATION ${ROOT}/include - ) - if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/v8/include) - file(REMOVE_RECURSE ${ROOT}/include) - message(FATAL_ERROR "Unable to find v8 headers") - endif() - file(COPY ${NODEJS_HEADERS_PATH}/deps/v8/include/ - DESTINATION ${ROOT}/include - ) - if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/zlib) - file(REMOVE_RECURSE ${ROOT}/include) - message(FATAL_ERROR "Unable to find zlib headers") - endif() - file(COPY ${NODEJS_HEADERS_PATH}/deps/zlib/ - DESTINATION ${ROOT}/include - ) - endif() - file(REMOVE_RECURSE ${NODEJS_HEADERS_PATH}) - unset(NODEJS_HEADERS_PATH CACHE) - endif() - - # Only download the libraries on windows, since its the only place - # its necessary. Note, this requires rerunning CMake if moving - # a module from one platform to another (should happen automatically - # with most generators) - if(WIN32) - # Download the win32 library for linking - file(STRINGS - ${ROOT}/CHECKSUM LIB32_CHECKSUM - LIMIT_COUNT 1 - REGEX ${LIB32_MATCH} - ) - if(NOT LIB32_CHECKSUM) - message(FATAL_ERROR "Unable to extract x86 library checksum") - endif() - string(REGEX MATCH ${LIB32_MATCH} LIB32_CHECKSUM ${LIB32_CHECKSUM}) - set(LIB32_CHECKSUM ${CMAKE_MATCH_1}) - set(LIB32_PATH win-x86) - set(LIB32_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5}) - set(LIB32_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB32_NAME}) - if(NOT EXISTS ${ROOT}/${LIB32_PATH}) - file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH}) - download_file( - "Node.js windows library (32-bit)" - ${URL}/${VERSION}/${LIB32_TARGET} - ${TEMP}/${LIB32_PATH}/${LIB32_NAME} - INACTIVITY_TIMEOUT 10 - EXPECTED_HASH ${CHECKTYPE}=${LIB32_CHECKSUM} - ) - file(REMOVE_RECURSE ${ROOT}/${LIB32_PATH}) - file(MAKE_DIRECTORY ${ROOT}/${LIB32_PATH}) - file(RENAME - ${TEMP}/${LIB32_PATH}/${LIB32_NAME} - ${ROOT}/${LIB32_PATH}/${LIB32_NAME} - ) - file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH}) - endif() - - # Download the win64 library for linking - file(STRINGS - ${ROOT}/CHECKSUM LIB64_CHECKSUM - LIMIT_COUNT 1 - REGEX ${LIB64_MATCH} - ) - if(NOT LIB64_CHECKSUM) - message(FATAL_ERROR "Unable to extract x64 library checksum") - endif() - string(REGEX MATCH ${LIB64_MATCH} LIB64_CHECKSUM ${LIB64_CHECKSUM}) - set(LIB64_CHECKSUM ${CMAKE_MATCH_1}) - set(LIB64_PATH win-x64) - set(LIB64_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5}) - set(LIB64_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB64_NAME}) - if(NOT EXISTS ${ROOT}/${LIB64_PATH}) - file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH}) - download_file( - "Node.js windows library (64-bit)" - ${URL}/${VERSION}/${LIB64_TARGET} - ${TEMP}/${LIB64_PATH}/${LIB64_NAME} - INACTIVITY_TIMEOUT 10 - EXPECTED_HASH ${CHECKTYPE}=${LIB64_CHECKSUM} - ) - file(REMOVE_RECURSE ${ROOT}/${LIB64_PATH}) - file(MAKE_DIRECTORY ${ROOT}/${LIB64_PATH}) - file(RENAME - ${TEMP}/${LIB64_PATH}/${LIB64_NAME} - ${ROOT}/${LIB64_PATH}/${LIB64_NAME} - ) - file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH}) - endif() - endif() - - # The downloaded headers should always be set for inclusion - list(APPEND INCLUDE_DIRS ${ROOT}/include) - - # Look for the NAN module, and add it to the includes - find_nodejs_module( - nan - ${CMAKE_CURRENT_SOURCE_DIR} - NODEJS_NAN_DIR - ) - if(NODEJS_NAN_DIR) - list(APPEND INCLUDE_DIRS ${NODEJS_NAN_DIR}) - endif() - - # Under windows, we need a bunch of libraries (due to the way - # dynamic linking works) - if(WIN32) - # Generate and use a delay load hook to allow the node binary - # name to be changed while still loading native modules - set(DELAY_LOAD_HOOK ${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c) - nodejs_generate_delayload_hook(${DELAY_LOAD_HOOK}) - set(SOURCES ${DELAY_LOAD_HOOK}) - - # Necessary flags to get delayload working correctly - list(APPEND LINK_FLAGS - "-IGNORE:4199" - "-DELAYLOAD:iojs.exe" - "-DELAYLOAD:node.exe" - "-DELAYLOAD:node.dll" - ) - - # Core system libraries used by node - list(APPEND LIBRARIES - kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib - odbc32.lib Shlwapi.lib DelayImp.lib - ) - - # Also link to the node stub itself (downloaded above) - if(CMAKE_CL_64) - list(APPEND LIBRARIES ${ROOT}/${LIB64_PATH}/${LIB64_NAME}) - else() - list(APPEND LIBRARIES ${ROOT}/${LIB32_PATH}/${LIB32_NAME}) - endif() - else() - # Non-windows platforms should use these flags - list(APPEND DEFINITIONS _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64) - endif() - - # Special handling for OSX / clang to allow undefined symbols - # Define is required by node on OSX - if(APPLE) - list(APPEND LINK_FLAGS "-undefined dynamic_lookup") - list(APPEND DEFINITIONS _DARWIN_USE_64_BIT_INODE=1) - endif() - - # Export all settings for use as arguments in the rest of the build - set(NODEJS_VERSION ${VERSION} PARENT_SCOPE) - set(NODEJS_SOURCES ${SOURCES} PARENT_SCOPE) - set(NODEJS_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) - set(NODEJS_LIBRARIES ${LIBRARIES} PARENT_SCOPE) - set(NODEJS_LINK_FLAGS ${LINK_FLAGS} PARENT_SCOPE) - set(NODEJS_DEFINITIONS ${DEFINITIONS} PARENT_SCOPE) - - # Prevents this function from executing more than once - set(NODEJS_INIT TRUE PARENT_SCOPE) -endfunction() - -# Helper function for defining a node module -# After nodejs_init, all of the settings and dependencies necessary to do -# this yourself are defined, but this helps make sure everything is configured -# correctly. Feel free to use it as a model to do this by hand (or to -# tweak this configuration if you need something custom). -function(add_nodejs_module NAME) - # Make sure node is initialized (variables set) before defining the module - if(NOT NODEJS_INIT) - message(FATAL_ERROR - "Node.js has not been initialized. " - "Call nodejs_init before adding any modules" - ) - endif() - # In order to match node-gyp, we need to build into type specific folders - # ncmake takes care of this, but be sure to set CMAKE_BUILD_TYPE yourself - # if invoking CMake directly - if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) - message(FATAL_ERROR - "Configuration type must be specified. " - "Set CMAKE_BUILD_TYPE or use a different generator" - ) - endif() - - # A node module is a shared library - add_library(${NAME} SHARED ${NODEJS_SOURCES} ${ARGN}) - # Add compiler defines for the module - # Two helpful ones: - # MODULE_NAME must match the name of the build library, define that here - target_compile_definitions(${NAME} - PRIVATE MODULE_NAME=${NAME} - PUBLIC ${NODEJS_DEFINITIONS} - ) - # This properly defines includes for the module - target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS}) - - # Add link flags to the module - target_link_libraries(${NAME} ${NODEJS_LIBRARIES}) - - # Set required properties for the module to build properly - # Correct naming, symbol visiblity and C++ standard - set_target_properties(${NAME} PROPERTIES - OUTPUT_NAME ${NAME} - PREFIX "" - SUFFIX ".node" - MACOSX_RPATH ON - C_VISIBILITY_PRESET hidden - CXX_VISIBILITY_PRESET hidden - POSITION_INDEPENDENT_CODE TRUE - CMAKE_CXX_STANDARD_REQUIRED TRUE - CXX_STANDARD 11 - LINK_FLAGS "${NODEJS_LINK_FLAGS}" - ) - - # Make sure we're buiilding in a build specific output directory - # Only necessary on single-target generators (Make, Ninja) - # Multi-target generators do this automatically - # This (luckily) mirrors node-gyp conventions - if(NOT CMAKE_CONFIGURATION_TYPES) - set_property(TARGET ${NAME} PROPERTY - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE} - ) - endif() -endfunction() diff --git a/cmake/loop-uv.cmake b/cmake/loop-uv.cmake new file mode 100644 index 0000000000..e1d3166b63 --- /dev/null +++ b/cmake/loop-uv.cmake @@ -0,0 +1,14 @@ +add_library(mbgl-loop-uv INTERFACE) + +target_sources(mbgl-loop-uv INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/async_task.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/run_loop.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/timer.cpp +) + +target_include_directories(mbgl-loop-uv INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +create_source_groups(mbgl-loop-uv) diff --git a/cmake/mbgl.cmake b/cmake/mbgl.cmake index f087c32511..88e24e3536 100644 --- a/cmake/mbgl.cmake +++ b/cmake/mbgl.cmake @@ -17,12 +17,32 @@ if(WITH_NODEJS) message(FATAL_ERROR "Could not find npm") endif() + execute_process( + COMMAND "${NodeJS_EXECUTABLE}" -e "process.stdout.write(process.versions.node)" + RESULT_VARIABLE _STATUS_CODE + OUTPUT_VARIABLE NodeJS_VERSION + ERROR_VARIABLE _STATUS_MESSAGE + ) + if(NOT _STATUS_CODE EQUAL 0) + message(FATAL_ERROR "Could not detect Node.js version: ${_STATUS_MESSAGE}") + endif() + + execute_process( + COMMAND "${NodeJS_EXECUTABLE}" -e "process.stdout.write(process.versions.modules)" + RESULT_VARIABLE _STATUS_CODE + OUTPUT_VARIABLE NodeJS_ABI + ERROR_VARIABLE _STATUS_MESSAGE + ) + if(NOT _STATUS_CODE EQUAL 0) + message(FATAL_ERROR "Could not detect Node.js ABI version: ${_STATUS_MESSAGE}") + endif() + function(_npm_install DIRECTORY NAME ADDITIONAL_DEPS) SET(NPM_INSTALL_FAILED FALSE) if("${DIRECTORY}/package.json" IS_NEWER_THAN "${DIRECTORY}/node_modules/.${NAME}.stamp") message(STATUS "Running 'npm install' for ${NAME}...") execute_process( - COMMAND ${NodeJS_EXECUTABLE} ${npm_EXECUTABLE} install --ignore-scripts + COMMAND "${NodeJS_EXECUTABLE}" "${npm_EXECUTABLE}" install --ignore-scripts WORKING_DIRECTORY "${DIRECTORY}" RESULT_VARIABLE NPM_INSTALL_FAILED) if(NOT NPM_INSTALL_FAILED) @@ -32,7 +52,7 @@ if(WITH_NODEJS) add_custom_command( OUTPUT "${DIRECTORY}/node_modules/.${NAME}.stamp" - COMMAND ${NodeJS_EXECUTABLE} ${npm_EXECUTABLE} install --ignore-scripts + COMMAND "${NodeJS_EXECUTABLE}" "${npm_EXECUTABLE}" install --ignore-scripts COMMAND ${CMAKE_COMMAND} -E touch "${DIRECTORY}/node_modules/.${NAME}.stamp" WORKING_DIRECTORY "${DIRECTORY}" DEPENDS ${ADDITIONAL_DEPS} "${DIRECTORY}/package.json" @@ -72,7 +92,12 @@ endif() # Generate source groups so the files are properly sorted in IDEs like Xcode. function(create_source_groups target) - get_target_property(sources ${target} SOURCES) + get_target_property(type ${target} TYPE) + if(type AND type STREQUAL "INTERFACE_LIBRARY") + get_target_property(sources ${target} INTERFACE_SOURCES) + else() + get_target_property(sources ${target} SOURCES) + endif() foreach(file ${sources}) get_filename_component(file "${file}" ABSOLUTE) string(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" group "${file}") diff --git a/cmake/node.cmake b/cmake/node.cmake index 90bec6575c..b6f7bb9dc0 100644 --- a/cmake/node.cmake +++ b/cmake/node.cmake @@ -1,87 +1,96 @@ # Load Node.js -include(cmake/NodeJS.cmake) -nodejs_init() +include(node_modules/@mapbox/cmake-node-module/module.cmake) -add_library(mbgl-loop-node STATIC - platform/default/async_task.cpp - platform/default/run_loop.cpp - platform/default/timer.cpp -) +add_library(mbgl-loop-node INTERFACE) -target_include_directories(mbgl-loop-node - PRIVATE include - PRIVATE src +target_sources(mbgl-loop-node INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/async_task.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/run_loop.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default/timer.cpp ) -target_include_directories(mbgl-loop-node PUBLIC ${NODEJS_INCLUDE_DIRS}) +target_include_directories(mbgl-loop-node INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/src +) create_source_groups(mbgl-loop-node) -xcode_create_scheme(TARGET mbgl-loop-node) -add_nodejs_module(mbgl-node - platform/node/src/node_mapbox_gl_native.cpp + +add_node_module(mbgl-node + INSTALL_DIR "lib" + NAN_VERSION "2.10.0" + EXCLUDE_NODE_ABIS 47 51 59 # Don't build old beta ABIs 5.x, 7.x, and 9.x ) -# NodeJS.cmake forces C++11. -# https://github.com/cjntaylor/node-cmake/issues/18 -set_target_properties("mbgl-node" PROPERTIES CXX_STANDARD 14) - -target_sources(mbgl-node - PRIVATE platform/node/src/node_logging.hpp - PRIVATE platform/node/src/node_logging.cpp - PRIVATE platform/node/src/node_conversion.hpp - PRIVATE platform/node/src/node_map.hpp - PRIVATE platform/node/src/node_map.cpp - PRIVATE platform/node/src/node_request.hpp - PRIVATE platform/node/src/node_request.cpp - PRIVATE platform/node/src/node_feature.hpp - PRIVATE platform/node/src/node_feature.cpp - PRIVATE platform/node/src/node_thread_pool.hpp - PRIVATE platform/node/src/node_thread_pool.cpp - PRIVATE platform/node/src/node_expression.hpp - PRIVATE platform/node/src/node_expression.cpp - PRIVATE platform/node/src/util/async_queue.hpp +target_sources(mbgl-node INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_mapbox_gl_native.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_mapbox_gl_native.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_logging.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_logging.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_conversion.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_map.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_map.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_request.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_request.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_feature.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_feature.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_thread_pool.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_thread_pool.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_expression.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/node_expression.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/platform/node/src/util/async_queue.hpp ) -target_include_directories(mbgl-node - PRIVATE platform/default +target_include_directories(mbgl-node INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/platform/default ) -target_link_libraries(mbgl-node - PRIVATE mbgl-core - PRIVATE mbgl-loop-node +target_link_libraries(mbgl-node INTERFACE + mbgl-core + mbgl-loop-node ) -target_add_mason_package(mbgl-node PRIVATE geojson) +target_add_mason_package(mbgl-node INTERFACE geojson) -add_custom_command( - TARGET mbgl-node - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_SOURCE_DIR}/lib/mapbox_gl_native.node -) +add_custom_target(mbgl-node.active DEPENDS mbgl-node.abi-${NodeJS_ABI}) mbgl_platform_node() create_source_groups(mbgl-node) -initialize_xcode_cxx_build_settings(mbgl-node) +foreach(ABI IN LISTS mbgl-node::abis) + initialize_xcode_cxx_build_settings(mbgl-node.abi-${ABI}) + xcode_create_scheme( + TARGET mbgl-node.abi-${ABI} + NAME "mbgl-node (ABI ${ABI})" + ) +endforeach() + +xcode_create_scheme( + TARGET mbgl-node.active + TYPE library + NAME "mbgl-node (Active ABI)" +) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.all + TYPE library + NAME "mbgl-node (All ABIs)" ) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.active TYPE node - NAME "node tests" + NAME "node tests (Active ABI)" ARGS "node_modules/.bin/tape platform/node/test/js/**/*.test.js" ) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.active TYPE node - NAME "node render tests" + NAME "node render tests (Active ABI)" ARGS "platform/node/test/render.test.js" OPTIONAL_ARGS @@ -90,9 +99,9 @@ xcode_create_scheme( ) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.active TYPE node - NAME "node query tests" + NAME "node query tests (Active ABI)" ARGS "platform/node/test/query.test.js" OPTIONAL_ARGS @@ -101,9 +110,9 @@ xcode_create_scheme( ) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.active TYPE node - NAME "node expression tests" + NAME "node expression tests (Active ABI)" ARGS "platform/node/test/expression.test.js" OPTIONAL_ARGS @@ -112,9 +121,9 @@ xcode_create_scheme( ) xcode_create_scheme( - TARGET mbgl-node + TARGET mbgl-node.active TYPE node - NAME "node-benchmark" + NAME "node-benchmark (Active ABI)" ARGS "platform/node/test/benchmark.js" OPTIONAL_ARGS diff --git a/package.json b/package.json index c3f0d7b8ae..39f64a3967 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "license": "BSD-2-Clause", "dependencies": { - "nan": "~2.10", + "@mapbox/cmake-node-module": "^1.0.0", "node-pre-gyp": "^0.6.37", "npm-run-all": "^4.0.2" }, diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake index 28573258d9..aa3f17eea1 100644 --- a/platform/macos/config.cmake +++ b/platform/macos/config.cmake @@ -154,7 +154,5 @@ macro(mbgl_platform_benchmark) endmacro() macro(mbgl_platform_node) - target_link_libraries(mbgl-node - PRIVATE "-Wl,-bind_at_load" - ) + # Define macro to enable this target on this platform endmacro() diff --git a/platform/node/index.js b/platform/node/index.js index 5944a0a27d..6f6b33058a 100644 --- a/platform/node/index.js +++ b/platform/node/index.js @@ -2,9 +2,8 @@ // Shim to wrap req.respond while preserving callback-passing API -var mbgl = require('../../lib/mapbox_gl_native.node'); +var mbgl = require('../../lib/mbgl-node.abi-' + process.versions.modules); var constructor = mbgl.Map.prototype.constructor; -var process = require('process'); var Map = function(options) { if (!(options instanceof Object)) { -- cgit v1.2.1