(WIP) Restructuring of the project, rework of addons.

This commit is contained in:
2025-09-20 12:16:54 +02:00
parent 7b2e5c7432
commit 5c17999cdf
29 changed files with 1238 additions and 56 deletions

81
test/v1_0_0/.gitignore vendored Normal file
View File

@@ -0,0 +1,81 @@
# Project
/.idea/
/.vs/
/.vscode/
/vs_project_files/
*.sln
# Executables
/bin
/bin_*
# Libraries
/lib
/lib_*
# Vulkan API dumps
/api_dump*
# Compile commands
compile_commands.json
# whatever this is
.cache
# ImGui config
/imgui.ini
# Environment setup
/.env
# Build Configuration
/config.py
/config_*.py
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Debug Info
*.pdb
# for projects that use SCons for building: http://http://www.scons.org/
.sconsign.dblite
/.sconf_temp
/config.log
# Byte-compiled / optimized python files
__pycache__/
*.py[cod]
# Backup files
*.bak

10
test/v1_0_0/SConstruct Normal file
View File

@@ -0,0 +1,10 @@
config = {
'PROJECT_NAME': 'S++ 1.0.0 Test'
}
env = SConscript('../../SConscript', exports = ['config'])
env = env.Module('private/test/SModule')
env.Finalize()

View File

@@ -0,0 +1,25 @@
Import('env')
env.ModuleConfig(
name = 'Test',
description = 'Test Module',
cxx_namespace = 'tst'
)
src_files = Split("""
main.cpp
test.cpp
""")
prog_app = env.UnityProgram(
name = 'Test',
target = env['BIN_DIR'] + '/test',
source = src_files,
dependencies = {
'mijin': {}
}
)
env.Default(prog_app)
Return('env')

View File

@@ -0,0 +1,8 @@
#include "./test.hpp"
int main(int, char**)
{
tst::printHelloWorld(100);
return 0;
}

View File

@@ -0,0 +1,15 @@
#include "./test.hpp"
#include <mijin/debug/assert.hpp>
#include <print>
namespace tst
{
void printHelloWorld(int param) noexcept
{
MIJIN_ASSERT(param > 0, "param is not >0 :(");
std::println("Hello World! Param is {}.", param);
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace tst
{
void printHelloWorld(int param) noexcept;
}

View File

@@ -0,0 +1,133 @@
import os
import math
from SCons.Script import *
from SCons.Node.FS import File
from SCons import Action
"""
Scons Unity Build Generator
Provides several generators for SCons to combine multiple source files into a bigger
one to reduce compilation time, so called "unity builds". This is achieved by generating
unity source files which in term include the actual source files and compile them using
one of the existing SCons builders.
Usage
-----
In order to use this, just place it inside your `site_scons/site_tools` folder, enable it by
adding "unity_build" to the tools when constructing your Environment and replace invocations
of the Program/Library/SharedLibrary/StaticLibrary builders with their Unity... counterpart:
env = Environment(tools = ['default', 'unity_build'])
source_files = ...
env.UnityProgram(
target = 'my_program',
source = source_files,
...
)
The tool will generate an amount of unity source files and invoke the Program builder on these,
forwarding any other arguments you passed.
Other Options
------------
You can control the behaviour of the builder using several Environment options:
env['UNITY_CACHE_DIR'] = '.unity' # Directory where the unity sources are stored.
# can be either a string or a Dir() node.
env['UNITY_MAX_SOURCES'] = 15 # Maximum number of source files per unity file.
env['UNITY_MIN_FILES'] = env.GetOption('num_jobs')
# Minimum number of unity files to generate (if possible).
# Defaults to the number of jobs passed to SCons.
env['UNITY_DISABLE'] = False # Set to True to completely disable unity builds. The commands
# will simply pass through their options to the regular builders.
Additionally any generator can be passed a `cache_dir` to overwrite the value from the Environment.
"""
def exists(env : Environment):
return True
def generate(env : Environment):
env.AddMethod(_make_generator(env.Program), 'UnityProgram')
env.AddMethod(_make_generator(env.Library), 'UnityLibrary')
env.AddMethod(_make_generator(env.StaticLibrary), 'UnityStaticLibrary')
env.AddMethod(_make_generator(env.SharedLibrary), 'UnitySharedLibrary')
# build for generating the unity source files
unity_source_builder = env.Builder(
action = Action.Action(_generate_unity_file, _generate_unity_file_msg)
)
env.Append(BUILDERS = {'UnitySource': unity_source_builder})
env.SetDefault(UNITY_CACHE_DIR = '.unity')
env.SetDefault(UNITY_MAX_SOURCES = 15)
env.SetDefault(UNITY_MIN_FILES = env.GetOption('num_jobs'))
env.SetDefault(UNITY_DISABLE = False)
def _make_generator(base_generator):
def generator(env, source, target, cache_dir = None, *args, **kwargs):
if env['UNITY_DISABLE']:
return base_generator(target = target, source = source, *args, **kwargs)
unity_source_files = []
source_files, other_nodes = _flatten_source(source)
max_sources_per_file = max(1, math.ceil(len(source_files) / env['UNITY_MIN_FILES']))
sources_per_file = min(max_sources_per_file, env['UNITY_MAX_SOURCES'])
num_unity_files = math.ceil(len(source_files) / sources_per_file)
if not cache_dir:
cache_dir = env['UNITY_CACHE_DIR']
if not isinstance(cache_dir, str):
cache_dir = cache_dir.abspath
os.makedirs(cache_dir, exist_ok=True)
target_base_name = os.path.basename(target)
for idx in range(num_unity_files):
unity_filename = f'{cache_dir}/{target_base_name}_{idx}.cpp'
unity_source_files.append(unity_filename)
begin = sources_per_file*idx
end = sources_per_file*(idx+1)
env.UnitySource(
target = unity_filename,
source = source_files[begin:end]
)
if len(other_nodes) > 0:
print(f'Exluded {len(other_nodes)} node(s) from Unity build.')
return [base_generator(target = target, source = unity_source_files + other_nodes, *args, **kwargs)]
return generator
def _flatten_source(source : list):
source_files = []
other_nodes = []
for ele in source:
if isinstance(ele, list):
more_sources, more_other = _flatten_source(ele)
source_files.extend(more_sources)
other_nodes.extend(more_other)
elif isinstance(ele, File):
source_files.append(ele.abspath)
elif isinstance(ele, str):
source_files.append(ele)
else:
other_nodes.append(ele)
return source_files, other_nodes
def _generate_unity_file_msg(target, source, env : Environment):
assert(len(target) == 1)
return f'Generating {str(target[0])} from {len(source)} source files.'
def _generate_unity_file(target, source, env : Environment):
assert(len(target) == 1)
unity_filename = target[0].abspath
with open(unity_filename, 'w') as f:
for source_file in source:
fpath = source_file.abspath.replace("\\", "\\\\")
f.write(f'#include "{fpath}"\n')