| name | cangjie-cjpm |
| description | Provides guidance on Cangjie's Project Manager (cjpm), dependency management, configuration files (cjpm.toml), workspaces, and build/test commands. Invoke when the user asks about adding dependencies, compiling projects, configuring cjpm.toml, resolving circular dependencies, or workspace setups. |
| modeSlugs | ["cangjie"] |
Cangjie Project Manager (cjpm) Guide
cjpm (Cangjie Project Manager) is the official project management, build system, and package manager for the Cangjie programming language. It is analogous to Cargo for Rust or npm for Node.js.
Common CLI Commands
cjpm init: Initialize a new project.
--name <value>: Specify root package name (default is folder name).
--path <value>: Specify project initialize path.
--type=<executable|static|dynamic>: Generate specified type of library instead of executable.
--workspace: Create a workspace cjpm.toml.
cjpm build: Compiles the current module.
-V or --verbose: Show detailed compilation logs (traces the cjc commands invoked).
-g: Emit debug compilation outputs.
-i / --incremental: Enable module-level incremental compilation.
-j / --jobs <N>: Specify parallel compilation concurrency.
--coverage: Generate coverage information.
cjpm run: Builds and runs an executable project.
-- [args]: Passes arguments to the executable. Example: cjpm run -- a b c
-g: Emit and run the debug compilation outputs.
cjpm test: Compiles and runs unit tests (*_test.cj files).
--coverage: Generate coverage information.
--filter=*MyClassTest.*: Run tests that match a filter.
--include-tags=Unittest: Run tests by Tag (uses the @Tag macro in code).
cjpm bench: Compiles and runs benchmark tests annotated with @Bench.
cjpm clean: Cleans up the target build directory.
cjpm check: Checks project dependencies and validates the build order.
cjpm tree: Visualizes the dependency tree.
--depth <N>: Specify maximum depth of dependency tree.
--invert [pkg_name]: View what depends on a specific package.
cjpm update: Updates cjpm.lock to lock dependency versions based on cjpm.toml.
cjpm install: Installs the compiled executable project to a specified path (~/.cjpm by default).
--path <value>: Install a local project module.
--git <url>: Install from a git repository.
cjpm uninstall: Uninstalls a previously installed Cangjie project.
Note on Circular Dependencies: If cjpm build throws a cyclic dependency error, you must resolve the circular import tree by removing redundant imports, refactoring shared code into a common package, or using the combine-all-deps = true feature where applicable.
cjpm.toml Configuration File
The cjpm.toml file stores project metadata and dependencies.
1. [package] Section
Used for single-module repositories. Cannot coexist with a [workspace] block in the same file.
[package]
cjc-version = "1.0.0"
name = "my_project"
version = "1.0.0"
description = "A description"
output-type = "executable"
compile-option = "-O2"
override-compile-option = ""
link-option = ""
src-dir = "src"
target-dir = "target"
2. [dependencies] Section
Dependencies can be linked locally or fetched from a Git repository.
[dependencies]
utils = { path = "../utils" }
lib_dynamic = { path = "../dynamic_lib", output-type = "dynamic" }
net_tools = { git = "https://gitee.com/cangjie/net_tools", branch = "dev" }
crypto = { git = "https://github.com/cangjie/crypto", tag = "v1.0" }
3. Other Dependencies Sections
[test-dependencies]: Dependencies only available to tests (*_test.cj). Will not be bundled in the production build.
[script-dependencies]: Dependencies specifically used for the build script (build.cj), if your project has one.
[replace]: Used to override an indirect dependency globally. Identical schema to dependencies. Only valid in the root cjpm.toml.
Example [replace]:
[dependencies]
libA = { path = "./libA" }
[replace]
libB = { path = "./patched_libB" }
4. [ffi.c] Section (C Language Interop)
Used to embed configurations for C code interoperability. Instructs cjpm where to search for external C libraries.
[ffi.c]
clib = { path = "./native_libs" }
In Cangjie, you will need to annotate external C functions with @Foreign[C].
5. [workspace] Section
Workspaces allow multiple modules to share the same dependencies and settings. A cjpm.toml with [workspace] cannot contain a [package] declaration.
[workspace]
members = ["submodule1", "path/to/submodule2"]
build-members = ["submodule1"]
compile-option = "-O2"
Output Types & Combined Configurations
When creating libraries, cjpm builds packages into static .a files or dynamic .so/.dll files based on the [package.package-configuration] configurations or the combined settings.
Custom Package Configurations
You can specify output-type and compile-option for specific subpackages:
[package.package-configuration."my_project.sub_package"]
output-type = "dynamic"
compile-option = "-g"
combine-all-deps = true
Profile Builds (LTO & Combined)
The [profile] table lets you customize command defaults.
[profile.build]
lto = "full"
incremental = true
performance_analysis = true
[profile.build.combined]
demo = "dynamic"
[profile.customized-option]
cfg1 = "--cfg=\"feature1=lion, feature2=cat\""
Test/Bench Command Options in cjpm.toml
[profile.test]
parallel = true
timeout-each = "5s"
report-format = "xml"
[profile.test.env]
MY_VAR = { value = "hello_world", splice-type = "replace" }
[profile.bench]
report-format = "csv"
Multi-Target Configuration (Cross-compilation)
You can assign specific dependencies and flags for a targeted OS and architecture.
[target.x86_64-w64-mingw32.dependencies]
windows-api = { path = "./windows_wrapper" }
[target.x86_64-unknown-linux-gnu]
compile-option = "-D LINUX"
[target.x86_64-unknown-linux-gnu.bin-dependencies]
path-option = ["./libs/pro1"]
Creating Executable Outputs in Sub-Packages
It is generally recommended that the root package contains the main entry point. However, if you need to create multiple executable entry points, you can do so by explicitly labelling certain subpackages as an executable:
[package.package-configuration."demo.binary_one"]
output-type = "executable"
[package.package-configuration."demo.binary_two"]
output-type = "executable"
When building, executing tree target/release/bin will show binaries built separately for binary_one and binary_two.