mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-23 18:14:06 +00:00
Rewrite the SContruct.
- Works with new /strategy/ structure. - Change architecture selection to use arch= instead of construction target.
This commit is contained in:
parent
4622d8392c
commit
4c3bbd4a35
292
SConstruct
292
SConstruct
|
@ -1,116 +1,236 @@
|
|||
""" SConstruct file fore building Kvazaar with Scons.
|
||||
|
||||
This file defines two targets, x86 and x64, and builds construction
|
||||
environments for both.
|
||||
This is an additional cross platform way to build the program.
|
||||
The main way is to use the Makefile and that is always kept up to date.
|
||||
|
||||
TODO:
|
||||
- add debug builds
|
||||
- whole program optimization for gcc
|
||||
This mostly exists so it can be used with a custom SConscript file that
|
||||
builds any old version of Kvazaar, ensuring that the compilation settings are
|
||||
the same and any compilation from a specific version of Kvazaar will not
|
||||
affect the comparison. The SConscript included in git version only compiles
|
||||
the current version.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import platform
|
||||
|
||||
Help("""
|
||||
Type: 'scons x86' to build a 32-bit release version,
|
||||
'scons x64' to build a 64-bit release version.
|
||||
'scons x86 x64 -c' to clear all build directories.
|
||||
""")
|
||||
|
||||
vars = Variables()
|
||||
|
||||
default_arch = 'amd64' if platform.machine().endswith('64') else 'x86'
|
||||
vars.Add(EnumVariable('arch', 'Set target arch.', default_arch,
|
||||
allowed_values=('x86', 'x64', 'amd64', 'ppc'),
|
||||
map={'x64': 'amd64'}))
|
||||
|
||||
vars.Add(PathVariable('win32pthreads',
|
||||
'Path to win32-pthreads dir.',
|
||||
r'./../pthreads.2'))
|
||||
|
||||
vars.Add(PathVariable('copyto',
|
||||
'Copy exe and required DLLs to this dir.',
|
||||
'',
|
||||
PathVariable.PathAccept))
|
||||
|
||||
vars.Add(BoolVariable('dump_env',
|
||||
'Dump of construction environment to stdout.',
|
||||
False))
|
||||
|
||||
vars.Add(BoolVariable('use_yasm',
|
||||
'Use yasm.',
|
||||
True))
|
||||
|
||||
|
||||
# Create construction environments for 32 and 64 bit builds.
|
||||
# Visual studio needs the architecture to be set in this stage. It can not be
|
||||
# modified later.
|
||||
env_x86 = Environment(
|
||||
#tools=['mingw'],
|
||||
ASCOM='yasm $ASFLAGS -o $TARGET $SOURCES',
|
||||
ENV={'PATH': os.environ['PATH']}, # to find yasm on Windows
|
||||
TARGET_ARCH='x86', # for Visual Studio
|
||||
)
|
||||
env_x64 = Environment(
|
||||
#tools=['mingw'],
|
||||
ASCOM='yasm $ASFLAGS -o $TARGET $SOURCES',
|
||||
ENV={'PATH': os.environ['PATH']}, # to find yasm on Windows
|
||||
TARGET_ARCH='amd64', # for Visual Studio
|
||||
# modified later. Other tools ignore TARGET_ARCH.
|
||||
# The variable substitution is done in the environment construction so $arch
|
||||
# will not work here. Get the value manually.
|
||||
arch = ARGUMENTS.get('arch', default_arch)
|
||||
if arch == 'x64':
|
||||
arch = 'amd64'
|
||||
env = Environment(
|
||||
variables=vars,
|
||||
tools=['msvc', 'mslink', 'nasm'],
|
||||
ENV={'PATH': os.environ['PATH']}, # to find yasm
|
||||
TARGET_ARCH=arch, # for Visual Studio
|
||||
AS='yasm',
|
||||
)
|
||||
|
||||
# YASM flags for different architectures. The object file format and name
|
||||
# mangling must be the same as used by the C compiler for that OS.
|
||||
# Indexed by platform.system().
|
||||
yasm_flags = {
|
||||
'Windows': {
|
||||
'x86': '-f win32 -DPREFIX',
|
||||
'x64': '-f win64'},
|
||||
'Darwin': {
|
||||
'x86': '-f macho32 -DPREFIX',
|
||||
'x64': '-f macho64 -DPREFIX'},
|
||||
'Linux': { # Flags for Unix-like.
|
||||
'x86': '-f elf32',
|
||||
'x64': '-f elf64'},
|
||||
'all': { # Flags for all systems.
|
||||
'x86': ' -DARCH_X86_64=0 -m x86',
|
||||
'x64': ' -DARCH_X86_64=1 -m amd64'},
|
||||
}
|
||||
# Set yasm flags for OS and architecture.
|
||||
target_yasm_flags = yasm_flags.get(platform.system(), yasm_flags['Linux'])
|
||||
env_x86.Replace(ASFLAGS=target_yasm_flags['x86'])
|
||||
env_x64.Replace(ASFLAGS=target_yasm_flags['x64'])
|
||||
env_x86.Append(ASFLAGS=yasm_flags['all']['x86'])
|
||||
env_x64.Append(ASFLAGS=yasm_flags['all']['x64'])
|
||||
|
||||
Help("""
|
||||
Example: 'scons arch=x64' to compile for amd64.
|
||||
'scons --jobs=8' to compile in parallel.
|
||||
""" + vars.GenerateHelpText(env))
|
||||
|
||||
if 'MSVS' in env:
|
||||
compiler = 'msvs'
|
||||
elif 'MSYSTEM' in os.environ:
|
||||
compiler = 'mingw'
|
||||
else:
|
||||
compiler = 'gcc'
|
||||
|
||||
env['use_yasm'] = env['use_yasm'] and env['arch'] not in ('ppc',)
|
||||
|
||||
# pthreads_dll location for copyto
|
||||
pthreads_dll = None
|
||||
|
||||
# Try and deal with all the remaining compiler specific differences that I
|
||||
# really with scons would handle.
|
||||
if 'MSVS' in env_x86:
|
||||
# /MD = multithreaded DLL runtime
|
||||
# /Ox = full optimization, sets /Ob2, /Og, /Oi, /Ot, /Oy
|
||||
# /GL = enable whole program optimization
|
||||
# /LTCG = link time code generation
|
||||
# /arch:SSE2 = use SSE2 (x86 only)
|
||||
# win32-pthreads is assumed to be in same level as kvazaar in dir pthreads
|
||||
env_x86.Append(
|
||||
CCFLAGS=r'/MD /Ox /GL /arch:SSE2 /I"..\..\pthreads\include"',
|
||||
LINKFLAGS=r'/LTCG /LIBPATH:"..\..\pthreads\x86" "pthreadVC2.lib"')
|
||||
env_x64.Append(
|
||||
CCFLAGS=r'/MD /Ox /GL /I"..\..\pthreads\include"',
|
||||
LINKFLAGS=r'/LTCG /LIBPATH:"..\pthreads\x64" "pthreadVC2.lib"')
|
||||
# really wish scons would handle.
|
||||
if compiler in ('msvs',):
|
||||
arch_dir = {'x86': r'x86', 'amd64': r'x64'}[env['arch']]
|
||||
pthreads_dll = os.path.join(env['win32pthreads'], 'dll', arch_dir, 'pthreadVC2.dll')
|
||||
|
||||
env.Append(
|
||||
CCFLAGS=r'/MD /Ox /GL /wd"4028"',
|
||||
LINKFLAGS=r'/LTCG',
|
||||
LIBPATH=r'#$win32pthreads\lib\\' + arch_dir,
|
||||
LIBS=r'pthreadVC2',
|
||||
CPPPATH=r'#$win32pthreads\include')
|
||||
else:
|
||||
# GCC flags
|
||||
# -m for arch, -O2 for optimization, -lm for math lib
|
||||
env_x86.MergeFlags('-m32 -O2 -lm -march=native -pthread')
|
||||
env_x64.MergeFlags('-m64 -O2 -lm -march=native -pthread')
|
||||
env.MergeFlags('-O2 -pthread -lm -lrt -march=native')
|
||||
if env['arch'] == 'x86':
|
||||
env.MergeFlags('-m32')
|
||||
elif env['arch'] == 'amd64':
|
||||
env.MergeFlags('-m64')
|
||||
|
||||
# platform.system() lies on msys2, so just try to detect msys/mingw.
|
||||
if 'MSYSTEM' in os.environ:
|
||||
# __USE_MINGW_ANSI_STDIO required on mingw for printf to function.
|
||||
env.MergeFlags('-D' + '__USE_MINGW_ANSI_STDIO=1')
|
||||
|
||||
|
||||
# VS2010 linker and mingw64 need TMP.
|
||||
if 'TMP' in os.environ:
|
||||
env_x86['ENV']['TMP'] = os.environ['TMP']
|
||||
env_x64['ENV']['TMP'] = os.environ['TMP']
|
||||
if compiler in ('msvs', 'mingw'):
|
||||
if 'TMP' in os.environ:
|
||||
env['ENV']['TMP'] = os.environ['TMP']
|
||||
|
||||
env_x86.MergeFlags('-I. -Iextras -Istrategies')
|
||||
env_x64.MergeFlags('-I. -Iextras -Istrategies')
|
||||
|
||||
env.MergeFlags('-I. -Iextras -Istrategies')
|
||||
|
||||
# Take comma separated list from 'D=' and pass them on to
|
||||
# preprocessor as defines.
|
||||
preprocessor_defines = ARGUMENTS.get('D', '')
|
||||
if preprocessor_defines:
|
||||
for define in preprocessor_defines.split():
|
||||
env_x86.MergeFlags('-D' + define)
|
||||
env_x64.MergeFlags('-D' + define)
|
||||
for define in preprocessor_defines.split(','):
|
||||
env.MergeFlags('-D' + define)
|
||||
|
||||
# Declare build targets.
|
||||
x86 = SConscript('src/SConscript',
|
||||
exports={'env': env_x86},
|
||||
variant_dir='scons_build_x86',
|
||||
variant_dir = 'scons_build'
|
||||
|
||||
|
||||
class EnvinronmentContainer(object):
|
||||
"""Class for initializing and holding optimization environments.
|
||||
|
||||
As far as I know, making a separate environment is the only way to compile
|
||||
different objects with different flags in scons. So this constructs all
|
||||
the required environments.
|
||||
|
||||
Yasm is also its own environment although it's not strictly necessary.
|
||||
It does however allow KVZ_COMPILE_ASM to only those files that require
|
||||
it, avoiding a complete recompile.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, env, compiler, arch):
|
||||
# If optimization is not supported for arch, use default env.
|
||||
self.env = env
|
||||
self.sse2 = env
|
||||
self.sse41 = env
|
||||
self.avx = env
|
||||
self.avx2 = env
|
||||
self.altivec = env
|
||||
self.asm = env
|
||||
|
||||
if compiler == 'msvs':
|
||||
self.avx = env.Clone()
|
||||
self.avx.Append(CCFLAGS='/arch:AVX')
|
||||
self.avx2 = env.Clone()
|
||||
self.avx2.Append(CCFLAGS='/arch:AVX2')
|
||||
elif compiler in ('gcc',) and arch in ('x86', 'x64'):
|
||||
self.sse2 = env.Clone()
|
||||
self.sse2.Append(CCFLAGS='-msse2')
|
||||
self.sse41 = env.Clone().Append(CCFLAGS='-msse4.1')
|
||||
self.avx = env.Clone().Append(CCFLAGS='-mavx')
|
||||
self.avx2 = env.Clone().Append(CCFLAGS='-mavx2')
|
||||
elif compiler in ('gcc',) and arch in ('ppc'):
|
||||
self.altivec = env.Clone().Append(CCFLAGS='-maltivec')
|
||||
|
||||
if env['use_yasm']:
|
||||
self._init_yasm()
|
||||
|
||||
|
||||
def _init_yasm(self):
|
||||
self.asm = env.Clone()
|
||||
self.asm.MergeFlags('-D' + 'KVZ_COMPILE_ASM')
|
||||
|
||||
# YASM flags for different architectures. The object file format and name
|
||||
# mangling must be the same as used by the C compiler for that OS.
|
||||
# Indexed by platform.system().
|
||||
yasm_flags = {
|
||||
'Windows': {
|
||||
'x86': '-f win32 -DPREFIX -DHAVE_ALIGNED_STACK=0 ',
|
||||
'amd64': '-f win64 -DHAVE_ALIGNED_STACK=1',
|
||||
},
|
||||
'Darwin': {
|
||||
'x86': '-f macho32 -DPREFIX',
|
||||
'amd64': '-f macho64 -DPREFIX',
|
||||
},
|
||||
'Linux': { # Flags for Unix-like.
|
||||
'x86': '-f elf32',
|
||||
'amd64': '-f elf64',
|
||||
},
|
||||
'all': { # Flags for all systems.
|
||||
'x86': ' -I./src/extras -DARCH_X86_64=0 -m x86',
|
||||
'amd64': ' -I./src/extras -DARCH_X86_64=1 -m amd64',
|
||||
},
|
||||
}
|
||||
|
||||
# Set yasm flags for OS and architecture.
|
||||
target_yasm_flags = yasm_flags.get(platform.system(), yasm_flags['Linux'])
|
||||
self.asm.Replace(ASFLAGS=target_yasm_flags[env['arch']])
|
||||
self.asm.Append(ASFLAGS=yasm_flags['all'][env['arch']])
|
||||
self.asm.Replace(AS='yasm')
|
||||
|
||||
|
||||
envs = EnvinronmentContainer(env, compiler, env['arch'])
|
||||
|
||||
|
||||
program = SConscript('src/SConscript',
|
||||
exports={'envs': envs},
|
||||
variant_dir=variant_dir,
|
||||
duplicate=False)
|
||||
Alias('x86', x86)
|
||||
|
||||
x64 = SConscript('src/SConscript',
|
||||
exports={'env': env_x64},
|
||||
variant_dir='scons_build_x64',
|
||||
duplicate=False)
|
||||
Alias('x64', x64)
|
||||
|
||||
|
||||
if platform.machine().endswith('64'):
|
||||
Default(x64)
|
||||
# Copy exe and dll's to the path from 'copyto=' argument.
|
||||
copy_dir = env['copyto']
|
||||
if copy_dir:
|
||||
env.Install(copy_dir, program)
|
||||
if pthreads_dll:
|
||||
env.Install(copy_dir, pthreads_dll)
|
||||
env.Alias('copyto', copy_dir)
|
||||
Default([program, 'copyto'])
|
||||
else:
|
||||
Default(x86)
|
||||
Default(program)
|
||||
|
||||
|
||||
# Dumpo environment to stdout.
|
||||
if env['dump_env']:
|
||||
import difflib
|
||||
|
||||
def get_diff(orig_env, new_env):
|
||||
return "\n".join(difflib.unified_diff(orig_env, new_env.Dump().splitlines(), n=0))
|
||||
|
||||
env_dump = env.Dump().splitlines()
|
||||
print "== env"
|
||||
print "\n".join(env_dump)
|
||||
print "== diff env envs.sse2"
|
||||
print get_diff(env_dump, envs.sse2)
|
||||
print "== diff env envs.sse41"
|
||||
print get_diff(env_dump, envs.sse41)
|
||||
print "== diff env envs.avx"
|
||||
print get_diff(env_dump, envs.avx)
|
||||
print "== diff env envs.avx2"
|
||||
print get_diff(env_dump, envs.avx2)
|
||||
print "== diff env envs.altivec"
|
||||
print get_diff(env_dump, envs.altivec)
|
||||
print "== diff env envs.asm"
|
||||
print get_diff(env_dump, envs.asm)
|
||||
|
||||
|
|
|
@ -3,14 +3,25 @@
|
|||
|
||||
import os
|
||||
|
||||
Import('env')
|
||||
Import('envs')
|
||||
env = envs.env
|
||||
|
||||
sources = []
|
||||
sources += env.Glob('*.c')
|
||||
sources += env.Glob('extras/*.c')
|
||||
|
||||
sources += env.Glob('strategies/*.c')
|
||||
sources += env.Glob('x86/*.asm')
|
||||
env.Depends('x86/cpu.asm', 'x86/x86inc.asm')
|
||||
sources += env.Glob('strategies/generic/*.c')
|
||||
sources += envs.sse2.Object(env.Glob('strategies/sse2/*.c'))
|
||||
sources += envs.sse41.Object(env.Glob('strategies/sse41/*.c'))
|
||||
sources += envs.avx.Object(env.Glob('strategies/avx/*.c'))
|
||||
sources += envs.avx2.Object(env.Glob('strategies/avx2/*.c'))
|
||||
sources += envs.altivec.Object(env.Glob('strategies/altivec/*.c'))
|
||||
|
||||
sources += envs.asm.Object(env.Glob('strategies/x86_asm/*.c'))
|
||||
if env['use_yasm']:
|
||||
sources += envs.asm.Object(env.Glob('strategies/x86_asm/*.asm'))
|
||||
sources += envs.asm.Object(env.Glob('extras/*.asm'))
|
||||
|
||||
prog = env.Program('kvazaar', sources)
|
||||
|
||||
|
|
Loading…
Reference in a new issue