import glob import pathlib import platform import re import shutil from SCons.Script import * _SCRIPT_STAMPFILE = '.spp_script_run' def _git_cook(env: Environment, repo, options: dict = {}) -> dict: checkout_root = repo['checkout_root'] enable_hlsl = options.get('enable_hlsl', False) # TODO: windows? did_run_script = os.path.exists(os.path.join(repo['checkout_root'], _SCRIPT_STAMPFILE)) if not did_run_script or env['UPDATE_REPOSITORIES']: python_exe = os.path.realpath(sys.executable) script_file = os.path.join(repo['checkout_root'], 'update_glslang_sources.py') prev_cwd = os.getcwd() os.chdir(repo['checkout_root']) if env.Execute(f'"{python_exe}" {script_file}'): env.Exit(1) os.chdir(prev_cwd) pathlib.Path(repo['checkout_root'], _SCRIPT_STAMPFILE).touch() # generate the build_info.h generator_script = os.path.join(repo['checkout_root'], 'build_info.py') generator_script_input = os.path.join(repo['checkout_root'], 'build_info.h.tmpl') generator_script_output = os.path.join(repo['checkout_root'], 'glslang/build_info.h') env.Command( target = generator_script_output, source = [generator_script, generator_script_input, os.path.join(repo['checkout_root'], 'CHANGES.md')], action = f'"$PYTHON" "{generator_script}" "{repo["checkout_root"]}" -i "{generator_script_input}" -o "$TARGET"' ) platform_source_dir = { 'Linux': 'Unix', 'Windows': 'Windows', 'Darwin': 'Unix' }.get(platform.system(), 'Unix') glslang_source_files = env.RGlob(os.path.join(repo['checkout_root'], 'glslang/GenericCodeGen/'), '*.cpp') \ + env.RGlob(os.path.join(repo['checkout_root'], 'glslang/MachineIndependent/'), '*.cpp') \ + env.RGlob(os.path.join(repo['checkout_root'], 'glslang/OGLCompilersDLL/'), '*.cpp') \ + env.RGlob(os.path.join(repo['checkout_root'], 'glslang/ResourceLimits/'), '*.cpp') \ + env.RGlob(os.path.join(repo['checkout_root'], 'SPIRV/'), '*.cpp') \ + [os.path.join(repo['checkout_root'], f'glslang/OSDependent/{platform_source_dir}/ossource.cpp')] if enable_hlsl: glslang_source_files.extend(env.RGlob(os.path.join(repo['checkout_root'], 'glslang/HLSL/'), '*.cpp')) # disable warnings additional_cxx_flags = { 'clang': ['-w'], 'gcc': ['-w'], 'cl': ['/w'] }.get(env['COMPILER_FAMILY'], []) additional_cppdefines = [] if enable_hlsl: additional_cppdefines.append('ENABLE_HLSL=1') env.StaticLibrary( CCFLAGS = env['CCFLAGS'] + additional_cxx_flags, CPPPATH = repo['checkout_root'], CPPDEFINES = list(env['CPPDEFINES']) + additional_cppdefines, target = env['LIB_DIR'] + '/glslang_full', source = glslang_source_files ) # build the include folder include_dir = os.path.join(checkout_root, 'include') if not os.path.exists(include_dir) or env['UPDATE_REPOSITORIES']: def copy_headers(dst, src): os.makedirs(dst, exist_ok=True) for file in glob.glob(os.path.join(src, '*.h')): shutil.copy(file, dst) copy_headers(os.path.join(include_dir, 'glslang/HLSL'), os.path.join(checkout_root, 'glslang/HLSL')) copy_headers(os.path.join(include_dir, 'glslang/Include'), os.path.join(checkout_root, 'glslang/Include')) copy_headers(os.path.join(include_dir, 'glslang/MachineIndependent'), os.path.join(checkout_root, 'glslang/MachineIndependent')) copy_headers(os.path.join(include_dir, 'glslang/Public'), os.path.join(checkout_root, 'glslang/Public')) copy_headers(os.path.join(include_dir, 'glslang/SPIRV'), os.path.join(checkout_root, 'SPIRV')) return { 'CPPPATH': [include_dir], 'LIBS': [os.path.join(env['LIB_DIR'], env.LibFilename('glslang_full'))] } _REPO_NAMES = { 'default': 'glslang', 'mewin': 'glslang_mewin' } _REPO_URLS = { 'default': 'https://github.com/KhronosGroup/glslang.git', 'mewin': 'https://git.mewin.de/mewin/glslang.git' } _TAG_PATTERNS = { 'default': re.compile(r'^([0-9]+)\.([0-9]+)\.([0-9]+)$'), 'mewin': None } def _ref_fn(env: Environment, version) -> str: remote = env.get('GLSLANG_REMOTE', 'default') if remote == 'default': return f'refs/tags/{version[0]}.{version[1]}.{version[2]}' elif remote == 'mewin': return 'master' else: raise Exception('invalid glslang remote') env.GitRecipe( globals = globals(), repo_name = lambda env: _REPO_NAMES[env.get('GLSLANG_REMOTE', 'default')], repo_url = lambda env: _REPO_URLS[env.get('GLSLANG_REMOTE', 'default')], tag_pattern = lambda env: _TAG_PATTERNS[env.get('GLSLANG_REMOTE', 'default')], cook_fn = _git_cook, ref_fn = _ref_fn )