SC::Build is a Tool and public API for describing builds in C++ and then either generating project files or building directly through a standalone native backend.
SC-build.cpp using SC::Build::Definition, Workspace, Project, and ConfigurationSC::Build::Generator::Native on macOS, Linux, and Windows hostscompile_commands.json on the native backend and from the Make / XCode generated flowsSC-package from Tools to download repository dependenciesaddExportLibraries and addExportAllLibraries🟨 MVP
SC::Build is used by this repository to generate projects and/or build the test suites, tools, examples, and the SC shared library. The generated-project backends remain part of the daily workflow, while the standalone native backend now supports direct host builds on macOS, Linux, and Windows.
Build descriptions are regular C++ files, conventionally named SC-build.cpp, that are compiled on the fly through the bootstrap scripts SC.sh and SC.bat.
The same public API serves two workflows:
_Build/_ProjectsThe repository tool surface is the SC-build tool described in Tools. Its command-line shape is:
Named options accepted by compile, run, and coverage are:
-c, --config <NAME>-g, --generator <NAME>-a, --arch <NAME>--target <PROFILE> (compile and run only)--toolchain <NAME>--triple <VALUE>--sysroot <PATH>--runner <MODE> (run only)--runner-path <PATH> (run only)-o, --output <MODE> (compile and run only)-q, --quiet (compile and run only)--normal (compile and run only)-v, --verbose (compile and run only)Generator values accepted by the tool are:
defaultnativemakexcodevs2022vs2019Architecture values accepted by the tool are:
arm64intel64intel32wasmanyTarget profiles accepted by the tool today are:
hostnativelinux-glibc-x86_64linux-glibc-arm64linux-musl-x86_64linux-musl-arm64windows-gnu-x86_64windows-msvc-x86_64windows-msvc-arm64windows-gnu-arm64Runner values accepted by build run today are:
autononewineqemucustomToolchain values accepted by compile and run today are:
defaulthost-defaultclangfilcgccmsvcclang-clllvm-mingwCurrent CLI behavior:
compile builds the whole default workspacerun requires a single executable target and forwards arguments placed after --Debug is usedvs2022 on Windows and make on macOS / Linuxconfigure is primarily for generated backends; the native backend builds directly into _Build/_Outputs and _Build/_Intermediatescompile / run accept quiet, normal, or verbose output control through --output or the --quiet / --normal / --verbose shortcuts--target selects a friendly host or cross target profile without requiring the caller to spell the toolchain triple manually--toolchain selects the compiler family orthogonally to --target--triple and --sysroot are raw escape hatches for advanced toolchain overrides--target, so they win over the friendly profile defaultsbuild run can use --runner / --runner-path to control how foreign executables are launched--generator, --arch, --runner, or --triple values now fail early with concrete CLI errorstarget as [configuration] [generator] [architecture] [output-mode]This is the repository Tools/SC-build.cpp file used to configure the default workspace:
The public API in Tools/SC-build/Build.h currently exposes:
Definition, Workspace, Project, and Configuration for the build graphMachine and TargetEnvironment for explicit host / target modelingTargetType::{ConsoleExecutable, GUIApplication, SharedLibrary, StaticLibrary}Generator::{Native, XCode, VisualStudio2022, VisualStudio2019, Make}Toolchain::{HostDefault, Clang, FilC, GCC, MSVC, ClangCL, LLVMMingw, CustomDriver}RunnerSpec::{Auto, None, Wine, QEMU, Custom}ExecutionOptions for native-backend parallelism / verbosity knobsOutputMode::{Quiet, Normal, Verbose} and ExecutionOptions::outputMode for native-backend presentation controlProject::addSpecificFileFlags for per-file flag groupsProject::addExportLibraries, addExportAllLibraries, and addExportDirectories for plugin host exports| Backend | Platforms | Target kinds | compile_commands.json | Notes |
|---|---|---|---|---|
Native | macOS, Linux, Windows hosts | Console executable, GUI application, shared library, static library | Yes | Direct compile / run / coverage flow; no project files are generated |
XCode | Apple | Console executable, GUI application, shared library, static library | Yes | GUI apps also emit storyboard / assets; Intel32 and Wasm architectures are unsupported |
VisualStudio2022 / VisualStudio2019 | Windows | Console executable, GUI application, shared library, static library | No | The repository defaults to VS2022, but VS2019 generation is still available |
Make | Apple, Linux | Console executable, GUI application, shared library, static library | Yes on clang-style flows | GCC builds still compile, but Makefile-side compile database generation is unavailable there |
The standalone backend is selected through SC::Build::Generator::Native.
Current implemented scope:
HostDefault, Clang, FilC, GCC, MSVC, ClangCL, LLVMMingw, and CustomDriverFilC is now exposed by the API and CLI through --toolchain filc, but it is Linux-only, compiler-first, and not a public target-profile row yetExecutionOptions::maxParallelJobsquiet hides progress lines and successful child output, normal shows progress plus grouped failures and summaries, and verbose also shows rebuild traces, skip lines, and successful compile output_Build/_Outputs, _Build/_Intermediates, and _Build/_BuildCacheCurrent cross-compilation scope:
windows-gnu-x86_64 and windows-gnu-arm64 through packaged llvm-mingwSC-package install filc plus build ... --toolchain filc; this is currently limited to native Linux x86_64 output and is still outside the public support matrix while compile/start validation hardensglibc and musl target profiles now exist as first-class native-backend profiles; they shape canonical target triples and sysroot flags, and macOS hosts now auto-select both a packaged LLVM toolchain and packaged Linux sysroots for them when the caller has not provided explicit compiler pathsSCTest compile validation for linux-glibc-x86_64, linux-glibc-arm64, linux-musl-x86_64, and linux-musl-arm64build run can now wrap foreign Linux targets through qemu-user; on macOS this can auto-resolve host qemu-* executables from PATH, and the runner passes -L <sysroot> so dynamically linked Linux targets can find their loader and libraries./SC.sh package install msvc and compile windows-msvc-x86_64 and windows-msvc-arm64 through the native backendwindows-msvc-x86_64 and windows-msvc-arm64; the package tool auto-prefers a generated box64 + wine64 wrapper when those host tools are installed, can fall back to an auto-installed packaged Linux Wine runner that resolves a maintained generic-arm box64 build when system box64 is absent, and native build run can now auto-install a separate ARM64 Wine runtime for windows-*-arm64 execution while still accepting plain wine64 / wine or an explicit --wine / SC_MSVC_WINE overrideSC-package install msvc also accepts explicit --import-directory <path> and --wine <path> overrides so imported layouts and custom Wine wrappers no longer have to be driven only through environment variablessc-msvc-package.json instead of requiring SC_MSVC_WINE or host Wine discovery againsc-msvc-package.json metadata and wrapper scripts in place, and SDK version detection now falls back from Windows Kits/10/bin to Include or Lib when the SDK tools directory is absentmacOS vs Linux) so shared workspaces do not reuse the wrong recorded Wine runner path across hostswindows-msvc-x86_64 has a clean native-backend SCTest compile validation plus a targeted BaseTest/new-delete run through the maintained packaged Box64 runner, and windows-msvc-arm64 now also has a clean native-backend SCTest compile plus a targeted BaseTest/new-delete run through an auto-installed native ARM64 Wine runnerbuild run now keeps Windows console targets on plain packaged wine instead of auto-switching to wineconsole, because the current Box64 Wine console path is less reliable than plain wine on this hostbuild run can auto-route windows-gnu-x86_64 executables through Wine on macOS and Linux, and Linux arm64 now also smoke-runs windows-gnu-arm64 through the packaged native ARM64 Wine runnerbuild run path now auto-prefers generated box64 + wine64 wrappers when the host provides those commands, and console targets still switch to a sibling wineconsole --backend=curses wrapper when it is available on Linux x64 hostswindows-msvc-x86_64, while Linux arm64 now has targeted SCTest BaseTest/new-delete smokes for both windows-msvc-x86_64 and windows-msvc-arm64build run now routes Wine launches through cmd /c with Windows-style paths, which fixes real macOS Wine startup for windows-gnu-x86_64windows-gnu-arm64 and windows-msvc-arm64 are no longer blocked by a hardcoded CLI rule; Linux arm64 now has a real ARM64-capable Wine runtime for targeted smokes, while the packaged macOS Wine runner still does not ship an ARM64 Windows loaderTypical native commands:
Important current limits:
qemu-user packagelinux-filc-* target profile exists yet, Linux x86_64 is the only intended output slice for the first milestone, and Linux arm64 hosts may still require imported local installs plus host-specific translation/linker helpers during validationrun is valid only for executable targets and only when a single project is selectedbuild configure command does not rely on a Windows-native generation pass because native builds do not need generated project filesProject::addSpecificFileFlags is implemented and used by this repository.
The current backend behavior is:
| Backend | Per-file behavior |
|---|---|
Native | Full compile-flag merge for the selected files |
Make | Full compile-flag merge, emitted as grouped per-file variables in the generated Makefile |
XCode | Per-file include paths, defines, and non-MSVC warning disables are emitted; other per-file compile knobs are not yet emitted, and conflicting higher-level flags cannot be removed |
VisualStudio2019 / VisualStudio2022 | Per-file include paths, defines, and MSVC warning disables are emitted; other per-file compile knobs are not yet emitted |
The repository example lives in Tools/SC-build.cpp, where the SCTest target applies a dedicated define, include path, and warning disables to a selected subset of files.
For host executables using the Plugin library:
Project::addExportLibraries adds the needed SC_EXPORT_LIBRARY_<LIBRARY>=1 defines to the host executableProject::addExportAllLibraries does the same for every Sane C++ library-rdynamicLinkFlags::preserveExportedSymbols currently performs fine-grained exported-symbol preservation only on the standalone native backend and on generated Makefiles. The XCode backend currently falls back to disabling dead-code stripping when preservation is requested.
Repository-generated paths are currently:
_Build/_Projects/XCode/SCWorkspace/..._Build/_Projects/VisualStudio2022/SCWorkspace/..._Build/_Projects/VisualStudio2019/SCWorkspace/..._Build/_Projects/Make/SCWorkspace/apple/..._Build/_Projects/Make/SCWorkspace/linux/..._Build/_Outputs/<expanded-configuration>/..._Build/_Intermediates/<project>/<expanded-configuration>/..._Build/_Intermediates/<workspace>/compile_commands.json for native workspace databases_Build/_BuildCache/... for native-backend stateSC-build itself through one of the repository build tasks or through build compileSC-build executable under your debugger with the same arguments passed by the bootstrapWith any debugger or IDE other than VSCode, debug _Build/_Tools/<Platform>/SC-build (or _Build/_Tools/Windows/SC-build.exe) and pass arguments similar to:
This is the list of videos that have been recorded showing some of the internal thoughts that have been going into this library:
Some relevant blog posts are: