C Container Collection (CCC)
Loading...
Searching...
No Matches
Building and Installation

Currently, this library utilizes some features that many compilers support such as gcc, clang, and AppleClang, but support is not ready for Windows. The C Container Collection supports freestanding environments.

Core Versus Specialized Containers

By default the C Container Collection offers a cohesive set of robust containers. However, some users may have niche runtime or space requirements. Therefore, there is a ccc-specialized-[VERSION].zip release available on the releases page. Obtaining either will not affect these build instructions. If the specialized/ directories are found, their files will be compiled. If they are absent, they are ignored. However, if you wish to force only compilation of the core library when all specialized/ directories are present, use the following CMake cache variable.

On the command line.

cmake --preset=clang-release -DCCC_BUILD_SPECIALIZED=0

As a CMake cache variable.

"cacheVariables": {
"CCC_BUILD_SPECIALIZED": "OFF"
}

This will likely not affect users as much as developers but the instruction is provided for completeness.

Fetch Content Install

This approach will allow CMake to build the collection from source as part of your project. The collection does not have external dependencies, besides the standard library, so this may be viable for you. This is helpful if you want the ability to build the library in release or debug mode along with your project and possibly step through it with a debugger during a debug build. If you would rather link to the release build library file see the next section for the manual install.

To avoid including tests, samples, and other extraneous files when fetching content download a release.

include(FetchContent)
FetchContent_Declare(
ccc
URL https://github.com/SkeletOSS/ccc/releases/download/v[MAJOR.MINOR.PATCH]/ccc-v[MAJOR.MINOR.PATCH].zip
SYSTEM # Optional flag to mark ccc as a system library and silence compiler and tooling warnings.
)
FetchContent_MakeAvailable(ccc)
# Include this line if you want to ignore compiler warnings from the ccc library when compiling your project.
target_compile_options(ccc PRIVATE "-w")

To link against the library in the project use the ccc namespace.

add_executable(main main.c)
target_link_libraries(main ccc::ccc)

Here is a concrete example with an arbitrary release that is likely out of date. Replace this version with the newest version on the releases page.

include(FetchContent)
FetchContent_Declare(
ccc
URL https://github.com/SkeletOSS/ccc/releases/download/v0.72.0/ccc-v0.72.0.zip
URL_HASH SHA256=9965d8ea2115a40ee7711b07f10ae15b1628825151b233b9cb95f5407425ab74
SYSTEM # Optional flag to mark ccc as a system library and silence compiler and tooling warnings.
)
FetchContent_MakeAvailable(ccc)
# Include this line if you want to ignore compiler warnings from the ccc library when compiling your project.
target_compile_options(ccc PRIVATE "-w")
add_executable(main main.c)
target_link_libraries(main ccc::ccc)

Now, the C Container Collection is part of your project build, allowing you to configure as you see fit. For a more traditional approach read the manual install section below.

Main Edge Installation

If you wish to track the bleeding edge of the collection, you can track the main release archive. GitHub maintains a zip file of the repository by default at https://github.com/SkeletOSS/ccc/archive/refs/heads/main.zip. This archive file respects the current .gitattributes file, producing a clean repository snapshot free of unnecessary files, similar to release archives. Change the FetchContent_Declare command as follows.

FetchContent_Declare(
ccc
URL https://github.com/SkeletOSS/ccc/archive/refs/heads/main.zip
SYSTEM
)

Keep in mind a few points about what you are opting in to if you take this approach.

  • The main edge includes all specialized containers.
  • Updating the URL is never required. Every time you rebuild your project you get the latest version of the library.
  • The API may break. You are exposed to naming and interface changes before a release finalizes such changes.
  • The main branch is continuously validated by CI with tests, sanitizers, and static analysis. All tests and checks must pass before merging into main so this URL should provide code that can always build and run.

Use this method if you don't care about versioning and want the latest changes. Prefer this method for consuming the library over fetching or cloning the main branch; cloning the main branch directly will download many unneeded files and folders from the repository.

Freestanding Environments

The C Container Collection uses the following functions or macros that must be supported by the user on freestanding targets.

Traditionally included via <string.h>:

  • memcpy()
  • memmove()
  • memset()
  • memcmp()

Traditionally included via <assert.h>:

  • assert()

To provide these functions, the user may create a header. For example, my_ccc_configuration.h.

my_project/
my_ccc_configuration/
my_ccc_configuration.h

In this header the user has two options: provide the listed functions directly or include their versions of the headers that provide the needed functionality. It is common for freestanding environments to provide their own <string.h> and <assert.h> that implement these functions.

#ifndef MY_CCC_CONFIGURATION_H
#define MY_CCC_CONFIGURATION_H
#include "lib/assert.h" /* IWYU pragma: export */
#include "lib/string.h" /* IWYU pragma: export */
#endif /* MY_CCC_CONFIGURATION_H */

The Include What You Use (IWYU) comment is helpful if you want to avoid tooling warnings in CCC code and have not marked CCC code as a system library to silence such warnings. If you are providing functions directly, this is not applicable. Then, ensure the C Container Collection can find that header.

include(FetchContent)
FetchContent_Declare(
ccc
URL https://github.com/SkeletOSS/ccc/releases/download/v0.72.0/ccc-v0.72.0.zip
URL_HASH SHA256=9965d8ea2115a40ee7711b07f10ae15b1628825151b233b9cb95f5407425ab74
SYSTEM # Optional flag to mark ccc as a system library and silence compiler and tooling warnings.
)
FetchContent_MakeAvailable(ccc)
# Include this line if you want to ignore compiler warnings from the ccc library when compiling your project.
target_compile_options(ccc PRIVATE "-w")
# New step allowing CCC to find the configuration header.
target_include_directories(ccc PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/my_ccc_configuration>
)
add_executable(freestanding freestanding.c)
target_link_libraries(freestanding ccc::ccc)

Now pass the flag to CMake at configure time via CMakePresets.json, CMakeUserPresets.json, or the command line.

"cacheVariables": {
"CCC_USER_CONFIGURATION": "my_ccc_configuration.h",
"CCC_FLAT_HASH_MAP_PORTABLE": "OFF"
}

Or they can be passed on the command line.

cmake --preset=my-preset\
-DCCC_USER_CONFIGURATION="my_ccc_configuration.h"\
-DCCC_FLAT_HASH_MAP_PORTABLE=ON

Now the C Container Collection is fully configured to be built as part of the user project in a freestanding environment.

Any other C headers that the collection uses internally, such as <stdint.h>, <stddef.h>, and <stdalign.h>, are those provided by the C23 standard on freestanding targets and do not require a user implementation.

See the flat hash map documentation for how to select the optimal Single Instruction Multiple Data or Single Register Multiple Data implementation. Even on freestanding targets, the compiler intrinsics used on x86-64 and ARM NEON platforms should be available. However, CCC_FLAT_HASH_MAP_PORTABLE is an available directive for users that need to force a portable fallback implementation when such compiler platform intrinsics are not available. See ccc/flat_hash_map.h for more.

Manual Install Quick Start

  1. Use the provided defaults.
  2. Build the library.
  3. Install the library.
  4. Include the library.

To complete steps 1-3 with one command try the following if your system supports make.

make clang-ccc [OPTIONAL/INSTALL/PATH]

Or build and install with gcc. However, a newer gcc than the default on many systems may be required. For example, I compile this library with gcc-14.2 as of the time of writing. To set up a CMakeUserPresets.json file to use a newer gcc.

make gcc-ccc [OPTIONAL/INSTALL/PATH]

This will use CMake and your default compiler to build and install the library in release mode. By default, this library does not touch your system paths and it is installed in the install/ directory of this folder. This is best for testing the library out while pointing cmake to the install location. Then, deleting the install/ folder deletes any trace of this library from your system.

Then, in your CMakeLists.txt:

find_package(ccc HINTS "~/path/to/ccc-v[VERSION]/install")

You can simply write the following command in your CMakeLists.txt.

find_package(ccc)

To do so, specify that this library shall be installed to a location CMake recognizes by default. For example, my preferred location is as follows:

make clang-ccc ~/.local

Then the installation looks like this.

~/.local
├── include
│   └── ccc
│   ├── flat_buffer.h
│   ├── flat_double_ended_priority_queue.h
│   ├── flat_hash_map.h
│   ├── doubly_linked_list.h
│   └── ...
└── lib
├── cmake
│   └── ccc
│   ├── cccConfig.cmake
│   ├── cccConfigVersion.cmake
│   ├── cccTargets.cmake
│   └── cccTargets-release.cmake
└── libccc_release.a

Now to delete the library if needed, simply find all folders and files with the *ccc* string somewhere within them and delete. You can also check the build/install_manifest.txt to confirm the locations of any files installed with this library.

Include the Library

Once CMake can find the package, link against it and include the container header.

The CMakeLists.txt file.

# Optionally use ccc as a system library so that your tooling like clang-tidy ignores ccc.
get_target_property(ccc_SOURCE_DIR ccc SOURCE_DIR)
add_executable(main main.c)
# Optionally include ccc source directory as system so that your tooling like clang-tidy ignores ccc.
target_include_directories(main SYSTEM PRIVATE ${ccc_SOURCE_DIR})
target_link_libraries(main ccc::ccc)

The C code.

The Flat Hash Map Interface.

Without Make

If your system does not support Makefiles or the make command here are the CMake commands one can run that will do the same.

# Configure the project cmake files.
# Replace this preset with your own if you'd like.
cmake --preset=clang-release -DCMAKE_INSTALL_PREFIX=[DESIRED/INSTALL/LOCATION]
cmake --build build --target install

User Presets

If you do not like the default presets, create a CMakeUserPresets.json in this folder and place your preferred configuration in that file. Here is my preferred configuration to get you started. I like to use the newest version of GCC that I have installed.

{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
"patch": 0
},
"configurePresets": [
{
"name": "my-gcc-debug",
"inherits": ["default-debug"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc-15.1"
}
},
{
"name": "my-gcc-release",
"inherits": ["default-release"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc-15.1"
}
},
{
"name": "my-clang-debug",
"inherits": ["default-debug"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang"
}
},
{
"name": "my-clang-release",
"inherits": ["default-release"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang"
}
},
{
"name": "my-sanitize-debug",
"inherits": ["gcc-sanitize-debug"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc-15.1"
}
},
{
"name": "my-sanitize-release",
"inherits": ["gcc-sanitize-release"],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc-15.1"
}
}
]
}

Then your preset can be invoked as follows:

# Your preferred preset with the same other steps as before.
cmake --preset=my-clang-release -DCMAKE_INSTALL_PREFIX=[DESIRED/INSTALL/LOCATION]
cmake --build build --target install

Generate Documentation

Documentation is available HERE. However, if you want to build the documentation locally you will need doxygen and graphviz installed. Then run:

doxygen Doxyfile

This will generate documentation in the docs folder. To view the docs in your local browser, double click the docs/doxygen/index.html file.