Cangjie stdx
Introduction
The extension library stdx is an extension module provided by the Cangjie programming language (i.e., a non-core standard library, but an official supplementary feature set). It is a key component of the language ecosystem, supplementing Cangjie with more practical capabilities covering multiple domains, including aspect-oriented programming, compression and decompression, security (secure encryption capabilities/message digest algorithms/Asymmetric encryption and decryption and signature algorithms/digital certificate processing functions), encoding and decoding (base64/hex/json/url), networking (http/tls), logging, syntax parsing, unit test extensions, concurrent programming model, non-local control operation and serialization.
Architecture Diagram:

- actors: Provides a concurrent programming model designed to simplify the handling of concurrent tasks.
- aspect_cj: Provides annotations related to aspect-oriented programming in Cangjie.
- compress: Provides compression and decompression functions.
- crypto: Provides a utility library for cryptographic operations.
- effect: Provides a powerful non-local control operation.
- encoding: Provides a basic utility library for data encoding and decoding.
- fuzz: Provides an automated software testing method.
- log: Provides a single logging API.
- logger: Provides log printing functions in text format and JSON format.
- net: Provides network communication and secure transmission functions.
- serialization: Provides the capability of serialization and deserialization.
- string_intern: Provides polled caching capability for string objects.
- syntax: Provides Cangjie source code syntax parsing functions.
- unittest: Provides the capability to supply test data in serialized input formats when writing unit test code for Cangjie projects.
Operating Instructions
For APIs related to stdx, please refer to API Interface Description. For relevant guidance, please refer to Development Guide.
Quick Start
This repository provides convenient scripts to quickly download and extract binary artifacts for a specific version.
Linux/macOS
This requires curl and unzip. Please ensure these tools are installed in your environment.
Execute directly in your command line (note the arguments at the end, modify as needed):
bash -c "$(curl -fsSL https://raw.gitcode.com/Cangjie/cangjie_stdx/raw/main/downloader.sh)" -- 1.0.0.1
Windows
Before running the script, you may need to adjust the PowerShell execution policy (only needs to be done once).
Please open PowerShell as an administrator and run the following command:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Then, run the script in a regular PowerShell window (note the arguments at the end, modify as needed):
irm https://raw.gitcode.com/Cangjie/cangjie_stdx/raw/main/downloader.ps1 -OutFile "$env:TEMP\downloader.ps1"; & "$env:TEMP\downloader.ps1" 1.0.0.1
Parameters
<version>: Required. Specifies the version to download, e.g.,1.0.0.1.-p <platform-arch>: Optional. Specifies the platform and architecture. If omitted, the script will auto-detect the current system.-d <extract-dir>: Optional. Specifies the target path for extraction. If omitted, it defaults to the current directory.
Usage Examples:
# On Linux/macOS, download the ohos-aarch64 version of v1.0.0.1 and extract it to the ./cangjie_libs directory
bash -c "$(curl -fsSL https://raw.gitcode.com/Cangjie/cangjie_stdx/raw/main/downloader.sh)" -- 1.0.0.1 -p ohos-aarch64 -d ./cangjie_libs
# On Windows, download the windows-x64 version of v1.0.0.1 and extract it to the C:\cangjie_libs directory
irm https://raw.gitcode.com/Cangjie/cangjie_stdx/raw/main/downloader.ps1 -OutFile "$env:TEMP\downloader.ps1"; & "$env:TEMP\downloader.ps1" 1.0.0.1 -p windows-x64 -d C:\cangjie_libs
Supported <platform-arch>
The following platform and architecture combinations are currently supported:
linux-aarch64linux-x64mac-aarch64mac-x64ohos-aarch64ohos-x64windows-x64
Project Directory
/stdx
├─ build # Directory of Engineering Construction
├─ doc # Directory of stdx library document
├─ figures # architecture pictures
├─ src # Directory of stdx package codes
│ └─ stdx
│ ├── actors # Provides Actors
│ ├── aspect_cj # Provides AOP
│ ├── compress # Provides compression and decompression
│ ├── crypto # Provide security related capabilities
│ ├── effect # Provides user-level APIs for handling the Effect Handler feature. This is an experimental feature and requires the use of a Cangjie compiler that supports this mechanism.
│ ├── dynamicLoader # OpenSSL dynamic loading module
│ ├── encoding # Provide JSON and string encoding related capabilities
│ ├── fuzz # Provides the Cangjie fuzz engine based on coverage feedback
│ ├── log # Provides logging related
│ ├── logger # Provides log printing functions in text format and JSON format
│ ├── net # Provide network communication and other capabilities
│ ├── serialization # Provides serialization and deserialization
│ ├── string_intern # Provides polled caching capability for string objects
│ ├── syntax # Provides syntax parsing functions
│ └── unittest # Provides unit testing extension
│
├─ third_party # Directory of third-party components
└─ target # Directory of constructed products
Constraints
Support for building stdx in Ubuntu/macOS (x86_64, aarch64), Cangjie SDK 1.0.0 and above versions, please refer to the Build Dependency Tools.
Note: Future versions of this extension library may contain incompatible changes, and cross-version backward compatibility is not guaranteed. Please fully assess the version adaptation risks before use.
Compilation and Building
Build Steps
Configure Cangjie SDK
Configure the Cangjie SDK environment:
source <cangjie sdk path>
Execute the following command to verify whether the installation is successful:
cjc -v
Prepare source code
Download the source code
git clone https://gitcode.com/Cangjie/cangjie_stdx.git
Build Command
Method 1
Enter the project directory, and run the following commands:
python3 build.py clean
python3 build.py build -t release --target-lib=<absolute path of openssl lib>
python3 build.py install
-
build.py cleancommand is used to clear temporary files in the workspace. -
build.py buildcommand starts the compilation:-tor--build-type,specifies the type of build artifact, which can be eitherreleaseordebug--target-libspecifies the openssl lib directory
-
build.py installcommand installs the build artifacts to thetargetdirectory.
If the compilation is successful, a product directory named target by default will be obtained in the project directory.
For more information, please take a look at the build.py or use --help
Method 2
Currently, stdx (main branch) also supports building via cjpm, and the build command is as follows:
cjpm build
For detailed usage of cjpm, refer to cjpm Documentation
Building via cjpm has some dependencies, see dependency list.
Currently, the stdx binary packages built via cjpm do not include aspect_cj and syntax, and there are no fuzz packages on the Windows platform.
Integration Build Guide
For integration building, please refer to the Cangjie SDK Integration Build Guide.
Instructions for use
Import stdx
stdx provides two types of binaries: static and dynamic. Both are used independently and developers can reference them according to actual conditions.
Add the following configuration to the cjpm.toml file of the code project:
[target.x86_64-w64-mingw32] # System architecture and OS information
[target.x86_64-w64-mingw32.bin-dependencies]
path-option = ["D:\\cangjiestdx\\windows_x86_64_cjnative\\stdx\\dynamic\\stdx"] # The stdx path is configured according to the actual situation
explain:
-
x86_64-w64-mingw32:This configuration item indicates the operating system architecture information of the machine where the code is compiled. This information can be obtained by executing
cjc -v. Developers should configure according to the actual situation. For example, the output of executingcjc -vis as follows, and the configuration isx86_64-w64-mingw32.Cangjie Compiler: 0.59.4 (cjnative) Target: x86_64-w64-mingw32 -
x86_64-w64-mingw32.bin-dependencies:Please replace x86_64-w64-mingw32 in the configuration with the actual operating system information.
-
path-option:
stdxThe path where the binary is located.
illustrate:
cjpm.tomlis the configuration file of the Cangjie package management tool CJPM. For details, please refer to the Cangjie Programming Language Tool User Guide.- The configuration method is the same for Windows, Linux, and macOS.
- On macOS, using stdx may trigger a popup warning about unknown source or inability to detect malware. After extracting stdx, you can run
xattr -dr com.apple.quarantine <stdx extraction path> &> /dev/null || truein the terminal to remove the quarantine attribute. For example:xattr -dr com.apple.quarantine ~/Downloads/darwin_x86_64_cjnative/ &> /dev/null || true- If you import the static library of
stdxand use the crypto and net packages, you need to add-lcrypt32tocompile-optiononWindows.- When using dynamic
stdxbinaries (.so/.dll), OpenSSL is resolved at runtime viadlopen/dlsym(Unix-like) orLoadLibrary/GetProcAddress(Windows); linking OpenSSL statically (.a/.lib) into the application will not be used by this runtime resolver.- On
Linux, the default staticstdxlibraries use an OpenSSL resolver inautomode: they prefer directly linked OpenSSL symbols, and fall back todlopen/dlsymonly when needed. If the fallback may be used, add-ldl.- When linking OpenSSL statically for the default
autostatic libraries,--whole-archiveis only needed if you want to forcelibssl.aandlibcrypto.ainto the final executable; otherwise the fallback path may still try to load systemlibssl/libcrypto.- For
static-static-link-extern/stdx, do not use--whole-archiveor-force_loadas the default. Place the OpenSSL archive inputs (libssl.aandlibcrypto.a) afterstdxlibraries that reference them so the linker pulls only the required objects.- In cross-compilation scenarios, if there is a need to develop custom macro packages and their business logic must rely on stdx for implementation, the stdx path for the local development platform must also be configured in addition to that for the target runtime platform.
Default static/stdx auto resolver example: after configuring the stdx static library path through cjpm.toml or your existing build command, set STATIC_OPENSSL_DIR to the directory that stores OpenSSL static libraries. The following command shows only the OpenSSL archive link options and forces the OpenSSL archives into the final executable.
export STATIC_OPENSSL_DIR=/path/to/openssl/lib
# GNU ld
cjc main.cj \
--link-option "-Bstatic" \
--link-option "--whole-archive" \
--link-option "${STATIC_OPENSSL_DIR}/libssl.a" \
--link-option "${STATIC_OPENSSL_DIR}/libcrypto.a" \
--link-option "--no-whole-archive" \
--link-option "-Bdynamic"
# Apple ld64
cjc main.cj \
--link-option "-force_load" \
--link-option "${STATIC_OPENSSL_DIR}/libssl.a" \
--link-option "-force_load" \
--link-option "${STATIC_OPENSSL_DIR}/libcrypto.a"
For static-static-link-extern/stdx, after configuring the stdx static library path through cjpm.toml or your existing build command, provide the OpenSSL archives normally. The following command shows only the OpenSSL archive link options:
export STATIC_OPENSSL_DIR=/path/to/openssl/lib
cjc main.cj \
--link-option "${STATIC_OPENSSL_DIR}/libssl.a" \
--link-option "${STATIC_OPENSSL_DIR}/libcrypto.a"
Installed Binary Layout
The following uses the installed stdx on Linux/cjnative as an example to illustrate its binary layout.
dynamic/stdx: dynamic libraries and related runtime artifactsstatic/stdx: default static libraries and FFI archivesstatic-static-link-extern/stdx: static libraries exposed for external static linking
The installed package should be documented against these output directories instead of intermediate files under build_temp.
OpenSSL Static Linking Layout
For Linux/cjnative, the installed static package layout distinguishes two OpenSSL-linking behaviors by directory:
static/stdx: the default static-library directorystatic-static-link-extern/stdx: the directory for external static linking
Key differences:
- Libraries from
static/stdxmay fall back to runtime OpenSSL loading when necessary. - Libraries from
static-static-link-extern/stdxdo not usedlopen/dlsymfallback and do not depend on system OpenSSL discovery at runtime. - When using
static-static-link-extern/stdx, the final application link step must provide the requiredlibssl.aandlibcrypto.a. - If the linked OpenSSL archive is missing required symbols, the build fails at final link time instead of falling back at runtime.
Version reminder:
stdxexpects an OpenSSL 3.x dependency set. If the OpenSSL version is too low, required symbols may be missing and the build or runtime may fail.- Do not mix different OpenSSL major versions across compile, link, and runtime stages. For example, compiling against OpenSSL 3 headers but linking or loading OpenSSL 1.1 can lead to missing symbols, ABI mismatch, or undefined behavior.
- When using
static-static-link-extern/stdx, make surelibssl.aandlibcrypto.acome from the same OpenSSL build and version. - When using
dynamic/stdxor libraries fromstatic/stdx, make sure the runtime-loadedlibsslandlibcryptofiles are from the same OpenSSL version family.
Suggested handling:
- If the OpenSSL version is too low, upgrade to a complete OpenSSL 3.x release first, then rebuild or relink the application.
- If compile-time headers, link-time archives, and runtime dynamic libraries are not from the same version family, replace them with artifacts from one consistent OpenSSL installation.
- If you use
static-static-link-extern/stdx, clean the old link inputs and relink with one matching pair oflibssl.aandlibcrypto.a. - When using
static-static-link-extern/stdx, the final link step must provide the OpenSSL symbols required by thestdxstatic libraries that participate in linking. - If you use a trimmed OpenSSL archive with
static-static-link-extern/stdxand the final link reports missing OpenSSL symbols, it means the currentstdxlink set still requires those symbols. Add back the corresponding real implementations inlibssl.aorlibcrypto.a. - Do not decide trimming only from the application's direct OpenSSL usage. Also check whether the linked
stdxstatic libraries still reference additional OpenSSL symbols. - Do not use hand-written empty implementations to bypass these link errors. An empty implementation may satisfy the linker, but it does not provide correct runtime behavior and may cause leaks, state corruption, functional errors, or security problems.
- If you use
dynamic/stdxorstatic/stdx, remove conflicting oldlibsslandlibcryptofiles from the runtime search path and keep only the intended OpenSSL 3.x library set visible to the loader. - If you encounter missing-symbol errors, first verify the exact library files that are being linked or loaded, then check whether they all come from the same OpenSSL version and architecture.
Typical OpenSSL-related libraries affected by this distinction include:
libstdx.crypto.digest.alibstdx.crypto.keys.alibstdx.crypto.crypto.alibstdx.crypto.x509.alibstdx.net.tls.a
Use static-static-link-extern/stdx when you want an explicit static-link contract with OpenSSL and do not want runtime fallback behavior. In this mode, OpenSSL archive location is controlled by the application's existing link flags such as -L and link-option.
Configuration example:Assuming the development environment is Windows x86_64 and importing the dynamic binary of stdx, the cjpm.toml configuration example is as follows:
[dependencies]
[package]
cjc-version = "0.59.4"
compile-option = ""
description = "nothing here"
link-option = ""
name = "test"
output-type = "executable"
override-compile-option = ""
src-dir = ""
target-dir = ""
version = "1.0.0"
package-configuration = {}
[target.x86_64-w64-mingw32] # System architecture and OS information
[target.x86_64-w64-mingw32.bin-dependencies]
path-option = ["D:\\cangjiestdx\\windows_x86_64_cjnative\\stdx\\dynamic\\stdx"] # The stdx path is configured according to the actual situation
Using stdx
In the Cangjie source code file that needs to use stdx, import the corresponding package provided by stdx through import, and then call the API provided by the package. The import format is:
import stdx.fullPackageName.itemName
fullPackageName is the package name given in package list, itemName is the name of a visible declaration or definition, * means importing all visible top-level declarations or definitions, for example:
- import stdx.net.http.ServerBuilder:Import the top-level declaration of ServerBuilder in the net.http package of the stdx module.
- import stdx.net.http.* :Import the net.http package of the stdx module.
- import stdx.log.* :Import the log package from the stdx module.
Usage Examples
Assuming that the developer is developing on Linux and wants to import the static binary of stdx, the cjpm.toml configuration reference is as follows:
[dependencies]
[package]
cjc-version = "0.59.4"
compile-option = "-ldl"
description = "nothing here"
link-option = ""
name = "test"
output-type = "executable"
src-dir = ""
target-dir = ""
version = "1.0.0"
package-configuration = {}
[target.x86_64-unknown-linux-gnu]
[target.x86_64-unknown-linux-gnu.bin-dependencies]
path-option = ["/target/linux_x86_64_cjnative/static/stdx"] # stdx path is configured according to actual situation
Write code: Create an HTTP service using the net.http package.
package test
import stdx.net.http.ServerBuilder
main () {
// 1. Build a Server instance
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.build()
// 2. Register HttpRequestHandler
server.distributor.register("/index", {httpContext =>
httpContext.responseBuilder.body("Hello 仓颉!")
})
// 3. Start the service
server.serve()
}
Configure stdx source dependencies
In addition to integrating stdx binaries, stdx currently supports source code dependency. For detailed usage, see see Source Code Integration Guidance
License
Please see LICENSE for more information.
Contribution Guidelines
Developers are welcome to make contributions in any form, including but not limited to code, documentation, and issues.