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, and more — all 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).
oh # build the project
oh run # build and run
oh clean # remove built filesNo 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.
git clone https://github.com/xyproto/orchideous
cd orchideous
make
sudo make installgit clone https://github.com/xyproto/orchideous
cd orchideous
make
sudo make install # use gmake on BSDgit clone https://github.com/xyproto/orchideous
cd orchideous
make
make installOr with go install:
go install github.com/xyproto/orchideous/cmd/oh@latest
sudo ln -sf ~/go/bin/oh /usr/local/bin/ohoh 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 cmake generate CMakeLists.txt
oh cmake ninja generate CMakeLists.txt and build with ninja
oh ninja build using existing CMakeLists.txt and ninja
oh ninja_install install from ninja build
oh ninja_clean clean ninja 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 make generate a standalone Makefile
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
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 runRebuild from scratch:
oh rebuildBuild with profile-guided optimization:
oh rec # builds, runs (collecting profiling data), then rebuilds with PGO
oh # subsequent builds use the profiling datamyproject/
├── 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 byoh test. include/andcommon/can also be at../includeand../common.
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).
- Source files can have corresponding
_testfiles (e.g.quaternions.cc→quaternions_test.cc). - Each
_test.*file must contain its ownmainfunction. - Run with
oh test.
Orchideous auto-detects libraries from #include directives in your source files using pkg-config. Supported libraries include:
- Graphics: OpenGL, GLUT, GLFW, GLEW, GLM, Vulkan, SDL2, 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).
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 examplesInstall to a package directory:
DESTDIR="$pkgdir" PREFIX=/usr oh installOr package into a local pkg/ directory:
oh pkgGenerate standalone build files for users without oh:
oh export # generates Makefile + build.sh + clean.shBuild for 64-bit Windows (requires x86_64-w64-mingw32-g++ or Docker):
oh win64
oh smallwin64
oh tinywin64Test Windows executables with Wine:
oh run # after oh win64, uses wine automaticallyoh fmt # formats source code using clang-format (Webkit style)The formatting style is fixed and not configurable, on purpose.
g++with C++23 support (or later)pkg-configmake(for the project Makefile, not for building C++ projects)
clang++— build withoh clanglldborgdb— for debuggingpkgfile(Arch Linux) orapt-file(Debian/Ubuntu) — for missing-package suggestionsx86_64-w64-mingw32-g++ordocker— for Windows cross-compilationwine— for testing Windows executablesvalgrind— for profiling (oh valgrind)clang-format— foroh fmtninja— foroh ninja/oh cmake ninja
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-loadersudo 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-devNote: 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.
Install a recent GCC and dependencies with Homebrew:
brew install gcc pkg-configUse gmake instead of make. Install dependencies:
# FreeBSD
pkg install pkgconf gmake
# NetBSD
pkgin install pkgconf gmakeInstall g++ 11+ and build with oh CXX=eg++.
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 SDL2Orchideous 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 SDL2Orchideous 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.
- No configuration files needed — follows the directory structure conventions above.
- Auto-detection of compiler flags, includes and libraries via
pkg-configand platform-specific package managers. - Incremental compilation — only recompiles changed source files.
- Profile-guided optimization —
oh reccollects 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.txtis specific to the system it was generated on.
- License: BSD-3
- Version: 1.0.3
- Author: Alexander F. Rødseth <xyproto@archlinux.org>