Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize Sample Extensions's AMBuildScript #2107

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
479 changes: 241 additions & 238 deletions public/sample_ext/AMBuildScript

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions public/sample_ext/AMBuilder
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
import os

# Name of your extesion, this will also be it's file name.
projectName = 'sample'

# smsdk_ext.cpp will be automatically added later
sourceFiles = [
'extension.cpp',
]

###############
# Make sure to edit PackageScript, which copies your files to their appropriate locations
# Simple extensions do not need to modify past this point.

project = Extension.HL2Project(builder, projectName + '.ext')
project = builder.LibraryProject(projectName)

if os.path.isfile(os.path.join(builder.currentSourcePath, 'sdk', 'smsdk_ext.cpp')):
# Use the copy included in the project
Expand All @@ -22,10 +19,16 @@ else:
project.sources += [os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp')]

project.sources += sourceFiles

for sdk_name in Extension.sdks:
sdk = Extension.sdks[sdk_name]

binary = Extension.HL2Config(project, projectName + '.ext.' + sdk.ext, sdk)
if sdk['name'] in ['mock']:
continue

for cxx in builder.targets:
if not cxx.target.arch in sdk['platforms'][cxx.target.platform]:
continue

binary = Extension.HL2ExtConfig(project, builder, cxx, projectName + '.ext.' + sdk['extension'], sdk)

Extension.extensions = builder.Add(project)
Extension.extensions += builder.Add(project)
10 changes: 9 additions & 1 deletion public/sample_ext/PackageScript
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ folder_list = [
#'addons/sourcemod/configs',
]

if 'x86_64' in Extension.target_archs:
folder_list.extend([
'addons/sourcemod/extensions/x64',
])

# Create the distribution folder hierarchy.
folder_map = {}
for folder in folder_list:
Expand Down Expand Up @@ -49,4 +54,7 @@ def CopyFiles(src, dest, files):

# Copy binaries.
for cxx_task in Extension.extensions:
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions'])
if cxx_task.target.arch == 'x86_64':
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions/x64'])
else:
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions'])
30 changes: 17 additions & 13 deletions public/sample_ext/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@

# Simple extensions do not need to modify this file.

builder = run.PrepareBuild(sourcePath = sys.path[0])

builder.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
builder.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source')
builder.options.add_option('--sm-path', type=str, dest='sm_path', default=None,
parser = run.BuildParser(sourcePath=sys.path[0], api='2.2')
parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
parser.options.add_argument('--hl2sdk-manifest-path', type=str, dest='hl2sdk_manifest', default=None,
help='Path to HL2SDK Manifests')
parser.options.add_argument('--sm-path', type=str, dest='sm_path', default=None,
help='Path to SourceMod')
builder.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source')

parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols')
builder.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
builder.options.add_option('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names (default: %default)')
parser.options.add_argument('-s', '--sdks', default='present', dest='sdks',
help='Build against specified SDKs; valid args are "none", "all", "present",'
' or comma-delimited list of engine names')
parser.options.add_argument('--targets', type=str, dest='targets', default=None,
help="Override the target architecture (use commas to separate multiple targets).")
parser.Configure()

builder.Configure()
163 changes: 112 additions & 51 deletions public/sample_ext_nosdk/AMBuildScript
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,45 @@ def ResolveEnvPath(env, folder):
def Normalize(path):
return os.path.abspath(os.path.normpath(path))

def SetArchFlags(compiler):
if compiler.behavior == 'gcc':
if compiler.target.arch == 'x86_64':
compiler.cflags += ['-fPIC']
elif compiler.like('msvc'):
if compiler.target.arch == 'x86_64':
compiler.defines += ['WIN64']

class ExtensionConfig(object):
def __init__(self):
self.binaries = []
self.extensions = []
self.generated_headers = None
self.mms_root = None
self.sm_root = None
self.all_targets = []
self.target_archs = set()

if builder.options.targets:
target_archs = builder.options.targets.split(',')
else:
target_archs = ['x86']
if builder.backend != 'amb2':
target_archs.append('x86_64')

for arch in target_archs:
try:
cxx = builder.DetectCxx(target_arch = arch)
self.target_archs.add(cxx.target.arch)
except Exception as e:
# Error if archs were manually overridden.
if builder.options.targets:
raise
print('Skipping target {}: {}'.format(arch, e))
continue
self.all_targets.append(cxx)

if not self.all_targets:
raise Exception('No suitable C/C++ compiler was found.')

@property
def tag(self):
Expand All @@ -42,7 +74,7 @@ class ExtensionConfig(object):
if builder.options.sm_path:
self.sm_root = builder.options.sm_path
else:
self.sm_root = ResolveEnvPath('SOURCEMOD18', 'sourcemod-1.8')
self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod')
if not self.sm_root:
Expand All @@ -66,14 +98,32 @@ class ExtensionConfig(object):
self.mms_root = Normalize(self.mms_root)

def configure(self):
cxx = builder.DetectCompilers()

allowed_archs = ['x86','x86_64']

if not set(self.target_archs).issubset(allowed_archs):
raise Exception('Unknown target architecture: {0}'.format(self.target_archs))

for cxx in self.all_targets:
self.configure_cxx(cxx)

def configure_cxx(self, cxx):
if cxx.family == 'msvc':
if cxx.version < 1914 and builder.options.generator != 'vs':
raise Exception(f'Only MSVC 2017 15.7 and later are supported, full C++17 support is required. ({str(cxx.version)} < 1914)')
elif cxx.family == 'gcc':
if cxx.version < 'gcc-9':
raise Exception('Only GCC versions 9 or later are supported, full C++17 support is required.')
elif cxx.family == 'clang':
if cxx.version < 'clang-5':
raise Exception('Only clang versions 5 or later are supported, full C++17 support is required.')

if cxx.like('gcc'):
self.configure_gcc(cxx)
elif cxx.vendor == 'msvc':
elif cxx.family == 'msvc':
self.configure_msvc(cxx)

# Optimization
# Optimizaiton
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']

Expand All @@ -82,16 +132,15 @@ class ExtensionConfig(object):
cxx.defines += ['DEBUG', '_DEBUG']

# Platform-specifics
if builder.target_platform == 'linux':
if cxx.target.platform == 'linux':
self.configure_linux(cxx)
elif builder.target_platform == 'mac':
elif cxx.target.platform == 'mac':
self.configure_mac(cxx)
elif builder.target_platform == 'windows':
elif cxx.target.platform == 'windows':
self.configure_windows(cxx)

# Finish up.
cxx.includes += [
os.path.join(self.sm_root, 'public'),
os.path.join(builder.sourcePath, 'public'),
]

def configure_gcc(self, cxx):
Expand All @@ -111,31 +160,39 @@ class ExtensionConfig(object):
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',
'-msse',
'-m32',
'-fvisibility=hidden',
]
if cxx.target.arch in ['x86', 'x86_64']:
cxx.cflags += ['-msse']

cxx.cxxflags += ['-std=c++17']

cxx.cxxflags += [
'-std=c++14',
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
'-Wno-register',
'-fvisibility-inlines-hidden',
]
cxx.linkflags += ['-m32']

have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if cxx.version >= 'clang-3.6':
have_gcc = cxx.family == 'gcc'
have_clang = cxx.family == 'clang'
if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0':
cxx.cxxflags += ['-Wno-expansion-to-defined']
if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
cxx.cflags += ['-Wno-varargs']
if cxx.version >= 'clang-3.4' or cxx.version >= 'apple-clang-7.0':
cxx.cxxflags += ['-Wno-inconsistent-missing-override']
if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
cxx.cxxflags += ['-Wno-null-dereference']
if have_clang or (cxx.version >= 'gcc-4.6'):
cxx.cflags += ['-Wno-narrowing']
if have_clang or (cxx.version >= 'gcc-4.7'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.version >= 'gcc-4.8':
cxx.cflags += ['-Wno-unused-result']

if cxx.version >= 'gcc-9.0':
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
Expand All @@ -144,13 +201,25 @@ class ExtensionConfig(object):
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']

# Work around SDK warnings.
if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0':
cxx.cflags += [
'-Wno-implicit-int-float-conversion',
'-Wno-tautological-overlap-compare',
]

if have_gcc:
cxx.cflags += ['-mfpmath=sse']
cxx.cflags += ['-Wno-maybe-uninitialized']

if builder.options.opt == '1':
cxx.cflags += ['-O3']
cxx.cflags += ['-O3']

# Don't omit the frame pointer.
cxx.cflags += ['-fno-omit-frame-pointer']

def configure_msvc(self, cxx):

if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
Expand All @@ -169,9 +238,9 @@ class ExtensionConfig(object):
'/EHsc',
'/GR-',
'/TP',
'/std:c++17',
]
cxx.linkflags += [
'/MACHINE:X86',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
Expand All @@ -198,23 +267,23 @@ class ExtensionConfig(object):
cxx.cflags += ['/Oy-']

def configure_linux(self, cxx):
cxx.defines += ['_LINUX', 'POSIX']
cxx.linkflags += ['-Wl,--exclude-libs,ALL', '-lm']
if cxx.vendor == 'gcc':
cxx.defines += ['LINUX', '_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
cxx.linkflags += ['-lm']
if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang':
elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh']
cxx.linkflags += ['-static-libstdc++']

def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
cxx.cflags += ['-mmacosx-version-min=10.15']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libstdc++',
'-mmacosx-version-min=10.15',
'-stdlib=libc++',
'-lc++',
]
cxx.cxxflags += ['-stdlib=libstdc++']
cxx.cxxflags += ['-stdlib=libc++']

def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS']
Expand All @@ -233,26 +302,14 @@ class ExtensionConfig(object):

def ConfigureForHL2(self, binary):
compiler = binary.compiler

mms_path = os.path.join(self.mms_root, 'core')
SetArchFlags(compiler)

compiler.cxxincludes += [
os.path.join(mms_path),
os.path.join(mms_path, 'sourcehook'),
os.path.join(self.mms_root, 'core'),
os.path.join(self.mms_root, 'core', 'sourcehook'),
]

compiler.defines += ['META_NO_HL2SDK']

if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
else:
compiler.defines += ['COMPILER_GCC']

if builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv')

return binary

def HL2Library(self, context, name):
Expand All @@ -261,18 +318,22 @@ class ExtensionConfig(object):
return self.ConfigureForHL2(binary)

def HL2Project(self, context, name):
project = context.compiler.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler)
project = builder.LibraryProject(name)
return project

def HL2Config(self, project, name):
binary = project.Configure(name, '{0}'.format(self.tag))
def HL2Config(self, context, project, name, compiler):
binary = project.Configure(compiler, name, '{0} - {1}'.format(self.tag, compiler.target.arch))
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary)

Extension = ExtensionConfig()
Extension.detectSDKs()
Extension.configure()

# This will clone the list and each cxx object as we recurse, preventing child
# scripts from messing up global state.
builder.targets = builder.CloneableList(Extension.all_targets)

# Add additional buildscripts here
BuildScripts = [
'AMBuilder',
Expand All @@ -283,4 +344,4 @@ if builder.backend == 'amb2':
'PackageScript',
]

builder.RunBuildScripts(BuildScripts, { 'Extension': Extension})
builder.Build(BuildScripts, { 'Extension': Extension })
Loading