Files
cpp-build-system/README.md
Scott E. Graves d75f346c61
All checks were successful
sgraves/cpp-build-system/pipeline/head This commit looks good
sgraves/cpp-build-system_mac/pipeline/head This commit looks good
refactored Info.plist handling and added comments
2025-10-18 09:59:58 -05:00

273 lines
8.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# cpp-build-system
A cross-platform C++ project template and lightweight package manager built on **CMake**, **Docker**, and **Jenkins CI**.
Designed to produce **single-binary, statically linked executables** on Linux using **musl-libc**, and **MinGW64** builds that are **as static as possible** — all reproducibly built inside **Alpine Linux containers**.
Supports **embedding Flutter UIs** directly within native C++ applications.
All builds are orchestrated through project scripts — **direct CMake invocation is not supported.**
---
### ✨ Features
- **Cross-Platform Build Targets**
- 🧱 **Linux (musl-libc)** — fully static binaries built inside **Alpine containers**
- 🪟 **Windows (MinGW64)** — cross-compiled from Alpine, mostly static except core Win32 runtime
- 🧩 **Windows (MSYS2)** — native dynamic builds for testing or fallback
- 🍎 **macOS** — native x86-64 and arm64 builds
- **Build & Automation**
- 🐳 **Alpine-based Docker environments** ensure fully reproducible builds
- 🤖 **Unified Jenkins pipelines** for Linux, Windows, and macOS targets
- 🧰 **Root-level project generator** (`create_project.sh` / `.cmd`) for instant scaffolding
- **Development & Integration**
- 💠 Optional **Flutter embedding** for hybrid C++/Flutter UIs
- 🧼 Integrated with **clangd**, **clang-format**, and **clang-tidy** for modern IDEs and CI
- 🪟 **Inno Setup** integration for automated Windows installer generation
---
## 🚀 Getting Started
### 1⃣ Clone the Build System
```bash
git clone https://git.fifthgrid.com/sgraves/cpp-build-system.git
git clone https://github.com/sgraves76/cpp-build-system.git
cd cpp-build-system
```
---
### 2⃣ Create a New Project
Run the root-level `create_project.sh` with:
1. The **project name**
2. The **parent directory** where the new project should live
Example:
```bash
./create_project.sh MyApp ~/dev
```
This creates:
```
~/dev/MyApp/
```
The new directory contains:
- A preconfigured cross-platform C++ project structure
- A `scripts/` folder for building and packaging
> 🧩 After creation, you'll work entirely within your new project — **cpp-build-system** remains the master template.
> ⚠️ Do **not** run `cmake` directly — always use the provided scripts.
---
### 3⃣ Configure the Project
In your new project directory (`~/dev/MyApp/`), edit these two files before your first build:
> ⚠️ **Important Notice:**
> Do **not modify** the root `CMakeLists.txt` file in your project.
> All changes, targets, and configurations must be made in **`project.cmake`** only.
> The top-level `CMakeLists.txt` is managed by cpp-build-system and is required for
> correct cross-platform builds, packaging, and CI integration.
#### **`config.sh`**
Defines your projects **identity, features, and build behavior**:
- **Identity & versioning:**
`PROJECT_NAME`, `PROJECT_DESC`, `PROJECT_URL`,
`PROJECT_MAJOR_VERSION`, `PROJECT_MINOR_VERSION`, `PROJECT_REVISION_VERSION`, `PROJECT_RELEASE_VERSION`, `PROJECT_ITERATION_VERSION`
- **Apps & testing:**
`PROJECT_APP_LIST` and `PROJECT_ENABLE_TESTING`
- **Build/link behavior:**
`PROJECT_STATIC_LINK` (defaults to ON), `PROJECT_ENABLE_*` flags for dependencies such as Boost, Curl, FUSE, JSON, libsodium, OpenSSL, RocksDB, SQLite, spdlog, etc.
- **Platform-specific settings:**
`PROJECT_ENABLE_WIN32_LONG_PATH_NAMES`, macOS bundle identifiers, app icons, bundle names
- **Security, signing, and keys:**
`PROJECT_PUBLIC_KEY`, `PROJECT_PRIVATE_KEY`
- **Optional Flutter integration:**
`PROJECT_FLUTTER_BASE_HREF`
- **Overrides:**
A local `override.sh` (if present) is automatically sourced for per-machine customizations and is, by default, ignored in `.gitignore`
#### **`project.cmake`**
Owns your projects **CMake build graph** — defining what gets built and how:
- **Targets:** Add **executables** and **libraries** (static/shared as needed)
- **Sources & includes:** Declare additional source lists and include paths
- **Config & resources:** Bundle configuration files and runtime assets
Together, `config.sh` (identity & features) and `project.cmake` (targets & wiring) define a complete, reproducible build configuration across all platforms.
---
### 4⃣ Build the Project
Use the provided build wrappers — they take two arguments:
```
<arch> <config>
```
> Default \<arch\> is `x86_64` if not specified
> Default \<configuration\> is `RelWithDebInfo` if not specified
#### 🐧 Unix/Linux/macOS (via Alpine containers)
```bash
./scripts/make_unix.sh # x86_64 RelWithDebInfo
./scripts/make_unix.sh x86_64 Release
./scripts/make_unix.sh aarch64 Debug
```
#### 🪟 Windows (MinGW64 or MSYS2)
```bash
# Cross-compile Windows x64 using MinGW64 (preferred)
./scripts/make_win32.sh x86_64 RelWithDebInfo
# Build on Windows via MSYS2 (dynamic, for testing)
./scripts/make_win32.cmd x86_64 Debug
```
> `make_unix.sh` automatically builds inside **Alpine containers** for reproducible static binaries using **musl-libc** unless `PROJECT_STATIC_LINK=OFF`.
> `make_win32.*` supports both **MinGW64 cross-builds** (mostly static) and **MSYS2** builds (dynamic fallback).
---
## 🧹 Package Cleanup & Restore
- **Automatic cleanup on first compile:**
After you configure `config.sh` and run your **first successful build**, the projects `cleanup.sh` will run to **remove any packages you set to `OFF`**. This reduces dependency bloat to exactly what your project needs.
- **Manual cleanup (optional):**
You can also run cleanup manually at any time from your project directory:
```bash
./scripts/cleanup.sh
```
- **Restoring removed packages:**
If you later want to **add back packages** you previously turned off (and which `cleanup.sh` removed), run the **templates** update script from the `cpp-build-system` repository root, pointing it at your project path:
```bash
# from the cpp-build-system repo root
./update_project.sh ~/dev/MyApp
```
This will **restore all template-managed packages and scripts** (including `cleanup.sh`) into your project so you can re-enable dependencies via `config.sh` and rebuild.
---
## 🧱 Linking Strategy
| Target | Linking Model | Build Environment | Notes |
|---------|----------------|------------------|-------|
| **Linux (musl)** | Fully static | Alpine | No shared libs — single binary |
| **Linux (MinGW64)** | Static as possible | Alpine | Only core Win32 runtime dynamically linked |
| **Windows (MSYS2)** | Dynamic | MSYS2 | Fallback/test build |
| **macOS** | Static as possible | Native | Standard Apple toolchain behavior |
> 💡 *Goal: portable, reproducible, single-binary builds across platforms.*
---
Default `project.cmake`:
```cmake
add_project_library(lib${PROJECT_NAME} "" "" "${PROJECT_ADDITIONAL_SOURCES}")
add_project_executable(${PROJECT_NAME} lib${PROJECT_NAME} lib${PROJECT_NAME})
add_project_test_executable(${PROJECT_NAME}_test lib${PROJECT_NAME} lib${PROJECT_NAME})
```
Default `config.sh`:
```bash
#!/usr/bin/env bash
PROJECT_NAME="test"
PROJECT_COMPANY_NAME=""
PROJECT_COPYRIGHT=""
PROJECT_DESC=""
PROJECT_URL=""
PROJECT_MACOS_BUNDLE_ID="com.test.${PROJECT_NAME}"
PROJECT_MACOS_ICNS_NAME=""
PROJECT_MAJOR_VERSION=0
PROJECT_MINOR_VERSION=0
PROJECT_REVISION_VERSION=1
PROJECT_RELEASE_NUM=0
PROJECT_RELEASE_ITER=alpha
PROJECT_APP_LIST=(${PROJECT_NAME})
PROJECT_PRIVATE_KEY=${DEVELOPER_PRIVATE_KEY}
PROJECT_PUBLIC_KEY=${DEVELOPER_PUBLIC_KEY}
PROJECT_STATIC_LINK=ON
PROJECT_MINGW64_COPY_DEPENDENCIES+=()
PROJECT_MSYS2_PACKAGE_LIST+=()
PROJECT_ENABLE_V2_ERRORS=ON
PROJECT_ENABLE_WIN32_LONG_PATH_NAMES=OFF
PROJECT_ENABLE_BACKWARD_CPP=OFF
PROJECT_ENABLE_BOOST=OFF
PROJECT_ENABLE_CLI11=OFF
PROJECT_ENABLE_CPP_HTTPLIB=OFF
PROJECT_ENABLE_CURL=OFF
PROJECT_ENABLE_CXXOPTS=OFF
PROJECT_ENABLE_DTL=OFF
PROJECT_ENABLE_FLAC=OFF
PROJECT_ENABLE_FMT=OFF
PROJECT_ENABLE_FONTCONFIG=OFF
PROJECT_ENABLE_FREETYPE2=OFF
PROJECT_ENABLE_FUSE=OFF
PROJECT_ENABLE_FZF=OFF
PROJECT_ENABLE_GTKMM=OFF
PROJECT_ENABLE_JSON=OFF
PROJECT_ENABLE_LIBBITCOIN_SYSTEM=OFF
PROJECT_ENABLE_LIBDSM=OFF
PROJECT_ENABLE_LIBEVENT=OFF
PROJECT_ENABLE_LIBICONV=OFF
PROJECT_ENABLE_LIBJPEG_TURBO=OFF
PROJECT_ENABLE_LIBPNG=OFF
PROJECT_ENABLE_LIBSODIUM=OFF
PROJECT_ENABLE_LIBTASN=OFF
PROJECT_ENABLE_NANA=OFF
PROJECT_ENABLE_NUSPELL=OFF
PROJECT_ENABLE_OGG=OFF
PROJECT_ENABLE_OPENAL=OFF
PROJECT_ENABLE_OPENSSL=OFF
PROJECT_ENABLE_PUGIXML=OFF
PROJECT_ENABLE_ROCKSDB=OFF
PROJECT_ENABLE_SAGO_PLATFORM_FOLDERS=OFF
PROJECT_ENABLE_SDL=OFF
PROJECT_ENABLE_SECP256K1=OFF
PROJECT_ENABLE_SFML=OFF
PROJECT_ENABLE_SPDLOG=OFF
PROJECT_ENABLE_SQLITE=OFF
PROJECT_ENABLE_STDUUID=OFF
PROJECT_ENABLE_TESTING=ON
PROJECT_ENABLE_TPL=OFF
PROJECT_ENABLE_VLC=OFF
PROJECT_ENABLE_VORBIS=OFF
PROJECT_ENABLE_WINFSP=OFF
PROJECT_ENABLE_WXWIDGETS=OFF
PROJECT_KEEP_BACKWARD_CPP=1
if [ "${PROJECT_ENABLE_TESTING}" == "ON" ]; then
PROJECT_APP_LIST+=(${PROJECT_NAME}_test)
fi
if [ -f "./override.sh" ]; then
. ./override.sh
fi
```