Emeralds
Emeralds
A module/package manager for C applications.
Installation
Homebrew
brew install Oblivious-Oblivious/tap/emeralds
One-line install
curl -fsSL https://raw.githubusercontent.com/Oblivious-Oblivious/Emeralds/v0.12.4/scripts/get.sh | sh
Windows with scoop.sh.
scoop install https://raw.githubusercontent.com/Oblivious-Oblivious/homebrew-tap/master/emeralds.json
From source
Requires Crystal and Shards. Clone the repo first.
*nix
rm -rf bin
shards build --release --no-debug
cp bin/emeralds bin/em
cp bin/em bin/emeralds /usr/local/bin/
Windows
if exist bin rmdir /s /q bin
shards.exe build --release --no-debug
copy /Y bin\emeralds.exe bin\em.exe
copy /Y bin\em.exe C:\msys64\ucrt64\bin\
copy /Y bin\emeralds.exe C:\msys64\ucrt64\bin\
Usage
em help
Emeralds - Help/Usage
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
emeralds/em [<command>]
Commands:
add [<name>] - Add a new .c/.h file pair
remove [<name>] - Remove a .c/.h file pair
build [app | lib] [debug | release] - Build the application in the `export` directory.
run - Run the compiled application.
clean - Run the clean script
help - Print this help message.
init [<name>] - Initialize a new library with an em.json file.
install [ | dev | all | git <link>] - Install dependencies into a flattened libs directory.
reinstall - Reinstall dependencies into a flattened libs directory.
uninstall [<name>] - Remove a dependency from em.json and libs.
list - List dependencies and project modules.
makefile - Generate a makefile for independent compilation
loc - Count the significant lines of code in the project
lint - Lint all project sources with clang-format.
test - Run the script of tests.
version - Print the current version of the emerald.
update - Update emeralds to the newest released version.
license - Update the license notice based on the em.json value.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
To start a new project:
em init YourApp
Emeralds - Initializing a new project
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Creating directory: YourApp
⚙ Writing initial files:
➔ em.json
➔ .git
➔ spec
➔ get_value
➔ get_value.module.spec.h
➔ YourApp.spec.c
➔ src
➔ get_value
➔ get_value.c
➔ get_value.h
➔ YourApp.h
➔ YourApp.c
➔ .clangd
➔ .clang-format
➔ .gitignore
➔ LICENSE
➔ README.md
➔ AGENTS.md
➔ CLAUDE.md -> AGENTS.md
➔ .cursorrules -> AGENTS.md
➔ GEMINI.md -> AGENTS.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.761 seconds
Add a new module, a .c/.h pair plus its test spec:
em add one
Emeralds - Adding new .c/.h pair...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ one
➔ one.c
➔ one/one.h
➔ YourApp.h
➔ one.module.spec.h
➔ YourApp.spec.c
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.001 seconds
This creates src/one/one.c, src/one/one.h, and spec/one/one.module.spec.h, then wires the module into spec/YourApp.spec.c by adding its #include and a T_one(); call to cspec_run_suite.
Remove a module, deleting its source, header, and spec:
em remove one
Emeralds - Removing .c/.h pair...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ one
➔ one.c
➔ one/one.h
➔ YourApp.h
➔ one.module.spec.h
➔ YourApp.spec.c
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.001 seconds
This deletes src/one/ and spec/one/, then strips the module's #include and T_one(); call from spec/YourApp.spec.c.
Manage dependencies, navigate into your project and list dependencies:
cd YourApp
em list
Emeralds - Em libraries used:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Dependencies:
⚙ cSpec
Modules:
⚙ get_value
➔ 1 dependency
➔ 1 module
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.001 seconds
Install dependencies:
em install all
Emeralds - Resolving all dependencies...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Installing `cSpec`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 3.822 seconds
Add and install a dependency from a git link:
em install git https://github.com/Oblivious-Oblivious/cSpec
This appends "https://github.com/Oblivious-Oblivious/cSpec": "latest" to em.json. You can pin versions by changing the value from latest to a release tag (such as 0.1.0).
Uninstall a dependency:
em uninstall cSpec
Emeralds - Uninstalling dependency...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Removed `cSpec` from em.json
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.001 seconds
This removes the named entry from both dependencies and dev-dependencies in em.json and deletes the corresponding libs/<name> directory.
Edit configuration json file:
cat em.json
{
"$schema": "https://raw.githubusercontent.com/Oblivious-Oblivious/Emeralds/master/schema/em.schema.json",
"author": "",
"name": "YourApp",
"version": "0.0.1",
"license": "mit",
"locignore": {
"extensions": [],
"directories": ["libs"]
},
"lintignore": {
"extensions": [],
"directories": ["libs"]
},
"scripts": {},
"compile-flags": {
"darwin": {
"cc": "clang",
"debug": {
"opt": "-O2",
"version": "-std=c89",
"flags": "-g -fsanitize=address",
"warnings": "-Wall -Wextra -Werror -pedantic -pedantic-errors -Wpedantic",
"libs": ""
},
"release": {
"opt": "-O2",
"version": "-std=c89",
"flags": "",
"warnings": "",
"libs": ""
}
},
"linux": {
"cc": "gcc",
"debug": {
"opt": "-Og",
"version": "-std=c89",
"flags": "-g",
"warnings": "-Wall -Wextra -Werror -pedantic -pedantic-errors -Wpedantic",
"libs": ""
},
"release": {
"opt": "-O2",
"version": "-std=c89",
"flags": "",
"warnings": "",
"libs": ""
}
},
"win32": {
"cc": "gcc",
"debug": {
"opt": "-O2",
"version": "-std=c89",
"flags": "-g",
"warnings": "-Wall -Wextra -Werror -pedantic -pedantic-errors -Wpedantic",
"libs": ""
},
"release": {
"opt": "-O2",
"version": "-std=c89",
"flags": "",
"warnings": "",
"libs": ""
}
}
},
"dependencies": {},
"dev-dependencies": {
"https://github.com/Oblivious-Oblivious/cSpec": "latest"
}
}
- author: The name of the author/creator of the project.
- name: The name of your application or library.
- version: The version number displayed with
em version. - license: The project's license. This should be a valid SPDX license identifier.
- Available license types:
mit,gpl-v2,apache-v2,gpl-v3,lgpl-v3,mpl-v2,epl-v2,agpl-v3,cc0-v1,cc0-v4
- Available license types:
- scripts: Custom commands runnable with
em <script>. Script names can override built-in commands. Values can be a string command or an array of command lines.
"scripts": {
"build": [
"mkdir -p export",
"clang -O2 -o export/YourApp src/YourApp.c"
]
}
- locignore: Extensions and project-relative directories ignored by
em loc. - lintignore: Extensions and project-relative directories ignored by
em lint. - compile-flags: The set of compiler flags.
- Platform keys can use Crystal-supported operating system flags (e.g.,
win32,linux,darwin,unix). - cc: The C compiler to use for that platform.
- debug: Debug build flags for that platform.
- release: Release build flags for that platform.
- opt: Optimization level (e.g., -Og, -O0).
- version: The C standard to use (e.g., -std=c89, -std=c11).
- flags: Additional compiler flags (e.g., -g -fsanitize=address).
- warnings: Warning flags to enable (e.g., -Wall -Wextra).
- libs Additional linked static or shared libraries.
- Platform keys can use Crystal-supported operating system flags (e.g.,
- dependencies: A table of dependencies required for the project to run. The key is the full git link to a repository and the value is the version:
latestfor the master branch, or a release tag (0.3.2) to fetch that specific archive. - dev-dependencies: A table of development dependencies not linked with the release version.
Testing your application and run the test suite:
em test
Emeralds - Running tests...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ rm -rf spec/spec_results
➔ clang -Og -std=c2x -g -fsanitize=address -Wall -Wextra -Werror -pedantic -pedantic-errors -Wpedantic -o spec/spec_results src/get_value/get_value.c spec/YourApp.spec.c
➔ ./spec/spec_results
/######## ########/
/##### cSpec #####/
/######## ########/
Module `T_get_value`
`#get_value`
✓ it returns `Hello, World!`
● 1 tests
✓ 1 passing
✗ 0 failing
- 0 skipped
★ Finished in 0.00487 ms
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 4.039 seconds
Build your application:
em build app release
Emeralds - Compiling as an app...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ clang -O2 -std=c89 -o export/YourApp src/get_value/get_value.c src/YourApp.c
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.424 seconds
Run the executable:
./export/YourApp
Hello, World!
Clean up project build artifacts:
em clean
Emeralds - Cleaning the library files...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ rm -rf spec/spec_results
➔ rm -rf export
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.003 seconds
Lint the project sources:
em lint
Emeralds - Linting sources...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
➔ spec/YourApp.spec.c
➔ spec/get_value/get_value.module.spec.h
➔ src/YourApp.c
➔ src/get_value/get_value.c
➔ src/get_value/get_value.h
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All done in 0.012 seconds
This runs clang-format on every file found from the project root, using the .clang-format generated by em init.
Contributing
- Fork it (https://github.com/Oblivious-Oblivious/Emeralds/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- atha - creator and maintainer
Emeralds
- 4
- 0
- 0
- 0
- 0
- about 6 hours ago
- June 22, 2020
MIT License
Thu, 04 Jun 2026 00:10:20 GMT