mirror of
https://github.com/bjornbytes/lovr.git
synced 2024-07-04 13:33:34 +00:00
This fixes issues with conf.lua not getting read properly, and also the weird quirk of getIdentity not working until setIdentity runs.
474 lines
16 KiB
Lua
474 lines
16 KiB
Lua
-- All the values here can be overridden in tup.config, or by using tup variants
|
|
-- To override subtables in tup.config, use singular subkeys (e.g. CONFIG_MODULE_AUDIO=n)
|
|
config = {
|
|
target = 'native', -- can be win32, macos, linux, android, wasm, or native
|
|
debug = true,
|
|
optimize = false,
|
|
supercharge = false, -- enables dangerous optimizations, plus link time optimization
|
|
sanitize = false, -- adds runtime checks to detect memory leaks and undefined behavior (slower)
|
|
strict = false, -- makes warnings fail the build
|
|
luajit = false, -- path to folder with LuaJIT library, or false to use PUC Lua
|
|
modules = {
|
|
audio = true,
|
|
data = true,
|
|
event = true,
|
|
filesystem = true,
|
|
graphics = true,
|
|
headset = true,
|
|
math = true,
|
|
physics = true,
|
|
system = true,
|
|
thread = true,
|
|
timer = true
|
|
},
|
|
headsets = {
|
|
desktop = true,
|
|
openxr = false, -- if provided, should be path to folder containing OpenXR loader library
|
|
webxr = false
|
|
},
|
|
spatializers = {
|
|
simple = true,
|
|
oculus = false,
|
|
phonon = false
|
|
},
|
|
android = {
|
|
sdk = '/path/to/sdk',
|
|
ndk = '/path/to/ndk',
|
|
version = 29,
|
|
buildtools = '30.0.3',
|
|
keystore = '/path/to/keystore',
|
|
keystorepass = 'pass:password',
|
|
flavor = 'oculus', -- or pico
|
|
manifest = nil, -- path to custom AndroidManifest.xml
|
|
package = nil, -- package id, like org.lovr.app
|
|
project = nil -- path to LÖVR project to include in apk
|
|
}
|
|
}
|
|
|
|
local function getConfig(key, default)
|
|
local value = tup.getconfig(key)
|
|
if value == 'y' then return true
|
|
elseif value == 'n' then return false
|
|
elseif #value > 0 then return value
|
|
else return default end
|
|
end
|
|
|
|
-- merge tup.config into config table
|
|
for k, v in pairs(config) do
|
|
if type(v) == 'table' then
|
|
for kk, vv in pairs(v) do
|
|
local key = k:match('(.-)s?$'):upper() .. '_' .. kk:upper()
|
|
v[kk] = getConfig(key, v[kk])
|
|
end
|
|
else
|
|
config[k] = getConfig(k:upper(), config[k])
|
|
end
|
|
end
|
|
|
|
---> setup
|
|
|
|
target = config.target == 'native' and tup.getconfig('TUP_PLATFORM') or config.target
|
|
if target == 'macosx' then target = 'macos' end
|
|
|
|
cc = 'clang'
|
|
cxx = 'clang++'
|
|
|
|
cflags = {
|
|
'-std=c11',
|
|
'-pedantic',
|
|
'-Wall',
|
|
'-Wextra',
|
|
config.strict and '-Werror' or '',
|
|
'-Wno-unused-parameter',
|
|
'-fdiagnostics-color=always',
|
|
'-fvisibility=hidden',
|
|
config.optimize and '-fdata-sections -ffunction-sections' or '',
|
|
'-Isrc',
|
|
'-Isrc/modules',
|
|
'-Isrc/lib/stdatomic',
|
|
}
|
|
|
|
bin = target == 'android' and 'bin/apk/lib/arm64-v8a' or 'bin'
|
|
lflags = '-L' .. bin
|
|
lflags += not config.debug and '-Wl,-s' or ''
|
|
lflags += config.optimize and (target == 'macos' and '-Wl,-dead_strip' or '-Wl,--gc-sections') or ''
|
|
|
|
base_flags = {
|
|
config.debug and '-g' or '',
|
|
config.optimize and '-Os' or '',
|
|
config.supercharge and '-flto -march=native -DLOVR_UNCHECKED' or '',
|
|
config.sanitize and '-fsanitize=address,undefined' or '',
|
|
}
|
|
|
|
if target == 'win32' then
|
|
cflags += '-DLOVR_GL'
|
|
cflags += '-D_CRT_SECURE_NO_WARNINGS'
|
|
cflags += '-DWINVER=0x0600' -- Vista
|
|
cflags += '-D_WIN32_WINNT=0x0600'
|
|
lflags += '-lshell32 -lole32 -luuid'
|
|
lflags += config.debug and '-Wl,--subsystem,console' or '-Wl,--subsystem,windows'
|
|
if not cc:match('mingw') then
|
|
extra_outputs += { 'bin/lovr.lib', 'bin/lovr.exp' }
|
|
if config.debug then
|
|
extra_outputs += { 'bin/lovr.pdb', 'bin/lovr.ilk' }
|
|
end
|
|
end
|
|
end
|
|
|
|
if target == 'macos' then
|
|
cflags += '-DLOVR_GL'
|
|
cflags_os_macos += '-xobjective-c'
|
|
lflags += '-Wl,-rpath,@executable_path'
|
|
lflags += '-lobjc'
|
|
lflags += '-framework AVFoundation'
|
|
end
|
|
|
|
if target == 'linux' then
|
|
cflags += '-DLOVR_GL'
|
|
cflags += '-D_POSIX_C_SOURCE=200809L'
|
|
cflags += '-D_DEFAULT_SOURCE'
|
|
lflags += '-lm -lpthread -ldl'
|
|
lflags += '-Wl,-rpath,\\$ORIGIN'
|
|
end
|
|
|
|
if target == 'wasm' then
|
|
cc = 'emcc'
|
|
cxx = 'em++'
|
|
cflags += '-DLOVR_WEBGL'
|
|
cflags += '-D_POSIX_C_SOURCE=200809L'
|
|
lflags += '-s USE_WEBGL2'
|
|
lflags += '-s FORCE_FILESYSTEM'
|
|
lflags += ([[-s EXPORTED_FUNCTIONS="[
|
|
'_main','_lovrDestroy','_webxr_attach','_webxr_detach','_lovrCanvasCreateFromHandle',
|
|
'_lovrCanvasDestroy','_lovrGraphicsSetBackbuffer','_lovrGraphicsSetViewMatrix',
|
|
'_lovrGraphicsSetProjection'
|
|
]"]]):gsub('\n', '')
|
|
if config.headsets.webxr then
|
|
lflags += '--js-library src/resources/webxr.js'
|
|
end
|
|
lflags += '--shell-file src/resources/lovr.html'
|
|
extra_outputs += { 'bin/lovr.js', 'bin/lovr.wasm' }
|
|
if config.modules.thread then
|
|
cflags += '-s USE_PTHREADS=1'
|
|
lflags += '-s USE_PTHREADS=1'
|
|
extra_outputs += 'bin/lovr.worker.js'
|
|
end
|
|
end
|
|
|
|
if target == 'android' then
|
|
assert(config.headsets.openxr, 'You probably want to enable OpenXR')
|
|
hosts = { win32 = 'windows-x86_64', macos = 'darwin-x86_64', linux = 'linux-x86_64' }
|
|
host = hosts[tup.getconfig('TUP_PLATFORM')]
|
|
cc = ('%s/toolchains/llvm/prebuilt/%s/bin/clang'):format(config.android.ndk, host)
|
|
cxx = cc .. '++'
|
|
base_flags += '--target=aarch64-linux-android' .. config.android.version
|
|
base_flags += config.debug and '-funwind-tables' or ''
|
|
cflags += '-DLOVR_GLES'
|
|
cflags += '-D_POSIX_C_SOURCE=200809L'
|
|
cflags += '-I' .. config.android.ndk .. '/sources/android/native_app_glue'
|
|
lflags += '-shared -landroid -lEGL -lGLESv3'
|
|
end
|
|
|
|
overrides = {
|
|
glad = '-Wno-pedantic',
|
|
os_android = '-Wno-format-pedantic',
|
|
miniaudio = '-Wno-unused-function',
|
|
}
|
|
|
|
for file, override in pairs(overrides) do
|
|
_G['cflags_' .. file] = override
|
|
end
|
|
|
|
---> deps
|
|
|
|
local function lib(name)
|
|
return (target == 'win32' and '$(bin)/%s.dll' or '$(bin)/lib%s.so'):format(name)
|
|
end
|
|
|
|
local function copy(from, to)
|
|
tup.rule(from, '^ CP %b^ cp %f %o', to)
|
|
end
|
|
|
|
if config.luajit then
|
|
if type(config.luajit) ~= 'string' then
|
|
error('Sorry, building LuaJIT is not supported yet. However, you can set config.luajit to a path to a folder containing the LuaJIT library.')
|
|
end
|
|
cflags += '-Ideps/luajit/src'
|
|
lflags += '-L' .. config.luajit
|
|
lflags += '-lluajit'
|
|
else
|
|
cflags += '-Ideps/lua'
|
|
lflags += '-llua'
|
|
lua_cflags += '-fPIC'
|
|
lua_cflags += '-Wno-empty-body'
|
|
lua_lflags += '-shared'
|
|
lua_lflags += '-lm'
|
|
lua_src = {
|
|
'lapi.c', 'lauxlib.c', 'lbaselib.c', 'lcode.c', 'ldblib.c', 'ldebug.c', 'ldo.c', 'ldump.c',
|
|
'lfunc.c', 'lgc.c', 'linit.c', 'liolib.c', 'llex.c', 'lmathlib.c', 'lmem.c', 'loadlib.c',
|
|
'lobject.c', 'lopcodes.c', 'loslib.c', 'lparser.c', 'lstate.c', 'lstring.c', 'lstrlib.c',
|
|
'ltable.c', 'ltablib.c', 'ltm.c', 'lundump.c', 'lvm.c', 'lzio.c'
|
|
}
|
|
for i = 1, #lua_src do lua_src[i] = 'deps/lua/' .. lua_src[i] end
|
|
tup.foreach_rule(lua_src, '^ CC lua/%b^ $(cc) $(base_flags) $(lua_cflags) -c %f -o %o', '.obj/lua/%B.o')
|
|
tup.rule('.obj/lua/*.o', '^ LD %o^ $(cc) $(base_flags) -o %o %f $(lua_lflags)', lib('lua'))
|
|
end
|
|
|
|
if target == 'win32' or target == 'macos' or target == 'linux' then
|
|
cflags += '-Ideps/glfw/include'
|
|
lflags += '-lglfw'
|
|
|
|
glfw_cflags += '-fPIC'
|
|
glfw_cflags += ({ win32 = '-D_GLFW_WIN32', macos = '-D_GLFW_COCOA', linux = '-D_GLFW_X11' })[target]
|
|
glfw_src += { 'init.c', 'context.c', 'input.c', 'monitor.c', 'vulkan.c', 'window.c' }
|
|
glfw_src += ({
|
|
win32 = { 'win32*.c', 'wgl*.c', 'egl*.c', 'osmesa*.c' },
|
|
macos = { 'cocoa*.c', 'cocoa*.m', 'posix_thread.c', 'egl*.c', 'nsgl*.m', 'osmesa*.c' },
|
|
linux = { 'x11*.c', 'xkb*.c', 'posix*.c', 'glx*.c', 'egl*.c', 'linux*.c', 'osmesa*.c' }
|
|
})[target]
|
|
for i = 1, #glfw_src do glfw_src[i] = 'deps/glfw/src/' .. glfw_src[i] end
|
|
glfw_lflags += '-shared'
|
|
glfw_lflags += target == 'win32' and '-lgdi32' or ''
|
|
glfw_lflags += target == 'macos' and '-lobjc -framework Cocoa -framework IOKit -framework CoreFoundation' or ''
|
|
tup.foreach_rule(glfw_src, '^ CC glfw/%b^ $(cc) $(base_flags) $(glfw_cflags) -c %f -o %o', '.obj/glfw/%B.o')
|
|
tup.rule('.obj/glfw/*.o', '^ LD %o^ $(cc) $(base_flags) -o %o %f $(glfw_lflags)', lib('glfw'))
|
|
end
|
|
|
|
if config.modules.data then
|
|
cflags_rasterizer += '-Ideps/msdfgen'
|
|
lflags += '-lmsdfgen'
|
|
|
|
msdfgen_cflags += '-fPIC'
|
|
msdfgen_src += 'deps/msdfgen/core/*.cpp'
|
|
tup.foreach_rule(msdfgen_src, '^ CC msdfgen/%b^ $(cxx) $(base_flags) $(msdfgen_cflags) -c %f -o %o', '.obj/msdfgen/%B.o')
|
|
tup.rule('.obj/msdfgen/*.o', '^ LD %o^ $(cxx) $(base_flags) -shared -static-libstdc++ -o %o %f', lib('msdfgen'))
|
|
end
|
|
|
|
if config.modules.physics then
|
|
cflags += '-Ideps/ode/include'
|
|
lflags += '-lode'
|
|
|
|
-- ou
|
|
ode_cflags += '-DMAC_OS_X_VERSION=1030'
|
|
ode_cflags += '-D_OU_NAMESPACE=odeou'
|
|
ode_cflags += '-D_OU_FEATURE_SET=_OU_FEATURE_SET_TLS'
|
|
ode_cflags += '-DdATOMICS_ENABLED=1'
|
|
ode_cflags += '-Ideps/ode/ou/include'
|
|
ode_src += 'deps/ode/ou/src/ou/*.cpp'
|
|
|
|
-- ccd
|
|
ode_cflags += '-Ideps/ode/libccd/src'
|
|
ode_cflags += '-Ideps/ode/libccd/src/custom'
|
|
ode_cflags += {
|
|
'-DdLIBCCD_ENABLED',
|
|
'-DdLIBCCD_INTERNAL',
|
|
'-DdLIBCCD_BOX_CYL',
|
|
'-DdLIBCCD_CYL_CYL',
|
|
'-DdLIBCCD_CAP_CYL',
|
|
'-DdLIBCCD_CONVEX_BOX',
|
|
'-DdLIBCCD_CONVEX_CAP',
|
|
'-DdLIBCCD_CONVEX_CYL',
|
|
'-DdLIBCCD_CONVEX_SPHERE',
|
|
'-DdLIBCCD_CONVEX_CONVEX'
|
|
}
|
|
ode_c_src += 'deps/ode/libccd/src/*.c'
|
|
|
|
-- OPCODE
|
|
ode_cflags += '-Ideps/ode/OPCODE'
|
|
ode_src += 'deps/ode/OPCODE/*.cpp'
|
|
ode_src += 'deps/ode/OPCODE/Ice/*.cpp'
|
|
|
|
-- ode
|
|
ode_cflags += '-fPIC'
|
|
ode_cflags += '-Wno-implicit-float-conversion'
|
|
ode_cflags += '-Wno-array-bounds'
|
|
ode_cflags += '-Wno-undefined-var-template'
|
|
ode_cflags += '-Wno-undefined-bool-conversion'
|
|
ode_cflags += '-Wno-unused-value'
|
|
ode_cflags += '-Wno-null-dereference'
|
|
ode_cflags += '-Ideps/ode/include'
|
|
ode_cflags += '-Ideps/ode/ode/src'
|
|
ode_c_src += 'deps/ode/ode/src/*.c'
|
|
ode_src += {
|
|
'deps/ode/ode/src/*.cpp',
|
|
'deps/ode/ode/src/joints/*.cpp'
|
|
}
|
|
|
|
for i = #ode_src, 1, -1 do
|
|
if ode_src[i]:match('gimpact') or ode_src[i]:match('dif') then
|
|
table.remove(ode_src, i)
|
|
end
|
|
end
|
|
|
|
tup.foreach_rule(ode_c_src, '^ CC ode/%b^ $(cc) $(base_flags) $(ode_cflags) -c %f -o %o', '.obj/ode/%B.o')
|
|
tup.foreach_rule(ode_src, '^ CC ode/%b^ $(cxx) $(base_flags) $(ode_cflags) -c %f -o %o', '.obj/ode/%B.o')
|
|
tup.rule('.obj/ode/*.o', '^ LD %o^ $(cxx) $(base_flags) -shared -static-libstdc++ -o %o %f', lib('ode'))
|
|
end
|
|
|
|
if config.headsets.openxr then
|
|
if target == 'android' then
|
|
cflags_headset_openxr += '-Ideps/openxr/include'
|
|
lflags += '-lopenxr_loader'
|
|
copy('deps/oculus-openxr/Libs/Android/arm64-v8a/Release/libopenxr_loader.so', '$(bin)/%b')
|
|
else
|
|
if type(config.headsets.openxr) ~= 'string' then
|
|
error('Sorry, building OpenXR is not supported yet. However, you can set config.headsets.openxr to a path to a folder containing the OpenXR library.')
|
|
end
|
|
cflags_headset_openxr += '-Ideps/openxr/include'
|
|
lflags += '-L' .. config.headsets.openxr
|
|
lflags += '-lopenxr_loader'
|
|
end
|
|
end
|
|
|
|
if config.spatializers.oculus then
|
|
cflags_headset_oculus += '-Ideps/AudioSDK/Include'
|
|
ovraudio_libs = {
|
|
win32 = 'deps/AudioSDK/Lib/x64/ovraudio64.dll',
|
|
linux = 'deps/AudioSDK/Lib/Linux64/libovraudio64.so',
|
|
android = 'deps/AudioSDK/Lib/Android/arm64-v8a/libovraudio64.so'
|
|
}
|
|
assert(ovraudio_libs[target], 'Oculus Audio is not supported on this target')
|
|
copy(ovraudio_libs[target], '$(bin)/%b')
|
|
end
|
|
|
|
if config.spatializers.phonon then
|
|
cflags_spatializer_phonon += '-Ideps/phonon/include'
|
|
phonon_libs = {
|
|
win32 = 'deps/phonon/bin/Windows/x64/phonon.dll',
|
|
macos = 'deps/phonon/lib/OSX/libphonon.dylib',
|
|
linux = 'deps/phonon/lib/Linux/x64/libphonon.so',
|
|
android = 'deps/phonon/lib/Android/arm64/libphonon.so'
|
|
}
|
|
assert(phonon_libs[target], 'Phonon is not supported on this target')
|
|
copy(phonon_libs[target], '$(bin)/%b')
|
|
end
|
|
|
|
---> lovr
|
|
|
|
src = {
|
|
'src/main.c',
|
|
'src/util.c',
|
|
'src/core/os_' .. target .. '.c',
|
|
'src/core/fs.c',
|
|
'src/core/map.c',
|
|
'src/core/zip.c',
|
|
'src/api/api.c',
|
|
'src/api/l_lovr.c'
|
|
}
|
|
|
|
-- TODO rearrange source so that things can be globbed/matched consistently
|
|
module_src = {
|
|
audio = 'src/modules/audio/audio.c',
|
|
data = 'src/modules/data/*.c',
|
|
event = 'src/modules/event/*.c',
|
|
filesystem = 'src/modules/filesystem/*.c',
|
|
graphics = 'src/modules/graphics/*.c',
|
|
headset = 'src/modules/headset/headset.c',
|
|
math = 'src/modules/math/*.c',
|
|
physics = 'src/modules/physics/*.c',
|
|
system = 'src/modules/system/*.c',
|
|
thread = 'src/modules/thread/*.c',
|
|
timer = 'src/modules/timer/*.c'
|
|
}
|
|
|
|
for module, enabled in pairs(config.modules) do
|
|
if enabled then
|
|
src += module_src[module]
|
|
src += 'src/api/l_' .. module .. '*.c'
|
|
else
|
|
cflags += '-DLOVR_DISABLE_' .. module:upper()
|
|
end
|
|
end
|
|
|
|
for headset, enabled in pairs(config.headsets) do
|
|
if enabled then
|
|
cflags += '-DLOVR_USE_' .. headset:upper()
|
|
src += 'src/modules/headset/headset_' .. headset .. '.c'
|
|
end
|
|
end
|
|
|
|
for spatializer, enabled in pairs(config.spatializers) do
|
|
if enabled then
|
|
cflags += '-DLOVR_ENABLE_' .. spatializer:upper() .. '_SPATIALIZER'
|
|
src += 'src/modules/audio/spatializer_' .. spatializer .. '.c'
|
|
end
|
|
end
|
|
|
|
src += 'src/lib/stb/*.c'
|
|
src += (config.modules.audio or config.modules.data) and 'src/lib/miniaudio/*.c' or nil
|
|
src += config.modules.data and 'src/lib/jsmn/*.c' or nil
|
|
src += config.modules.data and 'src/lib/minimp3/*.c' or nil
|
|
src += config.modules.graphics and 'src/lib/glad/*.c' or nil
|
|
src += config.modules.graphics and 'src/resources/shaders.c' or nil
|
|
src += config.modules.math and 'src/lib/noise1234/*.c' or nil
|
|
src += config.modules.thread and 'src/lib/tinycthread/*.c' or nil
|
|
|
|
res += 'src/resources/*.lua'
|
|
res += 'src/resources/*.ttf'
|
|
|
|
for i = 1, #res do
|
|
src.extra_inputs += res[i] .. '.h'
|
|
end
|
|
|
|
src.extra_inputs += extra_inputs
|
|
|
|
obj += '.obj/*.o'
|
|
obj.extra_inputs = lib('*')
|
|
|
|
---> build
|
|
|
|
output = {({
|
|
win32 = '$(bin)/lovr.exe',
|
|
macos = '$(bin)/lovr',
|
|
linux = '$(bin)/lovr',
|
|
android = '$(bin)/liblovr.so',
|
|
wasm = '$(bin)/lovr.html'
|
|
})[target]}
|
|
|
|
output.extra_outputs = extra_outputs
|
|
|
|
tup.foreach_rule(res, '^ XD %b^ xxd -i %f > %o', '%f.h')
|
|
tup.foreach_rule(src, '^ CC %b^ $(cc) $(base_flags) $(cflags) $(cflags_%B) -o %o -c %f', '.obj/%B.o')
|
|
tup.rule(obj, '^ LD %o^ $(cc) $(base_flags) -o %o %f $(lflags)', output)
|
|
|
|
---> apk
|
|
|
|
if target == 'android' then
|
|
for _, key in pairs({ 'manifest', 'package', 'project' }) do
|
|
local value = tup.getconfig('ANDROID_' .. key:upper())
|
|
config.android[key] = #value > 0 and value or config.android[key]
|
|
end
|
|
|
|
java = 'bin/Activity.java'
|
|
class = 'org/lovr/app/Activity.class'
|
|
binclass = 'bin/' .. class
|
|
jar = 'bin/lovr.jar'
|
|
dex = 'bin/apk/classes.dex'
|
|
unaligned = 'bin/.lovr.apk.unaligned'
|
|
unsigned = 'bin/.lovr.apk.unsigned'
|
|
apk = 'bin/lovr.apk'
|
|
|
|
manifest = config.android.manifest or ('src/resources/AndroidManifest_%s.xml'):format(config.android.flavor)
|
|
package = #config.android.package > 0 and ('--rename-manifest-package ' .. config.android.package) or ''
|
|
project = config.android.project and #config.android.project > 0 and ('-A ' .. config.android.project) or ''
|
|
|
|
version = config.android.version
|
|
ks = config.android.keystore
|
|
kspass = config.android.keystorepass
|
|
androidjar = ('%s/platforms/android-%d/android.jar'):format(config.android.sdk, version)
|
|
tools = config.android.sdk .. '/build-tools/' .. config.android.buildtools
|
|
|
|
copy(manifest, 'bin/AndroidManifest.xml')
|
|
copy('src/resources/Activity.java', java)
|
|
tup.rule(java, '^ JAVAC %b^ javac -classpath $(androidjar) -d bin %f', binclass)
|
|
tup.rule(binclass, '^ JAR %b^ jar -cf %o -C bin $(class)', jar)
|
|
tup.rule(jar, '^ D8 %b^ $(tools)/d8 --min-api $(version) --output bin/apk %f', dex)
|
|
tup.rule(
|
|
{ 'bin/AndroidManifest.xml', extra_inputs = { lib('*'), dex } },
|
|
'^ AAPT %b^ $(tools)/aapt package $(package) -F %o -M %f -0 so -I $(androidjar) $(project) bin/apk',
|
|
unaligned
|
|
)
|
|
tup.rule(unaligned, '^ ZIPALIGN %f^ $(tools)/zipalign -f -p 4 %f %o', unsigned)
|
|
tup.rule(unsigned, '^ APKSIGNER %o^ $(tools)/apksigner sign --ks $(ks) --ks-pass $(kspass) --out %o %f', { apk, extra_outputs = 'bin/lovr.apk.idsig' })
|
|
end
|