local CXX = "clang++" local config = { ["buildmode"]="debug", ["target"]="x86_64-windows", ["max_parallel"]=1 } local program_output = "build/lbs" local source_dirs = {"src", "thirdparty/uniproc/src"} local include_dirs = {"include", "src", "thirdparty/luajit/src", "thirdparty/uniproc/include"} local library_dirs = {"thirdparty/luajit/src"} local linker_inputs = {"lua51", "luajit"} local defines = {} local additional_arguments = {"-std=c++20"} local function load_config(cfg_table, args) for i=1,#args,1 do k = args[i] if (k:sub(1,2) == "-j") then if (tonumber(k:sub(3,-1),10) > 0) then cfg_table.max_parallel = tonumber(k:sub(3,-1),10) elseif (tonumber(args[i+1],10) > 0) then cfg_table.max_parallel = tonumber(args[i+1],10) i = i + 1 else print("ERROR: -j option must be formatted as -j or -j . Numbers must be positive integers greater than 0") return -1 end else cfg_table.buildmode = k end end return cfg_table end function table.shallow_copy(tbl) local new = {} for k,v in pairs(tbl) do new[k] = v end return new end local function get_required_objects(dirs, src_extension, obj_prefix, obj_postfix) obj_prefix = obj_prefix or "obj/" obj_postfix = obj_postfix or ".o" local objs = {} local new_src = {} for fsobj in fs.forall(dirs) do -- Get all files in the directory local src_files if fs.is_dir(fsobj) then src_files = fs.list_alldirs(fsobj) else src_files = {fsobj} end -- For each of the files, for _, src_file in pairs(src_files) do repeat -- Skip files that don't end in the provided extension if (fs.extension(src_file) ~= src_extension) then break end local obj_file = obj_prefix .. src_file .. obj_postfix -- Skip old files that do not need to be recompiled if not fs.is_newer(src_file) then break end -- Add the src and obj file to a table that will be returned objs[#objs+1] = obj_file new_src[#new_src+1] = src_file until true end end return objs, new_src end local function compile(CXX, src_dirs, include_dirs, defines, additional_arguments) local base_argv = {} additional_arguments[#additional_arguments+1] = "-c" for _,v in pairs(additional_arguments) do base_argv[#base_argv+1] = v end for _,v in pairs(include_dirs) do base_argv[#base_argv+1] = "-I\"" .. v .. "\"" end for k,v in pairs(defines) do base_argv[#base_argv+1] = "-D" .. k .. "=" .. v end local obj_files, src_files = get_required_objects(src_dirs, ".cpp") local argv = {} for k,obj_file in pairs(obj_files) do local args = table.shallow_copy(base_argv) args[#args+1] = src_files[k] args[#args+1] = "-o\"" .. obj_file .. "\"" argv[#argv+1] = args end local ec, stdout, stderr = platform.exec_parallel(CXX, config.max_parallel, argv) for i,ec in pairs(ec) do if (ec ~= 0) then print("Command \"" .. CXX .. " " .. table.concat(argv[i], " ") .. "\" failed with exit code " .. tostring(ec) .. " and output;") if (#stderr ~= 0) then print(stderr[i]) else print(stdout[i]) end print() end end end local function link(LNK, obj_dirs, library_dirs, linker_inputs, additional_arguments) local argv = {} for _,v in pairs(library_dirs) do argv[#argv+1] = "-L\"" .. v .. "\"" end for _,v in pairs(linker_inputs) do argv[#argv+1] = "-l\"" .. v .. "\"" end for _,v in pairs(additional_arguments) do argv[#argv+1] = v end local ec, stdout, stderr = platform.exec(LNK, argv) if (ec ~= 0) then print("Command \"" .. LNK .. " " .. table.concat(argv) .. "\" failed with exit code " .. tostring(ec) .. " and output;") if (#stderr ~= 0) then print(stderr[i]) else print(stdout[i]) end print() end end function build(...) local args = {...} config = load_config(config, args) print("Building " .. config.buildmode .. " with up to " .. tostring(config.max_parallel) .. " concurrent jobs") compile(CXX, source_dirs, include_dirs, defines, additional_arguments) link(CXX, "obj", library_dirs, linker_inputs, {}) end return 0