diff --git a/.gitignore b/.gitignore index 8de6d91d..309c967b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /coverage/ /.vs/ /.vscode/ +/.xmake/ /fuzz/luau.pb.* /crash-* /default.prof* diff --git a/xmake.lua b/xmake.lua new file mode 100644 index 00000000..2a6e1217 --- /dev/null +++ b/xmake.lua @@ -0,0 +1,100 @@ +set_xmakever('2.9.2') +add_rules('mode.release', 'mode.debug') +set_policy('build.ccache', not is_plat('windows')) +includes('xmake/xmake_func.lua') + +target('luau_base') +set_kind('phony') +add_defines('LUA_USE_LONGJMP', {public = true}) +add_includedirs('Common/include', {public = true}) + +target('luau_vm') +_config_project({ + project_kind = 'static' +}) +add_files('VM/src/*.cpp') +add_includedirs('VM/include', 'VM/src', { + public = true +}) +add_deps('luau_base') +target_end() + + +target('luau_codegen') +_config_project({ + project_kind = 'static' +}) +add_files('Codegen/src/*.cpp') +add_includedirs('Codegen/include', { + public = true +}) +add_deps('luau_vm') +target_end() + + +target('luau_ast') +_config_project({ + project_kind = 'static', + enable_exception = true +}) +add_files('Ast/src/*.cpp') +add_includedirs('Ast/include', { + public = true +}) +add_deps('luau_base') +target_end() + +target('luau_compiler') +_config_project({ + project_kind = 'static', + enable_exception = true +}) +add_files('Compiler/src/*.cpp') +add_includedirs('Compiler/include', { + public = true +}) +add_deps('luau_ast') +target_end() + + +target('luau_config') +_config_project({ + project_kind = 'static', +}) +add_files('Config/src/*.cpp') +add_includedirs('Config/include', { + public = true +}) +add_deps('luau_ast') +target_end() + + +target('luau_analysis') +_config_project({ + project_kind = 'static', + enable_exception = true +}) +add_files('Analysis/src/*.cpp') +add_includedirs('Analysis/include', { + public = true +}) +add_deps('luau_config') +target_end() + + +target('isocline') +_config_project({project_kind = 'static',}) +add_includedirs('extern/isocline/include', {public = true}) +add_files('extern/isocline/src/isocline.c') +target_end() + + +target('luau') +_config_project({ + project_kind = 'binary', + enable_exception = true +}) +add_files('CLI/ReplEntry.cpp', 'CLI/Repl.cpp', 'CLI/Flags.cpp', 'CLI/FileUtils.cpp', 'CLI/Profiler.cpp', 'CLI/Coverage.cpp', 'CLI/Require.cpp') +add_deps('luau_compiler', 'luau_analysis', 'luau_vm', 'luau_codegen', 'isocline') +target_end() + diff --git a/xmake/lib.lua b/xmake/lib.lua new file mode 100644 index 00000000..1b2df54a --- /dev/null +++ b/xmake/lib.lua @@ -0,0 +1,199 @@ +local function _mkdirs(p) + if os.exists(p) then + return + end + try {function() + local dir = path.directory(p) + if dir then + _mkdirs(dir) + end + os.mkdir(p) + end, catch {function() + end}} +end +function mkdirs(p) + _mkdirs(path.translate(p)) +end + +function string_split(str, chr) + return str:split(chr, {plain = true}) +end +function string_replace(str, from, to) + local s, _ = str:gsub(from, to) + return s +end + +function string_contains(str, sub_str) + return str:match(sub_str) ~= nil +end +local libc = import("core/base/libc") +local bytes = import("core/base/bytes") +local _string_builder = {} +function _string_builder:to_string() + return libc.strndup(self._ptr + 1, self._size) +end +local function _add_capacity(self, s) + local size = s + self._size + local capa = self._capacity + if capa >= size then + return + end + while capa < size do + capa = capa * 2 + end + local old_ptr = self._ptr + 1 + local new_ptr = libc.malloc(capa) + libc.memcpy(new_ptr, old_ptr, self._size) + libc.free(old_ptr) + self._ptr = new_ptr - 1 + self._capacity = capa +end +function _string_builder:reserve(s) + local capa = self._capacity + if capa >= s then + return + end + local old_ptr = self._ptr + 1 + local new_ptr = libc.malloc(s) + libc.memcpy(new_ptr, old_ptr, self._size) + libc.free(old_ptr) + self._ptr = new_ptr - 1 + self._capacity = s +end +function _string_builder:equal(str) + local str_ptr + local str_size + if type(str) == "string" then + str_ptr = libc.dataptr(str) + str_size = #str + else + str_ptr = str:caddr() + str_size = str:size() + end + if str_size ~= self.size() then + return false + end + local ptr = self._ptr + self._size + 1 + return libc.memcmp(ptr, str_ptr, str_size) == 0 +end +function _string_builder:add(str) + local str_ptr + local str_size + if type(str) == "string" then + str_ptr = libc.dataptr(str) + str_size = #str + else + str_ptr = str:caddr() + str_size = str:size() + end + if str_size == 0 then + return + end + _add_capacity(self, str_size) + local ptr = self._ptr + self._size + 1 + libc.memcpy(ptr, str_ptr, str_size) + self._size = self._size + str_size + return self +end +function _string_builder:subview(offset, size) + local sf = self + return { + _size = math.min(sf._size - offset + 1, size), + _ptr = sf._ptr + offset, + size = function(self) + return self._size + end, + caddr = function(self) + return self._ptr + end + } +end +function _string_builder:add_char(c) + _add_capacity(self, 1) + self._size = self._size + 1 + libc.setbyte(self._ptr, self._size, c) + return self +end +function _string_builder:dispose() + if self._ptr ~= -1 then + libc.free(self._ptr + 1) + self._ptr = -1 + end +end +function _string_builder:write_to(path) + local f = io.open(path, "wb") + f:write(self) + f:close() +end +function _string_builder:get(i) + return libc.byteof(self._ptr, i) +end +function _string_builder:set(i, v) + return libc.setbyte(self._ptr, i, v) +end +function _string_builder:erase(i) + self._size = math.max(self._size - i, 1) +end +function _string_builder:size() + return self._size +end +function _string_builder:capacity() + return self._capacity +end +function _string_builder:caddr() + return self._ptr + 1 +end +function _string_builder:cdata() + return self._ptr + 1 +end +function _string_builder:clear() + self._size = 0 +end +function StringBuilder(str) + local inst = table.inherit(_string_builder) + if str then + local str_ptr + local str_size + if type(str) == "string" then + str_ptr = libc.dataptr(str) + str_size = #str + else + str_ptr = str:caddr() + str_size = str:size() + end + local capa = math.max(32, str_size) + local addr = libc.malloc(capa) + inst._size = str_size + inst._capacity = capa + inst._ptr = addr - 1 + libc.memcpy(addr, str_ptr, str_size) + else + inst._size = 0 + inst._capacity = 32 + inst._ptr = libc.malloc(32) - 1 + end + return inst +end +function char(str) + return libc.byteof(libc.dataptr(str), 0) +end +function to_byte_array(input, out) + if input:size() <= 0 then + return 0 + end + local cut = char(',') + local str_ptr + local str_size + if type(input) == "string" then + str_ptr = libc.dataptr(input) + str_size = #input + else + str_ptr = input:caddr() + str_size = input:size() + end + for i = 0, (str_size - 1) do + out:add(tostring(libc.byteof(str_ptr, i))):add_char(cut) + end + out:erase(1) + return str_size +end diff --git a/xmake/xmake_func.lua b/xmake/xmake_func.lua new file mode 100644 index 00000000..d116a129 --- /dev/null +++ b/xmake/xmake_func.lua @@ -0,0 +1,161 @@ +rule("luau_basic_settings") +on_config(function(target) + local _, cc = target:tool("cxx") + if is_plat("linux") then + -- Linux should use -stdlib=libc++ + -- https://github.com/LuisaGroup/LuisaCompute/issues/58 + if (cc == "clang" or cc == "clangxx") then + target:add("cxflags", "-stdlib=libc++", { + force = true + }) + target:add("syslinks", "c++") + end + end + -- disable LTO + -- if cc == "cl" then + -- target:add("cxflags", "-GL") + -- elseif cc == "clang" or cc == "clangxx" then + -- target:add("cxflags", "-flto=thin") + -- elseif cc == "gcc" or cc == "gxx" then + -- target:add("cxflags", "-flto") + -- end + -- local _, ld = target:tool("ld") + -- if ld == "link" then + -- target:add("ldflags", "-LTCG") + -- target:add("shflags", "-LTCG") + -- elseif ld == "clang" or ld == "clangxx" then + -- target:add("ldflags", "-flto=thin") + -- target:add("shflags", "-flto=thin") + -- elseif ld == "gcc" or ld == "gxx" then + -- target:add("ldflags", "-flto") + -- target:add("shflags", "-flto") + -- end +end) +on_load(function(target) + local _get_or = function(name, default_value) + local v = target:extraconf("rules", "luau_basic_settings", name) + if v == nil then + return default_value + end + return v + end + local project_kind = _get_or("project_kind", nil) + if project_kind then + target:set("kind", project_kind) + end + if not is_plat("windows") then + if project_kind == "static" or project_kind == "object" then + target:add("cxflags", "-fPIC", { + tools = {"clang", "gcc"} + }) + end + end + -- fma support + if is_arch("x64", "x86_64") then + target:add("cxflags", "-mfma", { + tools = {"clang", "gcc"} + }) + end + local c_standard = target:values("c_standard") + local cxx_standard = target:values("cxx_standard") + if type(c_standard) == "string" and type(cxx_standard) == "string" then + target:set("languages", c_standard, cxx_standard, { + public = true + }) + else + target:set("languages", "clatest", "cxx20", { + public = true + }) + end + + local enable_exception = _get_or("enable_exception", nil) + if enable_exception then + target:set("exceptions", "cxx") + else + target:set("exceptions", "no-cxx") + end + + if is_mode("debug") then + target:set("runtimes", _get_or("runtime", "MDd"), { + public = true + }) + target:set("optimize", "none") + target:set("warnings", "none") + target:add("cxflags", "/GS", "/Gd", { + tools = {"clang_cl", "cl"} + }) + elseif is_mode("releasedbg") then + target:set("runtimes", _get_or("runtime", "MD"), { + public = true + }) + target:set("optimize", "none") + target:set("warnings", "none") + target:add("cxflags", "/GS-", "/Gd", { + tools = {"clang_cl", "cl"} + }) + else + target:set("runtimes", _get_or("runtime", "MD"), { + public = true + }) + target:set("optimize", "aggressive") + target:set("warnings", "none") + target:add("cxflags", "/GS-", "/Gd", { + tools = {"clang_cl", "cl"} + }) + end + target:set("fpmodels", "fast") + target:add("cxflags", "/Zc:preprocessor", { + tools = "cl", + public = true + }); + if _get_or("use_simd", true) then + if is_arch("arm64") then + target:add("vectorexts", "neon") + else + target:add("vectorexts", "avx", "avx2") + end + end + if _get_or("no_rtti", true) then + target:add("cxflags", "/GR-", { + tools = {"clang_cl", "cl"}, + public = true + }) + target:add("cxflags", "-fno-rtti", "-fno-rtti-data", { + tools = {"clang"}, + public = true + }) + target:add("cxflags", "-fno-rtti", { + tools = {"gcc"}, + public = true + }) + end +end) +rule_end() + + +-- In-case of submod, when there is override rules, do not overload +if _config_rules == nil then + _config_rules = {"luau_basic_settings"} +end +if _disable_unity_build == nil then + local unity_build = get_config("enable_unity_build") + if unity_build ~= nil then + _disable_unity_build = not unity_build + end +end +if not _config_project then + function _config_project(config) + local batch_size = config["batch_size"] + if type(batch_size) == "number" and batch_size > 1 and (not _disable_unity_build) then + add_rules("c.unity_build", { + batchsize = batch_size + }) + add_rules("c++.unity_build", { + batchsize = batch_size + }) + end + if type(_config_rules) == "table" then + add_rules(_config_rules, config) + end + end +end