orchideous

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: BSD-3-Clause Imports: 16 Imported by: 0

README

Orchideous

CI Standard License

Zero-configuration build tool for C and C++ projects.

Have you ever had a single main.cpp file that you just want to compile, without having to make sure the order of flags are correct and ideally without having to provide any flags at all?

Orchideous (or oh for short) handles compiler detection, flag ordering, library discovery via pkg-config, testing, formatting, cross-compilation, etc., without a single configuration file.

It should be possible to compile all of the examples in the examples directory, simply by running oh in each directory, as long as the right packages and libraries have been installed.

This is a Go port of xyproto/cxx (which does approximately the same, but uses Python + Scons instead).

Quick Start

oh              # build the project
oh run          # build and run
oh clean        # remove built files

No configuration files are needed, but the project needs to either be very simple (a single main.cpp) or have an oh-friendly directory structure.

The auto-detection of external libraries and headers relies on them being included in the main source file.

Badge

If you like, you can add this shield to your project to indicate that it can be compiled without any particular build-related configuration:

Compiles with Orchideous

Just make sure that it builds with oh first, then add this to your README.md:

[![Compiles with Orchideous](https://img.shields.io/badge/Compiles_with-Orchideous-2fc298)](https://github.com/xyproto/orchideous)

It is also possible to add it to the list of projects that compiles with Orchideous.

Installation

Arch Linux

git clone https://github.com/xyproto/orchideous
cd orchideous
make
sudo make install

Other Linux distros, FreeBSD, NetBSD, macOS

git clone https://github.com/xyproto/orchideous
cd orchideous
make
sudo make install    # use gmake on BSD

Windows (MSYS2)

git clone https://github.com/xyproto/orchideous
cd orchideous
make
make install

Or with go install:

go install github.com/xyproto/orchideous/cmd/oh@latest
sudo ln -sf ~/go/bin/oh /usr/local/bin/oh

All Commands

oh                  build the project
oh run              build and run
oh debug            debug build and launch debugger (gdb/cgdb)
oh debugbuild       debug build (without launching debugger)
oh debugnosan       debug build (without sanitizers)
oh opt              optimized build
oh strict           build with strict warning flags
oh sloppy           build with sloppy flags
oh small            build a smaller executable
oh tiny             build a tiny executable (+ sstrip/upx)
oh clang            build using clang++
oh clangdebug       debug build using clang++ (launches lldb)
oh clangstrict      use clang++ and strict flags
oh clangsloppy      use clang++ and sloppy flags
oh clangrebuild     clean and build with clang++
oh clangtest        build and run tests with clang++
oh clean            remove built files
oh fastclean        only remove executable and *.o
oh rebuild          clean and build
oh test             build and run tests
oh testbuild        build tests (without running)
oh rec              profile-guided optimization (build, run, rebuild)
oh fmt              format source code with clang-format
oh generate         generate CMakeLists.txt
oh cmake            build with cmake (generates CMakeLists.txt if needed, prefers ninja)
oh ninja            build with ninja (falls back to cmake+ninja)
oh ninja_install    install from ninja build
oh ninja_clean      clean ninja build
oh make             build with make (falls back to cmake+make)
oh make_install     install from cmake+make build
oh make_clean       clean cmake+make build
oh pro              generate QtCreator project file
oh install          install the project (PREFIX, DESTDIR)
oh pkg              package the project into pkg/
oh export           export a standalone Makefile and build.sh
oh script           generate build.sh and clean.sh
oh valgrind         build and profile with valgrind
oh win64            cross-compile for 64-bit Windows
oh smallwin64       small win64 build
oh tinywin64        tiny win64 build
oh zap              build using zapcc++
oh version          show version
oh -C <dir> ...     run in the given directory

Example Use

Create a main.cpp file:

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <ostream>
#include <string>

using namespace std::string_literals;

class Point {
public:
    double x;
    double y;
    double z;
};

std::ostream& operator<<(std::ostream& output, const Point& p)
{
    using std::setfill;
    using std::setw;
    output << "{ "s << setfill(' ') << setw(3) << p.x << ", "s << setfill(' ') << setw(3) << p.y
           << ", "s << setfill(' ') << setw(3) << p.z << " }"s;
    return output;
}

Point operator+(const Point& a, const Point& b)
{
    return Point { .x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z };
}

Point operator*(const Point& a, const Point& b)
{
    return Point { .x = a.x * b.x, .y = a.y * b.y, .z = a.z * b.z };
}

int main(int argc, char** argv)
{
    Point p1 { .x = 1, .y = 2, .z = 3 };
    Point p2 { .y = 42 };

    using std::cout;
    using std::endl;

    cout << "     p1 = " << p1 << endl;
    cout << "     p2 = " << p2 << endl;
    cout << "p1 + p2 = " << p1 + p2 << endl;
    cout << "p1 * p2 = " << p1 * p2 << endl;

    return EXIT_SUCCESS;
}

Then build and run:

oh run

Rebuild from scratch:

oh rebuild

Build with profile-guided optimization:

oh rec    # builds, runs (collecting profiling data), then rebuilds with PGO
oh        # subsequent builds use the profiling data

Directory Structure

myproject/
├── main.cpp              # main source (or main.cc, main.c)
├── include/              # project headers (.h, .hpp)
│   └── hello.h
├── common/               # shared source files
│   ├── hello.cpp
│   └── hello_test.cpp    # test file (must contain main())
├── img/                  # images
├── shaders/              # shaders
├── data/                 # data files
├── share/                # shared data files (or shared/)
└── scripts/              # script files
  • The main source file can live in the project root or src/.
  • The executable name matches the parent directory name.
  • Files ending with _test.* are compiled separately by oh test.
  • include/ and common/ can also be at ../include and ../common.

Defines

These defines are passed to the compiler, with paths that work both during development and after installation:

Define Development Installed
DATADIR ./data or ../data $PREFIX/share/$app/data
IMGDIR ./img or ../img $PREFIX/share/$app/img
SHADERDIR ./shaders or ../shaders $PREFIX/share/$app/shaders
SHAREDIR ./share or ../share $PREFIX/share/$app
RESOURCEDIR ./resources or ../resources $PREFIX/share/$app/resources
RESDIR ./res or ../res $PREFIX/share/$app/res
SCRIPTDIR ./scripts or ../scripts $PREFIX/share/$app/scripts

See examples/sdl2, examples/win64crate (uses IMGDIR) and examples/mixer (uses RESOURCEDIR).

Testing

  • Source files can have corresponding _test files (e.g. quaternions.ccquaternions_test.cc).
  • Each _test.* file must contain its own main function.
  • Run with oh test.

Library Auto-Detection

Orchideous auto-detects libraries from #include directives in your source files using pkg-config. Supported libraries include:

  • Graphics: OpenGL, GLUT, GLFW, GLEW, GLM, Vulkan, SDL (2 & 3), SFML (2 & 3), raylib
  • GUI: GTK (2, 3 & 4), Qt6, VTE
  • Audio: OpenAL, SDL2_mixer, PipeWire, rtaudio
  • Other: Boost, libconfig++, FastCGI, ReactPhysics3D, Gio/GLib, X11

For versioned libraries, the newest available version is preferred (e.g. GTK 4 over GTK 3, SFML 3 over SFML 2).

When a build fails due to a missing header, Orchideous will suggest which package to install (using pkgfile on Arch Linux or apt-file on Debian/Ubuntu).

Examples

Over 40 examples are included in the examples/ directory:

Category Examples
Basics hello, args, lambda, defer, invoke, visit, async, designated, entities, validorder, findfiles, platforms, config
Graphics sfml, sfml_audio, bisqwit, sdl2, sdl2_opengl, gl4_spirv, gles2_glfw, gles3_glfw, gles3_sdl2, raylib, raylib5, vulkan, vulkan_glfw, x11, x11_opengl, smallpt
GUI gtk4, gtk4ui, dunnetgtk, qt6
Audio openal, synth, mixer, pipewire, rtaudio
Other boost, boost_thread, notify, reactphysics, fastcgi, tinyhello, win64crate

Build all examples:

make examples

Packaging

Install to a package directory:

DESTDIR="$pkgdir" PREFIX=/usr oh install

Or package into a local pkg/ directory:

oh pkg

Generate standalone build files for users without oh:

oh export    # generates Makefile + build.sh + clean.sh

Cross-Compilation

Build for 64-bit Windows (requires x86_64-w64-mingw32-g++ or Docker):

oh win64
oh smallwin64
oh tinywin64

Test Windows executables with Wine:

oh run    # after oh win64, uses wine automatically

Source Code Formatting

oh fmt    # formats source code using clang-format (Webkit style)

The formatting style is fixed and not configurable, on purpose.

Requirements

  • g++ with C++23 support (or later)
  • pkg-config
  • make (for the project Makefile, not for building C++ projects)

Optional

  • clang++ — build with oh clang
  • lldb or gdb — for debugging
  • pkgfile (Arch Linux) or apt-file (Debian/Ubuntu) — for missing-package suggestions
  • x86_64-w64-mingw32-g++ or docker — for Windows cross-compilation
  • wine — for testing Windows executables
  • valgrind — for profiling (oh valgrind)
  • clang-format — for oh fmt
  • ninja — for oh ninja / oh cmake ninja

Arch Linux (all examples)

sudo pacman -S --needed base-devel boost fcgi freeglut glew glfw glibmm glm glu \
  gtk4 libconfig libpipewire libx11 openal qt6-base raylib reactphysics3d \
  rtaudio sdl2-compat sdl2_mixer sfml vte4 vulkan-headers vulkan-icd-loader

Debian / Ubuntu (all examples)

sudo apt-get install -y build-essential pkg-config \
  libboost-all-dev libconfig++-dev libfcgi-dev libglew-dev libglfw3-dev \
  libglibmm-2.4-dev libglm-dev libglu1-mesa-dev libgtk-4-dev libopenal-dev \
  libpipewire-0.3-dev libsdl2-dev libsdl2-mixer-dev libsfml-dev \
  libvte-2.91-gtk4-dev libvulkan-dev libx11-dev freeglut3-dev qt6-base-dev

Note: raylib and reactphysics3d are not available in Ubuntu repositories. Ubuntu 24.04 ships SFML 2 and rtaudio 5, while the included examples use SFML 3 and rtaudio 6 APIs — those examples will be skipped on Ubuntu. Examples that depend on unavailable libraries are automatically skipped in CI.

Platform Notes

macOS

Install a recent GCC and dependencies with Homebrew:

brew install gcc pkg-config

FreeBSD / NetBSD

Use gmake instead of make. Install dependencies:

# FreeBSD
pkg install pkgconf gmake

# NetBSD
pkgin install pkgconf gmake

OpenBSD

Install g++ 11+ and build with oh CXX=eg++.

Windows

Windows is supported via two development environments:

MSYS2 (recommended): Install MSYS2, then use pacman to install libraries:

pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-SDL2   # example: install SDL2

Orchideous auto-detects the MSYS2 environment via the MSYSTEM variable and uses pacman for package resolution, similar to Arch Linux.

vcpkg: Install vcpkg and set VCPKG_ROOT or add vcpkg to your PATH:

vcpkg install sdl2   # example: install SDL2

Orchideous uses vcpkg's pkg-config files and installed tree for library resolution. The default triplet is x64-windows (override with VCPKG_DEFAULT_TRIPLET).

In both cases, a GCC or Clang compiler must be available on PATH.

Features and Limitations

  • No configuration files needed — follows the directory structure conventions above.
  • Auto-detection of compiler flags, includes and libraries via pkg-config and platform-specific package managers.
  • Incremental compilation — only recompiles changed source files.
  • Profile-guided optimizationoh rec collects profiling data, subsequent builds use it.
  • Built-in support for testing, debugging, cross-compilation, and code generation.
  • Meant for building executables, not libraries.
  • Generated CMakeLists.txt is specific to the system it was generated on.

General Info

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ProgName = "oh"
	ProgURL  = "https://github.com/xyproto/orchideous"
)
View Source
var SourceExts = []string{".cpp", ".cc", ".cxx", ".c"}

SourceExts are the recognized C/C++ source file extensions.

Functions

func CompileSources

func CompileSources(srcs []string, output string, flags BuildFlags) error

func DoBuild

func DoBuild(opts BuildOptions) error

func DoCMakeBuild added in v1.0.7

func DoCMakeBuild(opts BuildOptions) error

func DoExport

func DoExport() error

func DoGenerate added in v1.0.7

func DoGenerate(opts BuildOptions) error

func DoGenerateMakefile added in v1.0.7

func DoGenerateMakefile() error

func DoInstall

func DoInstall() error

func DoMake added in v1.0.7

func DoMake() error

func DoNinja

func DoNinja() error

func DoNinjaClean

func DoNinjaClean()

func DoNinjaInstall

func DoNinjaInstall() error

func DoPkg

func DoPkg() error

func DoPro

func DoPro(opts BuildOptions) error

func DoScript

func DoScript() error

func DotSlash

func DotSlash(name string) string

func ExecutableName

func ExecutableName() string

func GetMainSourceFile added in v1.0.2

func GetMainSourceFile(testSrcs []string) string

GetMainSourceFile finds the main C/C++ source file in the current directory.

func GetTestSources

func GetTestSources() []string

Types

type BuildFlags

type BuildFlags struct {
	Compiler       string
	Std            string
	CFlags         []string
	LDFlags        []string
	Defines        []string
	IncPaths       []string
	ContainerImage string // if set, compile via "docker run" or "podman run" with this image
}

BuildFlags holds the assembled compiler and linker flags.

func AssembleFlags

func AssembleFlags(proj Project, opts BuildOptions) BuildFlags

type BuildOptions

type BuildOptions struct {
	InstallPrefix   string // If set, override dir defines with install paths
	Debug           bool
	Opt             bool
	Strict          bool
	Sloppy          bool
	Small           bool
	Tiny            bool
	Clang           bool
	Zap             bool
	Win64           bool
	NoSanitizers    bool
	ProfileGenerate bool
	ProfileUse      bool
}

BuildOptions holds the configuration for a build.

type BuildResult

type BuildResult struct {
	OutputExecutable string   // name of the produced executable (relative to sourceDir)
	Output           []byte   // combined compiler output (stdout+stderr)
	CommandsRun      []string // shell-style command strings that were executed
}

BuildResult contains the results of a build operation.

func Build

func Build(sourceDir string, opts BuildOptions) (BuildResult, error)

Build compiles the C/C++ project in the given directory. It detects sources, dependencies, and required flags automatically. The sourceDir is the directory containing the source files.

type Config added in v1.0.7

type Config struct {
	BuildOptions
	SourceDir string // if set, operate in this directory instead of the current one
}

Config holds the full configuration for an orchideous operation.

func ClangConfig added in v1.0.7

func ClangConfig() *Config

ClangConfig returns a Config that uses clang/clang++.

func DebugConfig added in v1.0.7

func DebugConfig() *Config

DebugConfig returns a Config for debug builds with sanitizers.

func DebugNoSanConfig added in v1.0.7

func DebugNoSanConfig() *Config

DebugNoSanConfig returns a Config for debug builds without sanitizers.

func NewConfig added in v1.0.7

func NewConfig() *Config

NewConfig returns a Config with default settings (standard build).

func OptConfig added in v1.0.7

func OptConfig() *Config

OptConfig returns a Config for optimized builds (-Ofast/-O3, -flto).

func SloppyConfig added in v1.0.7

func SloppyConfig() *Config

SloppyConfig returns a Config with permissive compilation flags.

func SmallConfig added in v1.0.7

func SmallConfig() *Config

SmallConfig returns a Config for size-optimized builds (-Os).

func SmallWin64Config added in v1.0.7

func SmallWin64Config() *Config

SmallWin64Config returns a Config for size-optimized Windows cross-compilation.

func StrictConfig added in v1.0.7

func StrictConfig() *Config

StrictConfig returns a Config with strict warning flags.

func TinyConfig added in v1.0.7

func TinyConfig() *Config

TinyConfig returns a Config for minimal-size builds (-Os + sstrip/upx).

func TinyWin64Config added in v1.0.7

func TinyWin64Config() *Config

TinyWin64Config returns a Config for minimal-size Windows cross-compilation.

func Win64Config added in v1.0.7

func Win64Config() *Config

Win64Config returns a Config for cross-compiling to 64-bit Windows.

func ZapConfig added in v1.0.7

func ZapConfig() *Config

ZapConfig returns a Config that uses zapcc++.

func (*Config) Build added in v1.0.7

func (c *Config) Build() error

Build compiles the project using the configured options.

func (*Config) CMakeBuild added in v1.0.7

func (c *Config) CMakeBuild() error

CMakeBuild builds using cmake, preferring ninja over make. Generates CMakeLists.txt first if it does not exist.

func (*Config) CMakeMakeClean added in v1.0.7

func (c *Config) CMakeMakeClean()

CMakeMakeClean removes the cmake+make build directory.

func (*Config) CMakeMakeInstall added in v1.0.7

func (c *Config) CMakeMakeInstall() error

CMakeMakeInstall installs from a cmake+make build.

func (*Config) Clean added in v1.0.7

func (c *Config) Clean()

Clean removes all build artifacts: runs make clean, ninja clean, removes the build/ directory, and cleans object files and executables.

func (*Config) Export added in v1.0.7

func (c *Config) Export() error

Export generates a standalone Makefile, build.sh, and clean.sh.

func (*Config) FastClean added in v1.0.7

func (c *Config) FastClean()

FastClean removes only the executable and object files.

func (*Config) Fmt added in v1.0.7

func (c *Config) Fmt() error

Fmt formats source code using clang-format.

func (*Config) Generate added in v1.0.7

func (c *Config) Generate() error

Generate generates a CMakeLists.txt file.

func (*Config) GenerateMakefile added in v1.0.7

func (c *Config) GenerateMakefile() error

GenerateMakefile generates a standalone Makefile.

func (*Config) Install added in v1.0.7

func (c *Config) Install() error

Install builds and installs the project (using PREFIX and DESTDIR environment variables).

func (*Config) LaunchDebugger added in v1.0.7

func (c *Config) LaunchDebugger() error

LaunchDebugger builds a debug version and launches the appropriate debugger. Uses lldb first when Clang is set, otherwise prefers cgdb/gdb.

func (*Config) Make added in v1.0.7

func (c *Config) Make() error

Make builds using make. If a Makefile exists, runs make directly. Otherwise falls back to cmake+make if CMakeLists.txt exists.

func (*Config) Ninja added in v1.0.7

func (c *Config) Ninja() error

Ninja builds using ninja. If build/build.ninja exists, runs ninja directly. Otherwise falls back to cmake+ninja if CMakeLists.txt exists.

func (*Config) NinjaClean added in v1.0.7

func (c *Config) NinjaClean()

NinjaClean removes the ninja build directory.

func (*Config) NinjaInstall added in v1.0.7

func (c *Config) NinjaInstall() error

NinjaInstall installs from a ninja build.

func (*Config) Pkg added in v1.0.7

func (c *Config) Pkg() error

Pkg packages the project into a pkg/ directory.

func (*Config) Pro added in v1.0.7

func (c *Config) Pro() error

Pro generates a QtCreator .pro project file.

func (*Config) Rebuild added in v1.0.7

func (c *Config) Rebuild() error

Rebuild cleans and then builds the project.

func (*Config) Rec added in v1.0.7

func (c *Config) Rec(args ...string) error

Rec performs profile-guided optimization: clean, build with profiling, run, rebuild with profile data.

func (*Config) Run added in v1.0.7

func (c *Config) Run(args ...string) error

Run builds the project and runs the resulting executable.

func (*Config) Script added in v1.0.7

func (c *Config) Script() error

Script generates build.sh and clean.sh scripts.

func (*Config) Test added in v1.0.7

func (c *Config) Test() error

Test builds and runs all test files.

func (*Config) TestBuild added in v1.0.7

func (c *Config) TestBuild() error

TestBuild builds the main executable and all test files without running them.

func (*Config) TinyBuild added in v1.0.7

func (c *Config) TinyBuild() error

TinyBuild builds with the configured options and applies sstrip/upx post-processing.

func (*Config) Valgrind added in v1.0.7

func (c *Config) Valgrind() error

Valgrind builds the project and profiles it with valgrind/callgrind.

type Project

type Project struct {
	MainSource    string
	DepSources    []string
	TestSources   []string
	Includes      []string // external includes from source files
	BoostLibs     []string
	IsC           bool // true if main source is a .c file
	HasOpenMP     bool
	HasBoost      bool
	HasQt6        bool
	HasMathLib    bool
	HasFS         bool
	HasThreads    bool
	HasWin64      bool // detected from #include <windows.h>
	HasGLFWVulkan bool // detected from #define GLFW_INCLUDE_VULKAN
	HasDlopen     bool // detected from #include <dlfcn.h>
}

Project holds all detected project information.

func DetectProject

func DetectProject() Project

Directories

Path Synopsis
cmd
oh command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL