275 строки
8.4 KiB
Python
Executable File
275 строки
8.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright 2014 The Emscripten Authors. All rights reserved.
|
|
# Emscripten is available under two separate licenses, the MIT license and the
|
|
# University of Illinois/NCSA Open Source License. Both these licenses can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Tool to manage building of system libraries and ports.
|
|
|
|
In general emcc will build them automatically on demand, so you do not
|
|
strictly need to use this tool, but it gives you more control over the
|
|
process (in particular, if emcc does this automatically, and you are
|
|
running multiple build commands in parallel, confusion can occur).
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
|
|
from tools import shared
|
|
from tools import system_libs
|
|
import emscripten
|
|
|
|
|
|
SYSTEM_LIBRARIES = system_libs.Library.get_all_variations()
|
|
SYSTEM_TASKS = list(SYSTEM_LIBRARIES.keys())
|
|
|
|
# This is needed to build the generated_struct_info.json file.
|
|
# It is not a system library, but it needs to be built before running with FROZEN_CACHE.
|
|
SYSTEM_TASKS += ['struct_info']
|
|
|
|
# Minimal subset of SYSTEM_TASKS used by CI systems to build enough to useful
|
|
MINIMAL_TASKS = [
|
|
'libcompiler_rt',
|
|
'libc',
|
|
'libc++abi',
|
|
'libc++abi-except',
|
|
'libc++abi-noexcept',
|
|
'libc++',
|
|
'libc++-except',
|
|
'libc++-noexcept',
|
|
'libal',
|
|
'libdlmalloc',
|
|
'libdlmalloc-debug',
|
|
'libemmalloc',
|
|
'libemmalloc-64bit',
|
|
'libpthread_stub',
|
|
'libsockets',
|
|
'libc_rt_wasm',
|
|
'struct_info',
|
|
'libstandalonewasm',
|
|
'crt1',
|
|
'libunwind-except'
|
|
]
|
|
|
|
USER_TASKS = [
|
|
'boost_headers',
|
|
'bullet',
|
|
'bzip2',
|
|
'cocos2d',
|
|
'freetype',
|
|
'harfbuzz',
|
|
'icu',
|
|
'libjpeg',
|
|
'libpng',
|
|
'ogg',
|
|
'regal',
|
|
'regal-mt',
|
|
'sdl2',
|
|
'sdl2-mt',
|
|
'sdl2-gfx',
|
|
'sdl2-image',
|
|
'sdl2-image-png',
|
|
'sdl2-image-jpg',
|
|
'sdl2-mixer',
|
|
'sdl2-mixer-ogg',
|
|
'sdl2-mixer-mp3',
|
|
'sdl2-net',
|
|
'sdl2-ttf',
|
|
'vorbis',
|
|
'zlib',
|
|
]
|
|
|
|
temp_files = shared.configuration.get_temp_files()
|
|
logger = logging.getLogger('embuilder')
|
|
force = False
|
|
|
|
|
|
def get_help():
|
|
all_tasks = SYSTEM_TASKS + USER_TASKS
|
|
all_tasks.sort()
|
|
return '''
|
|
Available targets:
|
|
|
|
build %s
|
|
|
|
Issuing 'embuilder.py build ALL' causes each task to be built.
|
|
''' % '\n '.join(all_tasks)
|
|
|
|
|
|
def build_port(port_name, lib_name):
|
|
if force:
|
|
shared.Cache.erase_file(lib_name)
|
|
|
|
system_libs.build_port(port_name, shared.Settings)
|
|
|
|
|
|
def main():
|
|
global force
|
|
parser = argparse.ArgumentParser(description=__doc__,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog=get_help())
|
|
parser.add_argument('--lto', action='store_true', help='build bitcode object for LTO')
|
|
parser.add_argument('--pic', action='store_true',
|
|
help='build relocatable objects for suitable for dynamic linking')
|
|
parser.add_argument('--force', action='store_true',
|
|
help='force rebuild of target (by removing it first)')
|
|
parser.add_argument('operation', help='currently only "build" is supported')
|
|
parser.add_argument('targets', nargs='+', help='see below')
|
|
args = parser.parse_args()
|
|
|
|
if args.operation != 'build':
|
|
shared.exit_with_error('unfamiliar operation: ' + args.operation)
|
|
|
|
# process flags
|
|
|
|
# Check sanity so that if settings file has changed, the cache is cleared here.
|
|
# Otherwise, the cache will clear in an emcc process, which is invoked while building
|
|
# a system library into the cache, causing trouble.
|
|
shared.check_sanity()
|
|
|
|
if args.lto:
|
|
shared.Settings.LTO = "full"
|
|
# Reconfigure the cache dir to reflect the change
|
|
shared.reconfigure_cache()
|
|
|
|
if args.pic:
|
|
shared.Settings.RELOCATABLE = 1
|
|
# Reconfigure the cache dir to reflect the change
|
|
shared.reconfigure_cache()
|
|
|
|
if args.force:
|
|
force = True
|
|
|
|
# process tasks
|
|
libname = system_libs.Ports.get_lib_name
|
|
|
|
auto_tasks = False
|
|
tasks = args.targets
|
|
if 'SYSTEM' in tasks:
|
|
tasks = SYSTEM_TASKS
|
|
auto_tasks = True
|
|
elif 'USER' in tasks:
|
|
tasks = USER_TASKS
|
|
auto_tasks = True
|
|
elif 'MINIMAL' in tasks:
|
|
tasks = MINIMAL_TASKS
|
|
auto_tasks = True
|
|
elif 'ALL' in tasks:
|
|
tasks = SYSTEM_TASKS + USER_TASKS
|
|
auto_tasks = True
|
|
if auto_tasks:
|
|
skip_tasks = []
|
|
if shared.Settings.RELOCATABLE:
|
|
# we don't support PIC + pthreads yet
|
|
for task in SYSTEM_TASKS + USER_TASKS:
|
|
if '-mt' in task:
|
|
skip_tasks.append(task)
|
|
if 'pthread' in task and 'stub' not in task:
|
|
skip_tasks.append(task)
|
|
print('Skipping building of %s, because we don\'t support threads and PIC code.' % ', '.join(skip_tasks))
|
|
# cocos2d: must be ported, errors on
|
|
# "Cannot recognize the target platform; are you targeting an unsupported platform?"
|
|
skip_tasks += ['cocos2d']
|
|
tasks = [x for x in tasks if x not in skip_tasks]
|
|
print('Building targets: %s' % ' '.join(tasks))
|
|
for what in tasks:
|
|
logger.info('building and verifying ' + what)
|
|
if what in SYSTEM_LIBRARIES:
|
|
library = SYSTEM_LIBRARIES[what]
|
|
if force:
|
|
library.erase()
|
|
library.get_path()
|
|
elif what == 'struct_info':
|
|
if force:
|
|
shared.Cache.erase_file('generated_struct_info.json')
|
|
emscripten.generate_struct_info()
|
|
elif what == 'icu':
|
|
build_port('icu', libname('libicuuc'))
|
|
elif what == 'zlib':
|
|
shared.Settings.USE_ZLIB = 1
|
|
build_port('zlib', 'libz.a')
|
|
shared.Settings.USE_ZLIB = 0
|
|
elif what == 'bzip2':
|
|
build_port('bzip2', 'libbz2.a')
|
|
elif what == 'bullet':
|
|
build_port('bullet', libname('libbullet'))
|
|
elif what == 'vorbis':
|
|
build_port('vorbis', libname('libvorbis'))
|
|
elif what == 'ogg':
|
|
build_port('ogg', libname('libogg'))
|
|
elif what == 'libjpeg':
|
|
build_port('libjpeg', libname('libjpeg'))
|
|
elif what == 'libpng':
|
|
build_port('libpng', libname('libpng'))
|
|
elif what == 'sdl2':
|
|
build_port('sdl2', libname('libSDL2'))
|
|
elif what == 'sdl2-mt':
|
|
shared.Settings.USE_PTHREADS = 1
|
|
build_port('sdl2', libname('libSDL2-mt'))
|
|
shared.Settings.USE_PTHREADS = 0
|
|
elif what == 'sdl2-gfx':
|
|
build_port('sdl2_gfx', libname('libSDL2_gfx'))
|
|
elif what == 'sdl2-image':
|
|
build_port('sdl2_image', libname('libSDL2_image'))
|
|
elif what == 'sdl2-image-png':
|
|
shared.Settings.SDL2_IMAGE_FORMATS = ["png"]
|
|
build_port('sdl2_image', libname('libSDL2_image_png'))
|
|
shared.Settings.SDL2_IMAGE_FORMATS = []
|
|
elif what == 'sdl2-image-jpg':
|
|
shared.Settings.SDL2_IMAGE_FORMATS = ["jpg"]
|
|
build_port('sdl2_image', libname('libSDL2_image_jpg'))
|
|
shared.Settings.SDL2_IMAGE_FORMATS = []
|
|
elif what == 'sdl2-net':
|
|
build_port('sdl2_net', libname('libSDL2_net'))
|
|
elif what == 'sdl2-mixer':
|
|
old_formats = shared.Settings.SDL2_MIXER_FORMATS
|
|
shared.Settings.SDL2_MIXER_FORMATS = []
|
|
build_port('sdl2_mixer', libname('libSDL2_mixer'))
|
|
shared.Settings.SDL2_MIXER_FORMATS = old_formats
|
|
elif what == 'sdl2-mixer-ogg':
|
|
old_formats = shared.Settings.SDL2_MIXER_FORMATS
|
|
shared.Settings.SDL2_MIXER_FORMATS = ["ogg"]
|
|
build_port('sdl2_mixer', libname('libSDL2_mixer_ogg'))
|
|
shared.Settings.SDL2_MIXER_FORMATS = old_formats
|
|
elif what == 'sdl2-mixer-mp3':
|
|
old_formats = shared.Settings.SDL2_MIXER_FORMATS
|
|
shared.Settings.SDL2_MIXER_FORMATS = ["mp3"]
|
|
build_port('sdl2_mixer', libname('libSDL2_mixer_mp3'))
|
|
shared.Settings.SDL2_MIXER_FORMATS = old_formats
|
|
elif what == 'freetype':
|
|
build_port('freetype', 'libfreetype.a')
|
|
elif what == 'harfbuzz':
|
|
build_port('harfbuzz', 'libharfbuzz.a')
|
|
elif what == 'harfbuzz-mt':
|
|
shared.Settings.USE_PTHREADS = 1
|
|
build_port('harfbuzz', 'libharfbuzz-mt.a')
|
|
shared.Settings.USE_PTHREADS = 0
|
|
elif what == 'sdl2-ttf':
|
|
build_port('sdl2_ttf', libname('libSDL2_ttf'))
|
|
elif what == 'cocos2d':
|
|
build_port('cocos2d', libname('libcocos2d'))
|
|
elif what == 'regal':
|
|
build_port('regal', libname('libregal'))
|
|
elif what == 'regal-mt':
|
|
shared.Settings.USE_PTHREADS = 1
|
|
build_port('regal', libname('libregal-mt'))
|
|
shared.Settings.USE_PTHREADS = 0
|
|
elif what == 'boost_headers':
|
|
build_port('boost_headers', libname('libboost_headers'))
|
|
else:
|
|
logger.error('unfamiliar build target: ' + what)
|
|
return 1
|
|
|
|
logger.info('...success')
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
sys.exit(main())
|
|
except KeyboardInterrupt:
|
|
logger.warning("KeyboardInterrupt")
|
|
sys.exit(1)
|