Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

aydwi/barrel

Repository files navigation

Barrel (Work in progress)

barrel

[C++ wrapper for the Homebrew CLI]

GitHub Twitter

 

Barrel is a portable, header-only C++ library that provides programmatic access to the Homebrew command line interface.

It is intended to help build generic, non-trivial wrappers around Homebrew. For example, using Barrel, you could write a feature-rich GUI frontend for Homebrew on macOS. Or it could be used to develop bespoke tooling to customize/automate Homebrew-based package configuration for your CI/CD jobs. Or it could help you work with homebrew on headless systems.

tl;dr: Use Barrel whenever you want to interact with Homebrew and the shell interface just doesn't cut it.

Barrel is highly performant, with almost no runtime overhead (see benchmarks). It exposes a well documented, succinct C++ API (see reference) which can be integrated with a wide variety of libraries, tools and frameworks (see examples).

 

Quick example

#include <Barrel/barrel.h>
#include <iostream>

int main(int argc, char** argv) {
    Brew brew;
    std::cout << brew.getInstallPath();    // /usr/local/bin/brew
    std::cout << brew.getInstallVersion(); // Homebrew 3.5.4
    
    BrewCommand<BrewCommandType::Builtin> cmd(brew, BrewCommandType::Builtin::INFO);
    cmd.execute();
    std::cout << cmd.getExitStatus(); // 0
    std::cout << cmd.getStreamDump(); // 120 kegs, 75,556 files, 1.8GB
    
    return 0;
}

This is the "Hello, World!" equivalent of using Barrel. It creates a default brew object to set up Homebrew execution environment, then creates a cmd object to execute the command brew info, and finally prints the exit status and output of the executed command.

 

Features

  • Header-only; no need to build before using

  • Self contained; no external dependencies

  • Readable, modern C++ source; easy to modify if needed

  • Negligible runtime overhead

  • Powerful ways to interact with Homebrew:

    • Validate and configure your Homebrew installation
    • Chain and execute any arbitrary brew command (except those which read from stdin interactively, if any)
    • Capture exit status, and stdout, stderr, or both
    • WIP Execute long running brew commands asynchronously (with support for early binding/delayed invocation) [1]
    • WIP Live-capture/poll output stream (stdout/stderr) data from a brew command as it is being generated [2]
    • WIP Execute brew commands on multiple threads on multi-core machines

 

Elaborate example

Now let's take a look at another example which shows how a client can use some of the advanced functionality offered by Barrel.

 

Project goals and non-goals

See the Wiki

 

Requirements

Barrel is a header-only library, written in C++20. Using it can be as simple as copying the include/ directory in your project and importing the primary header like "include/barrel.h". In most cases, however, you'd want to use a build system like GNU Make/Ninja, and a build automation tool like CMake to manage building your project.

Further, you need an installation of Homebrew. Barrel does not install Homebrew for you. A brew binary must be available somewhere in your environment before using Barrel, although it is not necessary for it to be present in $PATH.

Basic requirements

Optional requirements

  • Make
  • CMake (3.15 or higher)

 

Getting started

  1. Get the source (git clone for the latest developmental version, or get a versioned release)

  2. Build Barrel

    mkdir build && cd $_

    cmake ..

    cmake --build . --target install

    These steps do the following: 1. Create and enter a build directory in the project root, 2. Configure the project and prepare a build configuration for the actual build system (Make in my case), and 3. Call Make to build Barrel (by compiling/linking however specified), executing the predefined install target to install the library. You should see an install/ directory in the project root after step 3. Since Barrel is header-only, all the sources in include/ simply get copied over to install/Barrel/include/.

Alternatively, you could download a pre-built archive.

 

Linking to Barrel

Link to Barrel from your project:

  • As an external dependency

    Say you have a project you want to include Barrel in, but you do not want to add Barrel to your project's source tree. In this case, you can include Barrel as an external dependency after building it.

    CMake find_package makes it straightforward. I have included a simple CMakeLists.txt example you can consult at examples/external/CMakeLists.txt.

  • As an internal dependency

 

Credits

 

Build and test status

CircleCI

 

Footnotes

[1] Helpful, for example, when writing a GUI wrapper where you wouldn't want to block the main (UI) thread by running some compute-heavy routine.
[2] Again, helpful when writing an interactive/real-time/GUI wrapper around Homebrew. Anecdotally, I have been using Cakebrew which distinctly lacks this functionality (as of v1.3), which motivated me to start this project in the first place. I wanted the ability to see what was going on on stdout/stderr in real-time as opposed to getting a bulk of text dumped at once after the execution was finished. I like Cakebrew, but perhaps I will write my own GUI for Homebrew at some point using Barrel and Slint.

About

[No longer in development] C++ wrapper for the Homebrew CLI

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published