AMBuildScript
author Scott Ehlert <ds@alliedmods.net>
Sat May 17 16:19:00 2014 -0500 (2014-05-17)
changeset 914 d0ea7151b71d
parent 909 57797db1d513
child 916 f280cbd99586
permissions -rw-r--r--
Sync changes from SourceMod's bootstrap script.
[email protected]
     1
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
[email protected]
     2
import os, sys
[email protected]
     3
[email protected]
     4
class SDK(object):
[email protected]
     5
  def __init__(self, sdk, ext, aDef, name, platform, dir):
[email protected]
     6
    if dir == 'ep1':
[email protected]
     7
      folder = 'hl2sdk'
[email protected]
     8
    else:
[email protected]
     9
      folder = 'hl2sdk-' + dir
[email protected]
    10
    self.envvar = sdk
[email protected]
    11
    self.ext = ext
[email protected]
    12
    self.code = aDef
[email protected]
    13
    self.define = name
[email protected]
    14
    self.platform = platform
[email protected]
    15
    self.folder = folder # Default folder name.
[email protected]
    16
    self.name = dir
[email protected]
    17
    self.path = None # Actual path
[email protected]
    18
[email protected]
    19
WinOnly = ['windows']
[email protected]
    20
WinLinux = ['windows', 'linux']
[email protected]
    21
WinLinuxMac = ['windows', 'linux', 'mac']
[email protected]
    22
[email protected]
    23
PossibleSDKs = {
[email protected]
    24
  'ep1':  SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'ep1'),
[email protected]
    25
  'ep2':  SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'ob'),
[email protected]
    26
  'css':  SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
[email protected]
    27
  'hl2dm':  SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
[email protected]
    28
  'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
[email protected]
    29
  'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, '2013'),
[email protected]
    30
  'tf2':  SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
[email protected]
    31
  'l4d':  SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
[email protected]
    32
  'nd': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nd'),
[email protected]
    33
  'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '14', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
[email protected]
    34
  'darkm':  SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
[email protected]
    35
  'swarm':  SDK('HL2SDK-SWARM', '2.swarm', '15', 'ALIENSWARM', WinOnly, 'swarm'),
[email protected]
    36
  'bgt':  SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
[email protected]
    37
  'eye':  SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
[email protected]
    38
  'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'),
[email protected]
    39
  'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'),
[email protected]
    40
  'portal2':  SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
[email protected]
    41
  'blade':  SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'),
[email protected]
    42
  'insurgency':  SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'),
[email protected]
    43
  'contagion':  SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'),
[email protected]
    44
}
[email protected]
    45
[email protected]
    46
def ResolveEnvPath(env, folder):
[email protected]
    47
  if env in os.environ:
[email protected]
    48
    path = os.environ[env]
[email protected]
    49
    if os.path.isdir(path):
[email protected]
    50
      return path
[email protected]
    51
  else:
[email protected]
    52
    head = os.getcwd()
[email protected]
    53
    oldhead = None
[email protected]
    54
    while head != None and head != oldhead:
[email protected]
    55
      path = os.path.join(head, folder)
[email protected]
    56
      if os.path.isdir(path):
[email protected]
    57
        return path
[email protected]
    58
      oldhead = head
[email protected]
    59
      head, tail = os.path.split(head)
[email protected]
    60
  return None
[email protected]
    61
[email protected]
    62
class MMSConfig(object):
[email protected]
    63
  def __init__(self):
[email protected]
    64
    self.sdks = {}
[email protected]
    65
    self.binaries = []
[email protected]
    66
    self.generated_headers = None
[email protected]
    67
    self.versionlib = None
[email protected]
    68
[email protected]
    69
  def detectProductVersion(self):
[email protected]
    70
    builder.AddConfigureFile('product.version')
[email protected]
    71
[email protected]
    72
    # For OS X dylib versioning
[email protected]
    73
    import re
[email protected]
    74
    with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
[email protected]
    75
      productContents = fp.read()
[email protected]
    76
    m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
[email protected]
    77
    if m == None:
[email protected]
    78
      self.productVersion = '1.0.0'
[email protected]
    79
    else:
[email protected]
    80
      major, minor, release = m.groups()
[email protected]
    81
      self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
[email protected]
    82
[email protected]
    83
  def detectSDKs(self):
[email protected]
    84
    sdk_list = builder.options.sdks.split(',')
[email protected]
    85
    use_all = sdk_list[0] == 'all'
[email protected]
    86
    use_present = sdk_list[0] == 'present'
[email protected]
    87
[email protected]
    88
    for sdk_name in PossibleSDKs:
[email protected]
    89
      sdk = PossibleSDKs[sdk_name]
[email protected]
    90
      if builder.target_platform in sdk.platform:
[email protected]
    91
        sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
[email protected]
    92
        if sdk_path is None:
[email protected]
    93
          if use_all or sdk_name in sdk_list:
[email protected]
    94
            raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
[email protected]
    95
          continue
[email protected]
    96
        if use_all or use_present or sdk_name in sdk_list:
[email protected]
    97
          sdk.path = sdk_path
[email protected]
    98
          self.sdks[sdk_name] = sdk
[email protected]
    99
[email protected]
   100
    if len(self.sdks) < 1:
[email protected]
   101
      raise Exception('At least one SDK must be available.')
[email protected]
   102
[email protected]
   103
  def configure(self):
[email protected]
   104
    builder.AddConfigureFile('pushbuild.txt')
[email protected]
   105
[email protected]
   106
    cfg = builder.DetectCompilers()
[email protected]
   107
    cxx = cfg.cxx
[email protected]
   108
[email protected]
   109
    if cxx.behavior == 'gcc':
[email protected]
   110
      cfg.defines += [
[email protected]
   111
        'stricmp=strcasecmp',
[email protected]
   112
        '_stricmp=strcasecmp',
[email protected]
   113
        '_snprintf=snprintf',
[email protected]
   114
        '_vsnprintf=vsnprintf',
[email protected]
   115
        'HAVE_STDINT_H',
[email protected]
   116
        'GNUC',
[email protected]
   117
      ]
[email protected]
   118
      cfg.cflags += [
[email protected]
   119
        '-pipe',
[email protected]
   120
        '-fno-strict-aliasing',
[email protected]
   121
        '-Wall',
[email protected]
   122
        '-Werror',
[email protected]
   123
        '-Wno-uninitialized',
[email protected]
   124
        '-Wno-unused',
[email protected]
   125
        '-Wno-switch',
[email protected]
   126
        '-msse',
[email protected]
   127
        '-m32',
[email protected]
   128
      ]
[email protected]
   129
      if (cxx.name == 'gcc' and cxx.majorVersion >= 4) or cxx.name == 'clang':
[email protected]
   130
        cfg.cflags += ['-fvisibility=hidden']
[email protected]
   131
        cfg.cxxflags += ['-fvisibility-inlines-hidden']
[email protected]
   132
      cfg.linkflags += ['-m32']
[email protected]
   133
      cfg.cxxflags += [
[email protected]
   134
        '-fno-exceptions',
[email protected]
   135
        '-fno-rtti',
[email protected]
   136
        '-fno-threadsafe-statics',
[email protected]
   137
        '-Wno-non-virtual-dtor',
[email protected]
   138
        '-Wno-overloaded-virtual',
[email protected]
   139
      ]
[email protected]
   140
      if (cxx.name == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
[email protected]
   141
          (cxx.name == 'clang' and cxx.majorVersion >= 3):
[email protected]
   142
        cfg.cxxflags += ['-Wno-delete-non-virtual-dtor']
[email protected]
   143
      if cxx.name == 'gcc':
[email protected]
   144
        cfg.cflags += ['-mfpmath=sse']
[email protected]
   145
[email protected]
   146
    elif cxx.name == 'msvc':
[email protected]
   147
      if builder.options.debug == '1':
[email protected]
   148
        cfg.cflags += ['/MTd']
[email protected]
   149
        cfg.linkflags += ['/NODEFAULTLIB:libcmt']
[email protected]
   150
      else:
[email protected]
   151
        cfg.cflags += ['/MT']
[email protected]
   152
      cfg.defines += [
[email protected]
   153
        '_CRT_SECURE_NO_DEPRECATE',
[email protected]
   154
        '_CRT_SECURE_NO_WARNINGS',
[email protected]
   155
        '_CRT_NONSTDC_NO_DEPRECATE',
[email protected]
   156
      ]
[email protected]
   157
      cfg.cflags += [
[email protected]
   158
        '/W3',
[email protected]
   159
        '/Zi',
[email protected]
   160
      ]
[email protected]
   161
      cfg.cxxflags += ['/TP']
[email protected]
   162
      cfg.linkflags += [
[email protected]
   163
        '/MACHINE:X86',
[email protected]
   164
        '/SUBSYSTEM:WINDOWS',
[email protected]
   165
        'kernel32.lib',
[email protected]
   166
        'user32.lib',
[email protected]
   167
        'gdi32.lib',
[email protected]
   168
        'winspool.lib',
[email protected]
   169
        'comdlg32.lib',
[email protected]
   170
        'advapi32.lib',
[email protected]
   171
        'shell32.lib',
[email protected]
   172
        'ole32.lib',
[email protected]
   173
        'oleaut32.lib',
[email protected]
   174
        'uuid.lib',
[email protected]
   175
        'odbc32.lib',
[email protected]
   176
        'odbccp32.lib',
[email protected]
   177
      ] 
[email protected]
   178
[email protected]
   179
    # Optimization
[email protected]
   180
    if builder.options.opt == '1':
[email protected]
   181
      cfg.defines += ['NDEBUG']
[email protected]
   182
      if cxx.behavior == 'gcc':
[email protected]
   183
        cfg.cflags += ['-O3']
[email protected]
   184
      elif cxx.behavior == 'msvc':
[email protected]
   185
        cfg.cflags += ['/Ox']
[email protected]
   186
        cfg.linkflags += ['/OPT:ICF', '/OPT:REF']
[email protected]
   187
[email protected]
   188
    # Debugging
[email protected]
   189
    if builder.options.debug == '1':
[email protected]
   190
      cfg.defines += ['DEBUG', '_DEBUG']
[email protected]
   191
      if cxx.behavior == 'gcc':
[email protected]
   192
        cfg.cflags += ['-g3']
[email protected]
   193
      elif cxx.behavior == 'msvc':
[email protected]
   194
        cfg.cflags += ['/Od, /RTC1']
[email protected]
   195
[email protected]
   196
    # This needs to be after our optimization flags which could otherwise disable it.
[email protected]
   197
    if cxx.name == 'msvc':
[email protected]
   198
      # Don't omit the frame pointer.
[email protected]
   199
      cfg.cflags += ['/Oy-']
[email protected]
   200
[email protected]
   201
    # Platform-specifics
[email protected]
   202
    if builder.target_platform == 'linux':
[email protected]
   203
      cfg.defines += ['_LINUX', 'POSIX']
[email protected]
   204
      if cxx.name == 'gcc':
[email protected]
   205
        cfg.linkflags += ['-static-libgcc']
[email protected]
   206
      elif cxx.name == 'clang':
[email protected]
   207
        cfg.linkflags += ['-lgcc_eh']
[email protected]
   208
    elif builder.target_platform == 'mac':
[email protected]
   209
      cfg.defines += ['OSX', '_OSX', 'POSIX']
[email protected]
   210
      cfg.cflags += ['-mmacosx-version-min=10.5']
[email protected]
   211
      cfg.linkflags += [
[email protected]
   212
        '-mmacosx-version-min=10.5',
[email protected]
   213
        '-arch', 'i386',
[email protected]
   214
        '-lstdc++',
[email protected]
   215
      ]
[email protected]
   216
    elif builder.target_platform == 'windows':
[email protected]
   217
      cfg.defines += ['WIN32', '_WINDOWS']
[email protected]
   218
[email protected]
   219
    # Finish up.
[email protected]
   220
    cfg.defines += ['MMS_GENERATED_BUILD']
[email protected]
   221
    cfg.includes += [os.path.join(builder.buildPath, 'includes')]
[email protected]
   222
    cfg.includes += [os.path.join(builder.sourcePath, 'versionlib')]
[email protected]
   223
    cfg.cxxincludes += [os.path.join(builder.sourcePath, 'public')]
[email protected]
   224
[email protected]
   225
  def HL2Compiler(self, context, sdk):
[email protected]
   226
    compiler = context.compiler.clone()
[email protected]
   227
    compiler.cxxincludes += [
[email protected]
   228
      os.path.join(context.currentSourcePath),
[email protected]
   229
      os.path.join(context.currentSourcePath, 'sourcehook'),
[email protected]
   230
      os.path.join(context.sourcePath, 'loader'),
[email protected]
   231
    ]
[email protected]
   232
[email protected]
   233
    defines = ['SE_' + self.sdks[i].define + '=' + self.sdks[i].code for i in self.sdks]
[email protected]
   234
    compiler.defines += defines
[email protected]
   235
    paths = [['public'],
[email protected]
   236
             ['public', 'engine'],
[email protected]
   237
             ['public', 'mathlib'],
[email protected]
   238
             ['public', 'vstdlib'],
[email protected]
   239
             ['public', 'tier0'], ['public', 'tier1']]
[email protected]
   240
    if sdk.name == 'ep1' or sdk.name == 'darkm':
[email protected]
   241
      paths.append(['public', 'dlls'])
[email protected]
   242
      paths.append(['game_shared'])
[email protected]
   243
    else:
[email protected]
   244
      paths.append(['public', 'game', 'server'])
[email protected]
   245
      paths.append(['game', 'shared'])
[email protected]
   246
      paths.append(['common'])
[email protected]
   247
[email protected]
   248
    compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
[email protected]
   249
[email protected]
   250
    if sdk.name == '2013' and compiler.cxx.behavior == 'gcc':
[email protected]
   251
      # The 2013 SDK already has these in public/tier0/basetypes.h
[email protected]
   252
      compiler.defines.remove('stricmp=strcasecmp')
[email protected]
   253
      compiler.defines.remove('_stricmp=strcasecmp')
[email protected]
   254
      compiler.defines.remove('_snprintf=snprintf')
[email protected]
   255
      compiler.defines.remove('_vsnprintf=vsnprintf')
[email protected]
   256
[email protected]
   257
    if compiler.cc.behavior == 'msvc':
[email protected]
   258
      compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
[email protected]
   259
    else:
[email protected]
   260
      compiler.defines += ['COMPILER_GCC']
[email protected]
   261
[email protected]
   262
    if sdk.name in ['css', 'hl2dm', 'dods', '2013', 'tf2', 'nd', 'l4d2', 'dota']:
[email protected]
   263
      if builder.target_platform in ['linux', 'mac']:
[email protected]
   264
        compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
[email protected]
   265
[email protected]
   266
    for path in paths:
[email protected]
   267
      compiler.cxxincludes += [os.path.join(sdk.path, *path)]
[email protected]
   268
[email protected]
   269
    return compiler
[email protected]
   270
[email protected]
   271
  def LibraryBuilder(self, compiler, name):
[email protected]
   272
    binary = compiler.Library(name)
[email protected]
   273
    if builder.target_platform == 'windows':
[email protected]
   274
      binary.sources += ['version.rc']
[email protected]
   275
      binary.compiler.rcdefines += [
[email protected]
   276
        'BINARY_NAME="{0}"'.format(binary.outputFile),
[email protected]
   277
        'MMS_GENERATED_BUILD'
[email protected]
   278
      ]
[email protected]
   279
    elif builder.target_platform == 'mac':
[email protected]
   280
      binary.compiler.postlink += [
[email protected]
   281
        '-compatibility_version', '1.0.0',
[email protected]
   282
        '-current_version', self.productVersion
[email protected]
   283
      ]
[email protected]
   284
    binary.compiler.linkflags += [self.versionlib]
[email protected]
   285
    binary.compiler.sourcedeps += MMS.generated_headers
[email protected]
   286
    return binary
[email protected]
   287
[email protected]
   288
  def Library(self, context, name):
[email protected]
   289
    compiler = context.compiler.clone()
[email protected]
   290
    return self.LibraryBuilder(compiler, name)
[email protected]
   291
[email protected]
   292
  def HL2Library(self, context, name, sdk):
[email protected]
   293
    compiler = self.HL2Compiler(context, sdk)
[email protected]
   294
[email protected]
   295
    if builder.target_platform == 'linux':
[email protected]
   296
      if sdk.name == 'ep1':
[email protected]
   297
        lib_folder = os.path.join(sdk.path, 'linux_sdk')
[email protected]
   298
      elif sdk.name == '2013':
[email protected]
   299
        lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
[email protected]
   300
      else:
[email protected]
   301
        lib_folder = os.path.join(sdk.path, 'lib', 'linux')
[email protected]
   302
    elif builder.target_platform == 'mac':
[email protected]
   303
      if sdk.name == '2013':
[email protected]
   304
        lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
[email protected]
   305
      else:
[email protected]
   306
        lib_folder = os.path.join(sdk.path, 'lib', 'mac')
[email protected]
   307
[email protected]
   308
    if builder.target_platform in ['linux', 'mac']:
[email protected]
   309
      if sdk.name == '2013':
[email protected]
   310
        compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1.a'))]
[email protected]
   311
      else:
[email protected]
   312
        compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a'))]
[email protected]
   313
[email protected]
   314
      if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
[email protected]
   315
        compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
[email protected]
   316
[email protected]
   317
    binary = self.LibraryBuilder(compiler, name)
[email protected]
   318
[email protected]
   319
    dynamic_libs = []
[email protected]
   320
    if builder.target_platform == 'linux':
[email protected]
   321
      compiler.linkflags[0:0] = ['-lm']
[email protected]
   322
      if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', '2013', 'nd', 'l4d2']:
[email protected]
   323
        dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
[email protected]
   324
      elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
[email protected]
   325
        dynamic_libs = ['libtier0.so', 'libvstdlib.so']
[email protected]
   326
      else:
[email protected]
   327
        dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
[email protected]
   328
    elif builder.target_platform == 'mac':
[email protected]
   329
      binary.compiler.linkflags.append('-liconv')
[email protected]
   330
      dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
[email protected]
   331
    elif builder.target_platform == 'windows':
[email protected]
   332
      libs = ['tier0', 'tier1', 'vstdlib']
[email protected]
   333
      if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
[email protected]
   334
        libs.append('interfaces')
[email protected]
   335
      for lib in libs:
[email protected]
   336
        lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
[email protected]
   337
        binary.compiler.linkflags.append(binary.Dep(lib_path))
[email protected]
   338
[email protected]
   339
    for library in dynamic_libs:
[email protected]
   340
      source_path = os.path.join(lib_folder, library)
[email protected]
   341
      output_path = os.path.join(binary.localFolder, library)
[email protected]
   342
[email protected]
   343
      def make_linker(source_path, output_path):
[email protected]
   344
        def link(context, binary):
[email protected]
   345
          cmd_node, (output,) = context.AddSymlink(source_path, output_path)
[email protected]
   346
          return output
[email protected]
   347
        return link
[email protected]
   348
[email protected]
   349
      linker = make_linker(source_path, output_path)
[email protected]
   350
      binary.compiler.linkflags[0:0] = [binary.Dep(library, linker)]
[email protected]
   351
[email protected]
   352
    return binary
[email protected]
   353
[email protected]
   354
MMS = MMSConfig()
[email protected]
   355
MMS.detectProductVersion()
[email protected]
   356
MMS.detectSDKs()
[email protected]
   357
MMS.configure()
[email protected]
   358
[email protected]
   359
MMS.generated_headers = builder.RunScript(
[email protected]
   360
  'support/buildbot/Versioning',
[email protected]
   361
  { 'MMS': MMS }
[email protected]
   362
)
[email protected]
   363
MMS.versionlib = builder.RunScript(
[email protected]
   364
  'versionlib/AMBuildScript',
[email protected]
   365
  { 'MMS': MMS }
[email protected]
   366
)
[email protected]
   367
[email protected]
   368
builder.RunBuildScripts(
[email protected]
   369
  [
[email protected]
   370
    'loader/AMBuilder',
[email protected]
   371
    'core-legacy/AMBuilder',
[email protected]
   372
    'core/AMBuilder',
[email protected]
   373
    'support/buildbot/PackageScript',
[email protected]
   374
  ],
[email protected]
   375
  {
[email protected]
   376
    'MMS': MMS
[email protected]
   377
  }
[email protected]
   378
)
[email protected]
   379