summaryrefslogtreecommitdiff
path: root/xmake/rules
diff options
context:
space:
mode:
authorÂngelo Andrade Cirino <[email protected]>2022-01-10 10:23:17 -0300
committerÂngelo Andrade Cirino <[email protected]>2022-01-10 10:23:17 -0300
commited0c0c5e0249aa966ea7061b30710abdd0b09d87 (patch)
tree2a51c869a3aea1a093ed569e749bdf0465634a6c /xmake/rules
parent885d00da8caf74aeed758d030b9a1b50d9078e1f (diff)
parent2431dd7e6142ff98b55741cfd4de4d2e69f4f8b5 (diff)
Merged from upstream/master
Diffstat (limited to 'xmake/rules')
-rw-r--r--xmake/rules/c++/modules/build_modulefiles.lua151
-rw-r--r--xmake/rules/c++/modules/build_modules/clang.lua139
-rw-r--r--xmake/rules/c++/modules/build_modules/gcc.lua96
-rw-r--r--xmake/rules/c++/modules/build_modules/module_parser.lua118
-rw-r--r--xmake/rules/c++/modules/build_modules/msvc.lua181
-rw-r--r--xmake/rules/c++/modules/xmake.lua40
-rw-r--r--xmake/rules/c++/openmp/load.lua1
-rw-r--r--xmake/rules/c++/openmp/xmake.lua4
-rw-r--r--xmake/rules/c++/unity_build/unity_build.lua139
-rw-r--r--xmake/rules/c++/unity_build/xmake.lua63
-rw-r--r--xmake/rules/cuda/devlink/xmake.lua2
-rw-r--r--xmake/rules/cuda/env/xmake.lua2
-rw-r--r--xmake/rules/cuda/gencodes/xmake.lua44
-rw-r--r--xmake/rules/go/build/object.lua21
-rw-r--r--xmake/rules/go/xmake.lua4
-rw-r--r--xmake/rules/luarocks/module/xmake.lua2
-rw-r--r--xmake/rules/mdk/xmake.lua43
-rw-r--r--xmake/rules/nim/build/target.lua86
-rw-r--r--xmake/rules/nim/xmake.lua37
-rw-r--r--xmake/rules/pascal/build/target.lua88
-rw-r--r--xmake/rules/pascal/xmake.lua33
-rw-r--r--xmake/rules/platform/linux/driver/driver_modules.lua299
-rw-r--r--xmake/rules/platform/linux/driver/xmake.lua33
-rw-r--r--xmake/rules/platform/windows/def/xmake.lua3
-rw-r--r--xmake/rules/platform/windows/manifest/xmake.lua3
-rw-r--r--xmake/rules/plugin/vsxmake/xmake.lua9
-rw-r--r--xmake/rules/python/xmake.lua43
-rw-r--r--xmake/rules/qt/deploy/android.lua36
-rw-r--r--xmake/rules/qt/deploy/macosx.lua2
-rw-r--r--xmake/rules/qt/load.lua10
-rw-r--r--xmake/rules/qt/moc/xmake.lua3
-rw-r--r--xmake/rules/qt/qrc/xmake.lua3
-rw-r--r--xmake/rules/qt/ui/xmake.lua3
-rw-r--r--xmake/rules/qt/xmake.lua22
-rw-r--r--xmake/rules/rust/build/cxxbridge.lua50
-rw-r--r--xmake/rules/rust/build/target.lua26
-rw-r--r--xmake/rules/rust/xmake.lua48
-rw-r--r--xmake/rules/swig/build_module_file.lua55
-rw-r--r--xmake/rules/swig/xmake.lua98
-rw-r--r--xmake/rules/utils/bin2c/xmake.lua11
-rw-r--r--xmake/rules/utils/glsl2spv/xmake.lua90
-rw-r--r--xmake/rules/utils/inherit_links/inherit_links.lua28
-rw-r--r--xmake/rules/utils/install_importfiles/xmake.lua4
-rw-r--r--xmake/rules/utils/merge_archive/merge_archive.lua7
-rw-r--r--xmake/rules/utils/merge_archive/xmake.lua30
-rw-r--r--xmake/rules/utils/merge_object/xmake.lua2
-rw-r--r--xmake/rules/utils/symbols/export_all/export_all.lua5
-rw-r--r--xmake/rules/utils/symbols/export_all/xmake.lua2
-rw-r--r--xmake/rules/utils/symbols/extract/xmake.lua2
-rw-r--r--xmake/rules/vala/xmake.lua112
-rw-r--r--xmake/rules/wdk/env/xmake.lua2
-rw-r--r--xmake/rules/wdk/inf/xmake.lua4
-rw-r--r--xmake/rules/wdk/man/xmake.lua4
-rw-r--r--xmake/rules/wdk/mc/xmake.lua4
-rw-r--r--xmake/rules/wdk/mof/xmake.lua4
-rw-r--r--xmake/rules/wdk/sign/xmake.lua4
-rw-r--r--xmake/rules/wdk/tracewpp/xmake.lua4
-rw-r--r--xmake/rules/winsdk/dotnet/xmake.lua2
-rw-r--r--xmake/rules/winsdk/mfc/env/xmake.lua2
-rw-r--r--xmake/rules/winsdk/xmake.lua2
-rw-r--r--xmake/rules/xcode/application/build.lua2
-rw-r--r--xmake/rules/xcode/application/load.lua11
-rw-r--r--xmake/rules/xcode/application/run.lua4
-rw-r--r--xmake/rules/xcode/application/xmake.lua19
-rw-r--r--xmake/rules/xcode/bundle/xmake.lua4
-rw-r--r--xmake/rules/xcode/framework/xmake.lua4
-rw-r--r--xmake/rules/xcode/info_plist/xmake.lua2
-rw-r--r--xmake/rules/xcode/metal/xmake.lua145
-rw-r--r--xmake/rules/xcode/storyboard/xmake.lua2
-rw-r--r--xmake/rules/xcode/xcassets/xmake.lua2
-rw-r--r--xmake/rules/xmake_cli/xmake.lua2
71 files changed, 2241 insertions, 321 deletions
diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua
deleted file mode 100644
index 75593f0cc..000000000
--- a/xmake/rules/c++/modules/build_modulefiles.lua
+++ /dev/null
@@ -1,151 +0,0 @@
---!A cross-platform build utility based on Lua
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
---
--- Copyright (C) 2015-present, TBOOX Open Source Group.
---
--- @author ruki
--- @file build_modulefiles.lua
---
-
--- imports
-import("core.tool.compiler")
-
--- build module files using clang
-function _build_modulefiles_clang(target, sourcebatch, opt)
-
- -- attempt to compile the module files as cxx
- sourcebatch.sourcekind = "cxx"
- sourcebatch.objectfiles = sourcebatch.objectfiles or {}
- sourcebatch.dependfiles = sourcebatch.dependfiles or {}
- for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
- local objectfile = target:objectfile(sourcefile) .. ".pcm"
- table.insert(sourcebatch.objectfiles, objectfile)
- table.insert(sourcebatch.dependfiles, target:dependfile(objectfile))
- end
-
- -- compile module files to *.pcm
- opt = table.join(opt, {configs = {force = {cxxflags = {opt.modulesflag, "--precompile", "-x c++-module"}}}})
- import("private.action.build.object").build(target, sourcebatch, opt)
-
- -- compile *.pcm to object files
- local modulefiles = {}
- for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
- local modulefile = sourcebatch.objectfiles[idx]
- local objectfile = target:objectfile(sourcefile)
- sourcebatch.sourcefiles[idx] = modulefile
- sourcebatch.objectfiles[idx] = objectfile
- sourcebatch.dependfiles[idx] = target:dependfile(objectfile)
- table.insert(modulefiles, modulefile)
- end
- opt.configs = {cxxflags = {opt.modulesflag}}
- opt.quiet = true
- import("private.action.build.object").build(target, sourcebatch, opt)
-
- -- add module files
- target:add("cxxflags", opt.modulesflag)
- for _, modulefile in ipairs(modulefiles) do
- target:add("cxxflags", "-fmodules", "-fimplicit-modules", "-fimplicit-module-maps", "-fmodule-file=" .. modulefile)
- end
-end
-
--- TODO
--- build module files using gcc
-function _build_modulefiles_gcc(target, sourcebatch, opt)
-
- -- attempt to compile the module files as cxx
- local modulefiles = {}
- opt = table.join(opt, {configs = {}})
- sourcebatch.sourcekind = "cxx"
- sourcebatch.objectfiles = sourcebatch.objectfiles or {}
- sourcebatch.dependfiles = sourcebatch.dependfiles or {}
- for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
- local objectfile = target:objectfile(sourcefile)
- local dependfile = target:dependfile(objectfile)
- local modulefile = objectfile .. ".pcm"
-
- -- compile module file to *.pcm
- local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}}
- opt.configs.cxxflags = {"-fmodules-ts", "-x c++"}
- import("private.action.build.object").build(target, singlebatch, opt)
- table.insert(modulefiles, modulefile)
- table.insert(sourcebatch.objectfiles, objectfile)
- table.insert(sourcebatch.dependfiles, dependfile)
- end
-
- -- add module files
- for _, modulefile in ipairs(modulefiles) do
- target:add("cxxflags", "-fmodules-ts", "-fmodule-file=" .. modulefile)
- end
-end
-
--- build module files using msvc
-function _build_modulefiles_msvc(target, sourcebatch, opt)
-
- -- attempt to compile the module files as cxx
- local modulefiles = {}
- opt = table.join(opt, {configs = {}})
- sourcebatch.sourcekind = "cxx"
- sourcebatch.objectfiles = sourcebatch.objectfiles or {}
- sourcebatch.dependfiles = sourcebatch.dependfiles or {}
- for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
- local objectfile = target:objectfile(sourcefile)
- local dependfile = target:dependfile(objectfile)
- local modulefile = objectfile .. ".pcm"
-
- -- compile module file to *.pcm
- local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}}
- opt.configs.cxxflags = {"/experimental:module /module:interface /module:output " .. os.args(modulefile), "/TP"}
- import("private.action.build.object").build(target, singlebatch, opt)
- table.insert(modulefiles, modulefile)
- table.insert(sourcebatch.objectfiles, objectfile)
- table.insert(sourcebatch.dependfiles, dependfile)
- end
-
- -- add module files
- for _, modulefile in ipairs(modulefiles) do
- target:add("cxxflags", "/experimental:module /module:reference " .. os.args(modulefile))
- end
-end
-
--- build module files
-function main(target, sourcebatch, opt)
-
- -- do compile
- local modulesflag = nil
- local toolname = target:tool("cxx")
- local compinst = compiler.load("cxx")
- if toolname:find("clang", 1, true) or toolname:find("gcc", 1, true) or toolname:find("g++", 1, true) then
- if compinst:has_flags("-fmodules") then
- modulesflag = "-fmodules"
- elseif compinst:has_flags("-fmodules-ts") then
- modulesflag = "-fmodules-ts"
- end
- elseif toolname == "cl" then
- if compinst:has_flags("/experimental:module") then
- modulesflag = "/experimental:module"
- end
- end
- if modulesflag then
- opt.modulesflag = modulesflag
- if toolname:find("clang", 1, true) then
- _build_modulefiles_clang(target, sourcebatch, opt)
- elseif toolname:find("gcc", 1, true) or toolname:find("g++", 1, true) then
- _build_modulefiles_gcc(target, sourcebatch, opt)
- elseif toolname == "cl" then
- _build_modulefiles_msvc(target, sourcebatch, opt)
- else
- raise("compiler(%s): does not support c++ module!", toolname)
- end
- end
-end
diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua
new file mode 100644
index 000000000..523c61ad9
--- /dev/null
+++ b/xmake/rules/c++/modules/build_modules/clang.lua
@@ -0,0 +1,139 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file clang.lua
+--
+
+-- imports
+import("core.tool.compiler")
+import("private.action.build.object", {alias = "objectbuilder"})
+import("module_parser")
+
+-- load parent target with modules files
+function load_parent(target, opt)
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules") then
+ modulesflag = "-fmodules"
+ elseif compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(clang): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+
+ -- the module cache directory
+ for _, dep in ipairs(target:orderdeps()) do
+ local sourcebatches = dep:sourcebatches()
+ if sourcebatches and sourcebatches["c++.build.modules"] then
+ local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache")
+ target:add("cxxflags", "-fmodules-cache-path=" .. cachedir, {force = true})
+ target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true})
+ end
+ end
+end
+
+-- build module files
+function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules") then
+ modulesflag = "-fmodules"
+ elseif compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(clang): does not support c++ module!")
+
+ -- the module cache directory
+ local cachedir = path.join(target:autogendir(), "rules", "modules", "cache")
+
+ -- we need patch objectfiles to sourcebatch for linking module objects
+ local modulefiles = {}
+ sourcebatch.sourcekind = "cxx"
+ sourcebatch.objectfiles = sourcebatch.objectfiles or {}
+ sourcebatch.dependfiles = sourcebatch.dependfiles or {}
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local modulefile = path.join(cachedir, path.basename(sourcefile) .. ".pcm")
+ local objectfile = target:objectfile(sourcefile)
+ table.insert(sourcebatch.objectfiles, objectfile)
+ table.insert(sourcebatch.dependfiles, target:dependfile(objectfile))
+ table.insert(modulefiles, modulefile)
+ end
+
+ -- load moduledeps
+ local moduledeps = module_parser.load(target, sourcebatch, opt)
+
+ -- build moduledeps
+ local moduledeps_files = module_parser.build(moduledeps)
+
+ -- compile module files to object files
+ local count = 0
+ local sourcefiles_total = #sourcebatch.sourcefiles
+ for i = 1, sourcefiles_total do
+ local sourcefile = sourcebatch.sourcefiles[i]
+ local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile)
+ moduledep.job = batchjobs:newjob(sourcefile, function (index, total)
+
+ -- compile module files to *.pcm
+ local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag,
+ "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir,
+ "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}})
+ opt2.progress = (index * 100) / total
+ opt2.objectfile = modulefiles[i]
+ opt2.dependfile = target:dependfile(opt2.objectfile)
+ opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
+ objectbuilder.build_object(target, sourcefile, opt2)
+
+ -- compile *.pcm to object files
+ opt2.configs = {force = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir,
+ "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}}}
+ opt2.quiet = true
+ opt2.objectfile = sourcebatch.objectfiles[i]
+ opt2.dependfile = sourcebatch.dependfiles[i]
+ objectbuilder.build_object(target, modulefiles[i], opt2)
+
+ -- add module flags to other c++ files after building all modules
+ count = count + 1
+ if count == sourcefiles_total then
+ target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir, {force = true})
+ -- FIXME It is invalid for the module implementation unit
+ --target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true})
+ for _, modulefile in ipairs(modulefiles) do
+ target:add("cxxflags", "-fmodule-file=" .. modulefile, {force = true})
+ end
+ end
+
+ end)
+ end
+
+ -- build batchjobs
+ local rootjob = opt.rootjob
+ for _, moduledep in pairs(moduledeps) do
+ if moduledep.parents then
+ for _, parent in ipairs(moduledep.parents) do
+ batchjobs:add(moduledep.job, parent.job)
+ end
+ else
+ batchjobs:add(moduledep.job, rootjob)
+ end
+ end
+end
+
diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua
new file mode 100644
index 000000000..2abaa4f7f
--- /dev/null
+++ b/xmake/rules/c++/modules/build_modules/gcc.lua
@@ -0,0 +1,96 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file gcc.lua
+--
+
+-- imports
+import("core.tool.compiler")
+import("private.action.build.object", {alias = "objectbuilder"})
+import("module_parser")
+
+-- load parent target with modules files
+function load_parent(target, opt)
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(gcc): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+end
+
+-- build module files
+function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(gcc): does not support c++ module!")
+
+ -- we need patch objectfiles to sourcebatch for linking module objects
+ sourcebatch.sourcekind = "cxx"
+ sourcebatch.objectfiles = sourcebatch.objectfiles or {}
+ sourcebatch.dependfiles = sourcebatch.dependfiles or {}
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local objectfile = target:objectfile(sourcefile)
+ table.insert(sourcebatch.objectfiles, objectfile)
+ table.insert(sourcebatch.dependfiles, target:dependfile(objectfile))
+ end
+
+ -- load moduledeps
+ local moduledeps = module_parser.load(target, sourcebatch, opt)
+
+ -- build moduledeps
+ local moduledeps_files = module_parser.build(moduledeps)
+
+ -- compile module files to object files
+ for i = 1, #sourcebatch.sourcefiles do
+ local sourcefile = sourcebatch.sourcefiles[i]
+ local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile)
+ moduledep.job = batchjobs:newjob(sourcefile, function (index, total)
+ local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}})
+ opt2.progress = (index * 100) / total
+ opt2.objectfile = sourcebatch.objectfiles[i]
+ opt2.dependfile = sourcebatch.dependfiles[i]
+ opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
+ objectbuilder.build_object(target, sourcefile, opt2)
+ end)
+ end
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+
+ -- build batchjobs
+ local rootjob = opt.rootjob
+ for _, moduledep in pairs(moduledeps) do
+ if moduledep.parents then
+ for _, parent in ipairs(moduledep.parents) do
+ batchjobs:add(moduledep.job, parent.job)
+ end
+ else
+ batchjobs:add(moduledep.job, rootjob)
+ end
+ end
+end
+
diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua
new file mode 100644
index 000000000..b97b7e1d0
--- /dev/null
+++ b/xmake/rules/c++/modules/build_modules/module_parser.lua
@@ -0,0 +1,118 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file module_parser.lua
+--
+
+-- imports
+import("core.project.depend")
+
+-- get depend file of module source file
+function _get_dependfile_of_modulesource(target, sourcefile)
+ return target:dependfile(sourcefile)
+end
+
+-- get depend file of module object file, compiler will rewrite it
+function _get_dependfile_of_moduleobject(target, sourcefile)
+ local objectfile = target:objectfile(sourcefile)
+ return target:dependfile(objectfile)
+end
+
+-- generate module deps for the given file
+function _generate_moduledeps(target, sourcefile, opt)
+ local dependfile = _get_dependfile_of_modulesource(target, sourcefile)
+ depend.on_changed(function ()
+
+ -- trace
+ vprint("generating.moduledeps %s", sourcefile)
+
+ -- generating deps
+ local module_name
+ local module_deps
+ local sourcecode = io.readfile(sourcefile)
+ sourcecode = sourcecode:gsub("//.-\n", "\n")
+ sourcecode = sourcecode:gsub("/%*.-%*/", "")
+ for _, line in ipairs(sourcecode:split("\n", {plain = true})) do
+ if not module_name then
+ module_name = line:match("export%s+module%s+(.+)%s*;")
+ end
+ local module_depname = line:match("import%s+(.+)%s*;")
+ if module_depname then
+ -- partition? import :xxx;
+ if module_depname:startswith(":") then
+ module_depname = module_name .. module_depname
+ end
+ module_deps = module_deps or {}
+ table.insert(module_deps, module_depname)
+ end
+ end
+
+ -- save depend data
+ if module_name then
+ local dependinfo = {moduleinfo = {name = module_name, deps = module_deps, file = sourcefile}}
+ return dependinfo
+ end
+
+ end, {dependfile = dependfile, files = {sourcefile}})
+end
+
+-- generate module deps
+function generate(target, sourcebatch, opt)
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ _generate_moduledeps(target, sourcefile, opt)
+ end
+end
+
+-- load module deps
+function load(target, sourcebatch, opt)
+
+ -- do generate first
+ generate(target, sourcebatch, opt)
+
+ -- load deps
+ local moduledeps
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local dependfile = _get_dependfile_of_modulesource(target, sourcefile)
+ if os.isfile(dependfile) then
+ local data = io.load(dependfile)
+ if data then
+ local moduleinfo = data.moduleinfo
+ moduledeps = moduledeps or {}
+ moduledeps[moduleinfo.name] = moduleinfo
+ end
+ end
+ end
+ return moduledeps
+end
+
+-- build module deps
+function build(moduledeps)
+ local moduledeps_files = {}
+ for _, moduledep in pairs(moduledeps) do
+ if moduledep.deps then
+ for _, depname in ipairs(moduledep.deps) do
+ local dep = moduledeps[depname]
+ if dep then
+ dep.parents = dep.parents or {}
+ table.insert(dep.parents, moduledep)
+ end
+ end
+ end
+ moduledeps_files[moduledep.file] = moduledep
+ end
+ return moduledeps_files
+end
diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua
new file mode 100644
index 000000000..1dc04618f
--- /dev/null
+++ b/xmake/rules/c++/modules/build_modules/msvc.lua
@@ -0,0 +1,181 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file msvc.lua
+--
+
+-- imports
+import("core.tool.compiler")
+import("private.action.build.object", {alias = "objectbuilder"})
+import("module_parser")
+
+-- load parent target with modules files
+function load_parent(target, opt)
+
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("/experimental:module", "cxxflags") then
+ modulesflag = "/experimental:module"
+ end
+ assert(modulesflag, "compiler(msvc): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+
+ -- get output flag
+ if compinst:has_flags("/ifcOutput", "cxxflags") then
+ for _, dep in ipairs(target:orderdeps()) do
+ local sourcebatches = dep:sourcebatches()
+ if sourcebatches and sourcebatches["c++.build.modules"] then
+ local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache")
+ target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir), {force = true})
+ end
+ end
+ end
+end
+
+-- build module files
+function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("/experimental:module", "cxxflags") then
+ modulesflag = "/experimental:module"
+ end
+ assert(modulesflag, "compiler(msvc): does not support c++ module!")
+
+ -- get output flag
+ local cachedir
+ local outputflag
+ if compinst:has_flags("/ifcOutput", "cxxflags") then
+ outputflag = "/ifcOutput"
+ cachedir = path.join(target:autogendir(), "rules", "modules", "cache")
+ if not os.isdir(cachedir) then
+ os.mkdir(cachedir)
+ end
+ elseif compinst:has_flags("/module:output", "cxxflags") then
+ outputflag = "/module:output"
+ end
+ assert(outputflag, "compiler(msvc): does not support c++ module!")
+
+ -- get interface flag
+ local interfaceflag
+ if compinst:has_flags("/interface", "cxxflags") then
+ interfaceflag = "/interface"
+ elseif compinst:has_flags("/module:interface", "cxxflags") then
+ interfaceflag = "/module:interface"
+ end
+ assert(interfaceflag, "compiler(msvc): does not support c++ module!")
+
+ -- get reference flag
+ local referenceflag
+ if compinst:has_flags("/reference", "cxxflags") then
+ referenceflag = "/reference"
+ elseif compinst:has_flags("/module:interface", "cxxflags") then
+ referenceflag = "/module:reference"
+ end
+ assert(referenceflag, "compiler(msvc): does not support c++ module!")
+
+ -- get stdifcdir flag
+ local stdifcdirflag
+ if compinst:has_flags("/stdIfcDir", "cxxflags") then
+ stdifcdirflag = "/stdIfcDir"
+ elseif compinst:has_flags("/module:stdIfcDir", "cxxflags") then
+ stdifcdirflag = "/module:stdIfcDir"
+ end
+ assert(stdifcdirflag, "compiler(msvc): does not support c++ module!")
+
+ -- we need patch objectfiles to sourcebatch for linking module objects
+ local modulefiles = {}
+ sourcebatch.sourcekind = "cxx"
+ sourcebatch.objectfiles = sourcebatch.objectfiles or {}
+ sourcebatch.dependfiles = sourcebatch.dependfiles or {}
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local objectfile = target:objectfile(sourcefile)
+ local dependfile = target:dependfile(objectfile)
+ local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc"
+ table.insert(modulefiles, modulefile)
+ table.insert(sourcebatch.objectfiles, objectfile)
+ table.insert(sourcebatch.dependfiles, dependfile)
+ end
+
+ -- load moduledeps
+ local moduledeps = module_parser.load(target, sourcebatch, opt)
+
+ -- build moduledeps
+ local moduledeps_files = module_parser.build(moduledeps)
+
+ -- compile module files to object files
+ local count = 0
+ local sourcefiles_total = #sourcebatch.sourcefiles
+ for i = 1, sourcefiles_total do
+ local sourcefile = sourcebatch.sourcefiles[i]
+ local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile)
+ moduledep.job = batchjobs:newjob(sourcefile, function (index, total)
+ local opt2 = table.join(opt, {configs = {force = {cxxflags = {interfaceflag,
+ outputflag .. " " .. os.args(modulefiles[i]), "/TP"}}}})
+ opt2.progress = (index * 100) / total
+ opt2.objectfile = sourcebatch.objectfiles[i]
+ opt2.dependfile = sourcebatch.dependfiles[i]
+ opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
+ objectbuilder.build_object(target, sourcefile, opt2)
+
+ -- add module flags to other c++ files after building all modules
+ count = count + 1
+ if count == sourcefiles_total and not cachedir then
+ for _, modulefile in ipairs(modulefiles) do
+ target:add("cxxflags", referenceflag .. " " .. os.args(modulefile))
+ end
+ end
+ end)
+ end
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+ if cachedir then
+ target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir))
+ end
+ if stdifcdirflag then
+ for _, toolchain_inst in ipairs(target:toolchains()) do
+ if toolchain_inst:name() == "msvc" then
+ local vcvars = toolchain_inst:config("vcvars")
+ if vcvars.VCInstallDir and vcvars.VCToolsVersion then
+ local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86")
+ if os.isdir(stdifcdir) then
+ target:add("cxxflags", stdifcdirflag .. " " .. winos.short_path(stdifcdir))
+ end
+ end
+ break
+ end
+ end
+ end
+
+ -- build batchjobs
+ local rootjob = opt.rootjob
+ for _, moduledep in pairs(moduledeps) do
+ if moduledep.parents then
+ for _, parent in ipairs(moduledep.parents) do
+ batchjobs:add(moduledep.job, parent.job)
+ end
+ else
+ batchjobs:add(moduledep.job, rootjob)
+ end
+ end
+end
+
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index dfaf04897..c587a3912 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -21,5 +21,43 @@
-- define rule: c++.build.modules
rule("c++.build.modules")
set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
- before_build_files("build_modulefiles")
+ on_config(function (target)
+ -- we disable to build across targets in parallel, because the source files may depend on other target modules
+ -- @see https://github.com/xmake-io/xmake/issues/1858
+ local target_with_modules
+ for _, dep in ipairs(target:orderdeps()) do
+ local sourcebatches = dep:sourcebatches()
+ if sourcebatches and sourcebatches["c++.build.modules"] then
+ target_with_modules = true
+ break
+ end
+ end
+ if target_with_modules then
+ -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets,
+ -- even if some sub-targets do not contain C++ modules.
+ --
+ -- maybe we will have a more fine-grained configuration strategy to disable it in the future.
+ target:set("policy", "build.across_targets_in_parallel", false)
+ if target:has_tool("cxx", "clang", "clangxx") then
+ import("build_modules.clang").load_parent(target, opt)
+ elseif target:has_tool("cxx", "gcc", "gxx") then
+ import("build_modules.gcc").load_parent(target, opt)
+ elseif target:has_tool("cxx", "cl") then
+ import("build_modules.msvc").load_parent(target, opt)
+ else
+ raise("compiler(%s): does not support c++ module!", toolname)
+ end
+ end
+ end)
+ before_build_files(function (target, batchjobs, sourcebatch, opt)
+ if target:has_tool("cxx", "clang", "clangxx") then
+ import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+ elseif target:has_tool("cxx", "gcc", "gxx") then
+ import("build_modules.gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+ elseif target:has_tool("cxx", "cl") then
+ import("build_modules.msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+ else
+ raise("compiler(%s): does not support c++ module!", toolname)
+ end
+ end, {batch = true})
diff --git a/xmake/rules/c++/openmp/load.lua b/xmake/rules/c++/openmp/load.lua
index a4535f553..3f0508512 100644
--- a/xmake/rules/c++/openmp/load.lua
+++ b/xmake/rules/c++/openmp/load.lua
@@ -20,6 +20,7 @@
-- main entry
function main(target, sourcekind)
+ wprint("we no longer need add_rules(\"%s.openmp\") now, you just need to add add_packages(\"openmp\").", sourcekind == "cxx" and "c++" or "c")
local _, compiler_name = target:tool(sourcekind)
local flag_name = sourcekind == "cxx" and "cxxflags" or "cflags"
if compiler_name == "cl" then
diff --git a/xmake/rules/c++/openmp/xmake.lua b/xmake/rules/c++/openmp/xmake.lua
index 47dd2d07f..82e3cc562 100644
--- a/xmake/rules/c++/openmp/xmake.lua
+++ b/xmake/rules/c++/openmp/xmake.lua
@@ -20,12 +20,12 @@
-- define rule: c.openmp
rule("c.openmp")
- on_load(function (target)
+ on_config(function (target)
import("load")(target, "cc")
end)
-- define rule: c++.openmp
rule("c++.openmp")
- on_load(function (target)
+ on_config(function (target)
import("load")(target, "cxx")
end)
diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua
new file mode 100644
index 000000000..608f79fed
--- /dev/null
+++ b/xmake/rules/c++/unity_build/unity_build.lua
@@ -0,0 +1,139 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file unity_build.lua
+--
+
+-- imports
+import("core.project.depend")
+
+function _merge_unityfile(target, sourcefile_unity, sourcefiles, opt)
+ local dependfile = target:dependfile(sourcefile_unity)
+ depend.on_changed(function ()
+
+ -- trace
+ vprint("generating.unityfile %s", sourcefile_unity)
+
+ -- do merge
+ local uniqueid = target:data("unity_build.uniqueid")
+ local unityfile = io.open(sourcefile_unity, "w")
+ for _, sourcefile in ipairs(sourcefiles) do
+ sourcefile = path.absolute(sourcefile)
+ sourcefile_unity = path.absolute(sourcefile_unity)
+ sourcefile = path.relative(sourcefile, path.directory(sourcefile_unity))
+ if uniqueid then
+ unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1])
+ end
+ unityfile:print("#include \"%s\"", sourcefile)
+ if uniqueid then
+ unityfile:print("#undef %s", uniqueid)
+ end
+ end
+ unityfile:close()
+
+ end, {dependfile = dependfile, files = sourcefiles})
+end
+
+function generate_unityfiles(target, sourcebatch, opt)
+ local unity_batch = target:data("unity_build.unity_batch." .. sourcebatch.rulename)
+ if unity_batch then
+ for _, sourcefile_unity in ipairs(sourcebatch.sourcefiles) do
+ local sourceinfo = unity_batch[sourcefile_unity]
+ if sourceinfo then
+ local sourcefiles = sourceinfo.sourcefiles
+ if sourcefiles then
+ _merge_unityfile(target, sourcefile_unity, sourcefiles, opt)
+ end
+ end
+ end
+ end
+end
+
+-- use unity build
+--
+-- e.g.
+-- add_rules("c++.unity_build", {batchsize = 2})
+-- add_files("src/*.c", "src/*.cpp", {unity_ignored = true})
+-- add_files("src/foo/*.c", {unity_group = "foo"})
+-- add_files("src/bar/*.c", {unity_group = "bar"})
+--
+function main(target, sourcebatch)
+
+ -- get unit batch sources
+ local extraconf = target:extraconf("rules", sourcebatch.sourcekind == "cxx" and "c++.unity_build" or "c.unity_build")
+ local batchsize = extraconf and extraconf.batchsize
+ local uniqueid = extraconf and extraconf.uniqueid
+ local id = 1
+ local count = 0
+ local unity_batch = {}
+ local sourcefiles = {}
+ local objectfiles = {}
+ local dependfiles = {}
+ local sourcedir = path.join(target:autogendir({root = true}), "unity_build")
+ for idx, sourcefile in pairs(sourcebatch.sourcefiles) do
+ local sourcefile_unity
+ local objectfile = sourcebatch.objectfiles[idx]
+ local dependfile = sourcebatch.dependfiles[idx]
+ local fileconfig = target:fileconfig(sourcefile)
+ if fileconfig and fileconfig.unity_group then
+ sourcefile_unity = path.join(sourcedir, "unity_" .. fileconfig.unity_group .. path.extension(sourcefile))
+ elseif (fileconfig and fileconfig.unity_ignored) or (batchsize and batchsize <= 1) then
+ -- we do not add these files to unity file
+ table.insert(sourcefiles, sourcefile)
+ table.insert(objectfiles, objectfile)
+ table.insert(dependfiles, dependfile)
+ else
+ if batchsize and count > batchsize then
+ id = id + 1
+ end
+ sourcefile_unity = path.join(sourcedir, "unity_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile))
+ count = count + 1
+ end
+ if sourcefile_unity then
+ local sourceinfo = unity_batch[sourcefile_unity]
+ if not sourceinfo then
+ sourceinfo = {}
+ sourceinfo.objectfile = target:objectfile(sourcefile_unity)
+ sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile)
+ unity_batch[sourcefile_unity] = sourceinfo
+ end
+ sourceinfo.sourcefiles = sourceinfo.sourcefiles or {}
+ table.insert(sourceinfo.sourcefiles, sourcefile)
+ end
+ end
+
+ -- use unit batch
+ for _, sourcefile_unity in ipairs(table.orderkeys(unity_batch)) do
+ local sourceinfo = unity_batch[sourcefile_unity]
+ if #sourceinfo.sourcefiles > 1 then
+ table.insert(sourcefiles, sourcefile_unity)
+ table.insert(objectfiles, sourceinfo.objectfile)
+ table.insert(dependfiles, sourceinfo.dependfile)
+ else
+ table.insert(sourcefiles, sourceinfo.sourcefiles[1])
+ table.insert(objectfiles, sourceinfo.objectfile)
+ table.insert(dependfiles, sourceinfo.dependfile)
+ end
+ end
+ sourcebatch.sourcefiles = sourcefiles
+ sourcebatch.objectfiles = objectfiles
+ sourcebatch.dependfiles = dependfiles
+
+ -- save unit batch
+ target:data_set("unity_build.uniqueid", uniqueid)
+ target:data_set("unity_build.unity_batch." .. sourcebatch.rulename, unity_batch)
+end
diff --git a/xmake/rules/c++/unity_build/xmake.lua b/xmake/rules/c++/unity_build/xmake.lua
new file mode 100644
index 000000000..e0dfa9660
--- /dev/null
+++ b/xmake/rules/c++/unity_build/xmake.lua
@@ -0,0 +1,63 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+rule("c.unity_build")
+ after_load(function (target)
+ import("unity_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["c.build"]
+ if sourcebatch then
+ unity_build(target, sourcebatch)
+ end
+ end
+ end)
+ before_build(function (target, opt)
+ import("unity_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["c.build"]
+ if sourcebatch then
+ unity_build.generate_unityfiles(target, sourcebatch, opt)
+ end
+ end
+ end)
+
+rule("c++.unity_build")
+ after_load(function (target)
+ import("unity_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["c++.build"]
+ if sourcebatch then
+ unity_build(target, sourcebatch)
+ end
+ end
+ end)
+ before_build(function (target, opt)
+ import("unity_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["c++.build"]
+ if sourcebatch then
+ unity_build.generate_unityfiles(target, sourcebatch, opt)
+ end
+ end
+ end)
diff --git a/xmake/rules/cuda/devlink/xmake.lua b/xmake/rules/cuda/devlink/xmake.lua
index e92a0b779..fb1f603b0 100644
--- a/xmake/rules/cuda/devlink/xmake.lua
+++ b/xmake/rules/cuda/devlink/xmake.lua
@@ -34,7 +34,7 @@ rule("cuda.build.devlink")
import("core.project.depend")
import("core.tool.linker")
import("core.platform.platform")
- import("private.utils.progress")
+ import("utils.progress")
-- disable devlink?
if target:values("cuda.build.devlink") == false then
diff --git a/xmake/rules/cuda/env/xmake.lua b/xmake/rules/cuda/env/xmake.lua
index e6e802d71..96d587e41 100644
--- a/xmake/rules/cuda/env/xmake.lua
+++ b/xmake/rules/cuda/env/xmake.lua
@@ -21,7 +21,7 @@
-- define rule: environment
rule("cuda.env")
- before_load(function (target)
+ on_load(function (target)
-- imports
import("detect.sdks.find_cuda")
diff --git a/xmake/rules/cuda/gencodes/xmake.lua b/xmake/rules/cuda/gencodes/xmake.lua
index 0845178fe..c7ee45050 100644
--- a/xmake/rules/cuda/gencodes/xmake.lua
+++ b/xmake/rules/cuda/gencodes/xmake.lua
@@ -34,7 +34,7 @@ rule("cuda.gencodes")
-- if no available device is found, no `-gencode` flags will be added
-- @seealso xmake/modules/lib/detect/find_cudadevices
--
- before_load(function (target)
+ on_config(function (target)
-- imports
import("core.platform.platform")
@@ -47,14 +47,14 @@ rule("cuda.gencodes")
local known_r_archs = hashset.of(20, 30, 32, 35, 37, 50, 52, 53, 60, 61, 62, 70, 72, 75, 80)
local function nf_cugencode(archs)
- if type(archs) ~= 'string' then
+ if type(archs) ~= "string" then
return nil
end
archs = archs:trim():lower()
- if archs == 'native' then
+ if archs == "native" then
local device = find_cudadevices({ skip_compute_mode_prohibited = true, order_by_flops = true })[1]
if device then
- return nf_cugencode('sm_' .. device.major .. device.minor)
+ return nf_cugencode("sm_" .. device.major .. device.minor)
end
return nil
end
@@ -68,13 +68,13 @@ rule("cuda.gencodes")
end
local arch = tonumber(value:sub(#prefix + 1)) or tonumber(value:sub(#prefix + 2))
if arch == nil then
- raise("Unknown architecture: " .. value)
+ raise("unknown architecture: " .. value)
end
if not know_list:has(arch) then
if arch <= table.maxn(know_list:data()) then
- raise("Unknown architecture: " .. prefix .. "_" .. arch)
+ raise("unknown architecture: " .. prefix .. "_" .. arch)
else
- utils.warning("Unknown architecture: " .. prefix .. "_" .. arch)
+ utils.warning("unknown architecture: " .. prefix .. "_" .. arch)
end
end
return arch
@@ -82,20 +82,20 @@ rule("cuda.gencodes")
for _, v in ipairs(archs:split(',')) do
local arch = v:trim()
- local temp_r_arch = parse_arch(arch, 'sm', known_r_archs)
+ local temp_r_arch = parse_arch(arch, "sm", known_r_archs)
if temp_r_arch then
table.insert(r_archs, temp_r_arch)
end
- local temp_v_arch = parse_arch(arch, 'compute', known_v_archs)
+ local temp_v_arch = parse_arch(arch, "compute", known_v_archs)
if temp_v_arch then
if v_arch ~= nil then
- raise("More than one virtual architecture is defined in one gpu gencode option: compute_" .. v_arch .. " and compute_" .. temp_v_arch)
+ raise("more than one virtual architecture is defined in one gpu gencode option: compute_" .. v_arch .. " and compute_" .. temp_v_arch)
end
v_arch = temp_v_arch
end
if not (temp_r_arch or temp_v_arch) then
- raise("Unknown architecture: " .. arch)
+ raise("unknown architecture: " .. arch)
end
end
@@ -105,27 +105,28 @@ rule("cuda.gencodes")
if #r_archs == 0 then
return {
- clang = '--cuda-gpu-arch=sm_' .. v_arch
- , nvcc = '-gencode arch=compute_' .. v_arch .. ',code=compute_' .. v_arch }
+ clang = "--cuda-gpu-arch=sm_" .. v_arch,
+ nvcc = "-gencode arch=compute_" .. v_arch .. ",code=compute_" .. v_arch
+ }
end
if v_arch then
table.insert(r_archs, v_arch)
else
- v_arch = math.min(unpack(r_archs))
+ v_arch = math.min(table.unpack(r_archs))
end
r_archs = table.unique(r_archs)
local clang_flags = {}
for _, r_arch in ipairs(r_archs) do
- table.insert(clang_flags, '--cuda-gpu-arch=sm_' .. r_arch)
+ table.insert(clang_flags, "--cuda-gpu-arch=sm_" .. r_arch)
end
local nvcc_flags = nil
if #r_archs == 1 then
- nvcc_flags = '-gencode arch=compute_' .. v_arch .. ',code=sm_' .. r_archs[1]
+ nvcc_flags = "-gencode arch=compute_" .. v_arch .. ",code=sm_" .. r_archs[1]
else
- nvcc_flags = '-gencode arch=compute_' .. v_arch .. ',code=[sm_' .. table.concat(r_archs, ',sm_') .. ']'
+ nvcc_flags = "-gencode arch=compute_" .. v_arch .. ",code=[sm_" .. table.concat(r_archs, ",sm_") .. "]"
end
return { clang = clang_flags, nvcc = nvcc_flags }
@@ -138,13 +139,12 @@ rule("cuda.gencodes")
for _, v in ipairs(cugencodes) do
local flag = nf_cugencode(v)
if flag then
- local tool, toolname = platform.tool("cu")
- if (toolname or path.basename(tool)) == "nvcc" then
- target:add('cuflags', flag.nvcc)
+ if target:has_tool("cu", "nvcc") then
+ target:add("cuflags", flag.nvcc)
else
- target:add('cuflags', flag.clang)
+ target:add("cuflags", flag.clang)
end
- target:add('culdflags', flag.nvcc)
+ target:add("culdflags", flag.nvcc)
end
end
end)
diff --git a/xmake/rules/go/build/object.lua b/xmake/rules/go/build/object.lua
index cf6a1c9ff..21436be47 100644
--- a/xmake/rules/go/build/object.lua
+++ b/xmake/rules/go/build/object.lua
@@ -21,19 +21,13 @@
-- imports
import("core.base.option")
import("core.base.hashset")
-import("core.theme.theme")
import("core.tool.compiler")
import("core.project.depend")
+import("utils.progress")
-- build the source files
function main(target, sourcebatch, opt)
-
- -- is verbose?
- local verbose = option.get("verbose")
-
- -- get progress range
- local progress = assert(opt.progress, "no progress!")
-
+
-- get source files and kind
local sourcefiles = sourcebatch.sourcefiles
local sourcekind = sourcebatch.sourcekind
@@ -72,18 +66,11 @@ function main(target, sourcebatch, opt)
-- trace progress info
for index, sourcefile in ipairs(sourcefiles) do
- local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
- if verbose then
- cprint(progress_prefix .. "${dim color.build.object}compiling.$(mode) %s", progress, sourcefile)
- else
- cprint(progress_prefix .. "${color.build.object}compiling.$(mode) %s", progress, sourcefile)
- end
+ progress.show(opt.progress, "${color.build.object}compiling.$(mode) %s", sourcefile)
end
-- trace verbose info
- if verbose then
- print(compinst:compcmd(sourcefiles, objectfile, {compflags = compflags}))
- end
+ vprint(compinst:compcmd(sourcefiles, objectfile, {compflags = compflags}))
-- compile it
dependinfo.files = {}
diff --git a/xmake/rules/go/xmake.lua b/xmake/rules/go/xmake.lua
index ef6f04321..58890e260 100644
--- a/xmake/rules/go/xmake.lua
+++ b/xmake/rules/go/xmake.lua
@@ -24,6 +24,10 @@ rule("go.build")
on_load(function (target)
-- we disable to build across targets in parallel, because the source files may depend on other target modules
target:set("policy", "build.across_targets_in_parallel", false)
+ -- xxx.a
+ if target:is_static() then
+ target:set("prefixname", "")
+ end
end)
on_build_files("build.object")
diff --git a/xmake/rules/luarocks/module/xmake.lua b/xmake/rules/luarocks/module/xmake.lua
index e74080912..530e35070 100644
--- a/xmake/rules/luarocks/module/xmake.lua
+++ b/xmake/rules/luarocks/module/xmake.lua
@@ -19,7 +19,7 @@
--
rule("luarocks.module")
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.cache.detectcache")
diff --git a/xmake/rules/mdk/xmake.lua b/xmake/rules/mdk/xmake.lua
new file mode 100644
index 000000000..0c491b528
--- /dev/null
+++ b/xmake/rules/mdk/xmake.lua
@@ -0,0 +1,43 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+rule("mdk.console")
+ on_load(function (target)
+ -- we disable checking flags for cross toolchain automatically
+ target:set("policy", "check.auto_ignore_flags", false)
+ target:set("policy", "check.auto_map_flags", false)
+
+ -- set default output binary
+ target:set("kind", "binary")
+ if not target:get("extension") then
+ target:set("extension", ".axf")
+ end
+ end)
+
+rule("mdk.static")
+ on_load(function (target)
+ -- we disable checking flags for cross toolchain automatically
+ target:set("policy", "check.auto_ignore_flags", false)
+ target:set("policy", "check.auto_map_flags", false)
+
+ -- set default output binary
+ target:set("kind", "static")
+ end)
+
diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua
new file mode 100644
index 000000000..79e271063
--- /dev/null
+++ b/xmake/rules/nim/build/target.lua
@@ -0,0 +1,86 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file target.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.hashset")
+import("core.tool.compiler")
+import("core.project.depend")
+import("utils.progress")
+
+-- build the source files
+function build_sourcefiles(target, sourcebatch, opt)
+
+ -- get the target file
+ local targetfile = target:targetfile()
+
+ -- get source files and kind
+ local sourcefiles = sourcebatch.sourcefiles
+ local sourcekind = sourcebatch.sourcekind
+
+ -- get depend file
+ local dependfile = target:dependfile(targetfile)
+
+ -- load compiler
+ local compinst = compiler.load(sourcekind, {target = target})
+
+ -- get compile flags
+ local compflags = compinst:compflags({target = target})
+
+ -- load dependent info
+ local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
+
+ -- need build this object?
+ local depvalues = {compinst:program(), compflags}
+ if not depend.is_changed(dependinfo, {lastmtime = os.mtime(targetfile), values = depvalues}) then
+ return
+ end
+
+ -- trace progress into
+ progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile))
+
+ -- trace verbose info
+ vprint(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags}))
+
+ -- flush io buffer to update progress info
+ io.flush()
+
+ -- compile it
+ dependinfo.files = {}
+ assert(compinst:build(sourcefiles, targetfile, {target = target, dependinfo = dependinfo, compflags = compflags}))
+
+ -- update files and values to the dependent file
+ dependinfo.values = depvalues
+ table.join2(dependinfo.files, sourcefiles)
+ depend.save(dependinfo, dependfile)
+end
+
+-- build target
+function main(target, opt)
+
+ -- @note only support one source kind!
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["nim.build"]
+ if sourcebatch then
+ build_sourcefiles(target, sourcebatch, opt)
+ end
+ end
+end
diff --git a/xmake/rules/nim/xmake.lua b/xmake/rules/nim/xmake.lua
new file mode 100644
index 000000000..7d65c9c12
--- /dev/null
+++ b/xmake/rules/nim/xmake.lua
@@ -0,0 +1,37 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- define rule: nim.build
+rule("nim.build")
+ set_sourcekinds("nc")
+ on_load(function (target)
+ local cachedir = path.join(target:autogendir(), "nimcache")
+ target:add("ncflags", "--nimcache:" .. cachedir, {force = true})
+ end)
+ on_build("build.target")
+
+-- define rule: nim
+rule("nim")
+
+ -- add build rules
+ add_deps("nim.build")
+
+ -- inherit links and linkdirs of all dependent targets by default
+ add_deps("utils.inherit.links")
diff --git a/xmake/rules/pascal/build/target.lua b/xmake/rules/pascal/build/target.lua
new file mode 100644
index 000000000..646474606
--- /dev/null
+++ b/xmake/rules/pascal/build/target.lua
@@ -0,0 +1,88 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file target.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.hashset")
+import("core.theme.theme")
+import("core.tool.compiler")
+import("core.project.depend")
+import("utils.progress")
+
+-- build the source files
+function build_sourcefiles(target, sourcebatch, opt)
+
+ -- is verbose?
+ local verbose = option.get("verbose")
+
+ -- get the target file
+ local targetfile = target:targetfile()
+
+ -- get source files and kind
+ local sourcefiles = sourcebatch.sourcefiles
+ local sourcekind = sourcebatch.sourcekind
+
+ -- get depend file
+ local dependfile = target:dependfile(targetfile)
+
+ -- load compiler
+ local compinst = compiler.load(sourcekind, {target = target})
+
+ -- get compile flags
+ local compflags = compinst:compflags({target = target})
+
+ -- load dependent info
+ local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
+
+ -- need build this object?
+ local depvalues = {compinst:program(), compflags}
+ if not depend.is_changed(dependinfo, {lastmtime = os.mtime(targetfile), values = depvalues}) then
+ return
+ end
+
+ -- trace progress into
+ progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile))
+
+ -- trace verbose info
+ if verbose then
+ print(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags}))
+ end
+
+ -- compile it
+ dependinfo.files = {}
+ assert(compinst:build(sourcefiles, targetfile, {target = target, dependinfo = dependinfo, compflags = compflags}))
+
+ -- update files and values to the dependent file
+ dependinfo.values = depvalues
+ table.join2(dependinfo.files, sourcefiles)
+ depend.save(dependinfo, dependfile)
+end
+
+-- build target
+function main(target, opt)
+
+ -- @note only support one source kind!
+ for _, sourcebatch in pairs(target:sourcebatches()) do
+ if sourcebatch.sourcekind == "pc" then
+ build_sourcefiles(target, sourcebatch, opt)
+ break
+ end
+ end
+end
diff --git a/xmake/rules/pascal/xmake.lua b/xmake/rules/pascal/xmake.lua
new file mode 100644
index 000000000..5961c08d3
--- /dev/null
+++ b/xmake/rules/pascal/xmake.lua
@@ -0,0 +1,33 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- define rule: pascal.build
+rule("pascal.build")
+ set_sourcekinds("pc")
+ on_build("build.target")
+
+-- define rule: pascal
+rule("pascal")
+
+ -- add build rules
+ add_deps("pascal.build")
+
+ -- inherit links and linkdirs of all dependent targets by default
+ add_deps("utils.inherit.links")
diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua
new file mode 100644
index 000000000..4f2640c83
--- /dev/null
+++ b/xmake/rules/platform/linux/driver/driver_modules.lua
@@ -0,0 +1,299 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file driver_modules.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.depend")
+import("core.cache.memcache")
+import("lib.detect.find_tool")
+import("utils.progress")
+import("private.tools.ccache")
+
+-- get linux-headers sdk
+function _get_linux_headers_sdk(target)
+ local linux_headersdir = target:values("linux.driver.linux-headers")
+ if linux_headersdir then
+ return {sdkdir = linux_headersdir, includedir = path.join(linux_headersdir, "include")}
+ end
+ local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!")
+ local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs")
+ local version = linux_headers:version()
+ local includedir
+ for _, dir in ipairs(includedirs) do
+ if dir:find("linux-headers", 1, true) then
+ includedir = dir
+ linux_headersdir = path.directory(dir)
+ break
+ end
+ end
+ assert(linux_headersdir, "linux-headers not found!")
+ if not os.isfile(path.join(includedir, "generated/autoconf.h")) and
+ not os.isfile(path.join(includedir, "config/auto.conf")) then
+ raise("kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing.")
+ end
+ return {version = version, sdkdir = linux_headersdir, includedir = includedir}
+end
+
+-- get cflags from make
+function _get_cflags_from_make(target, sdkdir)
+ local key = target:plat() .. target:arch()
+ local cflags = memcache.get2("linux.driver", key, "cflags")
+ local ldflags_o = memcache.get2("linux.driver", key, "ldflags_o")
+ local ldflags_ko = memcache.get2("linux.driver", key, "ldflags_ko")
+ if cflags == nil then
+ local make = assert(find_tool("make"), "make not found!")
+ local tmpdir = os.tmpfile() .. ".dir"
+ local makefile = path.join(tmpdir, "Makefile")
+ local stubfile = path.join(tmpdir, "src/stub.c")
+ local foofile = path.join(tmpdir, "src/foo.c")
+ io.writefile(makefile, [[obj-m := stub.o
+stub-objs := src/stub.o src/foo.o]])
+ io.writefile(foofile, "")
+ io.writefile(stubfile, [[
+#include <linux/init.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Ruki");
+MODULE_DESCRIPTION("A simple Hello World Module");
+MODULE_ALIAS("a simplest module");
+
+int hello_init(void) {
+ printk(KERN_INFO "Hello World\n");
+ return 0;
+}
+
+void hello_exit(void) {
+ printk(KERN_INFO "Goodbye World\n");
+}
+
+module_init(hello_init);
+module_exit(hello_exit);
+ ]])
+ local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"}
+ if not target:is_plat(os.subhost()) then
+ -- e.g. $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules
+ local arch
+ if target:is_arch("arm", "armv7") then
+ arch = "arm"
+ elseif target:is_arch("arm64", "arm64-v8a") then
+ arch = "arm64"
+ elseif target:is_arch("mips") then
+ arch = "mips"
+ elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then
+ arch = "powerpc"
+ end
+ assert(arch, "unknown arch(%s)!", target:arch())
+ local cc = target:tool("cc")
+ local cross = cc:gsub("%-gcc$", "-")
+ table.insert(argv, "ARCH=" .. arch)
+ table.insert(argv, "CROSS_COMPILE=" .. cross)
+ end
+ local result, errors = try {function () return os.iorunv(make.program, argv, {curdir = tmpdir}) end}
+ if result then
+ for _, line in ipairs(result:split("\n", {plain = true})) do
+ if line:endswith("stub.c") then
+ local include_cflag = false
+ for _, cflag in ipairs(line:split("%s+")) do
+ local has_cflag = false
+ if cflag:startswith("-f") or cflag:startswith("-m")
+ or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,"))
+ or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") and not cflag:find("KBUILD_BASENAME=")) then
+ has_cflag = true
+ local macro = cflag:match("%-D\"(.+)\"") -- -D"KBUILD_XXX=xxx"
+ if macro then
+ cflag = "-D" .. macro
+ end
+ elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then
+ include_cflag = cflag
+ elseif cflag:startswith("-I") or include_cflag then
+ local includedir = cflag
+ if cflag:startswith("-I") then
+ includedir = cflag:sub(3)
+ end
+ if not path.is_absolute(includedir) then
+ includedir = path.absolute(includedir, sdkdir)
+ end
+ if cflag:startswith("-I") then
+ cflag = "-I" .. includedir
+ else
+ cflag = include_cflag .. " " .. includedir
+ end
+ has_cflag = true
+ include_cflag = nil
+ end
+ if has_cflag then
+ cflags = cflags or {}
+ table.insert(cflags, cflag)
+ end
+ end
+ end
+ local ldflags = line:match("%-ld (.+) %-o ") or line:match("ld (.+) %-o ")
+ if ldflags then
+ local ko = ldflags:find("-T ", 1, true)
+ for _, ldflag in ipairs(os.argv(ldflags)) do
+ if ldflag:endswith(".lds") then
+ if not path.is_absolute(ldflag) then
+ ldflag = path.absolute(ldflag, sdkdir)
+ end
+ end
+ if ko then
+ -- e.g. aarch64-linux-gnu-ld -r -EL -maarch64elf --build-id=sha1 -T scripts/module.lds -o hello.ko hello.o hello.mod.o
+ ldflags_ko = ldflags_ko or {}
+ table.insert(ldflags_ko, ldflag)
+ else
+ -- e.g. aarch64-linux-gnu-ld -EL -maarch64elf -r -o hello.o xxx.o
+ ldflags_o = ldflags_o or {}
+ table.insert(ldflags_o, ldflag)
+ end
+ end
+ end
+ if cflags and ldflags_o and ldflags_ko then
+ break
+ end
+ end
+ else
+ if option.get("diagnosis") then
+ print("rule(platform.linux.driver): cannot get cflags from make!")
+ print(errors)
+ end
+ end
+ os.tryrm(tmpdir)
+ memcache.set2("linux.driver", key, "cflags", cflags or false)
+ end
+ return cflags or nil, ldflags_o or nil, ldflags_ko or nil
+end
+
+function load(target)
+ -- we need only need binary kind, because we will rewrite on_link
+ target:set("kind", "binary")
+ target:set("extension", ".ko")
+end
+
+function config(target)
+
+ -- get and save linux-headers sdk
+ local linux_headers = _get_linux_headers_sdk(target)
+ target:data_set("linux.driver.linux_headers", linux_headers)
+
+ -- check compiler, we must use gcc
+ assert(target:has_tool("cc", "gcc"), "we must use gcc compiler!")
+
+ -- check rules
+ for _, rulename in ipairs({"mode.release", "mode.debug", "mode.releasedbg", "mode.minsizerel", "mode.asan", "mode.tsan"}) do
+ assert(not target:rule(rulename), "target(%s) is linux driver module, it need not rule(%s)!", target:name(), rulename)
+ end
+
+ -- we need disable includedirs from add_packages("linux-headers")
+ if target:pkg("linux-headers") then
+ target:pkg("linux-headers"):set("includedirs", nil)
+ target:pkg("linux-headers"):set("sysincludedirs", nil)
+ end
+
+ -- add compilation flags
+ target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"")
+ for _, sourcefile in ipairs(target:sourcefiles()) do
+ target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""})
+ end
+ local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, linux_headers.sdkdir)
+ if cflags then
+ target:add("cflags", cflags, {force = true})
+ target:data_set("linux.driver.ldflags_o", ldflags_o)
+ target:data_set("linux.driver.ldflags_ko", ldflags_ko)
+ end
+end
+
+function link(target, opt)
+ local targetfile = target:targetfile()
+ local dependfile = target:dependfile(targetfile)
+ local objectfiles = target:objectfiles()
+ depend.on_changed(function ()
+
+ -- trace
+ progress.show(opt.progress, "${color.build.object}linking.$(mode) %s", targetfile)
+
+ -- get module scripts
+ local modpost
+ local linux_headers = target:data("linux.driver.linux_headers")
+ if linux_headers then
+ modpost = path.join(linux_headers.sdkdir, "scripts", "mod", "modpost")
+ end
+ assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!")
+
+ -- get ld
+ local ld = target:tool("ld")
+ assert(ld, "ld not found!")
+ ld = ld:gsub("gcc$", "ld")
+ ld = ld:gsub("g%+%+$", "ld")
+
+ -- link target.o
+ local argv = {}
+ local ldflags_o = target:data("linux.driver.ldflags_o")
+ if ldflags_o then
+ table.join2(argv, ldflags_o)
+ end
+ local targetfile_o = target:objectfile(targetfile)
+ table.join2(argv, "-o", targetfile_o)
+ table.join2(argv, objectfiles)
+ os.mkdir(path.directory(targetfile_o))
+ os.vrunv(ld, argv)
+
+ -- generate target.mod
+ local targetfile_mod = targetfile_o:gsub("%.o$", ".mod")
+ io.writefile(targetfile_mod, table.concat(objectfiles, " ") .. "\n\n")
+
+ -- generate .sourcename.o.cmd
+ -- we need only touch an empty file, otherwise modpost command will raise error.
+ for _, objectfile in ipairs(objectfiles) do
+ local objectdir = path.directory(objectfile)
+ local objectname = path.filename(objectfile)
+ local cmdfile = path.join(objectdir, "." .. objectname .. ".cmd")
+ io.writefile(cmdfile, "")
+ end
+
+ -- generate target.mod.c
+ local orderfile = path.join(path.directory(targetfile_o), "modules.order")
+ local symversfile = path.join(path.directory(targetfile_o), "Module.symvers")
+ argv = {"-m", "-a", "-o", symversfile, "-e", "-N", "-T", "-"}
+ io.writefile(orderfile, targetfile_o .. "\n")
+ os.vrunv(modpost, argv, {stdin = orderfile})
+
+ -- compile target.mod.c
+ local targetfile_mod_c = targetfile_o:gsub("%.o$", ".mod.c")
+ local targetfile_mod_o = targetfile_o:gsub("%.o$", ".mod.o")
+ local compinst = target:compiler("cc")
+ if option.get("verbose") then
+ print(compinst:compcmd(targetfile_mod_c, targetfile_mod_o, {target = target, rawargs = true}))
+ end
+ assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target}))
+
+ -- link target.ko
+ argv = {}
+ local ldflags_ko = target:data("linux.driver.ldflags_ko")
+ if ldflags_ko then
+ table.join2(argv, ldflags_ko)
+ end
+ local targetfile_o = target:objectfile(targetfile)
+ table.join2(argv, "-o", targetfile, targetfile_o, targetfile_mod_o)
+ os.mkdir(path.directory(targetfile))
+ os.vrunv(ld, argv)
+
+ end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles})
+end
diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua
new file mode 100644
index 000000000..8192b9a7f
--- /dev/null
+++ b/xmake/rules/platform/linux/driver/xmake.lua
@@ -0,0 +1,33 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- build linux driver module
+rule("platform.linux.driver")
+ set_sourcekinds("cc")
+ on_load(function (target)
+ import("driver_modules").load(target)
+ end)
+ on_config(function (target)
+ import("driver_modules").config(target)
+ end)
+ on_link(function (target, opt)
+ import("driver_modules").link(target, opt)
+ end)
+
diff --git a/xmake/rules/platform/windows/def/xmake.lua b/xmake/rules/platform/windows/def/xmake.lua
index 06e960380..7919553de 100644
--- a/xmake/rules/platform/windows/def/xmake.lua
+++ b/xmake/rules/platform/windows/def/xmake.lua
@@ -22,8 +22,7 @@
rule("platform.windows.def")
set_extensions(".def")
on_config("windows", function (target)
- local _, toolname = target:tool("ld")
- if toolname == "link" then
+ if target:has_tool("ld", "link") then
for _, sourcebatch in pairs(target:sourcebatches()) do
if sourcebatch.rulename == "platform.windows.def" then
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
diff --git a/xmake/rules/platform/windows/manifest/xmake.lua b/xmake/rules/platform/windows/manifest/xmake.lua
index efb750edd..b476faeed 100644
--- a/xmake/rules/platform/windows/manifest/xmake.lua
+++ b/xmake/rules/platform/windows/manifest/xmake.lua
@@ -23,8 +23,7 @@
rule("platform.windows.manifest")
set_extensions(".manifest")
on_config("windows", function (target)
- local _, toolname = target:tool("ld")
- if toolname == "link" then
+ if target:has_tool("ld", "link") then
local manifest = false
for _, sourcebatch in pairs(target:sourcebatches()) do
if sourcebatch.rulename == "platform.windows.manifest" then
diff --git a/xmake/rules/plugin/vsxmake/xmake.lua b/xmake/rules/plugin/vsxmake/xmake.lua
index 88693599f..bb0f231e4 100644
--- a/xmake/rules/plugin/vsxmake/xmake.lua
+++ b/xmake/rules/plugin/vsxmake/xmake.lua
@@ -35,12 +35,17 @@ rule("plugin.vsxmake.autoupdate")
import("core.project.config")
import("core.project.depend")
import("core.project.project")
+ import("core.cache.localcache")
import("core.base.task")
-- run only once for all xmake process in vs
local tmpfile = path.join(config.buildir(), ".gens", "rules", "plugin.vsxmake.autoupdate")
local dependfile = tmpfile .. ".d"
local lockfile = io.openlock(tmpfile .. ".lock")
+ local kind = localcache.get("vsxmake", "kind")
+ local modes = localcache.get("vsxmake", "modes")
+ local archs = localcache.get("vsxmake", "archs")
+ local outputdir = localcache.get("vsxmake", "outputdir")
if lockfile:trylock() then
if os.getenv("XMAKE_IN_VSTUDIO") then
local sourcefiles = {}
@@ -50,8 +55,8 @@ rule("plugin.vsxmake.autoupdate")
table.sort(sourcefiles)
depend.on_changed(function ()
-- we use task instead of os.exec("xmake") to avoid the project lock
- print("update vsxmake project ..")
- task.run("project", {kind = "vsxmake"})
+ print("update vsxmake project -k %s %s ..", kind or "vsxmake", outputdir or "")
+ task.run("project", {kind = kind or "vsxmake", modes = modes, archs = archs, outputdir = outputdir})
print("update vsxmake project ok")
end, {dependfile = dependfile,
files = project.allfiles(),
diff --git a/xmake/rules/python/xmake.lua b/xmake/rules/python/xmake.lua
new file mode 100644
index 000000000..823495485
--- /dev/null
+++ b/xmake/rules/python/xmake.lua
@@ -0,0 +1,43 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- @see https://github.com/xmake-io/xmake/issues/1896
+rule("python.library")
+ on_load(function (target)
+ target:set("kind", "shared")
+ target:set("prefixname", "_")
+ local soabi = target:extraconf("rules", "python.library", "soabi")
+ if soabi then
+ import("lib.detect.find_tool")
+ local python = assert(find_tool("python3"), "python not found!")
+ local result = try { function() return os.iorunv(python.program, {"-c", "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"}) end}
+ if result then
+ result = result:trim()
+ if result ~= "None" then
+ target:set("extension", result)
+ end
+ end
+ else
+ if target:is_plat("windows") then
+ target:set("extension", ".pyd")
+ end
+ end
+ end)
+
diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua
index 97f97ea7a..326addbc1 100644
--- a/xmake/rules/qt/deploy/android.lua
+++ b/xmake/rules/qt/deploy/android.lua
@@ -25,7 +25,7 @@ import("core.base.semver")
import("core.project.config")
import("core.project.depend")
import("core.tool.toolchain")
-import("private.utils.progress")
+import("utils.progress")
-- escape path
function _escape_path(p)
@@ -71,6 +71,9 @@ function main(target, opt)
-- get androiddeployqt
local androiddeployqt = path.join(qt.bindir, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
+ if not os.isexec(androiddeployqt) and qt.bindir_host then
+ androiddeployqt = path.join(qt.bindir_host, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
+ end
assert(os.isexec(androiddeployqt), "androiddeployqt not found!")
-- get working directory
@@ -120,18 +123,6 @@ function main(target, opt)
os.cp(target:targetfile(), path.join(android_buildir, "libs", target_arch, path.filename(target:targetfile())))
end
- -- get the android srcs directory, e.g. android-build/java/res/values
- local android_srcs
- if qt_sdkver and qt_sdkver:ge("5.14") then
- -- @note we need patch values/res/strings.xml for Qt 5.14.0
- local valuesdir = path.join(android_buildir, "java", "res", "values")
- if not os.isdir(valuesdir) then
- os.mkdir(valuesdir)
- end
- os.cp(path.join(qt.sdkdir, "src", "android", "java", "res", "values", "*"), valuesdir)
- android_srcs = path.join(android_buildir, "java")
- end
-
-- get stdcpp path
local stdcpp_path = path.join(ndk, "sources/cxx-stl/llvm-libc++/libs", target_arch, "libc++_shared.so")
if qt_sdkver and qt_sdkver:ge("5.14") then
@@ -159,9 +150,21 @@ function main(target, opt)
settings_file:print(' "ndk-host": "%s",', ndk_host)
settings_file:print(' "target-architecture": "%s",', target_arch)
settings_file:print(' "qml-root-path": "%s",', _escape_path(os.projectdir()))
- if android_srcs then
- settings_file:print(' "android-package-source-directory": "%s",', _escape_path(android_srcs))
- --settings_file:print(' "android-extra-libs":"c:/libs",')
+ -- for 6.2.x
+ local qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner" .. (is_host("windows") and ".exe" or ""))
+ if not os.isexec(qmlimportscanner) and qt.libexecdir_host then
+ qmlimportscanner = path.join(qt.libexecdir_host, "qmlimportscanner" .. (is_host("windows") and ".exe" or ""))
+ end
+ if os.isexec(qmlimportscanner) then
+ settings_file:print(' "qml-importscanner-binary": "%s",', qmlimportscanner)
+ end
+ local minsdkversion = target:values("qt.android.minsdkversion")
+ if minsdkversion then
+ settings_file:print(' "android-min-sdk-version": "%s",', tostring(minsdkversion))
+ end
+ local targetsdkversion = target:values("qt.android.targetsdkversion")
+ if targetsdkversion then
+ settings_file:print(' "android-target-sdk-version": "%s",', tostring(targetsdkversion))
end
settings_file:print(' "useLLVM": true,')
if qt_sdkver and qt_sdkver:ge("5.14") then
@@ -194,7 +197,6 @@ function main(target, opt)
-- do deploy
local argv = {"--input", android_deployment_settings,
"--output", android_buildir,
- "--android-platform", android_platform,
"--jdk", java_home,
"--gradle", "--no-gdbserver"}
if option.get("verbose") and option.get("diagnosis") then
diff --git a/xmake/rules/qt/deploy/macosx.lua b/xmake/rules/qt/deploy/macosx.lua
index 5f7b8390d..26df10b14 100644
--- a/xmake/rules/qt/deploy/macosx.lua
+++ b/xmake/rules/qt/deploy/macosx.lua
@@ -25,7 +25,7 @@ import("core.project.config")
import("core.project.depend")
import("core.tool.toolchain")
import("lib.detect.find_path")
-import("private.utils.progress")
+import("utils.progress")
-- save Info.plist
function _save_info_plist(target, info_plist_file)
diff --git a/xmake/rules/qt/load.lua b/xmake/rules/qt/load.lua
index 03599f7e2..c5bec10af 100644
--- a/xmake/rules/qt/load.lua
+++ b/xmake/rules/qt/load.lua
@@ -36,7 +36,11 @@ function _link(linkdirs, framework, qt_sdkver)
elseif is_plat("android") or is_plat("linux") then
debug_suffix = ""
end
- framework = "Qt" .. qt_sdkver:major() .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "")
+ if qt_sdkver:ge("5.0") then
+ framework = "Qt" .. qt_sdkver:major() .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "")
+ else -- for qt4.x, e.g. QtGui4.lib
+ framework = "Qt" .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "") .. qt_sdkver:major()
+ end
if is_plat("android") then --> -lQt5Core_armeabi/-lQt5CoreDebug_armeabi for 5.14.x
local libinfo = find_library(framework .. "_" .. config.arch(), linkdirs)
if libinfo and libinfo.link then
@@ -77,10 +81,10 @@ function _add_plugins(target, plugins)
for name, plugin in pairs(plugins) do
target:values_add("qt.plugins", name)
if plugin.links then
- target:values_add("qt.links", unpack(table.wrap(plugin.links)))
+ target:values_add("qt.links", table.unpack(table.wrap(plugin.links)))
end
if plugin.linkdirs then
- target:values_add("qt.linkdirs", unpack(table.wrap(plugin.linkdirs)))
+ target:values_add("qt.linkdirs", table.unpack(table.wrap(plugin.linkdirs)))
end
end
end
diff --git a/xmake/rules/qt/moc/xmake.lua b/xmake/rules/qt/moc/xmake.lua
index 80ce37174..f12fcf217 100644
--- a/xmake/rules/qt/moc/xmake.lua
+++ b/xmake/rules/qt/moc/xmake.lua
@@ -32,6 +32,9 @@ rule("qt.moc")
if not os.isexec(moc) and qt.libexecdir then
moc = path.join(qt.libexecdir, is_host("windows") and "moc.exe" or "moc")
end
+ if not os.isexec(moc) and qt.libexecdir_host then
+ moc = path.join(qt.libexecdir_host, is_host("windows") and "moc.exe" or "moc")
+ end
assert(moc and os.isexec(moc), "moc not found!")
-- get c++ source file for moc
diff --git a/xmake/rules/qt/qrc/xmake.lua b/xmake/rules/qt/qrc/xmake.lua
index df416c2a9..64e37d2ab 100644
--- a/xmake/rules/qt/qrc/xmake.lua
+++ b/xmake/rules/qt/qrc/xmake.lua
@@ -29,6 +29,9 @@ rule("qt.qrc")
if not os.isexec(rcc) and qt.libexecdir then
rcc = path.join(qt.libexecdir, is_host("windows") and "rcc.exe" or "rcc")
end
+ if not os.isexec(rcc) and qt.libexecdir_host then
+ rcc = path.join(qt.libexecdir_host, is_host("windows") and "rcc.exe" or "rcc")
+ end
assert(os.isexec(rcc), "rcc not found!")
-- save rcc
diff --git a/xmake/rules/qt/ui/xmake.lua b/xmake/rules/qt/ui/xmake.lua
index dd377563b..2d02a134b 100644
--- a/xmake/rules/qt/ui/xmake.lua
+++ b/xmake/rules/qt/ui/xmake.lua
@@ -29,6 +29,9 @@ rule("qt.ui")
if not os.isexec(uic) and qt.libexecdir then
uic = path.join(qt.libexecdir, is_host("windows") and "uic.exe" or "uic")
end
+ if not os.isexec(uic) and qt.libexecdir_host then
+ uic = path.join(qt.libexecdir_host, is_host("windows") and "uic.exe" or "uic")
+ end
assert(uic and os.isexec(uic), "uic not found!")
-- add includedirs, @note we need create this directory first to suppress warning (file not found).
diff --git a/xmake/rules/qt/xmake.lua b/xmake/rules/qt/xmake.lua
index ed4deedb7..b26a458a5 100644
--- a/xmake/rules/qt/xmake.lua
+++ b/xmake/rules/qt/xmake.lua
@@ -87,7 +87,20 @@ rule("qt.widgetapp")
end)
on_config(function (target)
- import("load")(target, {gui = true, frameworks = {"QtGui", "QtWidgets", "QtCore"}})
+
+ -- get qt sdk version
+ local qt = target:data("qt")
+ local qt_sdkver = nil
+ if qt.sdkver then
+ import("core.base.semver")
+ qt_sdkver = semver.new(qt.sdkver)
+ end
+
+ local frameworks = {"QtGui", "QtWidgets", "QtCore"}
+ if qt_sdkver and qt_sdkver:lt("5.0") then
+ frameworks = {"QtGui", "QtCore"} -- qt4.x has not QtWidgets, it is in QtGui
+ end
+ import("load")(target, {gui = true, frameworks = frameworks})
end)
-- deploy application
@@ -124,9 +137,12 @@ rule("qt.widgetapp_static")
QtPlatformSupport = "QtPlatformCompositorSupport"
end
- -- laod some basic plugins and frameworks
+ -- load some basic plugins and frameworks
local plugins = {}
local frameworks = {"QtGui", "QtWidgets", "QtCore"}
+ if qt_sdkver and qt_sdkver:lt("5.0") then
+ frameworks = {"QtGui", "QtCore"} -- qt4.x has not QtWidgets, it is in QtGui
+ end
if target:is_plat("macosx") then
plugins.QCocoaIntegrationPlugin = {linkdirs = "plugins/platforms", links = {"qcocoa", "cups"}}
table.join2(frameworks, QtPlatformSupport, "QtWidgets")
@@ -195,7 +211,7 @@ rule("qt.quickapp_static")
QtPlatformSupport = "QtPlatformCompositorSupport"
end
- -- laod some basic plugins and frameworks
+ -- load some basic plugins and frameworks
local plugins = {}
local frameworks = {"QtGui", "QtQuick", "QtQml", "QtQmlModels", "QtCore", "QtNetwork"}
if target:is_plat("macosx") then
diff --git a/xmake/rules/rust/build/cxxbridge.lua b/xmake/rules/rust/build/cxxbridge.lua
new file mode 100644
index 000000000..1fc9b3778
--- /dev/null
+++ b/xmake/rules/rust/build/cxxbridge.lua
@@ -0,0 +1,50 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxbridge.lua
+--
+
+-- imports
+import("core.base.option")
+import("lib.detect.find_tool")
+
+function main(target, batchcmds, sourcefile, opt)
+ local cxxbridge = assert(find_tool("cxxbridge"), "cxxbridge not found, please run `cargo install cxxbridge` to install it first!")
+
+ -- get c/c++ source file for cxxbridge
+ local headerfile = path.join(target:autogendir(), "rules", "cxxbridge", path.basename(sourcefile) .. ".rs.h")
+ local sourcefile_cx = path.join(target:autogendir(), "rules", "cxxbridge", path.basename(sourcefile) .. ".rs.cc")
+
+ -- add includedirs
+ target:add("includedirs", path.directory(headerfile))
+
+ -- add objectfile
+ local objectfile = target:objectfile(sourcefile_cx)
+ table.insert(target:objectfiles(), objectfile)
+
+ -- add commands
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.cxxbridge %s", sourcefile)
+ batchcmds:mkdir(path.directory(sourcefile_cx))
+ batchcmds:vrunv(cxxbridge.program, {sourcefile}, {stdout = sourcefile_cx})
+ batchcmds:vrunv(cxxbridge.program, {sourcefile, "--header"}, {stdout = headerfile})
+ batchcmds:compile(sourcefile_cx, objectfile)
+
+ -- add deps
+ batchcmds:add_depfiles(sourcefile)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
+end
diff --git a/xmake/rules/rust/build/target.lua b/xmake/rules/rust/build/target.lua
index 67917ad29..5f0167693 100644
--- a/xmake/rules/rust/build/target.lua
+++ b/xmake/rules/rust/build/target.lua
@@ -21,19 +21,13 @@
-- imports
import("core.base.option")
import("core.base.hashset")
-import("core.theme.theme")
import("core.tool.compiler")
import("core.project.depend")
+import("utils.progress")
-- build the source files
function build_sourcefiles(target, sourcebatch, opt)
- -- is verbose?
- local verbose = option.get("verbose")
-
- -- get progress range
- local progress = assert(opt.progress, "no progress!")
-
-- get the target file
local targetfile = target:targetfile()
@@ -60,17 +54,10 @@ function build_sourcefiles(target, sourcebatch, opt)
end
-- trace progress into
- cprintf("${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} ", progress)
- if verbose then
- cprint("${dim color.build.target}linking.$(mode) %s", path.filename(targetfile))
- else
- cprint("${color.build.target}linking.$(mode) %s", path.filename(targetfile))
- end
+ progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile))
-- trace verbose info
- if verbose then
- print(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags}))
- end
+ vprint(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags}))
-- flush io buffer to update progress info
io.flush()
@@ -89,10 +76,11 @@ end
function main(target, opt)
-- @note only support one source kind!
- for _, sourcebatch in pairs(target:sourcebatches()) do
- if sourcebatch.sourcekind == "rc" then
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ local sourcebatch = sourcebatches["rust.build"]
+ if sourcebatch then
build_sourcefiles(target, sourcebatch, opt)
- break
end
end
end
diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua
index a8ccae429..e31e2f046 100644
--- a/xmake/rules/rust/xmake.lua
+++ b/xmake/rules/rust/xmake.lua
@@ -18,16 +18,52 @@
-- @file xmake.lua
--
--- define rule: rust.build
+-- generate bridge.rs.cc/h to call rust library in c++ code
+-- @see https://cxx.rs/build/other.html
+rule("rust.cxxbridge")
+ set_extensions(".rsx")
+ on_load(function (target)
+ if not target:get("languages") then
+ target:set("languages", "c++11")
+ end
+ end)
+ before_buildcmd_file("build.cxxbridge")
+
rule("rust.build")
set_sourcekinds("rc")
+ on_load(function (target)
+ -- set cratetype
+ local cratetype = target:values("rust.cratetype")
+ if cratetype == "staticlib" then
+ assert(target:is_static(), "target(%s) must be static kind for cratetype(staticlib)!", target:name())
+ target:add("arflags", "--crate-type=staticlib")
+ target:data_set("inherit.links.exportlinks", false)
+ elseif cratetype == "cdylib" then
+ assert(target:is_shared(), "target(%s) must be shared kind for cratetype(cdylib)!", target:name())
+ target:add("shflags", "--crate-type=cdylib")
+ target:add("shflags", "-C prefer-dynamic")
+ elseif target:is_static() then
+ target:set("extension", ".rlib")
+ target:add("arflags", "--crate-type=lib")
+ target:data_set("inherit.links.deplink", false)
+ elseif target:is_shared() then
+ target:add("shflags", "--crate-type=dylib")
+ -- fix cannot satisfy dependencies so `std` only shows up once
+ -- https://github.com/rust-lang/rust/issues/19680
+ --
+ -- but it will link dynamic @rpath/libstd-xxx.dylib,
+ -- so we can no longer modify and set other rpath paths
+ target:add("shflags", "-C prefer-dynamic")
+ elseif target:is_binary() then
+ target:add("ldflags", "--crate-type=bin")
+ end
+
+ -- set edition
+ local edition = target:values("rust.edition") or "2018"
+ target:add("rcflags", "--edition", edition, {force = true})
+ end)
on_build("build.target")
--- define rule: rust
rule("rust")
-
- -- add build rules
add_deps("rust.build")
-
- -- inherit links and linkdirs of all dependent targets by default
add_deps("utils.inherit.links")
diff --git a/xmake/rules/swig/build_module_file.lua b/xmake/rules/swig/build_module_file.lua
new file mode 100644
index 000000000..42c9d9238
--- /dev/null
+++ b/xmake/rules/swig/build_module_file.lua
@@ -0,0 +1,55 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file build_module_file.lua
+--
+
+-- imports
+import("lib.detect.find_tool")
+
+function main(target, batchcmds, sourcefile, opt)
+
+ -- get swig
+ opt = opt or {}
+ local swig = assert(find_tool("swig"), "swig not found!")
+ local sourcefile_cx = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile) .. (opt.sourcekind == "cxx" and ".cpp" or ".c"))
+
+ -- add objectfile
+ local objectfile = target:objectfile(sourcefile_cx)
+ table.insert(target:objectfiles(), objectfile)
+
+ -- add commands
+ local moduletype = assert(target:data("swig.moduletype"), "swig.moduletype not found!")
+ local argv = {"-" .. moduletype, "-o", sourcefile_cx}
+ if opt.sourcekind == "cxx" then
+ table.insert(argv, "-c++")
+ end
+ local fileconfig = target:fileconfig(sourcefile)
+ if fileconfig.swigflags then
+ table.join2(argv, fileconfig.swigflags)
+ end
+ table.insert(argv, sourcefile)
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.swig.%s %s", moduletype, sourcefile)
+ batchcmds:mkdir(path.directory(sourcefile_cx))
+ batchcmds:vrunv(swig.program, argv)
+ batchcmds:compile(sourcefile_cx, objectfile)
+
+ -- add deps
+ batchcmds:add_depfiles(sourcefile)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
+end
diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua
new file mode 100644
index 000000000..c0387a940
--- /dev/null
+++ b/xmake/rules/swig/xmake.lua
@@ -0,0 +1,98 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- references:
+--
+-- https://github.com/xmake-io/xmake/issues/1622
+-- http://www.swig.org/Doc4.0/SWIGDocumentation.html#Introduction_nn4
+--
+
+rule("swig.base")
+ on_load(function (target)
+ target:set("kind", "shared")
+ local moduletype = target:extraconf("rules", "swig.c", "moduletype") or target:extraconf("rules", "swig.cpp", "moduletype")
+ if moduletype == "python" then
+ target:set("prefixname", "_")
+ local soabi = target:extraconf("rules", "swig.c", "soabi") or target:extraconf("rules", "swig.cpp", "soabi")
+ if soabi then
+ import("lib.detect.find_tool")
+ local python = assert(find_tool("python3"), "python not found!")
+ local result = try { function() return os.iorunv(python.program, {"-c", "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"}) end}
+ if result then
+ result = result:trim()
+ if result ~= "None" then
+ target:set("extension", result)
+ end
+ end
+ else
+ if target:is_plat("windows") then
+ target:set("extension", ".pyd")
+ end
+ end
+ elseif moduletype == "lua" then
+ target:set("prefixname", "")
+ if not target:is_plat("windows") then
+ target:set("extension", ".so")
+ end
+ else
+ raise("unknown swig module type, please use `add_rules(\"swig.c\", {moduletype = \"python\"})` to set it!")
+ end
+ local scriptfiles = {}
+ for _, sourcebatch in pairs(target:sourcebatches()) do
+ if sourcebatch.rulename:startswith("swig.") then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local scriptdir
+ local fileconfig = target:fileconfig(sourcefile)
+ if fileconfig then
+ scriptdir = fileconfig.scriptdir
+ end
+ local scriptfile = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile))
+ if moduletype == "python" then
+ scriptfile = scriptfile .. ".py"
+ elseif moduletype == "lua" then
+ scriptfile = scriptfile .. ".lua"
+ end
+ table.insert(scriptfiles, scriptfile)
+ if scriptdir then
+ target:add("installfiles", scriptfile, {prefixdir = scriptdir})
+ end
+ end
+ end
+ end
+ -- for custom on_install/after_install, user can use it to install them
+ target:data_set("swig.scriptfiles", scriptfiles)
+ target:data_set("swig.moduletype", moduletype)
+ end)
+
+rule("swig.c")
+ set_extensions(".i")
+ add_deps("swig.base", "c.build")
+ on_buildcmd_file(function (target, batchcmds, sourcefile, opt)
+ import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cc"}, opt))
+ end)
+
+rule("swig.cpp")
+ set_extensions(".i")
+ add_deps("swig.base", "c++.build")
+ on_buildcmd_file(function (target, batchcmds, sourcefile, opt)
+ import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cxx"}, opt))
+ end)
+
+
diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua
index 12db55192..77f81125c 100644
--- a/xmake/rules/utils/bin2c/xmake.lua
+++ b/xmake/rules/utils/bin2c/xmake.lua
@@ -20,10 +20,17 @@
rule("utils.bin2c")
set_extensions(".bin")
+ on_load(function (target)
+ local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c")
+ if not os.isdir(headerdir) then
+ os.mkdir(headerdir)
+ end
+ target:add("includedirs", headerdir)
+ end)
before_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt)
-- get header file
- local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c")
+ local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c")
local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h")
target:add("includedirs", headerdir)
@@ -36,7 +43,7 @@ rule("utils.bin2c")
table.insert(argv, "-w")
table.insert(argv, tostring(linewidth))
end
- batchcmds:vrunv(os.programfile(), argv)
+ batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}})
-- add deps
batchcmds:add_depfiles(sourcefile_bin)
diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua
new file mode 100644
index 000000000..faf655ec6
--- /dev/null
+++ b/xmake/rules/utils/glsl2spv/xmake.lua
@@ -0,0 +1,90 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- compile glsl shader to spirv file, .spv
+--
+-- e.g.
+-- compile *.vert/*.frag to *.vert.spv/*.frag.spv files
+-- add_rules("utils.glsl2spv", {outputdir = "build"})
+--
+-- compile *.vert/*.frag and generate binary c header files
+-- add_rules("utils.glsl2spv", {bin2c = true})
+--
+-- in c code:
+-- static unsigned char g_test_frag_spv_data[] = {
+-- #include "test.frag.spv.h"
+-- };
+--
+--
+rule("utils.glsl2spv")
+ set_extensions(".vert", ".frag", ".tesc", ".tese", ".geom", ".comp", ".glsl")
+ on_load(function (target)
+ local is_bin2c = target:extraconf("rules", "utils.glsl2spv", "bin2c")
+ if is_bin2c then
+ local headerdir = path.join(target:autogendir(), "rules", "utils", "glsl2spv")
+ if not os.isdir(headerdir) then
+ os.mkdir(headerdir)
+ end
+ target:add("includedirs", headerdir)
+ end
+ end)
+ before_buildcmd_file(function (target, batchcmds, sourcefile_glsl, opt)
+ import("lib.detect.find_tool")
+
+ -- get glslangValidator
+ local glslc
+ local glslangValidator = find_tool("glslangValidator")
+ if not glslangValidator then
+ glslc = find_tool("glslc")
+ end
+ assert(glslangValidator or glslc, "glslangValidator or glslc not found!")
+
+ -- glsl to spv
+ local outputdir = target:extraconf("rules", "utils.glsl2spv", "outputdir") or path.join(target:autogendir(), "rules", "utils", "glsl2spv")
+ local spvfilepath = path.join(outputdir, path.filename(sourcefile_glsl) .. ".spv")
+ batchcmds:show_progress(opt.progress, "${color.build.object}generating.glsl2spv %s", sourcefile_glsl)
+ batchcmds:mkdir(outputdir)
+ if glslangValidator then
+ batchcmds:vrunv(glslangValidator.program, {"-V", "-o", spvfilepath, sourcefile_glsl})
+ else
+ batchcmds:vrunv(glslc.program, {"-o", spvfilepath, sourcefile_glsl})
+ end
+
+ -- do bin2c
+ local outputfile = spvfilepath
+ local is_bin2c = target:extraconf("rules", "utils.glsl2spv", "bin2c")
+ if is_bin2c then
+ -- get header file
+ local headerdir = outputdir
+ local headerfile = path.join(headerdir, path.filename(spvfilepath) .. ".h")
+ target:add("includedirs", headerdir)
+ outputfile = headerfile
+
+ -- add commands
+ local argv = {"lua", "private.utils.bin2c", "--nozeroend", "-i", spvfilepath, "-o", headerfile}
+ batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}})
+ end
+
+ -- add deps
+ batchcmds:add_depfiles(sourcefile_glsl)
+ batchcmds:set_depmtime(os.mtime(outputfile))
+ batchcmds:set_depcache(target:dependfile(outputfile))
+ end)
+
diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua
index 97c585ded..79c737503 100644
--- a/xmake/rules/utils/inherit_links/inherit_links.lua
+++ b/xmake/rules/utils/inherit_links/inherit_links.lua
@@ -46,7 +46,6 @@ function _add_export_value(target, name, value)
end
end
--- main entry
function main(target)
-- disable inherit.links for `add_deps()`?
@@ -59,12 +58,15 @@ function main(target)
if targetkind == "shared" or targetkind == "static" then
local targetfile = target:targetfile()
- -- we need move target link to head
- _add_export_value(target, "links", target:linkname())
- local links = target:get("links", {rawref = true})
- if links and type(links) == "table" and #links > 1 then
- table.insert(links, 1, links[#links])
- table.remove(links, #links)
+ -- rust maybe will disable inherit links, only inherit linkdirs
+ if target:data("inherit.links.deplink") ~= false then
+ -- we need move target link to head
+ _add_export_value(target, "links", target:linkname())
+ local links = target:get("links", {rawref = true})
+ if links and type(links) == "table" and #links > 1 then
+ table.insert(links, 1, links[#links])
+ table.remove(links, #links)
+ end
end
_add_export_value(target, "linkdirs", path.directory(targetfile))
@@ -78,11 +80,13 @@ function main(target)
-- @note we only export links for static target,
-- and we need pass `{public = true}` to add_packages/add_links/... to export it if want to export links for shared target
--
- if targetkind == "static" then
- for _, name in ipairs({"frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do
- local values = _get_values_from_target(target, name)
- if values and #values > 0 then
- target:add(name, values, {public = true})
+ if target:data("inherit.links.exportlinks") ~= false then
+ if targetkind == "static" then
+ for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do
+ local values = _get_values_from_target(target, name)
+ if values and #values > 0 then
+ target:add(name, values, {public = true})
+ end
end
end
end
diff --git a/xmake/rules/utils/install_importfiles/xmake.lua b/xmake/rules/utils/install_importfiles/xmake.lua
index 45e6616f8..848f215e1 100644
--- a/xmake/rules/utils/install_importfiles/xmake.lua
+++ b/xmake/rules/utils/install_importfiles/xmake.lua
@@ -21,7 +21,9 @@
-- install pkg-config/*.pc import files
rule("utils.install.pkgconfig_importfiles")
after_install(function (target, opt)
- import("target.action.install.pkgconfig_importfiles")(target, opt)
+ opt = opt or {}
+ local filename = target:extraconf("rules", "utils.install.pkgconfig_importfiles", "filename")
+ import("target.action.install.pkgconfig_importfiles")(target, table.join(opt, {filename = filename}))
end)
-- install *.cmake import files
diff --git a/xmake/rules/utils/merge_archive/merge_archive.lua b/xmake/rules/utils/merge_archive/merge_archive.lua
index 96069befb..02d572afc 100644
--- a/xmake/rules/utils/merge_archive/merge_archive.lua
+++ b/xmake/rules/utils/merge_archive/merge_archive.lua
@@ -23,7 +23,7 @@ import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
import("core.project.target", {alias = "project_target"})
-import("private.utils.progress")
+import("utils.progress")
import("core.tool.toolchain")
import("private.tools.vstool")
@@ -93,11 +93,12 @@ end
-- do extract
function _extract(target, libraryfile, objectdir)
- local program, toolname = target:tool("ex")
+ local program, toolname = target:tool("ar")
if program and toolname then
if toolname:find("ar") then
_extract_for_ar(program, libraryfile, objectdir)
- elseif toolname == "lib" then
+ elseif toolname == "link" then
+ program = program:replace("link.exe", "lib.exe", {plain = true})
_extract_for_msvclib(program, libraryfile, objectdir)
end
else
diff --git a/xmake/rules/utils/merge_archive/xmake.lua b/xmake/rules/utils/merge_archive/xmake.lua
index 6d57f55bb..fd7805d8b 100644
--- a/xmake/rules/utils/merge_archive/xmake.lua
+++ b/xmake/rules/utils/merge_archive/xmake.lua
@@ -18,12 +18,32 @@
-- @file xmake.lua
--
--- define rule: utils.merge.archive
rule("utils.merge.archive")
-
- -- set extensions
set_extensions(".a", ".lib")
-
- -- on build file
on_build_files("merge_archive")
+ after_link(function (target, opt)
+ if target:policy("build.merge_archive") and target:is_static() then
+ import("utils.archive.merge_staticlib")
+ import("core.project.depend")
+ import("utils.progress")
+ local libraryfiles = {}
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:is_static() then
+ table.insert(libraryfiles, dep:targetfile())
+ end
+ end
+ if #libraryfiles > 0 then
+ table.insert(libraryfiles, target:targetfile())
+ end
+ depend.on_changed(function ()
+ progress.show(opt.progress, "${color.build.target}merging.$(mode) %s", path.filename(target:targetfile()))
+ if #libraryfiles > 0 then
+ local tmpfile = os.tmpfile() .. path.extension(target:targetfile())
+ merge_staticlib(target, tmpfile, libraryfiles)
+ os.cp(tmpfile, target:targetfile())
+ os.rm(tmpfile)
+ end
+ end, {dependfile = target:dependfile(target:targetfile() .. ".merge_archive"), files = libraryfiles})
+ end
+ end)
diff --git a/xmake/rules/utils/merge_object/xmake.lua b/xmake/rules/utils/merge_object/xmake.lua
index 167e9013e..8bebb5f5c 100644
--- a/xmake/rules/utils/merge_object/xmake.lua
+++ b/xmake/rules/utils/merge_object/xmake.lua
@@ -31,7 +31,7 @@ rule("utils.merge.object")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- get object file
local objectfile = target:objectfile(sourcefile_obj)
diff --git a/xmake/rules/utils/symbols/export_all/export_all.lua b/xmake/rules/utils/symbols/export_all/export_all.lua
index 1a40e9820..f8247a878 100644
--- a/xmake/rules/utils/symbols/export_all/export_all.lua
+++ b/xmake/rules/utils/symbols/export_all/export_all.lua
@@ -24,7 +24,7 @@ import("core.tool.toolchain")
import("core.base.option")
import("core.base.hashset")
import("core.project.depend")
-import("private.utils.progress")
+import("utils.progress")
-- export all symbols for dynamic library
function main (target, opt)
@@ -56,8 +56,9 @@ function main (target, opt)
local objectsymbols = try { function () return os.iorunv(dumpbin.program, {"/symbols", "/nologo", objectfile}) end }
if objectsymbols then
for _, line in ipairs(objectsymbols:split('\n', {plain = true})) do
+ -- https://docs.microsoft.com/en-us/cpp/build/reference/symbols
-- 008 00000000 SECT3 notype () External | add
- if line:find("External") then
+ if line:find("External") and not line:find("UNDEF") then
local symbol = line:match(".*External%s+| (.*)")
if symbol then
symbol = symbol:split('%s')[1]
diff --git a/xmake/rules/utils/symbols/export_all/xmake.lua b/xmake/rules/utils/symbols/export_all/xmake.lua
index f804e3c3e..b808d63a9 100644
--- a/xmake/rules/utils/symbols/export_all/xmake.lua
+++ b/xmake/rules/utils/symbols/export_all/xmake.lua
@@ -26,7 +26,7 @@
-- @see https://github.com/xmake-io/xmake/issues/1123
--
rule("utils.symbols.export_all")
- before_load(function (target)
+ on_load(function (target)
-- @note it only supports windows/dll now
assert(target:is_shared(), 'rule("utils.symbols.export_all"): only for shared target(%s)!', target:name())
if target:is_plat("windows") then
diff --git a/xmake/rules/utils/symbols/extract/xmake.lua b/xmake/rules/utils/symbols/extract/xmake.lua
index f78cab808..dd1f3a1df 100644
--- a/xmake/rules/utils/symbols/extract/xmake.lua
+++ b/xmake/rules/utils/symbols/extract/xmake.lua
@@ -46,7 +46,7 @@ rule("utils.symbols.extract")
import("core.theme.theme")
import("core.project.depend")
import("core.platform.platform")
- import("private.utils.progress")
+ import("utils.progress")
-- get strip
local strip = target:tool("strip")
diff --git a/xmake/rules/vala/xmake.lua b/xmake/rules/vala/xmake.lua
index a2ce76937..6c3d36213 100644
--- a/xmake/rules/vala/xmake.lua
+++ b/xmake/rules/vala/xmake.lua
@@ -18,7 +18,7 @@
-- @file xmake.lua
--
-rule("vala")
+rule("vala.build")
set_extensions(".vala")
on_load(function (target)
-- only vala source files? we need patch c source kind for linker
@@ -26,6 +26,37 @@ rule("vala")
if #sourcekinds == 0 then
table.insert(sourcekinds, "cc")
end
+
+ -- we disable to build across targets in parallel, because the source files may depend on other target modules
+ target:set("policy", "build.across_targets_in_parallel", false)
+
+ -- get vapi file
+ local vapifile = target:data("vala.vapifile")
+ if not vapifile then
+ local vapiname = target:values("vala.vapi")
+ if vapiname then
+ vapifile = path.join(target:targetdir(), vapiname)
+ else
+ vapifile = path.join(target:targetdir(), target:name() .. ".vapi")
+ end
+ target:data_set("vala.vapifile", vapifile)
+ end
+
+ -- get header file
+ local headerfile = target:data("vala.headerfile")
+ if not headerfile then
+ local headername = target:values("vala.header")
+ if headername then
+ headerfile = path.join(target:targetdir(), headername)
+ else
+ headerfile = path.join(target:targetdir(), target:name() .. ".h")
+ end
+ target:data_set("vala.headerfile", headerfile)
+ end
+ if headerfile then
+ target:add("headerfiles", headerfile)
+ target:add("sysincludedirs", path.directory(headerfile), {public = true})
+ end
end)
before_buildcmd_file(function (target, batchcmds, sourcefile_vala, opt)
@@ -52,6 +83,34 @@ rule("vala")
table.insert(argv, package)
end
end
+ if target:is_binary() then
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:is_shared() or dep:is_static() then
+ local vapifile = dep:data("vala.vapifile")
+ if vapifile then
+ table.join2(argv, vapifile)
+ end
+ end
+ end
+ else
+ local vapifile = target:data("vala.vapifile")
+ if vapifile then
+ table.insert(argv, "--vapi=" .. vapifile)
+ end
+ local headerfile = target:data("vala.headerfile")
+ if headerfile then
+ table.insert(argv, "-H")
+ table.insert(argv, headerfile)
+ end
+ end
+ local vapidir = target:data("vala.vapidir")
+ if vapidir then
+ table.insert(argv, "--vapidir=" .. vapidir)
+ end
+ local valaflags = target:data("vala.flags")
+ if valaflags then
+ table.join2(argv, valaflags)
+ end
table.insert(argv, sourcefile_vala)
batchcmds:vrunv(valac.program, argv)
batchcmds:compile(sourcefile_c, objectfile)
@@ -62,3 +121,54 @@ rule("vala")
batchcmds:set_depcache(target:dependfile(objectfile))
end)
+ after_install(function (target)
+ if target:is_shared() or target:is_static() then
+ local vapifile = target:data("vala.vapifile")
+ if vapifile then
+ local installdir = target:installdir()
+ if installdir then
+ local sharedir = path.join(installdir, "share")
+ os.mkdir(sharedir)
+ os.vcp(vapifile, sharedir)
+ end
+ end
+ end
+ end)
+
+ after_uninstall(function (target)
+ if target:is_shared() or target:is_static() then
+ local vapifile = target:data("vala.vapifile")
+ if vapifile then
+ local installdir = target:installdir()
+ if installdir then
+ os.rm(path.join(installdir, "share", path.filename(vapifile)))
+ end
+ end
+ end
+ end)
+
+rule("vala")
+
+ -- add build rules
+ add_deps("vala.build")
+
+ -- set compiler runtime, e.g. vs runtime
+ add_deps("utils.compiler.runtime")
+
+ -- inherit links and linkdirs of all dependent targets by default
+ add_deps("utils.inherit.links")
+
+ -- support `add_files("src/*.o")` and `add_files("src/*.a")` to merge object and archive files to target
+ add_deps("utils.merge.object", "utils.merge.archive")
+
+ -- we attempt to extract symbols to the independent file and
+ -- strip self-target binary if `set_symbols("debug")` and `set_strip("all")` are enabled
+ add_deps("utils.symbols.extract")
+
+ -- check targets
+ add_deps("utils.check.targets")
+
+ -- check licenses
+ add_deps("utils.check.licenses")
+
+
diff --git a/xmake/rules/wdk/env/xmake.lua b/xmake/rules/wdk/env/xmake.lua
index 6b7690933..a9089dc5e 100644
--- a/xmake/rules/wdk/env/xmake.lua
+++ b/xmake/rules/wdk/env/xmake.lua
@@ -22,7 +22,7 @@
rule("wdk.env")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("os.winver", {alias = "os_winver"})
diff --git a/xmake/rules/wdk/inf/xmake.lua b/xmake/rules/wdk/inf/xmake.lua
index fe060a10a..354fbc5a7 100644
--- a/xmake/rules/wdk/inf/xmake.lua
+++ b/xmake/rules/wdk/inf/xmake.lua
@@ -28,7 +28,7 @@ rule("wdk.inf")
set_extensions(".inf", ".inx")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -54,7 +54,7 @@ rule("wdk.inf")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- the target file
local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".inf")
diff --git a/xmake/rules/wdk/man/xmake.lua b/xmake/rules/wdk/man/xmake.lua
index 25cce9f34..c5219aa56 100644
--- a/xmake/rules/wdk/man/xmake.lua
+++ b/xmake/rules/wdk/man/xmake.lua
@@ -28,7 +28,7 @@ rule("wdk.man")
set_extensions(".man")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -57,7 +57,7 @@ rule("wdk.man")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- get ctrpp
local ctrpp = target:data("wdk.ctrpp")
diff --git a/xmake/rules/wdk/mc/xmake.lua b/xmake/rules/wdk/mc/xmake.lua
index 32653dfc2..689c9786c 100644
--- a/xmake/rules/wdk/mc/xmake.lua
+++ b/xmake/rules/wdk/mc/xmake.lua
@@ -28,7 +28,7 @@ rule("wdk.mc")
set_extensions(".mc")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -57,7 +57,7 @@ rule("wdk.mc")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- get mc
local mc = target:data("wdk.mc")
diff --git a/xmake/rules/wdk/mof/xmake.lua b/xmake/rules/wdk/mof/xmake.lua
index 319eec5d7..a1a2a0366 100644
--- a/xmake/rules/wdk/mof/xmake.lua
+++ b/xmake/rules/wdk/mof/xmake.lua
@@ -28,7 +28,7 @@ rule("wdk.mof")
set_extensions(".mof")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -73,7 +73,7 @@ rule("wdk.mof")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- get mofcomp
local mofcomp = target:data("wdk.mofcomp")
diff --git a/xmake/rules/wdk/sign/xmake.lua b/xmake/rules/wdk/sign/xmake.lua
index 7dcc28785..6be72e7b3 100644
--- a/xmake/rules/wdk/sign/xmake.lua
+++ b/xmake/rules/wdk/sign/xmake.lua
@@ -34,7 +34,7 @@ rule("wdk.sign")
add_deps("wdk.env")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -93,7 +93,7 @@ rule("wdk.sign")
import("core.project.config")
import("core.project.depend")
import("lib.detect.find_file")
- import("private.utils.progress")
+ import("utils.progress")
-- need build this object?
local tempfile = os.tmpfile(target:targetfile())
diff --git a/xmake/rules/wdk/tracewpp/xmake.lua b/xmake/rules/wdk/tracewpp/xmake.lua
index 0c49bf5d0..75f4f37ef 100644
--- a/xmake/rules/wdk/tracewpp/xmake.lua
+++ b/xmake/rules/wdk/tracewpp/xmake.lua
@@ -25,7 +25,7 @@ rule("wdk.tracewpp")
add_deps("wdk.env")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
@@ -57,7 +57,7 @@ rule("wdk.tracewpp")
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
- import("private.utils.progress")
+ import("utils.progress")
-- get tracewpp
local tracewpp = target:data("wdk.tracewpp")
diff --git a/xmake/rules/winsdk/dotnet/xmake.lua b/xmake/rules/winsdk/dotnet/xmake.lua
index 5274f040a..1cfef7b58 100644
--- a/xmake/rules/winsdk/dotnet/xmake.lua
+++ b/xmake/rules/winsdk/dotnet/xmake.lua
@@ -22,7 +22,7 @@
rule("win.sdk.dotnet")
-- before load
- before_load(function (target)
+ on_load(function (target)
-- imports
import("core.project.config")
diff --git a/xmake/rules/winsdk/mfc/env/xmake.lua b/xmake/rules/winsdk/mfc/env/xmake.lua
index f603ebfe2..f553618b5 100644
--- a/xmake/rules/winsdk/mfc/env/xmake.lua
+++ b/xmake/rules/winsdk/mfc/env/xmake.lua
@@ -22,5 +22,5 @@
rule("win.sdk.mfc.env")
-- TODO: before load need check of vs's minverion, if defined
- before_load(function (target)
+ on_load(function (target)
end)
diff --git a/xmake/rules/winsdk/xmake.lua b/xmake/rules/winsdk/xmake.lua
index 0a3b105cc..297dfda75 100644
--- a/xmake/rules/winsdk/xmake.lua
+++ b/xmake/rules/winsdk/xmake.lua
@@ -27,7 +27,7 @@ rule("win.sdk.resource")
rule("win.sdk.application")
-- before load
- before_load(function (target)
+ on_load(function (target)
target:set("kind", "binary")
end)
diff --git a/xmake/rules/xcode/application/build.lua b/xmake/rules/xcode/application/build.lua
index 786f5da89..a4862ae86 100644
--- a/xmake/rules/xcode/application/build.lua
+++ b/xmake/rules/xcode/application/build.lua
@@ -23,7 +23,7 @@ import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
import("private.tools.codesign")
-import("private.utils.progress")
+import("utils.progress")
-- main entry
function main (target, opt)
diff --git a/xmake/rules/xcode/application/load.lua b/xmake/rules/xcode/application/load.lua
index 3071ccd58..354aa5b0c 100644
--- a/xmake/rules/xcode/application/load.lua
+++ b/xmake/rules/xcode/application/load.lua
@@ -54,15 +54,4 @@ function main (target)
-- register clean files for `xmake clean`
target:add("cleanfiles", bundledir)
-
- -- depend xcode.framework? we need disable `build.across_targets_in_parallel` policy
- local across_targets_in_parallel
- for _, dep in ipairs(target:orderdeps()) do
- if dep:rule("xcode.framework") then
- across_targets_in_parallel = false
- end
- end
- if across_targets_in_parallel ~= nil then
- target:set("policy", "build.across_targets_in_parallel", across_targets_in_parallel)
- end
end
diff --git a/xmake/rules/xcode/application/run.lua b/xmake/rules/xcode/application/run.lua
index e92397a29..0e0663207 100644
--- a/xmake/rules/xcode/application/run.lua
+++ b/xmake/rules/xcode/application/run.lua
@@ -40,10 +40,10 @@ function _run_on_macosx(target, opt)
-- add run environments
local addrunenvs, setrunenvs = make_runenvs(target)
for name, values in pairs(addrunenvs) do
- os.addenv(name, unpack(table.wrap(values)))
+ os.addenv(name, table.unpack(table.wrap(values)))
end
for name, value in pairs(setrunenvs) do
- os.setenv(name, unpack(table.wrap(value)))
+ os.setenv(name, table.unpack(table.wrap(value)))
end
-- debugging?
diff --git a/xmake/rules/xcode/application/xmake.lua b/xmake/rules/xcode/application/xmake.lua
index 5984bbb55..d328262c0 100644
--- a/xmake/rules/xcode/application/xmake.lua
+++ b/xmake/rules/xcode/application/xmake.lua
@@ -21,11 +21,24 @@
-- define rule: xcode application
rule("xcode.application")
- -- support add_files("Info.plist", "*.storyboard", "*.xcassets")
- add_deps("xcode.info_plist", "xcode.storyboard", "xcode.xcassets")
+ -- support add_files("Info.plist", "*.storyboard", "*.xcassets", "*.metal")
+ add_deps("xcode.info_plist", "xcode.storyboard", "xcode.xcassets", "xcode.metal")
-- we must set kind before target.on_load(), may we will use target in on_load()
- before_load("load")
+ on_load("load")
+
+ -- depend xcode.framework? we need disable `build.across_targets_in_parallel` policy
+ after_load(function (target)
+ local across_targets_in_parallel
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:rule("xcode.framework") then
+ across_targets_in_parallel = false
+ end
+ end
+ if across_targets_in_parallel ~= nil then
+ target:set("policy", "build.across_targets_in_parallel", across_targets_in_parallel)
+ end
+ end)
-- build *.app
after_build("build")
diff --git a/xmake/rules/xcode/bundle/xmake.lua b/xmake/rules/xcode/bundle/xmake.lua
index bd8e4329e..322a42418 100644
--- a/xmake/rules/xcode/bundle/xmake.lua
+++ b/xmake/rules/xcode/bundle/xmake.lua
@@ -25,7 +25,7 @@ rule("xcode.bundle")
add_deps("xcode.info_plist")
-- we must set kind before target.on_load(), may we will use target in on_load()
- before_load(function (target)
+ on_load(function (target)
-- get bundle directory
local targetdir = target:targetdir()
@@ -60,7 +60,7 @@ rule("xcode.bundle")
import("core.theme.theme")
import("core.project.depend")
import("private.tools.codesign")
- import("private.utils.progress")
+ import("utils.progress")
-- get bundle and resources directory
local bundledir = path.absolute(target:data("xcode.bundle.rootdir"))
diff --git a/xmake/rules/xcode/framework/xmake.lua b/xmake/rules/xcode/framework/xmake.lua
index b112dcaf1..de7d7c93c 100644
--- a/xmake/rules/xcode/framework/xmake.lua
+++ b/xmake/rules/xcode/framework/xmake.lua
@@ -25,7 +25,7 @@ rule("xcode.framework")
add_deps("xcode.info_plist")
-- we must set kind before target.on_load(), may we will use target in on_load()
- before_load(function (target)
+ on_load(function (target)
-- get framework directory
local targetdir = target:targetdir()
@@ -85,7 +85,7 @@ rule("xcode.framework")
import("core.theme.theme")
import("core.project.depend")
import("private.tools.codesign")
- import("private.utils.progress")
+ import("utils.progress")
-- get framework directory
local bundledir = path.absolute(target:data("xcode.bundle.rootdir"))
diff --git a/xmake/rules/xcode/info_plist/xmake.lua b/xmake/rules/xcode/info_plist/xmake.lua
index 57d3c9995..bd991b6e1 100644
--- a/xmake/rules/xcode/info_plist/xmake.lua
+++ b/xmake/rules/xcode/info_plist/xmake.lua
@@ -32,7 +32,7 @@ rule("xcode.info_plist")
import("core.theme.theme")
import("core.project.depend")
import("core.tool.toolchain")
- import("private.utils.progress")
+ import("utils.progress")
-- check
assert(path.filename(sourcefile) == "Info.plist", "we only support Info.plist file!")
diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua
new file mode 100644
index 000000000..a876f946b
--- /dev/null
+++ b/xmake/rules/xcode/metal/xmake.lua
@@ -0,0 +1,145 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- build metal files
+--
+-- @see https://developer.apple.com/documentation/metal/libraries/building_a_library_with_metal_s_command-line_tools
+--
+rule("xcode.metal")
+
+ -- support add_files("*.metal")
+ set_extensions(".metal")
+
+ on_load(function (target)
+ local cross
+ if target:is_plat("macosx") then
+ cross = "xcrun -sdk macosx "
+ elseif target:is_plat("iphoneos") then
+ cross = target:is_arch("i386", "x86_64") and "xcrun -sdk iphonesimulator " or "xcrun -sdk iphoneos "
+ elseif target:is_plat("watchos") then
+ cross = target:is_arch("i386") and "xcrun -sdk watchsimulator " or "xcrun -sdk watchos "
+ elseif target:is_plat("appletvos") then
+ cross = target:is_arch("i386", "x86_64") and "xcrun -sdk appletvsimulator " or "xcrun -sdk appletvos "
+ else
+ raise("unknown platform for xcode!")
+ end
+ target:data_set("xcode.metal.cross", cross)
+ end)
+
+ -- build *.metal to *.air
+ on_buildcmd_file(function (target, batchcmds, sourcefile, opt)
+
+ -- get metal
+ import("core.tool.toolchain")
+ import("lib.detect.find_tool")
+ local cross = target:data("xcode.metal.cross")
+ local metal = assert(find_tool("metal", {program = cross .. " metal"}), "metal command not found!")
+
+ -- get xcode toolchain
+ local xcode = toolchain.load("xcode", {plat = target:plat(), arch = target:arch()})
+ local target_minver = xcode:config("target_minver")
+ local xcode_sysroot = xcode:config("xcode_sysroot")
+
+ -- init metal arguments
+ local objectfile = target:objectfile(sourcefile) .. ".air"
+ local argv = {"-c", "-ffast-math", "-gline-tables-only"}
+ if target_minver then
+ table.insert(argv, "-target")
+ local airarch = target:is_arch("x86_64", "arm64") and "air64" or "air32"
+ if target:is_plat("macosx") then
+ table.insert(argv, airarch .. "-apple-macos" .. target_minver)
+ elseif target:is_plat("iphoneos") then
+ local airtarget = airarch .. "-apple-ios" .. target_minver
+ if target:is_arch("x86_64", "i386") then
+ airtarget = airtarget .. "-simulator"
+ end
+ table.insert(argv, airtarget)
+ elseif target:is_plat("watchos") then
+ local airtarget = airarch .. "-apple-watchos" .. target_minver
+ if target:is_arch("x86_64", "i386") then
+ airtarget = airtarget .. "-simulator"
+ end
+ table.insert(argv, airtarget)
+ elseif target:is_plat("appletvos") then
+ local airtarget = airarch .. "-apple-tvos" .. target_minver
+ if target:is_arch("x86_64", "i386") then
+ airtarget = airtarget .. "-simulator"
+ end
+ table.insert(argv, airtarget)
+ end
+ end
+ if xcode_sysroot then
+ table.insert(argv, "-isysroot")
+ table.insert(argv, xcode_sysroot)
+ end
+ table.insert(argv, "-o")
+ table.insert(argv, objectfile)
+ table.insert(argv, sourcefile)
+
+ -- add commands
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.metal %s", sourcefile)
+ batchcmds:mkdir(path.directory(objectfile))
+ batchcmds:vrunv(metal.program, argv)
+
+ -- add deps
+ batchcmds:add_depfiles(sourcefile)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
+ end)
+
+ -- link *.air to *.metallib
+ before_linkcmd(function (target, batchcmds, opt)
+
+ -- get objectfiles
+ local objectfiles = {}
+ for rulename, sourcebatch in pairs(target:sourcebatches()) do
+ if rulename == "xcode.metal" then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ table.insert(objectfiles, target:objectfile(sourcefile) .. ".air")
+ end
+ break
+ end
+ end
+ if #objectfiles == 0 then
+ return
+ end
+
+ -- get metallib
+ import("core.tool.toolchain")
+ import("lib.detect.find_tool")
+ local cross = target:data("xcode.metal.cross")
+ local metallib = assert(find_tool("metallib", {program = cross .. " metallib"}), "metallib command not found!")
+
+ -- get xcode toolchain
+ local xcode = toolchain.load("xcode", {plat = target:plat(), arch = target:arch()})
+ local xcode_sysroot = xcode:config("xcode_sysroot")
+
+ -- add commands
+ local resourcesdir = path.absolute(target:data("xcode.bundle.resourcesdir"))
+ local libraryfile = resourcesdir and path.join(resourcesdir, "default.metallib") or (target:targetfile() .. ".metallib")
+ batchcmds:show_progress(opt.progress, "${color.build.target}linking.metal %s", path.filename(libraryfile))
+ batchcmds:mkdir(path.directory(libraryfile))
+ batchcmds:vrunv(metallib.program, table.join({"-o", libraryfile}, objectfiles), {envs = {SDKROOT = xcode_sysroot}})
+
+ -- add deps
+ batchcmds:add_depfiles(objectfiles)
+ batchcmds:set_depmtime(os.mtime(libraryfile))
+ batchcmds:set_depcache(target:dependfile(libraryfile))
+ end)
diff --git a/xmake/rules/xcode/storyboard/xmake.lua b/xmake/rules/xcode/storyboard/xmake.lua
index 6ec23dd80..d96a1c002 100644
--- a/xmake/rules/xcode/storyboard/xmake.lua
+++ b/xmake/rules/xcode/storyboard/xmake.lua
@@ -32,7 +32,7 @@ rule("xcode.storyboard")
import("core.theme.theme")
import("core.project.depend")
import("core.tool.toolchain")
- import("private.utils.progress")
+ import("utils.progress")
-- get xcode sdk directory
local xcode_sdkdir = assert(get_config("xcode"), "xcode not found!")
diff --git a/xmake/rules/xcode/xcassets/xmake.lua b/xmake/rules/xcode/xcassets/xmake.lua
index 09185b226..9322d10c1 100644
--- a/xmake/rules/xcode/xcassets/xmake.lua
+++ b/xmake/rules/xcode/xcassets/xmake.lua
@@ -32,7 +32,7 @@ rule("xcode.xcassets")
import("core.theme.theme")
import("core.project.depend")
import("core.tool.toolchain")
- import("private.utils.progress")
+ import("utils.progress")
-- get xcode sdk directory
local xcode_sdkdir = assert(get_config("xcode"), "xcode not found!")
diff --git a/xmake/rules/xmake_cli/xmake.lua b/xmake/rules/xmake_cli/xmake.lua
index 2375c9e3b..a7e21a9e1 100644
--- a/xmake/rules/xmake_cli/xmake.lua
+++ b/xmake/rules/xmake_cli/xmake.lua
@@ -20,7 +20,7 @@
-- define rule: xmake cli program
rule("xmake.cli")
- before_load(function (target)
+ on_load(function (target)
target:set("kind", "binary")
assert(target:pkg("libxmake"), 'please add_packages("libxmake") to target(%s) first!', target:name())
end)