Amazon Developer

as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support
Skip to main content
This topic provides additional information that is useful in when creating complex Turbo Modules.

Turbo Module CMAKE helper

The kepler_add_turbo_module_library function is a CMake helper that simplifies the process of defining a Turbo Module library target for use with the React Native for Vega runtime. It handles common configuration and optimization settings required for Turbo Module libraries, streamlining the process by automatically applying the necessary settings and optimizations. This helper function provides the following benefits:
  • Simplified Configuration: Reduces boilerplate CMake code with a single function call
  • Consistent Best Practices: Makes sure that all Turbo Modules follow the same configuration patterns and provides a central place to roll out common settings in the future
  • Improved Application Binary Interface (ABI) Stability: Applies proper symbol visibility settings automatically
  • Optimized Performance: Makes sure that performance optimizations such as link-time and size optimizations are applied

Key symbol contracts for Turbo Module DSO

All Turbo Modules on Vega platforms must adhere to two critical requirements:
  1. Export EntryPoint function: The Turbo Module library must export a single symbol named autoLinkVegaTurboModulesV1. This symbol serves as the entry point that the Vega runtime uses to automatically link and load your Turbo Module.
  2. Hidden Symbol Visibility: All other symbols in the Turbo Module library should be hidden. This prevents symbol conflicts with other libraries, ensures a stable ABI, improves TurboModule loading time, and can reduce the size of the library in many cases.
The kepler_add_turbo_module_library helper automatically configures these requirements for you, eliminating the need for manual symbol visibility management.

Functionality provided

The kepler_add_turbo_module_library function provides several key features that simplify the creation of Turbo Module libraries. These features are organized into three main categories.

Shared library creation

The helper function provides support for shared libraries as follows:
  • Creates a shared library with the specified name using the standard CMake add_library command.
  • Links the turbomoduleAPI static library, which provides the C++ methods to develop Turbo Modules, and the necessary platform-level functionality, to the library.
  • Handles the proper setup of the library target, similar to what you would do manually with add_library and target_link_libraries.

Symbol visibility control

The helper function automatically configures symbol visibility to ensure ABI stability:
  • Sets default visibility to “hidden” for all symbols
  • Applies a version script that explicitly exports only the autoLinkVegaTurboModulesV1 symbol
  • Disables symbol interposition with -fno-semantic-interposition and applies local binding of global references with -Bsymbolic to prevent symbol conflicts

Performance optimizations

The helper function applies several optimizations to improve the performance and size of your Turbo Module:
  • Enables link-time optimization (LTO) for better performance and smaller binary size
  • Applies size optimizations by applying garbage collection of unused sections

Usage

To use the kepler_add_turbo_module_library function, add the following to your CMakeLists.txt.

Frequently Asked Questions

Yes. If you have an existing Turbo Module, you are strongly recommended to migrate to this helper function. The current approach of propagating optimization flags as INTERFACE flags via the turbomoduleAPI library will be removed in the future. This helper function is part of a broader strategy to provide more explicit and maintainable configuration for Turbo Modules while avoiding implicit propagation of build settings that can lead to surprising behavior.
Follow these steps to migrate:
  1. Review your current CMakeLists.txt to understand how your TurboModule is configured
  2. Make sure that you have the find_package(turbomoduleAPI CONFIG REQUIRED) line in your CMakeLists.txt
  3. Replace your add_library call and all subsequent configuration with a single kepler_add_turbo_module_library call
  4. Delete the version-script (.map file) previously used for managing the autoLinkVegaTurboModulesV1 export
  5. Test your build to ensure everything works correctly
The following examples show the CMake configuration before and after migration.

Before (manual configuration)

After (Using the helper)

The helper function automatically applies a version script that exports only the autoLinkVegaTurboModulesV1 symbol. If you’re already using a version script, remove your existing version script applications from your CMake configuration to avoid conflicts. If you need to export additional symbols beyond autoLinkVegaTurboModulesV1, you can apply another version script after calling the helper function, but ensure there’s no overlap between the symbols exported by each script. This approach should be used sparingly, as exporting additional symbols may compromise ABI stability.
You can check the generated compilation database (compile_commands.json found in build directory) to inspect the compiler and linker flags being used. The helper function enables EXPORT_COMPILE_COMMANDS ON by default, which creates this database. You can open the database with IDEs to see the exact flags applied.
The helper function already handles platform-specific behavior. If you need additional settings, you can add them after calling the helper function:

Symbol hiding

The Vega Turbo Module API (TMAPI) is a stable API that provide backwards-compatibility which guarantees that you don’t need to constantly update your Turbo Module to keep up with API changes. This stability ensures that the communication is ABI-safe, and the compiled shared libraries of your Turbo Modules are binary compatible with any version of the Vega OS. Compiled native binaries include symbols, which are named entities such as variables, functions, class, and namespaces. Occasionally, symbols in the turbomodule library may clash with symbols generated from other libraries in your app or from the OS sysroot, and this unintentional exposure of symbols may potentially lead to ABI issues. To ensure overall stability of your Turbo Modules, Amazon recommends using symbol hiding. This ensures that internal symbols from your library are hidden by default, and avoid any leaks or clashes. Hiding the internal symbols in your Turbo Module library is important for the following reasons:
  • Dynamic overriding of symbols: When internal symbols are exposed, it may be possible for symbols from different binaries to override each other depending on the order they are loaded into the process. This might lead to unintended behaviors, compatibility issues, and potential security vulnerabilities.
  • Different versions of standard C++ library: Binaries compiled with different C++ standard libraries (e.g. libstdc++ or libcpp) can introduced compatibility issues when symbols are exposed.

Hiding symbols in your TurboModule projects

To hide symbols in your Vega TurboModule projects created with Vega SDK v0.9 and before, make these changes in your sources. Starting with V0.10, the Vega templates include these improvements and symbols are hidden by default for all new projects.
  1. Add a symbol map. A symbol map file specifies the version node(s) exported symbols are labeled with, and also used to hide local symbols. Vega selectively exposes symbols from the auto-link function used to register the Turbo Module, and hide all other symbols. In the case of Turbo Module projects created with Vega templates, the function used is autoLinkVegaTurboModulesV1.
    NOTE: Read more about Symbol Versioning and symbol map files on the Symbol Versioning page of the GNU wiki.
  2. Update CMakeLists.txt to use symbol map file in cmake linker options.
    The target_link_options command applies the --version-script linker option to the tmapp target, which uses the specified symbol map file during the linking process.

Validate that the symbols are correctly hidden

To verify the effectiveness of symbol hiding, you can inspect the symbols exposed by the Turbo Module binary before and after applying the symbol hiding changes. Use the llvm-nm tool, which is already available in the Vega SDK, to view exposed symbols from your libraries.

Get the path for llvm-nm tool from kepler sdk cache folder

List symbols without the updates

Without symbol hiding, the Turbo Module binary exposes a large number of internal symbols, including those related to the implementation of the Turbo Module’s functionality.

List symbols after symbol hiding updates

After implementing symbol hiding, the Turbo Module binary only exposes the intended, stable public API symbol.

Threading

All Turbo Module methods are invoked on the JSThread. To maintain good performance, it is crucial to avoid blocking the JSThread, by using a separate non-JSThread wherever it is beneficial, such as for Promise or Callback usages. You can use a thread utility library or even std::thread directly to create and manage a separate non-JSThread for your Turbo Module, depending on your specific requirements.

Event handling

Turbo Modules can send events from C++ to JavaScript, but the @amzn/keplerscript-turbomodule-api package currently does not include support for handling these events. To listen for events, you can use NativeEventEmitter from react-native. Turbo Modules can signal events to JavaScript by using the built-in emit method, which accepts most Turbo Module C++ types as a payload. When on JSThread (i.e., no new thread was created for emitting events), you should use emitSync instead.
The JavaScript side can register to receive events using NativeEventEmitter. The following example builds on the instructions found in Implement JavaScript Layer.

Error handling

Many of the exceptions which might be encountered when running a Turbo Module are thrown into the JavaScript layer. If you have a JavaScript implementation which is wrapped over the native module, you can use a try/catch to address these errors there. Create a Turbo Module
Last modified on November 3, 2025