- how to build python with node-gyp?
- Разработка нативных расширений для Node.js
- Основы разработки нативных расширений для Node.js
- Базовые инструменты
- ▍Файл binding.gyp
- ▍Инструмент node-gyp
- ▍Инструмент node-bindings
- ▍API n-api
- ▍Инструмент node-addon-api
- Первые шаги в мире нативных расширений
- История нативных расширений для Node.js и полезные материалы
- Windows node gyp python
how to build python with node-gyp?
I’ve seen the official tutorial as well as this one showing how to build python from source and edit it with visual studio etc., but how do I build it with node-gyp to use it as a native application in node?
For example, in the tutorial, they tell you to download the source code, and then (in windows) type in that directory:
and then that builds the Visual Studio solution and python in general etc., but now how do I do that with node-gyp? In general, to include external dependencies to build with node-gyp, you just include them in the binding.gyp file. For python, I first installed 64 bit (and later 32 bit, same error as below) python to C:/Python382, then I copied that folder to my another folder in my C++ application, and set the binding.gyp file to this (to get the include and libs):
and my hello.cc file, which is the other source, simply includes Python.h . When I run this build using node-gyp build or node-gyp rebuild , it actually builds fine with no errors at all, but then when I copy over the file addon.node to my actual nodeJS server, which simply has the one line var addon = require(«./addon») , I get the following error output in CMD (however, it works fine with no errors without including Python.h in my .cc source file):
The main part seems to be:
addon.node is not a valid Win32 application.
I tried doing this with python for 64bit windows, and for 32bit windows, my system in 64 bit, my nodeJS installation is 64 bit, but I also tried it with 32 bit note; I don’t know how to fix this exactly, or if there is another way entirely to build python with node-gyp?
What steps need to be taken in windows to build python through node-gyp, to be able to use python natively with nodejs without having to resort to child-process?
Разработка нативных расширений для Node.js
В этом материале мы поговорим о важнейших концепциях разработки нативных расширений для Node.js. В частности, здесь будет рассмотрен практический пример создания такого расширения, который вполне может стать вашим первым проектом в этой области.
Основы разработки нативных расширений для Node.js
Если в двух словах рассказать о нативных расширениях для Node.js, можно отметить, что они представляют собой некую логику, реализованную на C++, которую можно вызывать из JavaScript-кода. Здесь стоит прояснить особенности работы Node.js и рассмотреть составные части этой платформы. Важно знать, что, в контексте Node.js, мы можем говорить о двух языках — JavaScript и C++. Всё это можно описать так:
- JavaScript — это язык программирования, на котором пишут проекты под Node.js.
- V8 — это движок, занятый выполнением JS-кода.
- Libuv — это библиотека, написанная на C, реализующая асинхронное выполнение кода.
Где же в этой схеме находятся нативные расширения? Рассмотрим это на примере операций для работы с диском. Доступ к дисковой подсистеме не входит в возможности JavaScript или V8. Libuv даёт возможности асинхронного выполнения кода. Однако, пользуясь Node.js, можно писать данные на диск и читать их. Именно здесь на помощь приходят нативные расширения. Модуль fs реализован средствами C++ (у него имеется доступ к диску), он даёт нам методы, вроде writeFile и readFile , которые можно вызывать из JavaScript.
Взаимодействие с нативными расширениями из JS-кода
Понимая этот механизм, мы можем сделать первые шаги в разработке нативных расширений. Но, прежде чем заняться программированием, поговорим об инструментах.
Базовые инструменты
▍Файл binding.gyp
Этот файл позволяет настраивать параметры компиляции нативных расширений. Один из важнейших моментов, которые нам надо определить, заключается в том, какие файлы будут компилироваться, и в том, как мы будем вызывать готовую библиотеку. Структура этого файла напоминает JSON, он содержит настройки цели (target) и исходников (sources) для компиляции.
▍Инструмент node-gyp
Средство node-gyp предназначено для компиляции нативных расширений. Оно реализовано на базе Node.js и доступно в npm, что позволяет скомпилировать расширение соответствующей командой. В ответ на эту команду система обнаружит файл binging.gyp , находящийся в корневой директории, и приступит к компиляции расширения.
Кроме того, node-gyp позволяет, по умолчанию, формировать релизные сборки или сборки для отладки. В результате, в зависимости от настроек, после компиляции, в папке release или debug , будет создан бинарный файл с расширением .node .
▍Инструмент node-bindings
Пакет node-bindings позволяет экспортировать нативные расширения. Он отвечает за поиск соответствующих файлов в папке build или release .
▍API n-api
N-api — это API, созданное средствами C, которое позволяет взаимодействовать с движком абстрактным способом, не зависящим от нижележащей среды исполнения. На наш взгляд, такой подход является результатом развития платформы, в ходе которого предпринимались усилия по портированию Node.js на различные архитектуры.
N-api даёт стабильность и совместимость при работе с различными версиями Node.js. Таким образом, если некое нативное расширение было скомпилировано для Node 8.1, не потребуется компилировать его снова для Node 8.6 или 9.3. Это упрощает жизнь тем, кто занимается поддержкой расширения или участвует в его разработке.
В данный момент n-api находится в экспериментальном состоянии.
▍Инструмент node-addon-api
Модуль node-addon-api даёт в распоряжение разработчика C++-реализацию n-api, которая позволят пользоваться возможностями этого языка.
Первые шаги в мире нативных расширений
Обратите внимание на то, что для этого примера использована платформа Node 9.3.
Для того, чтобы приступить к разработке нативных расширений, мы напишем классическое приложение «Hello World». Идея этого приложения позволяет реализовать его с помощью достаточно простого кода, не перегруженного дополнительной логикой, что даст нам возможность сосредоточиться на основных конструкциях, рассмотреть минимально необходимый код.
Начнём с инициализации npm, что позволит затем установить зависимости.
Теперь устанавливаем зависимости.
На данном этапе нужно создать файл на C++, содержащий логику расширения.
В этом файле имеется три важных части, которые мы рассмотрим, начиная с той, которая находится в нижней части текста.
- NODE_API_MODULE . Первый аргумент представляет собой имя нативного расширения, второй — имя функции, которая инициализирует это расширение.
- init . Это — функция, которая ответственна за инициализацию расширения. Тут мы должны экспортировать функции, которые будут вызываться из JS-кода. Для того чтобы это сделать, нужно записать имя функции в объект exports и задать саму функцию, которая будет вызываться. Функция init должна возвращать объект exports .
- sayHi . Эта функция будет выполнена при вызове нашего нативного расширения из JavaScript.
Теперь создадим файл binding.gyp , который будет содержать конфигурацию нативного расширения.
А вот как выглядит JavaScript-код, в котором подключается расширение и осуществляется работа с ним.
Теперь осталось лишь скомпилировать расширение и запустить JS-файл. Вот как это выглядит.
Компиляция и использование нативного расширения
История нативных расширений для Node.js и полезные материалы
Полагаем, полезно рассказать об истории нативных расширений, так как изучение этого вопроса позволяет исследовать большой объём полезной документации и обнаружить множество примеров. N-api пришло на смену nan. Эта аббревиатура расшифровывается как Native Abstraction for Node.js. Nan — это C++-библиотека, которая не отличается той же гибкостью, что и n-api. Она позволяет, в абстрактном виде, работать с V8, но привязана к релизу V8. В результате, в новых релизах Node.js могут присутствовать изменения V8, которые способны нарушить работу нативных расширений. Решение этой проблемы — одна из причин появления n-api.
Знание о существовании nan позволяет нам исследовать соответствующие примеры и документацию. Всё это может стать полезным источником знаний для тех, кто изучает разработку нативных расширений для Node.js.
Вот список полезных материалов, посвящённых разработке нативных расширений для Node:
Windows node gyp python
node-gyp — Node.js native addon build tool
node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. It contains a vendored copy of the gyp-next project that was previously used by the Chromium team, extended to support the development of Node.js native addons.
Note that node-gyp is not used to build Node.js itself.
Multiple target versions of Node.js are supported (i.e. 0.8 , . 4 , 5 , 6 , etc.), regardless of what version of Node.js is actually installed on your system ( node-gyp downloads the necessary development files or headers for the target version).
- The same build commands work on any of the supported platforms
- Supports the targeting of different versions of Node.js
You can install node-gyp using npm :
Depending on your operating system, you will need to install:
- Python v3.6, v3.7, v3.8, or v3.9
- make
- A proper C/C++ compiler toolchain, like GCC
ATTENTION: If your Mac has been upgraded to macOS Catalina (10.15), please read macOS_Catalina.md.
- Python v3.6, v3.7, v3.8, or v3.9
- Xcode
- You also need to install the XCode Command Line Tools by running xcode-select —install . Alternatively, if you already have the full Xcode installed, you can find them under the menu Xcode -> Open Developer Tool -> More Developer Tools. . This step will install clang , clang++ , and make .
Install the current version of Python from the Microsoft Store package.
Install tools and configuration manually:
- Install Visual C++ Build Environment: Visual Studio Build Tools (using «Visual C++ build tools» workload) or Visual Studio 2017 Community (using the «Desktop development with C++» workload)
- Launch cmd, npm config set msvs_version 2017
If the above steps didn’t work for you, please visit Microsoft’s Node.js Guidelines for Windows for additional tips.
To target native ARM64 Node.js on Windows 10 on ARM, add the components «Visual C++ compilers and libraries for ARM64» and «Visual C++ ATL for ARM64».
Configuring Python Dependency
node-gyp requires that you have installed a compatible version of Python, one of: v3.6, v3.7, v3.8, or v3.9. If you have multiple Python versions installed, you can identify which Python version node-gyp should use in one of the following ways:
- by setting the —python command-line option, e.g.:
- If node-gyp is called by way of npm , and you have multiple versions of Python installed, then you can set npm ‘s ‘python’ config key to the appropriate value:
If the PYTHON environment variable is set to the path of a Python executable, then that version will be used, if it is a compatible version.
If the NODE_GYP_FORCE_PYTHON environment variable is set to the path of a Python executable, it will be used instead of any of the other configured or builtin Python search paths. If it’s not a compatible version, no further searching will be done.
To compile your native addon, first go to its root directory:
The next step is to generate the appropriate project build files for the current platform. Use configure for that:
Auto-detection fails for Visual C++ Build Tools 2015, so —msvs_version=2015 needs to be added (not needed when run by npm as configured above):
Note: The configure step looks for a binding.gyp file in the current directory to process. See below for instructions on creating a binding.gyp file.
Now you will have either a Makefile (on Unix platforms) or a vcxproj file (on Windows) in the build/ directory. Next, invoke the build command:
Now you have your compiled .node bindings file! The compiled bindings end up in build/Debug/ or build/Release/ , depending on the build mode. At this point, you can require the .node file with Node.js and run your tests!
Note: To create a Debug build of the bindings file, pass the —debug (or -d ) switch when running either the configure , build or rebuild commands.
The binding.gyp file
A binding.gyp file describes the configuration to build your module, in a JSON-like format. This file gets placed in the root of your package, alongside package.json .
A barebones gyp file appropriate for building a Node.js addon could look like:
Some additional resources for Node.js native addons and writing gyp configuration files:
node-gyp responds to the following commands:
Command | Description |
---|---|
help | Shows the help dialog |
build | Invokes make / msbuild.exe and builds the native addon |
clean | Removes the build directory if it exists |
configure | Generates project build files for the current platform |
rebuild | Runs clean , configure and build all in a row |
install | Installs Node.js header files for the given version |
list | Lists the currently installed Node.js header versions |
remove | Removes the Node.js header files for the given version |
node-gyp accepts the following command options:
Command | Description |
---|---|
-j n , —jobs n | Run make in parallel. The value max will use all available CPU cores |
—target=v6.2.1 | Node.js version to build for (default is process.version ) |
—silly , —loglevel=silly | Log all progress to console |
—verbose , —loglevel=verbose | Log most progress to console |
—silent , —loglevel=silent | Don’t log anything to console |
debug , —debug | Make Debug build (default is Release ) |
—release , —no-debug | Make Release build |
-C $dir , —directory=$dir | Run command in different directory |
—make=$make | Override make command (e.g. gmake ) |
—thin=yes | Enable thin static libraries |
—arch=$arch | Set target architecture (e.g. ia32) |
—tarball=$path | Get headers from a local tarball |
—devdir=$path | SDK download directory (default is OS cache directory) |
—ensure | Don’t reinstall headers if already present |
—dist-url=$url | Download header tarball from custom URL |
—proxy=$url | Set HTTP(S) proxy for downloading header tarball |
—noproxy=$urls | Set urls to ignore proxies when downloading header tarball |
—cafile=$cafile | Override default CA chain (to download tarball) |
—nodedir=$path | Set the path to the node source code |
—python=$path | Set path to the Python binary |
—msvs_version=$version | Set Visual Studio version (Windows only) |
—solution=$solution | Set Visual Studio Solution version (Windows only) |
Use the form npm_config_OPTION_NAME for any of the command options listed above (dashes in option names should be replaced by underscores).
For example, to set devdir equal to /tmp/.gyp , you would:
Run this on Unix:
Or this on Windows:
Use the form OPTION_NAME for any of the command options listed above.
For example, to set devdir equal to /tmp/.gyp , you would run:
Note: Configuration set via npm will only be used when node-gyp is run via npm , not when node-gyp is run directly.
node-gyp is available under the MIT license. See the LICENSE file for details.