From 40cb2e1dc32b4ccac1858e7ebb272dd8de13692c Mon Sep 17 00:00:00 2001 From: Jason Jarvis Date: Sat, 30 Sep 2023 17:51:07 -0700 Subject: [PATCH 1/3] revise lua script to use zig tool chain for stride --- .gitignore | 1 + tools/np-build-driver-stride.lua | 113 ++++++++++++++++++++++++ tools/np-build-stride.lua | 144 +++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 tools/np-build-driver-stride.lua create mode 100644 tools/np-build-stride.lua diff --git a/.gitignore b/.gitignore index cf58ade..2af6eff 100644 --- a/.gitignore +++ b/.gitignore @@ -251,3 +251,4 @@ tools/WindowsUWP/x86/libCompilerRt.lib *.a *.bc *.lib +*.o \ No newline at end of file diff --git a/tools/np-build-driver-stride.lua b/tools/np-build-driver-stride.lua new file mode 100644 index 0000000..684921d --- /dev/null +++ b/tools/np-build-driver-stride.lua @@ -0,0 +1,113 @@ +ffi = require 'ffi' + +local SLASH = "/" +if ffi.os == "Windows" then SLASH = "\\" end + +-- Code by David Kastrup +require "lfs" + +function dirtree(dir) + assert(dir and dir ~= "", "directory parameter is missing or empty") + if string.sub(dir, -1) == SLASH then + dir=string.sub(dir, 1, -2) + end + + local function yieldtree(dir) + for entry in lfs.dir(dir) do + if entry ~= "." and entry ~= ".." then + entry=dir..SLASH..entry + local attr=lfs.attributes(entry) + coroutine.yield(entry,attr) + if attr.mode == "directory" then + yieldtree(entry) + end + end + end + end + + return coroutine.wrap(function() yieldtree(dir) end) +end + +function string.ends(String,End) + return End=='' or string.sub(String,-string.len(End))==End +end + +function string.starts(String,Start) + return string.sub(String,1,string.len(Start))==Start +end + +local exclude_dirs = {} +local exclude_files = {} +local directory = "" + +-- We may need to support both build approaches for now (iOS / android) +common_flags = "-ffast-math -fno-threadsafe-statics -nostdlibinc -nobuiltininc -nostdinc++ -Wno-macro-redefined -DFLOAT_APPROX -I.."..SLASH.."NativePath -I.."..SLASH.."NativePath"..SLASH.."standard" +zig_common_flags = "-Wno-ignored-attributes -Wno-delete-non-virtual-dtor -Wno-macro-redefined -fno-rtti -fno-exceptions" + +objs = {} +cfiles = {} +cppfiles = {} +hfiles = {} +debug = false +is_verbose = false +is_shared = false +platform = "windows" +outputName = "lib" + +function table.contains(table, element) + for _, value in pairs(table) do + if string.starts(element, value) then + return true + end + end + return false +end + +for i,v in ipairs(arg) do + if v == "debug" then + debug = true + elseif string.starts(v, "-I") then + local includeDir = string.sub(v, 3) + common_flags = common_flags.." -I"..includeDir + zig_common_flags = zig_common_flags.." -I"..includeDir + elseif string.starts(v, "-D") then + local includeDir = string.sub(v, 3) + common_flags = common_flags.." -D"..includeDir + zig_common_flags = zig_common_flags.." -D"..includeDir + elseif string.starts(v, "-n") then + local n = string.sub(v, 3) + outputName = n + elseif string.starts(v, "-E") then + local n = string.sub(v, 3) + table.insert(exclude_dirs, n) + elseif string.starts(v, "-e") then + local n = string.sub(v, 3) + table.insert(exclude_files, n) + elseif v == "--verbose" or v == "-v" then + is_verbose = true + elseif v == "--shared" then + is_shared = true + elseif string.starts(v, "-p") then + platform = string.sub(v, 3) + else + directory = v + end +end + +for filename, attr in dirtree(directory) do + if table.contains(exclude_dirs, filename) ~= true and table.contains(exclude_files, filename) ~= true then + if string.ends(filename, ".c") and attr.mode == "file" and table.contains(exclude_files, filename) ~= true then + table.insert(cfiles, filename) + if is_verbose == true then + print("Keeping: "..filename) + end + elseif string.ends(filename, ".cpp") and attr.mode == "file" and table.contains(exclude_files, filename) ~= true then + table.insert(cppfiles, filename) + if is_verbose == true then + print("Keeping: "..filename) + end + end + elseif is_verbose == true then + print("Excluding: "..filename) + end +end diff --git a/tools/np-build-stride.lua b/tools/np-build-stride.lua new file mode 100644 index 0000000..24e9207 --- /dev/null +++ b/tools/np-build-stride.lua @@ -0,0 +1,144 @@ +-- Special trick to load the parent path of the current script. +local parent_path = string.match(arg[0], "(.-)([^\\/]-%.?([^%.\\/]*))$") +-- Add that path to the list of places where lua will load packages +package.path = package.path .. ";" .. parent_path .. "?.lua" +-- Load the driver package which will take care of the command line arguments and other settings +-- as here we just focus on the code necessary to build our supported platforms +require "np-build-driver-stride" + +local debug_flags = "-O0 -g" +local debug_ms_flags = "-Od" +local release_flags = "-O3" +local release_ms_flags = "-O2" + +-- NOTE: This is a cleaned up version of np-build.lua specific to the needs of Stride, and uses Zig CC cross compiler instead of clang, etc. +-- We can port over other commands from np-build.lua as needed. + +-- we require Zig v0.12.0 reachable from your path. this only works on Windows for now +local zig = "zig.exe" + +function BuildZig(cfile, target, platform_args) + local flags = "" + if debug then flags = debug_flags else flags = release_flags end + + local cmd = zig.." cc "..platform_args.." -target "..target.." "..zig_common_flags.." "..flags.." -o "..cfile..".o ".." -c "..cfile + if is_verbose == true then + print(cmd) + end + if os.execute(cmd) == 0 then table.insert(objs, cfile..".o") end +end + +function LinkZigStatic(target, folder, ext) + local objs_str = "" + for i, o in ipairs(objs) do + objs_str = objs_str..o.." " + end + local cmd = zig.." build-lib -static -target "..target.." -femit-bin="..folder.."\\"..outputName.."."..ext.." "..objs_str + if is_verbose == true then + print(cmd) + end + os.execute(cmd) +end + +-- TODO: Unused for now +-- function LinkZigShared(target, folder, ext) +-- local objs_str = "" +-- for i, o in ipairs(objs) do +-- objs_str = objs_str..o.." " +-- end + +-- local cmd = zig.." build-lib -shared -target "..target.." -femit-bin="..folder.."\\"..outputName.."."..ext.." "..objs_str +-- if is_verbose == true then +-- print(cmd) +-- end +-- os.execute(cmd) +-- end + +if platform == "windows" then + lfs.mkdir("libs") + lfs.chdir("libs") + lfs.mkdir("win-x86") + lfs.mkdir("win-x64") + lfs.mkdir("win-arm64") + lfs.chdir("..") + + objs = {} + print ("Building Windows x86...") + for i,f in ipairs(cfiles) do + BuildZig(f, "x86-windows-gnu", "-DNP_WIN32 -m32 -gcodeview -fno-ms-extensions") + end + LinkZigStatic("x86-windows-gnu", "libs\\win-x86", "lib") + + objs = {} + print ("Building Windows x64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "x86_64-windows-gnu", "-DNP_WIN32 -m64 -gcodeview -fno-ms-extensions") + end + LinkZigStatic("x86_64-windows-gnu", "libs\\win-x64", "lib") + + objs = {} + print ("Building Windows arm64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "aarch64-windows-gnu", "-DNP_WIN32 -m64 -gcodeview -fno-ms-extensions") + end + LinkZigStatic("aarch64-windows-gnu", "libs\\win-arm64", "lib") + +elseif platform == "ios" then + -- TODO: port over to Zig + +elseif platform == "macos" then + lfs.mkdir("libs") + lfs.chdir("libs") + lfs.mkdir("osx-x64") + lfs.mkdir("osx-arm64") + lfs.chdir("..") + + objs = {} + print ("Building macOS x64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "x86_64-macos", "-DNP_MACOS -mmacosx-version-min=10.5") + end + LinkZigStatic("x86_64-macos", "libs\\osx-x64", "a") + + objs = {} + print ("Building macOS arm64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "aarch64-macos", "-DNP_MACOS -mmacosx-version-min=10.5") + end + LinkZigStatic("aarch64-macos", "libs\\osx-arm64", "a") + + -- lfs.mkdir("macOS") + + if is_verbose == true then + print(cmd) + end + -- Not sure we need lipo anymore + -- os.execute("lipo macOS\\"..outputName.."_i386.a macOS\\"..outputName.."_x86_64.a -create -output macOS\\"..outputName..".a") + -- os.remove("macOS\\"..outputName.."_i386.a") + -- os.remove("macOS\\"..outputName.."_x86_64.a") + +elseif platform == "linux" then + lfs.mkdir("libs") + lfs.chdir("libs") + lfs.mkdir("linux-x64") + lfs.mkdir("linux-arm64") + lfs.chdir("..") + + objs = {} + print ("Building Linux x64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "x86_64-linux-gnu", "-DNP_LINUX -fPIC") + end + LinkZigStatic("x86_64-linux-gnu", "libs\\linux-x64", "a") + + objs = {} + print ("Building Linux arm64...") + for i,f in ipairs(cfiles) do + BuildZig(f, "aarch64-linux-gnu", "-DNP_LINUX -fPIC") + end + LinkZigStatic("aarch64-linux-gnu", "libs\\linux-arm64", "a") + +elseif platform == "android" then + -- TODO: port over to Zig + +end From 7d837fb55fbac2b947c8106d286f8446676476d7 Mon Sep 17 00:00:00 2001 From: Jason Jarvis Date: Sat, 30 Sep 2023 22:43:45 -0700 Subject: [PATCH 2/3] fix issue with linker source libs --- tools/np-build-stride.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/np-build-stride.lua b/tools/np-build-stride.lua index 24e9207..e1b90de 100644 --- a/tools/np-build-stride.lua +++ b/tools/np-build-stride.lua @@ -17,6 +17,9 @@ local release_ms_flags = "-O2" -- we require Zig v0.12.0 reachable from your path. this only works on Windows for now local zig = "zig.exe" +-- For testing alternative versions of Zig, etc +-- local zig = "c:\\devtools\\zig-0.11.0\\zig.exe" + function BuildZig(cfile, target, platform_args) local flags = "" if debug then flags = debug_flags else flags = release_flags end @@ -25,7 +28,9 @@ function BuildZig(cfile, target, platform_args) if is_verbose == true then print(cmd) end - if os.execute(cmd) == 0 then table.insert(objs, cfile..".o") end + + os.execute(cmd) + table.insert(objs, cfile..".o") end function LinkZigStatic(target, folder, ext) From 35cf54d2694bee88934f84db21a3e5bb0f4d16f6 Mon Sep 17 00:00:00 2001 From: Jason Jarvis Date: Sun, 1 Oct 2023 09:32:08 -0700 Subject: [PATCH 3/3] address some PR feedback --- tools/np-build-driver-stride.lua | 113 ------------------------------- tools/np-build-driver.lua | 57 +++++++++------- tools/np-build-stride.lua | 10 +-- 3 files changed, 36 insertions(+), 144 deletions(-) delete mode 100644 tools/np-build-driver-stride.lua diff --git a/tools/np-build-driver-stride.lua b/tools/np-build-driver-stride.lua deleted file mode 100644 index 684921d..0000000 --- a/tools/np-build-driver-stride.lua +++ /dev/null @@ -1,113 +0,0 @@ -ffi = require 'ffi' - -local SLASH = "/" -if ffi.os == "Windows" then SLASH = "\\" end - --- Code by David Kastrup -require "lfs" - -function dirtree(dir) - assert(dir and dir ~= "", "directory parameter is missing or empty") - if string.sub(dir, -1) == SLASH then - dir=string.sub(dir, 1, -2) - end - - local function yieldtree(dir) - for entry in lfs.dir(dir) do - if entry ~= "." and entry ~= ".." then - entry=dir..SLASH..entry - local attr=lfs.attributes(entry) - coroutine.yield(entry,attr) - if attr.mode == "directory" then - yieldtree(entry) - end - end - end - end - - return coroutine.wrap(function() yieldtree(dir) end) -end - -function string.ends(String,End) - return End=='' or string.sub(String,-string.len(End))==End -end - -function string.starts(String,Start) - return string.sub(String,1,string.len(Start))==Start -end - -local exclude_dirs = {} -local exclude_files = {} -local directory = "" - --- We may need to support both build approaches for now (iOS / android) -common_flags = "-ffast-math -fno-threadsafe-statics -nostdlibinc -nobuiltininc -nostdinc++ -Wno-macro-redefined -DFLOAT_APPROX -I.."..SLASH.."NativePath -I.."..SLASH.."NativePath"..SLASH.."standard" -zig_common_flags = "-Wno-ignored-attributes -Wno-delete-non-virtual-dtor -Wno-macro-redefined -fno-rtti -fno-exceptions" - -objs = {} -cfiles = {} -cppfiles = {} -hfiles = {} -debug = false -is_verbose = false -is_shared = false -platform = "windows" -outputName = "lib" - -function table.contains(table, element) - for _, value in pairs(table) do - if string.starts(element, value) then - return true - end - end - return false -end - -for i,v in ipairs(arg) do - if v == "debug" then - debug = true - elseif string.starts(v, "-I") then - local includeDir = string.sub(v, 3) - common_flags = common_flags.." -I"..includeDir - zig_common_flags = zig_common_flags.." -I"..includeDir - elseif string.starts(v, "-D") then - local includeDir = string.sub(v, 3) - common_flags = common_flags.." -D"..includeDir - zig_common_flags = zig_common_flags.." -D"..includeDir - elseif string.starts(v, "-n") then - local n = string.sub(v, 3) - outputName = n - elseif string.starts(v, "-E") then - local n = string.sub(v, 3) - table.insert(exclude_dirs, n) - elseif string.starts(v, "-e") then - local n = string.sub(v, 3) - table.insert(exclude_files, n) - elseif v == "--verbose" or v == "-v" then - is_verbose = true - elseif v == "--shared" then - is_shared = true - elseif string.starts(v, "-p") then - platform = string.sub(v, 3) - else - directory = v - end -end - -for filename, attr in dirtree(directory) do - if table.contains(exclude_dirs, filename) ~= true and table.contains(exclude_files, filename) ~= true then - if string.ends(filename, ".c") and attr.mode == "file" and table.contains(exclude_files, filename) ~= true then - table.insert(cfiles, filename) - if is_verbose == true then - print("Keeping: "..filename) - end - elseif string.ends(filename, ".cpp") and attr.mode == "file" and table.contains(exclude_files, filename) ~= true then - table.insert(cppfiles, filename) - if is_verbose == true then - print("Keeping: "..filename) - end - end - elseif is_verbose == true then - print("Excluding: "..filename) - end -end diff --git a/tools/np-build-driver.lua b/tools/np-build-driver.lua index 7d10044..dec016d 100644 --- a/tools/np-build-driver.lua +++ b/tools/np-build-driver.lua @@ -41,6 +41,7 @@ local exclude_files = {} local directory = "" common_flags = "-ffast-math -fno-threadsafe-statics -nostdlibinc -nobuiltininc -nostdinc++ -Wno-macro-redefined -I.."..SLASH.."NativePath -I.."..SLASH.."NativePath"..SLASH.."standard" +zig_common_flags = "-Wno-ignored-attributes -Wno-delete-non-virtual-dtor -Wno-macro-redefined -fno-rtti -fno-exceptions" objs = {} cfiles = {} @@ -60,33 +61,41 @@ function table.contains(table, element) return false end +-- Process the zig command line options for i,v in ipairs(arg) do - if v == "debug" then - debug = true - elseif string.starts(v, "-I") then - local includeDir = string.sub(v, 3) - common_flags = common_flags.." -I"..includeDir - elseif string.starts(v, "-D") then - local includeDir = string.sub(v, 3) - common_flags = common_flags.." -D"..includeDir - elseif string.starts(v, "-n") then - local n = string.sub(v, 3) - outputName = n - elseif string.starts(v, "-E") then - local n = string.sub(v, 3) - table.insert(exclude_dirs, n) - elseif string.starts(v, "-e") then - local n = string.sub(v, 3) - table.insert(exclude_files, n) - elseif v == "--verbose" or v == "-v" then - is_verbose = true - elseif string.starts(v, "-p") then - platform = string.sub(v, 3) - else - directory = v - end + if v == "debug" then + debug = true + elseif string.starts(v, "-I") then + -- add an include directory to the compiler flags + local includeDir = string.sub(v, 3) + common_flags = common_flags.." -I"..includeDir + zig_common_flags = zig_common_flags.." -I"..includeDir + elseif string.starts(v, "-D") then + -- add a define to the compiler flags + local includeDir = string.sub(v, 3) + common_flags = common_flags.." -D"..includeDir + zig_common_flags = zig_common_flags.." -D"..includeDir + elseif string.starts(v, "-n") then + local n = string.sub(v, 3) + outputName = n + elseif string.starts(v, "-E") then + local n = string.sub(v, 3) + table.insert(exclude_dirs, n) + elseif string.starts(v, "-e") then + local n = string.sub(v, 3) + table.insert(exclude_files, n) + elseif v == "--verbose" or v == "-v" then + is_verbose = true + elseif v == "--shared" then + is_shared = true + elseif string.starts(v, "-p") then + platform = string.sub(v, 3) + else + directory = v + end end +-- Build a list of all source files to compile excluding those that we do not want via -E or -e see above. for filename, attr in dirtree(directory) do if table.contains(exclude_dirs, filename) ~= true and table.contains(exclude_files, filename) ~= true then if string.ends(filename, ".c") and attr.mode == "file" and table.contains(exclude_files, filename) ~= true then diff --git a/tools/np-build-stride.lua b/tools/np-build-stride.lua index e1b90de..6c6db46 100644 --- a/tools/np-build-stride.lua +++ b/tools/np-build-stride.lua @@ -4,7 +4,7 @@ local parent_path = string.match(arg[0], "(.-)([^\\/]-%.?([^%.\\/]*))$") package.path = package.path .. ";" .. parent_path .. "?.lua" -- Load the driver package which will take care of the command line arguments and other settings -- as here we just focus on the code necessary to build our supported platforms -require "np-build-driver-stride" +require "np-build-driver" local debug_flags = "-O0 -g" local debug_ms_flags = "-Od" @@ -112,12 +112,8 @@ elseif platform == "macos" then end LinkZigStatic("aarch64-macos", "libs\\osx-arm64", "a") - -- lfs.mkdir("macOS") - - if is_verbose == true then - print(cmd) - end - -- Not sure we need lipo anymore + -- TODO: Not sure we need lipo anymore? since we target each runtime separately, and only x64/aarch64 + -- lfs.mkdir("macOS") -- os.execute("lipo macOS\\"..outputName.."_i386.a macOS\\"..outputName.."_x86_64.a -create -output macOS\\"..outputName..".a") -- os.remove("macOS\\"..outputName.."_i386.a") -- os.remove("macOS\\"..outputName.."_x86_64.a")