diff --git a/scripts/waifulib/c_emscripten.py b/scripts/waifulib/c_emscripten.py new file mode 100644 index 00000000..47e2e79b --- /dev/null +++ b/scripts/waifulib/c_emscripten.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: utf-8 vi:ts=4:noexpandtab + +from waflib.Tools import ccroot, gcc, gxx +from waflib.Configure import conf +from waflib.TaskGen import feature, after_method +from waflib import Utils + +@conf +def get_emscripten_version(conf, cc): + k = conf.get_cc_version(cc, clang=True) + + if '__EMSCRIPTEN__' not in k: + conf.fatal('Could not determine the emscripten compiler version') + + conf.env.DEST_OS = 'emscripten' + conf.env.DEST_CPU = 'wasm' + +@conf +def find_emcc(conf): + cc = conf.find_program(['emcc'], var='CC') + conf.get_emscripten_version(cc) + conf.env.CC_NAME = 'clang' + +@conf +def find_emxx(conf): + cxx = conf.find_program(['em++'], var='CXX') + conf.get_emscripten_version(cxx) + conf.env.CXX_NAME = 'clang' + +@conf +def gcc_modifier_emscripten(conf): + v = conf.env + + conf.env.cshlib_PATTERN = 'lib%s.wasm' + conf.env.cprogram_PATTERN = '%s.html' + + conf.env.CFLAGS_cshlib = ['-fPIC', '-sSIDE_MODULE=1'] + conf.env.CFLAGS_cstlib = ['-fPIC'] + conf.env.CFLAGS_cprogram = ['-sMAIN_MODULE=1'] + + conf.env.LINKFLAGS_cshlib = ['-sSIDE_MODULE=1'] + conf.env.LINKFLAGS_cprogram = ['-sMAIN_MODULE=1'] + +@conf +def gxx_modifier_emscripten(conf): + v = conf.env + + conf.env.cxxshlib_PATTERN = 'lib%s.wasm' + conf.env.cxxprogram_PATTERN = '%s.html' + conf.env.CXXFLAGS_cxxshlib = ['-fPIC', '-sSIDE_MODULE=1'] + conf.env.CXXFLAGS_cxxstlib = ['-fPIC'] + conf.env.CXXFLAGS_cxxprogram = ['-sMAIN_MODULE=1'] + + conf.env.LINKFLAGS_cxxshlib = ['-sSIDE_MODULE=1'] + conf.env.LINKFLAGS_cxxprogram = ['-sMAIN_MODULE=1'] + +@feature('cxxprogram', 'cprogram') +@after_method('apply_link') +def apply_indexhtml(self): + if self.env.DEST_OS != 'emscripten': + return + + tsk = self.link_task + node = tsk.outputs[0] + + tsk.outputs.append(node.change_ext('.js')) + tsk.outputs.append(node.change_ext('.wasm')) + + if '--preload-file' in getattr(self, 'linkflags', []) + self.env.LINKFLAGS: + tsk.outputs.append(node.change_ext('.data')) + + inst_to = getattr(self, 'special_install_path', None) + if inst_to: + self.add_install_as(install_to=inst_to + '/index.html', + install_from=tsk.outputs[0], chmod=Utils.O644, task=tsk) + + self.add_install_files(install_to=inst_to, + install_from=tsk.outputs[1:], chmod=Utils.O644, task=tsk) + +def configure(conf): + if not conf.env.CC: + conf.find_emcc() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() + + if not conf.env.AR: + conf.find_program(['emar'], var='AR') + conf.find_ar() + + if not conf.env.CXX: + conf.find_emxx() + conf.gxx_common_flags() + conf.gxx_modifier_platform() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index fde539a1..a13a6a8e 100644 --- a/scripts/waifulib/xcompile.py +++ b/scripts/waifulib/xcompile.py @@ -539,6 +539,8 @@ def options(opt): help='enable building for PlayStation Vita [default: %(default)s]') xc.add_option('--sailfish', action='store', dest='SAILFISH', default = None, help='enable building for Sailfish/Aurora') + xc.add_option('--emscripten', action='store_true', dest='EMSCRIPTEN', default = None, + help='enable building for Emscripten') def configure(conf): if conf.options.ANDROID_OPTS: @@ -627,11 +629,21 @@ def configure(conf): conf.env.LIB_M = ['m'] conf.env.VRTLD = ['vrtld'] conf.env.DEST_OS = 'psvita' + elif conf.options.EMSCRIPTEN: + # Emscripten compiler is just wrapper to clang + # But we need to setup platform modifiers, they all are contained inside c_emscripten.py for now + # In future, that could be upstreamed to waf itself and this wouldn't be needed + conf.environ['CC'] = 'emcc' + conf.environ['CXX'] = 'em++' + conf.environ['AR'] = 'emar' + conf.environ['STRIP'] = 'emstrip' + conf.environ['OBJCOPY'] = 'llvm-objcopy' + conf.load('c_emscripten') conf.env.MAGX = conf.options.MAGX conf.env.MSVC_WINE = conf.options.MSVC_WINE conf.env.SAILFISH = conf.options.SAILFISH - MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch', '__vita__' : 'psvita', '__wasi__': 'wasi' }) + MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__SWITCH__' : 'nswitch', '__vita__' : 'psvita', '__wasi__': 'wasi', '__EMSCRIPTEN__' : 'emscripten' }) for k in c_config.MACRO_TO_DESTOS: MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS