@dcloudio/uni-gyp
v1.0.1
Published
GYP command-line wrapper with uni-app x platform generators
Readme
@dcloudio/uni-gyp
@dcloudio/uni-gyp packages a vendored gyp-next fork as a project-local
command-line tool. It forwards GYP arguments to gyp/gyp_main.py, including
the custom Android, HarmonyOS, and iOS CMake generators included in this
package.
Requirements
- Node.js 22 or newer
- Python 3.9 or newer
- CMake 3.22 or newer and Ninja for Android and HarmonyOS builds
- macOS with Xcode for iOS builds
Python is selected in this order:
--python=/path/to/pythonUNI_GYP_PYTHONnpm_config_pythonPYTHONpython3, then the platform Python launcher
Installation
Install the package as a development dependency:
pnpm add -D @dcloudio/uni-gyp
# or
npm install --save-dev @dcloudio/uni-gypThe package manager installs the uni-gyp executable into
node_modules/.bin, so it can be used from package scripts or directly:
pnpm exec uni-gyp --version
pnpm exec uni-gyp --platform=android --depth=. binding.gypThe package entry point exposes its installation and bundled Node-API header directories for GYP files or other build tooling:
const { root_dir, include_dir } = require('@dcloudio/uni-gyp')Creating a project
Create a native uni-app x uasm plugin project from the bundled basic template:
pnpm exec uni-gyp create awesome-codec
cd awesome-codec
pnpm installThe plugin ID must use lowercase kebab-case. By default, the project is
created in a new directory named after the plugin ID. Use --directory to
select another destination, --template to select a bundled template, or
--dry-run to list the generated files without writing them:
pnpm exec uni-gyp create awesome-codec \
--directory packages/codec \
--template basicThe command refuses to overwrite an existing destination. The basic template
contains a shared binding.gyp, a minimal Node-API hello() implementation,
package scripts, and TypeScript declarations.
Generated projects put the Uasm prefix directly in the GYP target_name.
For example, uni-awesome-codec uses UasmUniAwesomeCodec as its target and
produces libUasmUniAwesomeCodec.so on Android and HarmonyOS and
UasmUniAwesomeCodec.xcframework on iOS. The uni_modules directory still
uses the plugin ID, uni-awesome-codec.
Use --template basic-and-uts when the plugin also needs Android Kotlin and
iOS Swift UTS channels. The generated channel filenames and class names use
the PascalCase plugin ID: for example, uni-awesome-codec produces
UniAwesomeCodec.kt and UniAwesomeCodec.swift. This template starts with an
add(a, b) example that adds two double-precision values across the Node-API,
JNI, and Swift C bridges.
Select the target with --platform=android, --platform=harmony, or
--platform=ios. The old GYP -f/--format option is not exposed by uni-gyp.
Platform, architecture, toolchain, build, and Python options documented here
are provided by uni-gyp; the remaining arguments use gyp-next syntax.
Multi-platform projects
Use a single binding.gyp to describe Android, HarmonyOS, and iOS builds. Put
sources and settings shared by every platform directly on the target, and use
OS == "android", OS == "harmony", or OS == "ios" conditions only for
platform-specific settings. Separate files such as android.gyp,
harmony.gyp, and ios.gyp are not required.
Each invocation builds one target platform: --platform sets OS and selects
the corresponding branch before GYP evaluates the file. Run uni-gyp separately
for each operating system that the project needs to build. On iOS,
--sdk=all builds device and Simulator variants of the iOS branch; it does not
select the Android or HarmonyOS branches.
Every target automatically searches the package's bundled include directory,
which contains the Node-API headers. Targets can continue to add
project-specific directories through their own include_dirs settings.
uni-gyp also applies its bundled Node-API export list for the selected platform when a shared-library or loadable-module target does not configure one. A project that exports additional JNI or C bridge symbols can provide its own linker flag in the platform condition:
{
'variables': {
'module-root-dir': '<!(node -p "require(\'path\').resolve(\'.\')")',
},
'conditions': [
['OS == "android"', {
'ldflags': ['-Wl,--version-script=<(module-root-dir)/android.exports'],
}],
['OS == "harmony"', {
'ldflags': ['-Wl,--version-script=<(module-root-dir)/harmony.exports'],
}],
['OS == "ios"', {
'ldflags': [
'-Wl,-exported_symbols_list,<(module-root-dir)/ios.exports',
],
}],
],
}An explicit platform export flag suppresses the corresponding bundled file; the project should therefore retain the two Node-API entry points in addition to its extra exported symbols.
To generate and build the Android branch of binding.gyp in one invocation,
provide an Android NDK and request a GYP configuration:
pnpm exec uni-gyp --platform=android --depth=. \
--ndk-path="$ANDROID_NDK_HOME" \
--arch=arm64 \
--api-level=23 \
--build=Debug \
binding.gypANDROID_NDK_HOME or ANDROID_NDK_ROOT can be used instead of --ndk-path.
When none is provided, uni-gyp searches the
SDK from ANDROID_SDK_ROOT, ANDROID_HOME, the adb executable, and the
standard Android Studio SDK locations, then selects the newest installed NDK.
It also selects the newest SDK-managed CMake from cmake/<version>/bin and its
bundled Ninja, so these tools do not need to be added to PATH.
For an SDK in a non-standard location, use --sdk-path=<path>. CMake can be
overridden independently with --cmake-path=<path>; the value may be the CMake
executable, its bin directory, or its version directory.
The architecture defaults to arm64 and the API level defaults to 23. The
arm64 value is translated to Android's native arm64-v8a ABI. Use
--arch=x64 (or the native ABI name x86_64) for a 64-bit x86 build.
A single CMake project containing all GYP configurations is generated at
build/android/CMakeLists.txt. Android build files and products are written
under build/android/<abi>/<configuration>.
HarmonyOS CMake
Use --platform=harmony to evaluate the OS == "harmony" branch in the shared
binding.gyp. The native SDK path may point to the SDK version directory, its
native directory, or the sibling toolchains directory used by DevEco
Studio:
pnpm exec uni-gyp --platform=harmony --depth=. \
--ndk-path="$OHOS_NDK_HOME" \
--arch=arm64 \
--api-level=OHOS \
--stl=c++_shared \
--build=Debug \
binding.gypHARMONY_NDK_HOME, OHOS_NDK_HOME, OHOS_SDK_NATIVE, or
HARMONY_SDK_HOME can be used instead of --ndk-path. The selected
native SDK must contain build/cmake/ohos.toolchain.cmake. The architecture
defaults to arm64, platform to OHOS, and STL to c++_shared. The arm64
value is translated to the native arm64-v8a architecture. Use
--arch=x64 (or x86_64) for a 64-bit x86 build. Generated files and
products are written under
build/harmony/<architecture>/<configuration>.
iOS CMake
Use --platform=ios to evaluate the OS == "ios" branch. In the shared
binding.gyp, a dynamic framework target can use the existing GYP bundle
fields in its iOS condition:
{
'target_name': 'example',
'type': 'shared_library',
'sources': ['include/example.h', 'src/example.cc'],
'conditions': [
['OS == "ios"', {
'mac_bundle': 1,
'mac_framework_headers': ['include/example.h'],
'xcode_settings': {
'PRODUCT_BUNDLE_IDENTIFIER': 'com.example.framework',
},
}],
],
}Generate build/ios/CMakeLists.txt, configure an Xcode project, and build an
arm64 device framework with:
pnpm exec uni-gyp --platform=ios --depth=. \
--sdk=iphoneos \
--arch=arm64 \
--deployment-target=15.0 \
--build=Release \
binding.gypUse --sdk=iphonesimulator for a Simulator build. iphoneos supports only
arm64; iphonesimulator supports arm64, x64 (or x86_64), and the
multi-architecture list arm64,x64. A multi-architecture framework can
therefore be produced only for the Simulator. --sdk defaults to iphoneos,
--arch to arm64, and --deployment-target to 15.0.
Each Xcode project contains only the requested GYP configuration and is written
to build/ios/<sdk>/<architectures>/<configuration>. Code signing is disabled
for the generated framework; the consuming application must embed and sign it.
The x64 alias is normalized to the native x86_64 name in CMake output paths
and toolchain arguments. For a single-architecture x64 Simulator build, GYP
conditions see target_arch == "x64".
Use --sdk=all to build both device and Simulator products and aggregate every
shared_library target with xcodebuild -create-xcframework. With
--arch=arm64,x64, the requested architectures are split by SDK: the device
framework uses arm64, while the Simulator framework uses arm64;x86_64.
GYP is evaluated once before this split, so this combined build does not expose
a single target_arch value to GYP conditions:
pnpm exec uni-gyp --platform=ios --depth=. \
--sdk=all \
--arch=arm64,x64 \
--build=Release \
binding.gypXCFrameworks are written to
build/ios/xcframework/<configuration>/<Product>.xcframework. Dynamic
libraries distributed for iOS must set mac_bundle: 1; this builds each device
and Simulator slice as a .framework bundle before passing both bundles to
xcodebuild -create-xcframework. Raw .dylib XCFramework slices are only
supported for dynamic linking on macOS and must not be used for iOS targets.
Packaging uni_modules
uni-gyp module-pack copies products from the standard uni-gyp build
directories into a uni_modules native module layout. It does not evaluate a
GYP file, build targets, or invoke package scripts. The caller is responsible
for completing all requested platform builds before running the command.
After building the platforms selected by the project, package every matching product with:
pnpm exec uni-gyp module-pack \
--target exampleBy default, the command discovers existing Android, HarmonyOS, and iOS products, regardless of the host operating system. Android ABIs and HarmonyOS architectures are read from matching products in the standard build directories. At least one product must exist.
Use --platform, --android-abi, or --harmony-arch to constrain discovery.
List options may be repeated or provided as comma-separated lists. Explicitly
requested platforms and architectures must exist. --configuration defaults
to Release, --build-root to build, and --module-root to uni_modules.
When a GYP target sets a product_name that differs from its target name, pass
the product name with --product-name. Use --module-name when the
uni_modules directory name differs from the GYP target name, as in the
generated project scripts.
For a lowercase name with hyphen-separated words, module-pack resolves the
product name as Uasm plus PascalCase while keeping the supplied name for the
uni_modules directory. For example, --target uni-zstd packages
libUasmUniZstd.so and UasmUniZstd.xcframework into uni_modules/uni-zstd.
Other target names are used as supplied. Pass --product-name to use an exact
product name instead of this conversion.
The build uses the GYP target_name or explicit product_name without adding
Uasm or changing case. For example, a target named example-native-module
produces libexample-native-module.so on Android and HarmonyOS and
example-native-module.xcframework on iOS. The lib prefix for Android and
HarmonyOS shared libraries remains the normal GYP behavior.
The command validates every selected source product before changing any destination. It then copies products using this mapping:
build/android/<abi>/<configuration>/lib.target/lib<Product>.so
-> uni_modules/<module-name>/uasm/app-android/libs/<abi>/lib<Product>.so
build/harmony/<arch>/<configuration>/lib.target/lib<Product>.so
-> uni_modules/<module-name>/uasm/app-harmony/libs/<arch>/lib<Product>.so
build/ios/xcframework/<configuration>/<Product>.xcframework
-> uni_modules/<module-name>/uasm/app-ios/frameworks/<Product>.xcframeworkOnly discovered or explicitly selected platforms are modified. XCFramework
destinations are replaced as complete directories so obsolete slices cannot
remain from an earlier build. Automatic discovery packages matching products
already present under build, including products left by an earlier build;
use explicit selection or clean the build directory when a workflow must
exclude stale products.
License
uni-gyp is distributed under the BSD-3-Clause license. It includes code from
gyp-next and other third-party projects; their copyright and license notices
are retained in the package. See LICENSE and THIRD_PARTY_NOTICES.md.
