A standalone tool to generate Linglong (linyaps) .uab packages from CMake projects.
The tool reads LINGLONG_* configuration variables from the project's CMakeLists.txt,
generates linglong.yaml, and then calls ll-builder build and ll-builder export
to build the Linglong package.
No host project dependencies are required; no cmake .. configuration is needed.
ll-builder build runs inside a container.
ll-builder(fromlinglong-builderpackage)libyaml-cpp0.7(YAML generation and parsing)libcli11-dev(command-line argument parsing)- CMake 3.16+, C++17 compiler
sudo apt install libyaml-cpp-dev libcli11-dev cmake linglong-buildercd linglong_cmake_pack
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
sudo cmake --build build --target installcd /path/to/your/cmake/project
# 1. Initialize linglong packaging configuration
linglong-cmake-pack init
# 2. Build the linglong package
linglong-cmake-pack packlinglong-cmake-pack init --interactivelinglong-cmake-pack init --dry-runlinglong-cmake-pack init --from-cmakelinglong-cmake-pack pack --build-only # build only, skip export
linglong-cmake-pack pack --export-only # export only, skip buildIf you prefer not to compile the C++ tool, use the shell fallback script directly:
./scripts/linglong-pack.sh /path/to/your/project| Option | Description | Default |
|---|---|---|
--template <path> |
Custom CMakeLists.txt config block template. ${VAR} placeholders are replaced with actual config values. |
Built-in template |
--interactive |
Interactive configuration mode. Prompts for each config value; press Enter to accept defaults. Writes back to CMakeLists.txt if a config block exists. | Off |
--force |
Overwrite existing config. Required when # === LINGLONG PACKAGING === already exists in CMakeLists.txt. |
Off |
--dry-run |
Preview mode. Shows what would be generated without writing any files. | Off |
--from-cmake |
Use cmake -P native path to read variables. For complex projects with conditionals, variable expansion, or generator expressions that the regex parser cannot handle. Requires cmake. |
Off |
--cmake-script <path> |
Path to the LinglongVarReader.cmake script. Defaults to the compiled-in path (LINGLONG_VAR_READER_PATH). |
Installed path |
# Basic init (reads LINGLONG_* from CMakeLists.txt)
linglong-cmake-pack init
# Interactive mode
linglong-cmake-pack init --interactive
# Dry-run (preview without writing)
linglong-cmake-pack init --dry-run
# Force overwrite existing config
linglong-cmake-pack init --force
# cmake -P native path (complex projects)
linglong-cmake-pack init --from-cmake
# Custom template
linglong-cmake-pack init --template /path/to/template.cmake
# Combined: force + dry-run
linglong-cmake-pack init --force --dry-run
# Combined: cmake -P + interactive
linglong-cmake-pack init --from-cmake --interactive| Option | Description | Default |
|---|---|---|
--build-only |
Only run ll-builder build, skip export. Use for debugging the build process. |
Off |
--export-only |
Only run ll-builder export, skip build. Requires a previous successful build. |
Off |
-o, --output <path> |
Output .uab file path. Defaults to {id}_{version}_{arch}.uab in the project directory. |
Auto-generated |
--architecture <arch> |
Override architecture detection. Available values: x86_64, arm64, loongarch64, loong64, sw64, mips64, riscv64. |
Auto-detected |
# Full build (build + export)
linglong-cmake-pack pack
# Build only, skip export
linglong-cmake-pack pack --build-only
# Export only, skip build
linglong-cmake-pack pack --export-only
# Custom output path
linglong-cmake-pack pack -o /path/to/output.uab
# Override architecture
linglong-cmake-pack pack --architecture loongarch64| Option | Description | Default |
|---|---|---|
-C, --directory <path> |
Working directory (project root). Defaults to the current directory. | . |
-v, --verbose |
Verbose output. Prints more debug information. | Off |
-h, --help |
Print help and exit. | - |
--version |
Print version and exit. | - |
# Help
linglong-cmake-pack --help
# Version
linglong-cmake-pack --version
# Specify working directory
linglong-cmake-pack -C /path/to/project init
# Verbose output
linglong-cmake-pack -v packAdd the following variables to your project's CMakeLists.txt (prefix LINGLONG_*, tool-specific semantics):
# Package ID (required)
set(LINGLONG_PACKAGE_ID "org.example.app")
# Package version (required, auto-padded to 4 parts)
set(LINGLONG_PACKAGE_VERSION "1.0.0.0")
# Base environment (required)
set(LINGLONG_BASE "org.deepin.base/23.1.0")
# Start command (required for app kind)
set(LINGLONG_COMMAND "app")
# Optional settings
set(LINGLONG_PACKAGE_NAME "app") # defaults to project() name
set(LINGLONG_PACKAGE_KIND "app") # defaults to app, can be runtime
set(LINGLONG_PACKAGE_DESCRIPTION "A demo app.") # defaults to package name
set(LINGLONG_RUNTIME "org.deepin.runtime.dtk/23.1.0")
set(LINGLONG_BUILD_DEPENDS "build-essential cmake")
set(LINGLONG_DEPENDS "libqt5widgets5")
set(LINGLONG_BUILD_COMMANDS "rm -rf build || true
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=\$PREFIX ..
make
make install
cd ..")
set(LINGLONG_ARCHITECTURE "x86_64") # defaults to auto-detection
set(LINGLONG_PACKAGE_CHANNEL "main") # defaults to main
set(LINGLONG_FILE_NAME "org.example.app_1.0.0.0_x86_64.uab")
set(LINGLONG_SOURCE_DIRECTORY "${CMAKE_SOURCE_DIR}")You can also run linglong-cmake-pack init to auto-generate the config block instead of writing it manually.
| Variable | Required | Default | Description |
|---|---|---|---|
LINGLONG_PACKAGE_ID |
Yes | - | Package ID, reverse domain notation |
LINGLONG_PACKAGE_VERSION |
Yes | - | Version, auto-padded to 4 parts |
LINGLONG_BASE |
Yes | - | Base environment, e.g. org.deepin.base/23.1.0 |
LINGLONG_COMMAND |
app kind | - | Start command |
LINGLONG_PACKAGE_NAME |
No | project() name |
Package name |
LINGLONG_PACKAGE_KIND |
No | app |
Package kind (app/runtime) |
LINGLONG_PACKAGE_DESCRIPTION |
No | Package name | Description |
LINGLONG_RUNTIME |
No | - | Runtime environment |
LINGLONG_BUILD_DEPENDS |
No | - | Build dependencies (space-separated) |
LINGLONG_DEPENDS |
No | - | Runtime dependencies (space-separated) |
LINGLONG_BUILD_COMMANDS |
No | Default cmake build | Custom build commands |
LINGLONG_ARCHITECTURE |
No | Auto-detected | Target architecture |
LINGLONG_PACKAGE_CHANNEL |
No | main |
Distribution channel |
LINGLONG_FILE_NAME |
No | Auto-generated | Output file name |
LINGLONG_SOURCE_DIRECTORY |
No | CMAKE_SOURCE_DIR |
Source directory path |
--template allows you to provide a custom CMakeLists.txt config block template instead of the built-in default.
The template file is a CMake snippet that supports ${VAR} placeholders, replaced at runtime with actual config values:
| Placeholder | Replaced With | Source |
|---|---|---|
${LINGLONG_PACKAGE_ID} |
Package ID | LINGLONG_PACKAGE_ID |
${LINGLONG_PACKAGE_NAME} |
Package name | LINGLONG_PACKAGE_NAME or project() |
${LINGLONG_PACKAGE_VERSION} |
Version | LINGLONG_PACKAGE_VERSION, auto-padded to 4 parts |
${LINGLONG_PACKAGE_KIND} |
Package kind | LINGLONG_PACKAGE_KIND or app |
${LINGLONG_PACKAGE_DESCRIPTION} |
Description | LINGLONG_PACKAGE_DESCRIPTION or package name |
${LINGLONG_COMMAND} |
Start command | LINGLONG_COMMAND or executable name |
${LINGLONG_BASE} |
Base environment | LINGLONG_BASE |
${LINGLONG_RUNTIME} |
Runtime environment | LINGLONG_RUNTIME |
${LINGLONG_ARCHITECTURE} |
Target architecture | LINGLONG_ARCHITECTURE or auto-detected |
${LINGLONG_PACKAGE_CHANNEL} |
Distribution channel | LINGLONG_PACKAGE_CHANNEL or main |
Create a file named my-template.cmake:
# === LINGLONG PACKAGING ===
# Custom template, used by linglong-cmake-pack init --template
set(LINGLONG_PACKAGE_ID "${LINGLONG_PACKAGE_ID}")
set(LINGLONG_PACKAGE_VERSION "${LINGLONG_PACKAGE_VERSION}")
set(LINGLONG_BASE "${LINGLONG_BASE}")
set(LINGLONG_COMMAND "${LINGLONG_COMMAND}")
# Optional settings — uncomment as needed
# set(LINGLONG_PACKAGE_NAME "${LINGLONG_PACKAGE_NAME}")
# set(LINGLONG_RUNTIME "${LINGLONG_RUNTIME}")
# set(LINGLONG_ARCHITECTURE "${LINGLONG_ARCHITECTURE}")
# === END LINGLONG PACKAGING ===Usage:
linglong-cmake-pack init --template /path/to/my-template.cmakeIf --template is not specified, the built-in default template (generated by generateConfigBlock()) is used.
--cmake-script specifies a CMake -P script used to read LINGLONG_* variables from CMakeLists.txt via the cmake -P native path. This is useful when the default regex parser cannot handle complex CMake syntax.
- Receives the
PROJECT_DIRCMake variable pointing to the project root directory - Reads
LINGLONG_*variables fromPROJECT_DIR/CMakeLists.txt - Outputs the variable values as JSON to stdout
{
"LINGLONG_PACKAGE_ID": "org.example.app",
"LINGLONG_PACKAGE_NAME": "MyApp",
"LINGLONG_PACKAGE_VERSION": "1.0.0.0",
"LINGLONG_PACKAGE_KIND": "app",
"LINGLONG_PACKAGE_DESCRIPTION": "My App",
"LINGLONG_COMMAND": "myapp",
"LINGLONG_BASE": "org.deepin.base/23.1.0",
"LINGLONG_RUNTIME": "org.deepin.runtime.dtk/23.1.0",
"LINGLONG_BUILD_DEPENDS": [],
"LINGLONG_DEPENDS": [],
"LINGLONG_BUILD_COMMANDS": "",
"LINGLONG_ARCHITECTURE": "x86_64",
"LINGLONG_PACKAGE_CHANNEL": "main",
"LINGLONG_FILE_NAME": "",
"LINGLONG_SOURCE_DIRECTORY": ""
}- All fields are strings
LINGLONG_BUILD_DEPENDSandLINGLONG_DEPENDSare string arrays- Missing or empty fields output an empty string
""
The built-in default script is at cmake/LinglongVarReader.cmake, which serves as a reference for custom scripts.
Usage:
# Use the default installed script (compiled-in path)
linglong-cmake-pack init --from-cmake
# Use a custom script
linglong-cmake-pack init --from-cmake --cmake-script /path/to/custom-script.cmakelinglong_cmake_pack/
├── CMakeLists.txt # Build file
├── LICENSE -> LICENSES/LGPL-3.0-or-later.txt
├── LICENSES/
│ └── LGPL-3.0-or-later.txt # LGPL-3.0 license
├── debian/ # Debian packaging
│ ├── changelog
│ ├── control
│ ├── copyright
│ ├── rules
│ ├── watch
│ └── source/
├── src/ # C++ source code
│ ├── main.cpp # Entry point, CLI parsing
│ ├── config.h # Configuration struct
│ ├── cmake_parser.cpp/.h # CMakeLists.txt regex parser
│ ├── cmake_native_parser.cpp/.h # cmake -P variable reader
│ ├── yaml_generator.cpp/.h # linglong.yaml generator
│ ├── ll_builder.cpp/.h # ll-builder wrapper
│ ├── init_command.cpp/.h # --init command
│ └── pack_command.cpp/.h # --pack command
├── cmake/
│ └── LinglongVarReader.cmake # cmake -P variable reader script
├── scripts/
│ ├── linglong-cmake-pack-completion.bash # Bash completion
│ ├── _linglong-cmake-pack # Zsh completion
│ ├── linglong-cmake-pack.fish # Fish completion
│ └── linglong-pack.sh # Zero-dependency fallback script
└── tests/ # Unit tests
├── CMakeLists.txt
├── test_config.cpp
├── test_cmake_parser.cpp
├── test_cmake_native_parser.cpp
├── test_yaml_generator.cpp
└── test_ll_builder.cpp
cd build && ctestThe regex parser (cmake_parser) only parses top-level set() calls. It does not support conditionals, variable expansion, or generator expressions. For complex projects, use linglong-cmake-pack init --from-cmake.