config = { c2 = { "app", "asset", "c2", "camera", "debugdraw", "editor", "maths", "model", "physics", "pipeline", "scene", "ui", "video", "world", }, qstd = { "memory", "plat", "str", "pack" }, cfg = { "cfgparse" }, sc = { "sc", "includer" }, packer = { "packer" }, convtexture = { "convtexture" }, convmodel = { "convmodel" }, convmaterial = { "convmaterial" }, shaders = { "debug", "mip_spec", "sky", "surface", "surface_depthonly", "tonemap", "triangle", "ui", }, materials = { "bricks", "plastic", "greybox" }, models = { "monkey", "cube" }, textures = { { "22", "bmp", "bc1" }, { "kita", "bmp", "bc1" }, { "brick_albedo", "bmp", "bc1" }, { "brick_ao", "bmp", "bc4" }, { "brick_normal", "bmp", "bc5" }, { "sky", "hdr", "rgba16f" } } } local system = arg[1] if system ~= "windows" and system ~= "unix" then print("Invalid system, needs to be 'windows' or 'unix'.") os.exit(1) end function build_unix() local compiler_c = nil local compiler_cpp = nil local ar = nil if os.execute("gcc --version") then compiler_c = "gcc" compiler_cpp = "g++" elseif os.execute("clang --version") then compiler_c = "clang" compiler_cpp = "clang++" end if os.execute("ar --version") then ar = "ar" end if not compiler_c or not compiler_cpp then print("didn't find a valid compiler :(") os.exit(2) end print("c compiler: " .. compiler_c) print("c++ compiler: " .. compiler_cpp) print("ar: " .. ar) local outfile = io.open("Makefile", "w") if not outfile then print("Failed to open Makefile.") exit(3) end local std_flag = { c = "-std=gnu99", cpp = "-std=c++20" } outfile:write("# generated by configure.lua\n\n") outfile:write( "cflags = -pedantic -Wall -Wextra " .. "-Dplat_x11 -Dplat_x86 -Dplat_posix -Dallocation_default_alignment=8 " .. "-Icfg -Iqstd -Isc/glslang " .. "-MMD -MF $(basename $@).d " .. "\n\n" ) outfile:write(".PHONY: all clean\n") outfile:write("all: c2\n\n") outfile:write("ifndef config\n") outfile:write(" config=debug\n") outfile:write("endif\n") outfile:write("ifeq ($(config),debug)\n") outfile:write(" opt_com = -DDEBUG -g -O0\n") outfile:write(" opt_lnk =\n") outfile:write("endif\n") outfile:write("ifeq ($(config),release)\n") outfile:write(" opt_com = -DNDEBUG -O3\n") outfile:write(" opt_lnk = -s\n") outfile:write("endif\n\n") local all_objs = {} local all_deps = {} local all_assets = {} local all_shaders = {} local function objs(com, ext, tab, dir) local std = std_flag[ext] for _, fname in ipairs(tab) do outfile:write(string.format( "%s%s.o: %s%s.%s\n\t%s %s $(opt_com) $(cflags) -c %s%s.%s -o %s%s.o\n", dir, fname, dir, fname, ext, com, std, dir, fname, ext, dir, fname )) all_objs[#all_objs + 1] = dir .. fname .. '.o' all_deps[#all_deps + 1] = dir .. fname .. '.d' end end local function lib(com, tab, name, dir) objs(com, 'c', tab, dir) outfile:write(name .. ": ") for _, fname in ipairs(tab) do outfile:write(dir .. fname .. ".o ") end outfile:write("\n\t") outfile:write(ar .. " -rcs " .. name .. " ") for _, fname in ipairs(tab) do outfile:write(dir .. fname .. ".o ") end outfile:write("\n\n") end local function prog(type, com, tab, name, dir, dep, lib) objs(com, type, tab, dir) outfile:write(name .. ": ") for _, fname in ipairs(tab) do outfile:write(dir .. fname .. ".o ") end for _, fname in ipairs(dep) do outfile:write(fname .. " ") end outfile:write("\n\t") outfile:write(com .. " $(opt_lnk) $(lflags) -o " .. name .. " ") for _, fname in ipairs(tab) do outfile:write(dir .. fname .. ".o ") end for _, fname in ipairs(dep) do outfile:write(fname .. " ") end for _, fname in ipairs(lib) do outfile:write(fname .. " ") end outfile:write("\n\n") end local function shaders(stype, dtype, tool, tab) for _, fname in ipairs(tab) do outfile:write(string.format( "data/%s.%s: intermediate/%s.%s %s | data\n\t./%s intermediate/%s.%s data/%s.%s\n", fname, dtype, fname, stype, tool, tool, fname, stype, fname, dtype )) all_shaders[#all_shaders + 1] = "data/" .. fname .. "." .. dtype all_assets[#all_assets + 1] = fname .. "." .. dtype end outfile:write("\n") end local function models(tab) for _, fname in ipairs(tab) do outfile:write(string.format( "data/%s.mdl: convmodel intermediate/%s.glb ", fname, fname )) for _, fname in ipairs(all_shaders) do outfile:write(fname .. " ") end outfile:write("| data\n\t") outfile:write(string.format( "./convmodel data intermediate/%s.glb data/%s.mdl\n", fname, fname )) all_assets[#all_assets + 1] = fname .. ".mdl" end outfile:write("\n") end local function textures(tab) for _, c in ipairs(tab) do local fname = c[1] local ext = c[2] local fmt = c[3] outfile:write(string.format( "data/%s.tex: convtexture intermediate/%s.%s ", fname, fname, ext )) outfile:write("| data\n\t") outfile:write(string.format( "./convtexture intermediate/%s.%s data/%s.tex %s\n", fname, ext, fname, fmt )) all_assets[#all_assets + 1] = fname .. ".tex" end outfile:write("\n") end local function materials(tab) for _, fname in ipairs(tab) do outfile:write(string.format( "data/%s.mat: convmaterial intermediate/%s.mat ", fname, fname )) outfile:write("| data\n\t") outfile:write(string.format( "./convmaterial intermediate/%s.mat data/%s.mat\n", fname, fname )) all_assets[#all_assets + 1] = fname .. ".mat" end outfile:write("\n") end local function pack() outfile:write("pack: packer ") for _, fname in ipairs(all_assets) do outfile:write("data/" .. fname .. " ") end outfile:write("\n\t./packer pack data ") for _, fname in ipairs(all_assets) do outfile:write(fname .. " ") end outfile:write("\n\n") end lib(compiler_c, config.qstd, "libqstd.a", "qstd/") lib(compiler_c, config.cfg, "libcfg.a", "cfg/") prog( "cpp", compiler_cpp, config.sc, "shadercompiler", "sc/", { "libqstd.a", "libcfg.a" }, { "-Lsc/glslang/build/glslang", "-Lsc/glslang/build/SPIRV", "-Lsc/glslang/build/glslang/OSDependent/Unix", "-Lsc/glslang/build/External/spirv-tools/source", "-Lsc/glslang/build/External/spirv-tools/source/link", "-Lsc/glslang/build/External/spirv-tools/source/opt", "-lglslang", "-lglslang-default-resource-limits", "-lSPIRV", "-lMachineIndependent", "-lSPVRemapper", "-lOSDependent", "-lGenericCodeGen", "-lSPIRV-Tools-link", "-lSPIRV-Tools-opt", "-lSPIRV-Tools" } ) prog( "cpp", compiler_cpp, config.c2, "c2", "", { "libqstd.a" }, { "-lX11", "-lm" } ) outfile:write("c2: pack\n\n") prog( "c", compiler_c, config.convtexture, "convtexture", "", { "libqstd.a" }, {} ) prog( "c", compiler_c, config.convmodel, "convmodel", "", { "libqstd.a" }, {} ) prog( "c", compiler_c, config.convmaterial, "convmaterial", "", { "libqstd.a", "libcfg.a" }, {} ) prog( "c", compiler_c, config.packer, "packer", "", { "libqstd.a" }, {} ) shaders("glsl", "csh", "shadercompiler", config.shaders) models(config.models) textures(config.textures) materials(config.materials) pack() outfile:write("data:\n\tmkdir -p data\n\n") outfile:write("-include ") for _, fname in ipairs(all_deps) do outfile:write(fname .. " ") end outfile:write("\n\n") outfile:write("clean:\n\trm -f ") for _, fname in ipairs(all_objs) do outfile:write(fname .. " ") end for _, fname in ipairs(all_deps) do outfile:write(fname .. " ") end for _, fname in ipairs(all_assets) do outfile:write("data/" .. fname .. " ") end outfile:write("\n\trm -f shadercompiler\n") outfile:write("\trmdir data\n") outfile:write("\trm -f c2\n") outfile:write("\trm -f convtexture\n") outfile:write("\trm -f convmodel\n") outfile:write("\trm -f convmaterial\n") outfile:write("\trm -f libqstd.a\n") outfile:write("\trm -f libcfg.a\n") outfile:write("\n") print("done.") end if system == "unix" then build_unix() end if system == "windows" then local outfile = io.open("build.ninja", "w") if not outfile then print("Failed to open build.ninja.") exit(3) end outfile:write("# generated by configure.lua\n\n") local function staticlib(name, dir, tab, ext) for _, fname in ipairs(tab) do outfile:write(string.format("build %s/%s.obj: cpp %s/%s.%s\n", dir, fname, dir, fname, ext)) end outfile:write("build " .. dir .. "/" .. name .. ".lib: lib ") for i = 1, #tab - 1 do local fname = tab[i] outfile:write(dir .. "/" .. fname .. ".obj ") end outfile:write(dir .. "/" .. tab[#tab] .. ".obj\n") outfile:write("\n") end local function tool(name, dir, tab, ext, libs, deps) for _, fname in ipairs(tab) do outfile:write(string.format("build %s/%s.obj: cpp %s/%s.%s\n", dir, fname, dir, fname, ext)) end outfile:write("build " .. name .. ".exe: link ") for i = 1, #tab - 1 do local fname = tab[i] outfile:write(dir .. "/" .. fname .. ".obj ") end outfile:write(dir .. "/" .. tab[#tab] .. ".obj") if #libs > 0 then for _, l in ipairs(libs) do outfile:write(" " .. l) end end outfile:write("\n") if #deps > 0 then outfile:write(" libs = ") for _, d in ipairs(deps) do outfile:write(d .. " ") end end outfile:write("\n\n") end all_assets = {} local function assets(tab, tool, exts, extd, deps) local depstr = "" if deps then for _, dep in ipairs(deps) do depstr = depstr .. " " .. dep end end for _, fname in ipairs(tab) do outfile:write(string.format("build data/%s.%s: %s intermediate/%s.%s | %s.exe", fname, extd, tool, fname, exts, tool)) all_assets[#all_assets + 1] = "data/" .. fname .. "." .. extd outfile:write(depstr .. "\n") end outfile:write("\n") end local function textures(tab, tool) for _, item in ipairs(tab) do local fname = item[1] local exts = item[2] local format = item[3] local extd = "tex" outfile:write(string.format("build data/%s.%s: %s intermediate/%s.%s | %s.exe\n", fname, extd, tool, fname, exts, tool)) outfile:write(" format = " .. format .. "\n") all_assets[#all_assets + 1] = "data/" .. fname .. "." .. extd end outfile:write("\n") end local function pack() outfile:write("build pack: packer ") for _, asset in ipairs(all_assets) do outfile:write(asset .. " ") end outfile:write("| packer.exe\n") end outfile:write("cflags = /nologo /Z7 /DDEBUG /MD /std:c++20 /Isc\\glslang /Iqstd /Icfg /Dplat_win /Dplat_x86 /Dallocation_default_alignment=8\n") outfile:write("\n") outfile:write("rule cpp\n") outfile:write(" command = cl $cflags $in /c /Fo: \"$out\"\n") outfile:write(" deps = msvc\n\n") outfile:write("rule link\n") outfile:write(" command = cl /nologo $in /Fe: \"$out\" /link /DEBUG $libs\n\n") outfile:write("rule lib\n") outfile:write(" command = lib /nologo $in /out:\"$out\"\n\n") for _, fname in ipairs(config.c2) do outfile:write("build " .. fname .. ".obj: cpp " .. fname .. ".cpp\n") end outfile:write("build c2.exe: link qstd/qstd.lib ") for i = 1, #config.c2 - 1 do local fname = config.c2[i] outfile:write(fname .. ".obj ") end outfile:write(config.c2[#config.c2] .. ".obj\n") outfile:write(" libs = user32.lib\n") outfile:write("\n") staticlib("qstd", "qstd", config.qstd, "c") staticlib("cfg", "cfg", config.cfg, "c") tool( "shadercompiler", "sc", config.sc, "cpp", { "qstd/qstd.lib", "cfg/cfg.lib" }, { "/LIBPATH:sc/glslang/build/glslang/Release", "/LIBPATH:sc/glslang/build/SPIRV/Release", "/LIBPATH:sc/glslang/build/glslang/OSDependent/Windows/Release", "/LIBPATH:sc/glslang/build/External/spirv-tools/source/Release", "/LIBPATH:sc/glslang/build/External/spirv-tools/source/link/Release", "/LIBPATH:sc/glslang/build/External/spirv-tools/source/opt/Release", "glslang.lib", "glslang-default-resource-limits.lib", "SPIRV.lib", "MachineIndependent.lib", "SPVRemapper.lib", "OSDependent.lib", "GenericCodeGen.lib", "SPIRV-Tools-link.lib", "SPIRV-Tools-opt.lib", "SPIRV-Tools.lib" } ) tool( "packer", ".", config.packer, "c", { "qstd/qstd.lib" }, {} ) tool( "convtexture", ".", config.convtexture, "c", { "qstd/qstd.lib" }, {} ) tool( "convmodel", ".", config.convmodel, "c", { "qstd/qstd.lib" }, {} ) tool( "convmaterial", ".", config.convmaterial, "c", { "qstd/qstd.lib", "cfg/cfg.lib" }, {} ) local function tool_rule(name) outfile:write(string.format("rule %s\n command = %s.exe $in $out\n\n", name, name)) end tool_rule("shadercompiler") tool_rule("convmaterial") outfile:write("rule convmodel\n command = convmodel.exe data $in $out\n\n") outfile:write("rule convtexture\n command = convtexture.exe $in $out $format\n\n") outfile:write("rule packer\n command = packer.exe $out -data $in\n\n") assets(config.shaders, "shadercompiler", "glsl", "csh") assets(config.models, "convmodel", "glb", "mdl", all_assets) assets(config.materials, "convmaterial", "mat", "mat") textures(config.textures, "convtexture") pack() end