cpkg

A simple project management tool

About

With existing solutions, project/dependency management is extremely complex in C and C++ projects.

The most versatile solution is generally a CMake project whereas the most configurable is generally a Python script.

To achieve the best qualities of both, with a minimalist approach, cpkg uses Lua and Ninja to allow for a custom, yet simple and powerful build script.

Installation

Download

You can download the latest release of cpkg from the official GitHub repository.

CMake

cpkg is built using CMake. Just run cmake . and then cmake -B build -S . to build the project.

Support for Windows 11 and Linux. Requires C23/C++23.

Windows users may require a Microsoft Visual C++ Redistributable package. Linux users may need to update glibc.

Lua is embedded in cpkg. However, build tools binaries (including Ninja) must be present in the PATH environment variable in order for cpkg to work.

Lua

Quick reference

Variables

  • projectDir — The project directory
  • outputDir — The build directory (default: ./build)
  • config — The configuration to use (default: debug)
  • platform — The user's operating system

Functions

  • file_exists(string path) — Returns true/false if a file exists
  • dir_exists(string path) — Returns true/false if a path exists and is a directory
  • is_dir(string path) — Returns true/false if a path is a directory
  • add_dependency(string name, string version, string[] libPaths, string[] includeDirs, string cFlags, string cxxFlags, string ldFlags) — Adds an external dependency
  • add_project(string name, string version, string[] sourceFiles, string[] includeDirs, string[] libDirs, string[] dependencies, string cFlags, string cxxFlags, string ldFlags, string outputDir, string buildType, string compiler, string cFlagsExport, string cxxFlagsExport, string ldFlagsExport) — Adds a project
  • build() — Generates build.ninja and calls Ninja
  • find_source_files(string path) — Gets a list of all the source files in a directory
  • find_module_files(string path) — Gets a list of all the module files in a directory
  • find_header_files(string path) — Gets a list of all the header files in a directory
  • cmake() — Call CMake (INOP)
  • http_get(string url) — Return content from HTTP GET request
  • download(string url, string fileName) — Download content from HTTP GET request
  • read_file(string path) — Returns the content of a file
  • run_command(string cmd, string[] args) — Runs a shell command

It is important to note that these are C++ exported functions. Mismatched types will cause exceptions.

Example cpkg.lua file

-- Quick Reference:
-- > projectDir: The directory of the project file
-- > outputDir: The directory to output the build files to
-- > config: The configuration to build for

-- Project settings
local projectName = "myProject"
local version = "1.0.0"

-- Project files
local sourceFiles = find_source_files(projectDir .. "/src")
local includeDirs = find_header_files(projectDir .. "/include")
local cFlags = ""
local ldFlags = ""

-- Debug config
function debug()
    add_project(
        projectName,                  -- Name
        "1.0.0",                      -- Version
        sourceFiles,                  -- Source files (Lua array -> std::vector)
        includeDirs,                  -- Include directories (Lua array -> std::vector)
        {},                           -- Library directories (Lua array -> std::vector)
        {},                           -- Dependencies (Lua array -> std::vector)
        cFlags, cFlags, ldFlags,      -- (C,CXX,LD) Flags
        outputDir,                    -- Output directory
        "executable",                 -- Build type
        "gcc",                        -- Compiler
        "", "", ""                    -- (C,CXX,LD) Export Flags
    )

    build()
end

if config == "debug" then
    debug()
else
    print('To do: add more configs')
end
                    

Online Lua files

The thing that makes cpkg unique is that you can pretty easily run external scripts. Here's an example:

-- Download an online test file
if not file_exists("test.lua") then
    download('https://raw.githubusercontent.com/tyqualters/voidtools/refs/heads/master/scripts/example_file.lua', 'test.lua')
end

-- Load the test file and run it
local test, err = load(read_file('test.lua'))
if test then
    test()
else
    print(err)
end
                    

Commit to the community. Publish a script that can download, configure, build and import a package automatically.
This feature was intentionally added to allow for cross-platform pseudo-package management without limitations.

Just be cautious! Always review Lua files before you run them!

License

The core cpkg project is licensed MIT.

Please check individual files as they may have differing licenses. (Ex. src/ninja_syntax.cpp and src/ninja_syntax.hpp both licensed Apache-2.0)

For dependency (vendor) licenses, see their respective LICENSE, COPYING, NOTICE, or README files.