Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SC::Build

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.

Features

  • Describe builds in SC-build.cpp using SC::Build::Definition, Workspace, Project, and Configuration
  • Generate XCode 14+ projects, Visual Studio 2019 / 2022 projects, and Makefiles
  • Build directly through SC::Build::Generator::Native on macOS, Linux, and Windows hosts
  • Build console executables, GUI applications, shared libraries, and static libraries
  • Attach compile/link settings at project, configuration, and per-file granularity
  • Build workspace-local static-library dependencies in dependency order on the native backend
  • Track header dependencies through compiler-generated dependency information
  • Emit compile_commands.json on the native backend and from the Make / XCode generated flows
  • Integrate with SC-package from Tools to download repository dependencies
  • Export Sane C++ libraries for Plugin hosts through addExportLibraries and addExportAllLibraries

Status

🟨 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.

Description

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:

  • Generated backends: emit XCode, Visual Studio, or Make projects into _Build/_Projects
  • Native backend: invoke compiler, linker, and archiver child processes directly without generating project files first

The repository tool surface is the SC-build tool described in Tools. Its command-line shape is:

./SC.sh build configure [workspace:project | project]
./SC.sh build compile [workspace:project | project] [configuration] [generator] [architecture] [-- extra args...]
./SC.sh build run [workspace:project | project] [configuration] [generator] [architecture] [-- extra args...]
./SC.sh build coverage [workspace:project | project] [configuration] [generator] [architecture]

Generator keywords accepted by the tool are:

  • default
  • native
  • make
  • xcode
  • vs2022
  • vs2019

Architecture keywords accepted by the tool are:

  • arm64
  • intel64
  • intel32
  • wasm
  • any

Current CLI behavior:

  • If no project is specified, compile builds the whole default workspace
  • run requires a single executable target and forwards arguments placed after --
  • If no configuration is specified, Debug is used
  • Host-default generator selection is vs2022 on Windows and make on macOS / Linux
  • configure is primarily for generated backends; the native backend builds directly into _Build/_Outputs and _Build/_Intermediates

This is the repository Tools/SC-build.cpp file used to configure the default workspace:

// Copyright (c) Stefano Cristiano
// SPDX-License-Identifier: MIT
#include "SC-build.h"
#include "../Libraries/FileSystemIterator/FileSystemIterator.h"
#include "SC-build/Build.inl"
namespace SC
{
namespace Tools
{
Result installSokol(const Build::Directories& directories, Package& package)
{
Download download;
download.packagesCacheDirectory = directories.packagesCacheDirectory;
download.packagesInstallDirectory = directories.packagesInstallDirectory;
download.packageName = "sokol";
download.packageVersion = "d5863cb";
download.shallowClone = "d5863cb78ea1552558c81d6db780dfcec49557ce";
download.url = "https://github.com/floooh/sokol.git";
download.isGitClone = true;
download.createLink = false;
package.packageBaseName = "sokol";
CustomFunctions functions;
functions.testFunction = &verifyGitCommitHashCache;
SC_TRY(packageInstall(download, package, functions));
return Result(true);
}
Result installDearImGui(const Build::Directories& directories, Package& package)
{
Download download;
download.packagesCacheDirectory = directories.packagesCacheDirectory;
download.packagesInstallDirectory = directories.packagesInstallDirectory;
download.packageName = "dear-imgui";
download.packageVersion = "af987eb";
download.url = "https://github.com/ocornut/imgui.git";
download.shallowClone = "af987eb1176fb4c11a6f0a4f2550d9907d113df5";
download.isGitClone = true;
download.createLink = false;
package.packageBaseName = "dear-imgui";
CustomFunctions functions;
functions.testFunction = &verifyGitCommitHashCache;
SC_TRY(packageInstall(download, package, functions));
return Result(true);
}
} // namespace Tools
namespace Build
{
SC_COMPILER_WARNING_PUSH_UNUSED_RESULT; // Doing some optimistic coding here, ignoring all failures
void addSaneCppLibraries(Project& project, const Parameters& parameters)
{
// Files
project.addFiles("Libraries", "**.cpp"); // recursively add all cpp files
project.addFiles("Libraries", "**.h"); // recursively add all header files
project.addFiles("Libraries", "**.inl"); // recursively add all inline files
// Libraries to link
if (parameters.platform == Platform::Apple)
{
project.addLinkFrameworks({"CoreFoundation", "CoreServices", "CFNetwork", "Foundation"});
}
if (parameters.platform == Platform::Windows)
{
project.addLinkLibraries({"Advapi32"});
}
else
{
project.addLinkLibraries({"dl", "pthread"});
}
// Debug visualization helpers
if (parameters.generator == Generator::VisualStudio2022)
{
project.addFiles("Support/DebugVisualizers/MSVC", "*.natvis");
}
else
{
project.addFiles("Support/DebugVisualizers/LLDB", "*");
}
}
static constexpr StringView TEST_PROJECT_NAME = "SCTest";
static constexpr StringView BUILD_TEST_PROJECT_NAME = "SCBuildTest";
Result configureTests(const Parameters& parameters, Workspace& workspace)
{
Project project = {TargetType::ConsoleExecutable, TEST_PROJECT_NAME};
// All relative paths are evaluated from this project root directory.
project.setRootDirectory(parameters.directories.libraryDirectory.view());
// Project Configurations
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
project.addPresetConfiguration(Configuration::Preset::DebugCoverage, parameters);
project.configurations.back().coverage.excludeRegex =
".*\\/Tools.*|"
".*\\Test.(cpp|h|c)|"
".*\\test.(c|h)|"
".*\\/Tests/.*\\.*|"
".*\\/LibC\\+\\+.inl|" // new / delete overloads
".*\\/Assert.h|" // Can't test Assert::unreachable
".*\\/PluginMacros.h|" // macros for client plugins
".*\\/ProcessPosixFork.inl|" // Can't compute coverage for fork
".*\\/EnvironmentTable.h|" // Can't compute coverage for fork
".*\\/InitializerList.h|" // C++ Language Support
".*\\/Reflection/.*\\.*|" // constexpr and templates
".*\\/ContainersReflection/.*\\.*|" // constexpr and templates
".*\\/SerializationBinary/.*\\.*|" // constexpr and templates
".*\\/Extra/Deprecated/.*\\.*";
if (parameters.platform == Platform::Linux)
{
project.addPresetConfiguration(Configuration::Preset::Debug, parameters, "DebugValgrind");
project.configurations.back().compile.enableASAN = false; // ASAN and Valgrind don't mix
project.configurations.back().link.enableASAN = false; // ASAN and Valgrind don't mix
}
// Defines
// $(PROJECT_ROOT) expands to Project::setRootDirectory expressed relative to $(PROJECT_DIR)
project.addDefines({"SC_LIBRARY_PATH=$(PROJECT_ROOT)", "SC_COMPILER_ENABLE_CONFIG=1"});
// Includes
project.addIncludePaths({
".", // Libraries path (for PluginTest)
"Tests/SCTest", // SCConfig.h path (enabled by SC_COMPILER_ENABLE_CONFIG == 1)
});
addSaneCppLibraries(project, parameters);
project.addFiles("Tests/SCTest", "*.cpp"); // add all .cpp from SCTest directory
project.addFiles("Tests/SCTest", "*.h"); // add all .h from SCTest directory
project.addFiles("Tests/Libraries", "**.c*"); // add all tests from Libraries directory
project.addFiles("Tests/Libraries", "**.inl"); // add all tests from Libraries directory
project.removeFiles("Tests/Libraries/Build", "BuildTest.cpp");
project.addFiles("Tests/Support", "**.cpp"); // add all tests from Support directory
project.addFiles("Tests/Tools", "**.cpp"); // add all tests from Tools directory
project.addFiles("Tools", "SC-*.cpp"); // add all tools
project.addFiles("Tools", "*.h"); // add tools headers
if (not project.addExportLibraries({"Foundation", "Memory", "Strings", "Containers"}))
{
return Result::Error("Failed to configure exported SCTest libraries");
}
project.link.preserveExportedSymbols = true;
// Deprecated code tests and libraries (to be removed when deprecated code will be removed)
project.addFiles("Extra/Deprecated/Tests", "**.cpp"); // add all deprecated tests
project.addFiles("Extra/Deprecated/Libraries", "**.h"); // add all deprecated libraries header files
project.addFiles("Extra/Deprecated/Libraries", "**.cpp"); // add all deprecated libraries cpp files
// This is a totally useless per-file define to test "per-file" flags SC::Build feature.
SourceFiles specificFiles;
// For testing purposes let's create a needlessly complex selection filter for "SC Spaces.cpp"
specificFiles.addSelection("Tests/SCTest", "*.cpp");
specificFiles.removeSelection("Tests/SCTest", "SCTest.cpp");
// Add an useless define to be checked inside "SC Spaces.cpp" and "SCTest.cpp"
specificFiles.compile.addDefines({"SC_SPACES_SPECIFIC_DEFINE=1"});
specificFiles.compile.addIncludePaths({"../Directory With Spaces"});
// For testing purposes disable some warnings caused in "SC Spaces.cpp"
specificFiles.compile.disableWarnings({4100}); // MSVC only
specificFiles.compile.disableWarnings({"unused-parameter"}); // GCC and Clang
specificFiles.compile.disableClangWarnings({"reserved-user-defined-literal"}); // Clang Only
project.addSpecificFileFlags(specificFiles);
SC_TRY(workspace.projects.push_back(move(project)));
return Result(true);
}
Result configureSCBuildTest(const Parameters& parameters, Workspace& workspace)
{
Project project = {TargetType::ConsoleExecutable, BUILD_TEST_PROJECT_NAME};
project.setRootDirectory(parameters.directories.libraryDirectory.view());
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
project.addDefines({"SC_LIBRARY_PATH=$(PROJECT_ROOT)", "SC_COMPILER_ENABLE_CONFIG=1"});
project.addIncludePaths({
".",
"Tests/SCBuildTest",
});
addSaneCppLibraries(project, parameters);
project.addFiles("Tests/SCBuildTest", "*.cpp");
project.addFiles("Tests/SCBuildTest", "*.h");
project.addFiles("Tests/Libraries/Build", "BuildTest.cpp");
project.addFiles("Tools", "SC-*.cpp");
project.addFiles("Tools", "*.h");
SC_TRY(workspace.projects.push_back(move(project)));
return Result(true);
}
Result configureSCSharedLibrary(const Parameters& parameters, Workspace& workspace)
{
Project project = {TargetType::SharedLibrary, "SC"};
project.setRootDirectory(parameters.directories.libraryDirectory.view());
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
project.addIncludePaths({"."});
addSaneCppLibraries(project, parameters);
SC_TRY_MSG(project.addExportAllLibraries(), "Failed to configure exported Sane C++ libraries");
SC_TRY(workspace.projects.push_back(move(project)));
return Result(true);
}
Result configureTestSTLInterop(const Parameters& parameters, Workspace& workspace)
{
Project project = {TargetType::ConsoleExecutable, "InteropSTL"};
// All relative paths are evaluated from this project root directory.
project.setRootDirectory(parameters.directories.libraryDirectory.view());
// Project Configurations
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
// Enable C++ STL, exceptions and RTTI
project.files.compile.enableStdCpp = true;
project.files.compile.enableExceptions = true;
project.files.compile.enableRTTI = true;
project.files.compile.cppStandard = CppStandard::CPP17; // string_view requires C++17
// $(PROJECT_ROOT) expands to Project::setRootDirectory expressed relative to $(PROJECT_DIR)
project.addDefines({"SC_COMPILER_ENABLE_STD_CPP=1"});
project.addIncludePaths({"."}); // Libraries path
addSaneCppLibraries(project, parameters);
project.addFiles("Tests/InteropSTL", "*.cpp");
project.addFiles("Tests/InteropSTL", "*.h");
workspace.projects.push_back(move(project));
return Result(true);
}
static constexpr StringView EXAMPLE_PROJECT_NAME = "SCExample";
Result configureExamplesGUI(const Parameters& parameters, Workspace& workspace)
{
Project project = {TargetType::GUIApplication, EXAMPLE_PROJECT_NAME};
// All relative paths are evaluated from this project root directory.
project.setRootDirectory(parameters.directories.libraryDirectory.view());
// Project icon (currently used only by Xcode backend)
project.iconPath = "Documentation/Doxygen/SC.svg";
// Install dependencies
Tools::Package sokol;
SC_TRY(Tools::installSokol(parameters.directories, sokol));
Tools::Package imgui;
SC_TRY(Tools::installDearImGui(parameters.directories, imgui));
// Add includes
project.addIncludePaths({".", sokol.packageLocalDirectory.view(), imgui.packageLocalDirectory.view()});
// Project Configurations
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
project.addPresetConfiguration(Configuration::Preset::DebugCoverage, parameters);
addSaneCppLibraries(project, parameters); // add all SC Libraries
project.addFiles(imgui.packageLocalDirectory.view(), "*.cpp");
project.addFiles(sokol.packageLocalDirectory.view(), "*.h");
String imguiRelative, imguiDefine;
SC_TRY(Path::relativeFromTo(imguiRelative, project.rootDirectory.view(), imgui.packageLocalDirectory.view(),
Path::AsNative));
SC_TRY(StringBuilder::format(imguiDefine, "SC_IMGUI_PATH=$(PROJECT_ROOT)/{}", imguiRelative));
project.addDefines({"SC_LIBRARY_PATH=$(PROJECT_ROOT)", imguiDefine.view()});
project.addExportAllLibraries(); // Export all SC libraries for plugins
SC_TRY(project.addExportDirectories({imgui.packageLocalDirectory.view()}));
project.link.preserveExportedSymbols = true;
if (parameters.platform == Platform::Apple)
{
project.addFiles("Examples/SCExample", "*.m"); // add all .m from SCExample directory
project.addLinkFrameworks({"Metal", "MetalKit", "QuartzCore"});
project.addLinkFrameworksMacOS({"Cocoa"});
project.addLinkFrameworksIOS({"UIKit", "Foundation"});
}
else
{
project.addFiles("Examples/SCExample", "*.c"); // add all .c from SCExample directory
if (parameters.platform == Platform::Linux)
{
project.addLinkLibraries({"GL", "EGL", "X11", "Xi", "Xcursor"});
}
}
if (parameters.platform == Platform::Windows)
{
project.addDefines({"IMGUI_API=__declspec( dllexport )"});
}
else
{
project.addDefines({"IMGUI_API=__attribute__((visibility(\"default\")))"});
}
project.addFiles("Examples/SCExample", "**.h"); // add all .h from SCExample directory recursively
project.addFiles("Examples/SCExample", "**.cpp"); // add all .cpp from SCExample directory recursively
if (not project.addExportLibraries({"Async", "Containers", "ContainersReflection", "File", "FileSystem",
"Foundation", "Http", "Memory", "Plugin", "Process", "Reflection",
"SerializationBinary", "SerializationText", "Socket", "Strings", "Threading"}))
{
return Result::Error("Failed to configure exported SCExample libraries");
}
SC_TRY(workspace.projects.push_back(move(project)));
return Result(true);
}
Result configureExamplesConsole(const Parameters& parameters, Workspace& workspace)
{
// Read all projects from Examples directory
FileSystemIterator::FolderState entries[2];
FileSystemIterator fsi;
String path;
SC_TRY(Path::join(path, {parameters.directories.libraryDirectory.view(), "Examples"}));
fsi.init(path.view(), entries);
// Create a project for folder containing a .cpp file
while (fsi.enumerateNext())
{
FileSystemIterator::Entry entry = fsi.get();
if (not entry.isDirectory() or entry.name == EXAMPLE_PROJECT_NAME)
continue;
StringView name, extension;
SC_TRY(Path::parseNameExtension(entry.name, name, extension));
Project project;
project.targetType = TargetType::ConsoleExecutable;
project.name = name;
project.targetName = name;
// All relative paths are evaluated from this project root directory.
project.setRootDirectory(parameters.directories.libraryDirectory.view());
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
#if 0 // Flip this ifdef to add all Sane C++ Libraries instead of using the SC.cpp unity build
addSaneCppLibraries(project, parameters);
#else
project.addFile("SC.cpp"); // Unity build file including all Sane C++ Libraries
if (parameters.platform == Platform::Apple)
{
project.addLinkFrameworks({"CoreFoundation", "CoreServices"});
}
if (parameters.platform != Platform::Windows)
{
project.addLinkLibraries({"dl", "pthread"});
}
#endif
project.addFiles(entry.path, "**.cpp");
workspace.projects.push_back(move(project));
}
return Result(true);
}
Result configureSingleFileLibs(Definition& definition, const Parameters& parameters)
{
Workspace workspace = {"SCSingleFileLibs"};
// Read all single file libraries from the _Build/_SingleFileLibrariesTest directory
FileSystemIterator::FolderState entries[1];
FileSystemIterator fsi;
String path;
SC_TRY(Path::join(path, {parameters.directories.libraryDirectory.view(), "_Build", "_SingleFileLibrariesTest"}));
SC_TRY_MSG(fsi.init(path.view(), entries), "Cannot access _Build/_SingleFileLibrariesTest");
// Create a project for each single file library
while (fsi.enumerateNext())
{
StringView name, extension;
SC_TRY(Path::parseNameExtension(fsi.get().name, name, extension));
if (extension != "cpp" or not name.startsWith("Test_"))
continue; // Only process .cpp files
Project project;
project.targetType = TargetType::ConsoleExecutable;
project.name = name;
project.targetName = project.name;
// All relative paths are evaluated from this project root directory.
project.setRootDirectory(parameters.directories.libraryDirectory.view());
project.addPresetConfiguration(Configuration::Preset::Debug, parameters);
project.addPresetConfiguration(Configuration::Preset::Release, parameters);
// Link C++ stdlib to avoid needing to link Memory library to define __cxa_guard_acquire etc.
project.addDefines({"SC_COMPILER_ENABLE_STD_CPP=1"});
project.configurations[0].compile.enableStdCpp = true;
project.configurations[1].compile.enableStdCpp = true;
project.addIncludePaths({"_Build/_SingleFileLibraries"});
project.addFile(fsi.get().path);
// Libraries to link
if (parameters.platform == Platform::Apple)
{
project.addLinkFrameworks({"CoreFoundation", "CoreServices"});
}
if (parameters.platform != Platform::Windows)
{
project.addLinkLibraries({"dl", "pthread"});
}
workspace.projects.push_back(move(project));
}
definition.workspaces.push_back(move(workspace));
return Result(true);
}
static constexpr StringView DEFAULT_WORKSPACE = "SCWorkspace";
Result configure(Definition& definition, const Parameters& parameters)
{
Workspace defaultWorkspace = {DEFAULT_WORKSPACE};
SC_TRY(configureTests(parameters, defaultWorkspace));
SC_TRY(configureSCBuildTest(parameters, defaultWorkspace));
SC_TRY(configureSCSharedLibrary(parameters, defaultWorkspace));
SC_TRY(configureTestSTLInterop(parameters, defaultWorkspace));
SC_TRY(configureExamplesConsole(parameters, defaultWorkspace));
SC_TRY(configureExamplesGUI(parameters, defaultWorkspace));
definition.workspaces.push_back(move(defaultWorkspace));
// Ignore errors from configuring single file libraries
(void)configureSingleFileLibs(definition, parameters);
return Result(true);
}
Result executeAction(const Action& action) { return Build::Action::execute(action, configure, DEFAULT_WORKSPACE); }
} // namespace Build
} // namespace SC
#define SC_COMPILER_WARNING_POP
Pops warning from inside a macro.
Definition Compiler.h:120
#define SC_COMPILER_WARNING_PUSH_UNUSED_RESULT
Disables unused-result warning (due to ignoring a return value marked as [[nodiscard]])
Definition Compiler.h:155
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition Compiler.h:274
#define SC_TRY_MSG(expression, failedMessage)
Checks the value of the given expression and if failed, returns a result with failedMessage to caller...
Definition Result.h:60
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition Result.h:49

Public API

The public API in Tools/SC-build/Build.h currently exposes:

  • Definition, Workspace, Project, and Configuration for the build graph
  • TargetType::{ConsoleExecutable, GUIApplication, SharedLibrary, StaticLibrary}
  • Generator::{Native, XCode, VisualStudio2022, VisualStudio2019, Make}
  • Toolchain::{HostDefault, Clang, GCC, MSVC, ClangCL, ZigCC, CustomDriver}
  • ExecutionOptions for native-backend parallelism / verbosity knobs
  • Project::addSpecificFileFlags for per-file flag groups
  • Project::addExportLibraries, addExportAllLibraries, and addExportDirectories for plugin host exports

Backend Matrix

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

Native Backend

The standalone backend is selected through SC::Build::Generator::Native.

Current implemented scope:

  • Host platforms: macOS, Linux and Windows
  • Toolchain families exposed by the API: HostDefault, Clang, GCC, MSVC, ClangCL, ZigCC, and CustomDriver
  • Target kinds: console executables, GUI applications, shared libraries, and static libraries
  • Dependency tracking: compiler-generated dependency files / dependency output
  • Incrementality: skips up-to-date compile and link steps
  • Workspace dependency ordering: native executable targets can link workspace-local static libraries by name
  • Parallelism: compile fan-out is controlled by ExecutionOptions::maxParallelJobs
  • Output layout: _Build/_Outputs, _Build/_Intermediates, and _Build/_BuildCache

Typical native commands:

./SC.sh build compile SCBuildTest Debug native
./SC.sh build run SCBuildTest Debug native -- --test "BuildTest"
SC.bat build compile SCTest Debug native

Important current limits:

  • Windows native sysroot selection is not implemented yet
  • run is valid only for executable targets and only when a single project is selected
  • The repository build configure command does not rely on a Windows-native generation pass because native builds do not need generated project files

Per-file Flags

Project::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.

Plugin Host Exports

For host executables using the Plugin library:

  • Project::addExportLibraries adds the needed SC_EXPORT_LIBRARY_<LIBRARY>=1 defines to the host executable
  • Project::addExportAllLibraries does the same for every Sane C++ library
  • On Linux both helpers also add -rdynamic

LinkFlags::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.

Generated Layout

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 state

How To Debug

  1. Build SC-build itself through one of the repository build tasks or through build compile
  2. Launch the generated SC-build executable under your debugger with the same arguments passed by the bootstrap

With 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:

"name": "Debug SC-build [linux] (lldb)",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/_Build/_Tools/Linux/SC-build",
"args": [
"${workspaceFolder}",
"${workspaceFolder}/Tools",
"${workspaceFolder}/_Build",
"build",
"configure",
"SCTest",
"Debug"
],

Videos

This is the list of videos that have been recorded showing some of the internal thoughts that have been going into this library:

Blog

Some relevant blog posts are: