# This is executable Markdown that's tested on CI.
# How is that possible? See https://gist.github.com/bwoods/1c25cb7723a06a076c2152a2781d4d49
set -o errexit -o nounset -o xtrace
alias ~~~=":<<'~~~sh'";:<<'~~~sh'
This repo includes:
- 🧱 Latest version of Bazel and dependencies
- 📦 Curated bazelrc flags via [bazelrc-preset.bzl]
- 🧰 Developer environment setup with [bazel_env.bzl]
- 🎨
clang-formatandclang-tidy, using rules_lint - ✅ Pre-commit hooks for automatic linting and formatting
Note
You can customize languages and features with the interactive wizard in the aspect init command.
init is an alternative to this starter repo, which was generated using the 'cpp' preset.
See https://docs.aspect.build/cli/overview
First, we recommend you setup a Bazel-based developer environment with direnv.
- install https://direnv.net/docs/installation.html
- run
direnv allowand follow the prompts tobazel run //tools:bazel_env
This isn't strictly required, but the commands which follow assume that needed tools are on the PATH,
so skipping direnv means you're responsible for installing them yourself.
To start with, let's get the simplest possible program to execute.
Lets create an application that prints “hello world” to the standard out:
mkdir src
>src/hello.c cat <<EOF
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello world!");
return 0;
}
EOFNext run the BUILD file generator to produce a cc_binary target:
bazel run gazelleYou can now run the program to see the output.
bazel run src:helloMany libraries already have BUILD files in the Bazel Central Registry (BCR).
For example, we can search for the libmagic, and find that it’s there:
https://registry.bazel.build/modules/libmagic
To install it, just add to MODULE.bazel
echo 'bazel_dep(name = "libmagic", version = "5.46.bcr.4")' >> MODULE.bazelLet's add another program src/magic.c that depends on libmagic:
>src/magic.c cat <<EOF
#include <stdio.h>
#include <stdlib.h>
#include <magic.h>
int main(int argc, char *argv[]) {
// Check if filename is provided
if (argc != (int)2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
// Initialize magic handle
magic_t magic = magic_open(MAGIC_MIME_TYPE);
if (magic == NULL) {
fprintf(stderr, "Failed to initialize libmagic\n");
return 1;
}
// Load magic database
if (magic_load(magic, NULL) != 0) {
fprintf(stderr, "Cannot load magic database: %s\n", magic_error(magic));
magic_close(magic);
return 1;
}
// Get MIME type
const char *mime_type = magic_file(magic, argv[1]);
if (mime_type == NULL) {
fprintf(stderr, "Error determining MIME type: %s\n", magic_error(magic));
magic_close(magic);
return 1;
}
// Print result
printf("MIME type: %s\n", mime_type);
// Cleanup
magic_close(magic);
return 0;
}
EOFNow re-generate the BUILD file:
bazel run gazelleIf we run the program now, we find that it fails with
Cannot load magic database: Size of '/usr/share/file/magic.mgc' 7273344 is not a multiple of 432
this is because it has a runtime dependency on locating a file it expects to be part of the operating system
distribution.
We can set the 'MAGIC' environment variable to a Bazel-managed path instead:
buildozer 'add data @libmagic//:magic.mgc' src:magic
buildozer 'dict_set env MAGIC:"$(rootpath\ @libmagic//:magic.mgc)"' src:magicNow running the program produces expected output:
output=$(bazel run src:magic $PWD/BUILD)
[ "$output" = "MIME type: text/plain" ] || {
echo >&2 "Wanted output 'MIME type: text/plain' but got '${output}'"
exit 1
}FIXME(alexeagle): aspect-build/rules_lint#703 for cpp aspect lint