mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 11:24:05 +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
290
SConstruct
290
SConstruct
|
@ -1,116 +1,236 @@
|
||||||
""" SConstruct file fore building Kvazaar with Scons.
|
""" SConstruct file fore building Kvazaar with Scons.
|
||||||
|
|
||||||
This file defines two targets, x86 and x64, and builds construction
|
This is an additional cross platform way to build the program.
|
||||||
environments for both.
|
The main way is to use the Makefile and that is always kept up to date.
|
||||||
|
|
||||||
TODO:
|
This mostly exists so it can be used with a custom SConscript file that
|
||||||
- add debug builds
|
builds any old version of Kvazaar, ensuring that the compilation settings are
|
||||||
- whole program optimization for gcc
|
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 os
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
Help("""
|
|
||||||
Type: 'scons x86' to build a 32-bit release version,
|
vars = Variables()
|
||||||
'scons x64' to build a 64-bit release version.
|
|
||||||
'scons x86 x64 -c' to clear all build directories.
|
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
|
# Visual studio needs the architecture to be set in this stage. It can not be
|
||||||
# modified later.
|
# modified later. Other tools ignore TARGET_ARCH.
|
||||||
env_x86 = Environment(
|
# The variable substitution is done in the environment construction so $arch
|
||||||
#tools=['mingw'],
|
# will not work here. Get the value manually.
|
||||||
ASCOM='yasm $ASFLAGS -o $TARGET $SOURCES',
|
arch = ARGUMENTS.get('arch', default_arch)
|
||||||
ENV={'PATH': os.environ['PATH']}, # to find yasm on Windows
|
if arch == 'x64':
|
||||||
TARGET_ARCH='x86', # for Visual Studio
|
arch = 'amd64'
|
||||||
)
|
env = Environment(
|
||||||
env_x64 = Environment(
|
variables=vars,
|
||||||
#tools=['mingw'],
|
tools=['msvc', 'mslink', 'nasm'],
|
||||||
ASCOM='yasm $ASFLAGS -o $TARGET $SOURCES',
|
ENV={'PATH': os.environ['PATH']}, # to find yasm
|
||||||
ENV={'PATH': os.environ['PATH']}, # to find yasm on Windows
|
TARGET_ARCH=arch, # for Visual Studio
|
||||||
TARGET_ARCH='amd64', # 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
|
# Try and deal with all the remaining compiler specific differences that I
|
||||||
# really with scons would handle.
|
# really wish scons would handle.
|
||||||
if 'MSVS' in env_x86:
|
if compiler in ('msvs',):
|
||||||
# /MD = multithreaded DLL runtime
|
arch_dir = {'x86': r'x86', 'amd64': r'x64'}[env['arch']]
|
||||||
# /Ox = full optimization, sets /Ob2, /Og, /Oi, /Ot, /Oy
|
pthreads_dll = os.path.join(env['win32pthreads'], 'dll', arch_dir, 'pthreadVC2.dll')
|
||||||
# /GL = enable whole program optimization
|
|
||||||
# /LTCG = link time code generation
|
env.Append(
|
||||||
# /arch:SSE2 = use SSE2 (x86 only)
|
CCFLAGS=r'/MD /Ox /GL /wd"4028"',
|
||||||
# win32-pthreads is assumed to be in same level as kvazaar in dir pthreads
|
LINKFLAGS=r'/LTCG',
|
||||||
env_x86.Append(
|
LIBPATH=r'#$win32pthreads\lib\\' + arch_dir,
|
||||||
CCFLAGS=r'/MD /Ox /GL /arch:SSE2 /I"..\..\pthreads\include"',
|
LIBS=r'pthreadVC2',
|
||||||
LINKFLAGS=r'/LTCG /LIBPATH:"..\..\pthreads\x86" "pthreadVC2.lib"')
|
CPPPATH=r'#$win32pthreads\include')
|
||||||
env_x64.Append(
|
|
||||||
CCFLAGS=r'/MD /Ox /GL /I"..\..\pthreads\include"',
|
|
||||||
LINKFLAGS=r'/LTCG /LIBPATH:"..\pthreads\x64" "pthreadVC2.lib"')
|
|
||||||
else:
|
else:
|
||||||
# GCC flags
|
env.MergeFlags('-O2 -pthread -lm -lrt -march=native')
|
||||||
# -m for arch, -O2 for optimization, -lm for math lib
|
if env['arch'] == 'x86':
|
||||||
env_x86.MergeFlags('-m32 -O2 -lm -march=native -pthread')
|
env.MergeFlags('-m32')
|
||||||
env_x64.MergeFlags('-m64 -O2 -lm -march=native -pthread')
|
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.
|
# VS2010 linker and mingw64 need TMP.
|
||||||
if 'TMP' in os.environ:
|
if compiler in ('msvs', 'mingw'):
|
||||||
env_x86['ENV']['TMP'] = os.environ['TMP']
|
if 'TMP' in os.environ:
|
||||||
env_x64['ENV']['TMP'] = os.environ['TMP']
|
env['ENV']['TMP'] = os.environ['TMP']
|
||||||
|
|
||||||
env_x86.MergeFlags('-I. -Iextras -Istrategies')
|
env.MergeFlags('-I. -Iextras -Istrategies')
|
||||||
env_x64.MergeFlags('-I. -Iextras -Istrategies')
|
|
||||||
|
|
||||||
|
# Take comma separated list from 'D=' and pass them on to
|
||||||
|
# preprocessor as defines.
|
||||||
preprocessor_defines = ARGUMENTS.get('D', '')
|
preprocessor_defines = ARGUMENTS.get('D', '')
|
||||||
if preprocessor_defines:
|
if preprocessor_defines:
|
||||||
for define in preprocessor_defines.split():
|
for define in preprocessor_defines.split(','):
|
||||||
env_x86.MergeFlags('-D' + define)
|
env.MergeFlags('-D' + define)
|
||||||
env_x64.MergeFlags('-D' + define)
|
|
||||||
|
|
||||||
# Declare build targets.
|
# Declare build targets.
|
||||||
x86 = SConscript('src/SConscript',
|
variant_dir = 'scons_build'
|
||||||
exports={'env': env_x86},
|
|
||||||
variant_dir='scons_build_x86',
|
|
||||||
|
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)
|
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'):
|
# Copy exe and dll's to the path from 'copyto=' argument.
|
||||||
Default(x64)
|
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:
|
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 os
|
||||||
|
|
||||||
Import('env')
|
Import('envs')
|
||||||
|
env = envs.env
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
sources += env.Glob('*.c')
|
sources += env.Glob('*.c')
|
||||||
sources += env.Glob('extras/*.c')
|
sources += env.Glob('extras/*.c')
|
||||||
|
|
||||||
sources += env.Glob('strategies/*.c')
|
sources += env.Glob('strategies/*.c')
|
||||||
sources += env.Glob('x86/*.asm')
|
sources += env.Glob('strategies/generic/*.c')
|
||||||
env.Depends('x86/cpu.asm', 'x86/x86inc.asm')
|
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)
|
prog = env.Program('kvazaar', sources)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue