initial commit
This commit is contained in:
commit
347148afe7
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "scons-plus-plus"]
|
||||
path = external/scons-plus-plus
|
||||
url = https://git.mewin.de/mewin/scons-plus-plus.git
|
8
SConstruct
Normal file
8
SConstruct
Normal file
@ -0,0 +1,8 @@
|
||||
config = {
|
||||
'PROJECT_NAME': 'spp_template'
|
||||
}
|
||||
env = SConscript('external/scons-plus-plus/SConscript', exports = ['config'])
|
||||
env.Append(CPPPATH = [Dir('private'), Dir('public')])
|
||||
|
||||
# app
|
||||
env = SConscript('private/app/SConscript', exports = 'env', variant_dir = env['VARIANT_DIR'], src_dir = '.')
|
1
external/scons-plus-plus
vendored
Submodule
1
external/scons-plus-plus
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 93dd09e3247048996c29b3f8be6f7675cb5e89d5
|
18
private/app/SConscript
Normal file
18
private/app/SConscript
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
Import('env')
|
||||
|
||||
# Mijin
|
||||
lib_mijin = env.Cook('mijin')
|
||||
|
||||
src_files = Split("""
|
||||
main.cpp
|
||||
""")
|
||||
|
||||
prog_app = env.UnityProgram(
|
||||
target = env['BIN_DIR'] + '/app',
|
||||
source = src_files,
|
||||
dependencies = [lib_mijin]
|
||||
)
|
||||
env.Default(prog_app)
|
||||
|
||||
Return('env')
|
5
private/app/main.cpp
Normal file
5
private/app/main.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
return 0;
|
||||
}
|
BIN
site_scons/site_tools/__pycache__/unity_build.cpython-311.pyc
Normal file
BIN
site_scons/site_tools/__pycache__/unity_build.cpython-311.pyc
Normal file
Binary file not shown.
133
site_scons/site_tools/unity_build.py
Normal file
133
site_scons/site_tools/unity_build.py
Normal 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')
|
Loading…
x
Reference in New Issue
Block a user