mirror of
https://github.com/ZDoom/zdoom-macos-deps.git
synced 2024-11-22 03:51:33 +00:00
build script: extract target logic from builder class
this allows to have: * target with build system other than cmake * target with source code origin other than git repository
This commit is contained in:
parent
b3d06b1a29
commit
d04d4cc55e
1 changed files with 206 additions and 174 deletions
380
build.py
380
build.py
|
@ -32,17 +32,96 @@ import subprocess
|
|||
|
||||
|
||||
class Target:
|
||||
def __init__(self: str):
|
||||
self.name = None
|
||||
self.url = None
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
self.src_root = ''
|
||||
self.cmake_options = {}
|
||||
self.post_build = None
|
||||
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
pass
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
pass
|
||||
|
||||
def detect(self, builder: 'Builder') -> bool:
|
||||
return False
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
pass
|
||||
|
||||
def _assign_common_linker_flags(self, builder: 'Builder'):
|
||||
def build(self, builder: 'Builder'):
|
||||
pass
|
||||
|
||||
def post_build(self, builder: 'Builder'):
|
||||
pass
|
||||
|
||||
|
||||
class CMakeTarget(Target):
|
||||
def __init__(self, name=None):
|
||||
super().__init__(name)
|
||||
|
||||
def detect(self, builder: 'Builder') -> bool:
|
||||
src_root = self.src_root and os.sep + self.src_root or ''
|
||||
cmakelists_path = builder.source_path + src_root + os.sep + 'CMakeLists.txt'
|
||||
|
||||
if not os.path.exists(cmakelists_path):
|
||||
return False
|
||||
|
||||
for line in open(cmakelists_path).readlines():
|
||||
project_name = CMakeTarget._extract_project_name(line)
|
||||
if project_name:
|
||||
project_name = project_name.lower()
|
||||
project_name = project_name.replace(' ', '-')
|
||||
break
|
||||
else:
|
||||
return False
|
||||
|
||||
return project_name == self.name
|
||||
|
||||
@staticmethod
|
||||
def _extract_project_name(line: str):
|
||||
project_name = None
|
||||
|
||||
# Try to get project name without whitespaces in it
|
||||
match = re.search(r'project\s*\(\s*(\w[\w-]+)', line, re.IGNORECASE)
|
||||
|
||||
if not match:
|
||||
# Try to get project name that contains whitespaces
|
||||
match = re.search(r'project\s*\(\s*"?(\w[\s\w-]+)"?', line, re.IGNORECASE)
|
||||
|
||||
if match:
|
||||
project_name = match.group(1)
|
||||
|
||||
return project_name
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
environ = os.environ
|
||||
environ['PATH'] = environ['PATH'] \
|
||||
+ os.pathsep + '/Applications/CMake.app/Contents/bin' \
|
||||
+ os.pathsep + builder.bin_path
|
||||
environ['PKG_CONFIG_PATH'] = builder.lib_path + 'pkgconfig'
|
||||
|
||||
os.makedirs(builder.build_path, exist_ok=True)
|
||||
|
||||
args = [
|
||||
'cmake',
|
||||
builder.xcode and '-GXcode' or '-GUnix Makefiles',
|
||||
'-DCMAKE_BUILD_TYPE=Release',
|
||||
'-DCMAKE_PREFIX_PATH=' + builder.prefix_path,
|
||||
'-DCMAKE_OSX_DEPLOYMENT_TARGET=' + builder.os_version,
|
||||
]
|
||||
|
||||
if builder.sdk_path:
|
||||
args.append('-DCMAKE_OSX_SYSROOT=' + builder.sdk_path)
|
||||
|
||||
for cmake_arg_name, cmake_arg_value in self.cmake_options.items():
|
||||
args.append(f'-D{cmake_arg_name}={cmake_arg_value}')
|
||||
|
||||
args.append(builder.source_path + self.src_root)
|
||||
|
||||
subprocess.check_call(args, cwd=builder.build_path, env=environ)
|
||||
|
||||
def _link_with_sound_libraries(self, builder: 'Builder'):
|
||||
extra_libs = (
|
||||
'mpg123',
|
||||
|
||||
|
@ -73,13 +152,26 @@ class Target:
|
|||
|
||||
self.cmake_options['CMAKE_EXE_LINKER_FLAGS'] = linker_args
|
||||
|
||||
def build(self, builder: 'Builder'):
|
||||
if builder.xcode:
|
||||
# TODO: support case-sensitive file system
|
||||
args = ('open', self.name + '.xcodeproj')
|
||||
else:
|
||||
jobs = subprocess.check_output(['sysctl', '-n', 'hw.ncpu']).decode('ascii').strip()
|
||||
args = ['make', '-j', jobs]
|
||||
|
||||
class ZDoomBaseTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
if builder.verbose:
|
||||
args.append('VERBOSE=1')
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
subprocess.check_call(args, cwd=builder.build_path)
|
||||
|
||||
|
||||
class ZDoomBaseTarget(CMakeTarget):
|
||||
def __init__(self, name=None):
|
||||
super().__init__(name)
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
opts = self.cmake_options
|
||||
opts['PK3_QUIET_ZIPDIR'] = 'YES'
|
||||
|
@ -90,14 +182,14 @@ class ZDoomBaseTarget(Target):
|
|||
|
||||
|
||||
class GZDoomTarget(ZDoomBaseTarget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'gzdoom'
|
||||
self.url = 'https://github.com/coelckers/gzdoom.git'
|
||||
self.post_build = GZDoomTarget._copy_moltenvk
|
||||
def __init__(self, name='gzdoom'):
|
||||
super().__init__(name)
|
||||
|
||||
@staticmethod
|
||||
def _copy_moltenvk(builder: 'Builder'):
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/coelckers/gzdoom.git')
|
||||
|
||||
def post_build(self, builder: 'Builder'):
|
||||
# Put MoltenVK library into application bundle
|
||||
molten_lib = 'libMoltenVK.dylib'
|
||||
src_path = builder.lib_path + molten_lib
|
||||
dst_path = builder.build_path
|
||||
|
@ -106,7 +198,7 @@ class GZDoomTarget(ZDoomBaseTarget):
|
|||
# TODO: Support other configurations
|
||||
dst_path += 'Debug' + os.sep
|
||||
|
||||
dst_path += builder.target.name + '.app/Contents/MacOS' + os.sep
|
||||
dst_path += self.name + '.app/Contents/MacOS' + os.sep
|
||||
os.makedirs(dst_path, exist_ok=True)
|
||||
|
||||
dst_path += molten_lib
|
||||
|
@ -117,20 +209,22 @@ class GZDoomTarget(ZDoomBaseTarget):
|
|||
|
||||
|
||||
class QZDoomTarget(GZDoomTarget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'qzdoom'
|
||||
self.url = 'https://github.com/madame-rachelle/qzdoom.git'
|
||||
def __init__(self, name='qzdoom'):
|
||||
super().__init__(name)
|
||||
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/madame-rachelle/qzdoom.git')
|
||||
|
||||
|
||||
class LZDoomTarget(ZDoomBaseTarget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'lzdoom'
|
||||
self.url = 'https://github.com/drfrag666/gzdoom.git'
|
||||
def __init__(self, name='lzdoom'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
super().configure(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/drfrag666/gzdoom.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
super().initialize(builder)
|
||||
|
||||
opts = self.cmake_options
|
||||
opts['DYN_FLUIDSYNTH'] = 'NO'
|
||||
|
@ -139,19 +233,22 @@ class LZDoomTarget(ZDoomBaseTarget):
|
|||
|
||||
|
||||
class RazeTarget(ZDoomBaseTarget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'raze'
|
||||
self.url = 'https://github.com/coelckers/Raze.git'
|
||||
def __init__(self, name='raze'):
|
||||
super().__init__(name)
|
||||
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/coelckers/Raze.git')
|
||||
|
||||
|
||||
class ZandronumTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'zandronum'
|
||||
self.url = 'https://github.com/TorrSamaho/zandronum.git'
|
||||
class ZandronumTarget(CMakeTarget):
|
||||
def __init__(self, name='zandronum'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
# TODO: use official Mercurial repository
|
||||
builder.checkout_git('https://github.com/TorrSamaho/zandronum.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
opts = self.cmake_options
|
||||
opts['CMAKE_EXE_LINKER_FLAGS'] = '-framework AudioUnit -framework Carbon -framework IOKit'
|
||||
# TODO: Linking to FluidSynth is disabled because Zandronum doesn't support FluidSynth 2.x
|
||||
|
@ -160,22 +257,24 @@ class ZandronumTarget(Target):
|
|||
opts['FMOD_LIBRARY'] = builder.lib_path + 'libfmodex.dylib'
|
||||
|
||||
|
||||
class AccTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'acc'
|
||||
self.url = 'https://github.com/rheit/acc.git'
|
||||
class AccTarget(CMakeTarget):
|
||||
def __init__(self, name='acc'):
|
||||
super().__init__(name)
|
||||
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/rheit/acc.git')
|
||||
|
||||
|
||||
class PrBoomPlusTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'prboom-plus'
|
||||
self.url = 'https://github.com/coelckers/prboom-plus.git'
|
||||
class PrBoomPlusTarget(CMakeTarget):
|
||||
def __init__(self, name='prboom-plus'):
|
||||
super().__init__(name)
|
||||
self.src_root = 'prboom2'
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/coelckers/prboom-plus.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
extra_linker_args = ' -framework ForceFeedback -framework IOKit'
|
||||
|
||||
|
@ -195,14 +294,15 @@ class PrBoomPlusTarget(Target):
|
|||
opts['CMAKE_POLICY_DEFAULT_CMP0056'] = 'NEW'
|
||||
|
||||
|
||||
class ChocolateDoomTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'chocolate-doom'
|
||||
self.url = 'https://github.com/chocolate-doom/chocolate-doom.git'
|
||||
class ChocolateDoomTarget(CMakeTarget):
|
||||
def __init__(self, name='chocolate-doom'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/chocolate-doom/chocolate-doom.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
extra_linker_args = ' -lc++ -framework Cocoa -framework ForceFeedback -framework IOKit'
|
||||
|
||||
|
@ -229,20 +329,22 @@ class ChocolateDoomTarget(Target):
|
|||
|
||||
|
||||
class CrispyDoomTarget(ChocolateDoomTarget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'crispy-doom'
|
||||
self.url = 'https://github.com/fabiangreffrath/crispy-doom.git'
|
||||
def __init__(self, name='crispy-doom'):
|
||||
super().__init__(name)
|
||||
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/fabiangreffrath/crispy-doom.git')
|
||||
|
||||
|
||||
class DoomRetroTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'doomretro'
|
||||
self.url = 'https://github.com/bradharding/doomretro.git'
|
||||
class DoomRetroTarget(CMakeTarget):
|
||||
def __init__(self, name='doomretro'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/bradharding/doomretro.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
extra_linker_args = ' -lc++ -framework Cocoa -framework ForceFeedback -framework IOKit'
|
||||
|
||||
|
@ -272,28 +374,30 @@ class DoomRetroTarget(Target):
|
|||
opts['CMAKE_EXE_LINKER_FLAGS'] += extra_linker_args
|
||||
|
||||
|
||||
class Doom64EXTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'doom64ex'
|
||||
self.url = 'https://github.com/svkaiser/Doom64EX.git'
|
||||
class Doom64EXTarget(CMakeTarget):
|
||||
def __init__(self, name='doom64ex'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/svkaiser/Doom64EX.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
opts = self.cmake_options
|
||||
opts['ENABLE_SYSTEM_FLUIDSYNTH'] = 'YES'
|
||||
opts['CMAKE_EXE_LINKER_FLAGS'] += ' -framework Cocoa -framework ForceFeedback -framework IOKit'
|
||||
|
||||
|
||||
class DevilutionXTarget(Target):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'devilutionx'
|
||||
self.url = 'https://github.com/diasurgical/devilutionX.git'
|
||||
class DevilutionXTarget(CMakeTarget):
|
||||
def __init__(self, name='devilutionx'):
|
||||
super().__init__(name)
|
||||
|
||||
def configure(self, builder: 'Builder'):
|
||||
self._assign_common_linker_flags(builder)
|
||||
def prepare_source(self, builder: 'Builder'):
|
||||
builder.checkout_git('https://github.com/diasurgical/devilutionX.git')
|
||||
|
||||
def initialize(self, builder: 'Builder'):
|
||||
self._link_with_sound_libraries(builder)
|
||||
|
||||
extra_linker_args = ' -framework Cocoa -framework ForceFeedback -framework IOKit'
|
||||
|
||||
|
@ -350,13 +454,16 @@ class Builder(object):
|
|||
self.source_path += os.sep
|
||||
self.build_path += os.sep
|
||||
|
||||
self.target.configure(self)
|
||||
self.target.initialize(self)
|
||||
|
||||
def run(self):
|
||||
self._create_prefix_directory()
|
||||
self._prepare_source()
|
||||
self._generate_cmake()
|
||||
self._build_target()
|
||||
|
||||
target = self.target
|
||||
target.prepare_source(self)
|
||||
target.configure(self)
|
||||
target.build(self)
|
||||
target.post_build(self)
|
||||
|
||||
def _create_prefix_directory(self):
|
||||
os.makedirs(self.bin_path, exist_ok=True)
|
||||
|
@ -396,97 +503,13 @@ class Builder(object):
|
|||
symlink_deps('include')
|
||||
symlink_deps('lib')
|
||||
|
||||
def _prepare_source(self):
|
||||
if not os.path.exists(self.source_path):
|
||||
args = ('git', 'clone', '--recurse-submodules', self.target.url, self.source_path)
|
||||
subprocess.check_call(args, cwd=self.root_path)
|
||||
|
||||
if self.checkout_commit:
|
||||
args = ['git', 'checkout', self.checkout_commit]
|
||||
subprocess.check_call(args, cwd=self.source_path)
|
||||
|
||||
def _generate_cmake(self):
|
||||
environ = os.environ
|
||||
environ['PATH'] = environ['PATH'] \
|
||||
+ os.pathsep + '/Applications/CMake.app/Contents/bin' \
|
||||
+ os.pathsep + self.bin_path
|
||||
environ['PKG_CONFIG_PATH'] = self.lib_path + 'pkgconfig'
|
||||
|
||||
os.makedirs(self.build_path, exist_ok=True)
|
||||
|
||||
args = [
|
||||
'cmake',
|
||||
self.xcode and '-GXcode' or '-GUnix Makefiles',
|
||||
'-DCMAKE_BUILD_TYPE=Release',
|
||||
'-DCMAKE_PREFIX_PATH=' + self.prefix_path,
|
||||
'-DCMAKE_OSX_DEPLOYMENT_TARGET=' + self.os_version,
|
||||
]
|
||||
|
||||
if self.sdk_path:
|
||||
args.append('-DCMAKE_OSX_SYSROOT=' + self.sdk_path)
|
||||
|
||||
for cmake_arg_name, cmake_arg_value in self.target.cmake_options.items():
|
||||
args.append(f'-D{cmake_arg_name}={cmake_arg_value}')
|
||||
|
||||
args.append(self.source_path + self.target.src_root)
|
||||
|
||||
subprocess.check_call(args, cwd=self.build_path, env=environ)
|
||||
|
||||
def _build_target(self):
|
||||
if self.xcode:
|
||||
# TODO: support case-sensitive file system
|
||||
args = ('open', self.target.name + '.xcodeproj')
|
||||
else:
|
||||
jobs = subprocess.check_output(['sysctl', '-n', 'hw.ncpu']).decode('ascii').strip()
|
||||
args = ['make', '-j', jobs]
|
||||
|
||||
if self.verbose:
|
||||
args.append('VERBOSE=1')
|
||||
|
||||
subprocess.check_call(args, cwd=self.build_path)
|
||||
|
||||
if self.target.post_build:
|
||||
self.target.post_build(self)
|
||||
|
||||
@staticmethod
|
||||
def extract_project_name(line: str):
|
||||
project_name = None
|
||||
|
||||
# Try to get project name without whitespaces in it
|
||||
match = re.search(r'project\s*\(\s*(\w[\w-]+)', line, re.IGNORECASE)
|
||||
|
||||
if not match:
|
||||
# Try to get project name that contains whitespaces
|
||||
match = re.search(r'project\s*\(\s*"?(\w[\s\w-]+)"?', line, re.IGNORECASE)
|
||||
|
||||
if match:
|
||||
project_name = match.group(1)
|
||||
|
||||
return project_name
|
||||
|
||||
def _detect_target(self):
|
||||
cmakelists_path = None
|
||||
|
||||
for target in self.targets.values():
|
||||
src_root = target.src_root and os.sep + target.src_root or ''
|
||||
probe_path = self.source_path + src_root + os.sep + 'CMakeLists.txt'
|
||||
|
||||
if os.path.exists(probe_path):
|
||||
cmakelists_path = probe_path
|
||||
for name, target in self.targets.items():
|
||||
if target.detect(self):
|
||||
self.target = self.targets[name]
|
||||
break
|
||||
|
||||
assert cmakelists_path
|
||||
project_name = None
|
||||
|
||||
for line in open(cmakelists_path).readlines():
|
||||
project_name = Builder.extract_project_name(line)
|
||||
if project_name:
|
||||
project_name = project_name.lower()
|
||||
break
|
||||
|
||||
assert project_name
|
||||
project_name = project_name.replace(' ', '-')
|
||||
self.target = self.targets[project_name]
|
||||
assert self.target
|
||||
|
||||
def _create_targets(self):
|
||||
targets = (
|
||||
|
@ -526,6 +549,15 @@ class Builder(object):
|
|||
|
||||
return parser.parse_args(args)
|
||||
|
||||
def checkout_git(self, url: str):
|
||||
if not os.path.exists(self.source_path):
|
||||
args = ('git', 'clone', '--recurse-submodules', url, self.source_path)
|
||||
subprocess.check_call(args, cwd=self.root_path)
|
||||
|
||||
if self.checkout_commit:
|
||||
args = ['git', 'checkout', self.checkout_commit]
|
||||
subprocess.check_call(args, cwd=self.source_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Builder(sys.argv[1:]).run()
|
||||
|
|
Loading…
Reference in a new issue