summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-10-17 23:56:16 +0800
committerruki <[email protected]>2021-10-17 23:56:16 +0800
commit9dbe8c62ebbfb7fe0fb3335790af184b2b7860a1 (patch)
tree82d9b8dc251265239b055eea662095aca8b3d12d
parentf91fc985a24094fd90a825f68c9ca63f7aa83ce0 (diff)
add unit_build rule
-rw-r--r--xmake/core/project/target.lua4
-rw-r--r--xmake/rules/c++/unit_build/unit_build.lua108
-rw-r--r--xmake/rules/c++/unit_build/xmake.lua24
3 files changed, 132 insertions, 4 deletions
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index d6bba579a..08ab720c0 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -1688,11 +1688,7 @@ function _instance:sourcebatches()
end
end
end
-
- -- cache it
self._SOURCEBATCHES = sourcebatches
-
- -- ok?
return sourcebatches, modified
end
diff --git a/xmake/rules/c++/unit_build/unit_build.lua b/xmake/rules/c++/unit_build/unit_build.lua
new file mode 100644
index 000000000..030639f1a
--- /dev/null
+++ b/xmake/rules/c++/unit_build/unit_build.lua
@@ -0,0 +1,108 @@
+--!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 unit_build.lua
+--
+
+-- imports
+import("core.project.depend")
+
+function _merge_unitfile(target, sourcefile_unit, sourcefiles, opt)
+ local dependfile = target:dependfile(sourcefile_unit)
+ depend.on_changed(function ()
+
+ -- trace
+ vprint("generating.unitfile %s", sourcefile_unit)
+
+ -- do merge
+ local unitfile = io.open(sourcefile_unit, "w")
+ for _, sourcefile in ipairs(sourcefiles) do
+ sourcefile = path.absolute(sourcefile)
+ sourcefile_unit = path.absolute(sourcefile_unit)
+ sourcefile = path.relative(sourcefile, path.directory(sourcefile_unit))
+ unitfile:print("#include \"%s\"", sourcefile)
+ end
+ unitfile:close()
+
+ end, {dependfile = dependfile, files = sourcefiles})
+end
+
+function generate_unitfiles(target, sourcebatch, opt)
+ local unitbatch = target:data("unit_build.unitbatch." .. sourcebatch.rulename)
+ if unitbatch then
+ for _, sourcefile_unit in ipairs(sourcebatch.sourcefiles) do
+ local sourceinfo = unitbatch[sourcefile_unit]
+ if sourceinfo then
+ local sourcefiles = sourceinfo.sourcefiles
+ if sourcefiles then
+ _merge_unitfile(target, sourcefile_unit, sourcefiles, opt)
+ end
+ end
+ end
+ end
+end
+
+function main(target, sourcebatch)
+
+ -- get unit batch sources
+ local extraconf = target:extraconf("rules", "c++.unit_build")
+ local batchsize = extraconf.batchsize
+ local id = 1
+ local count = 0
+ local unitbatch = {}
+ local sourcedir = path.join(target:autogendir({root = true}), "unit_build")
+ for idx, sourcefile in pairs(sourcebatch.sourcefiles) do
+ local sourcefile_unit
+ local objectfile = sourcebatch.objectfiles[idx]
+ local dependfile = sourcebatch.dependfiles[idx]
+ local fileconfig = target:fileconfig(sourcefile)
+ if fileconfig and fileconfig.unit_group then
+ sourcefile_unit = path.join(sourcedir, "unit_" .. fileconfig.unit_group .. path.extension(sourcefile))
+ else
+ if batchsize and count > batchsize then
+ id = id + 1
+ end
+ sourcefile_unit = path.join(sourcedir, "unit_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile))
+ count = count + 1
+ end
+ local sourceinfo = unitbatch[sourcefile_unit]
+ if not sourceinfo then
+ sourceinfo = {}
+ sourceinfo.objectfile = target:objectfile(sourcefile_unit)
+ sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile)
+ unitbatch[sourcefile_unit] = sourceinfo
+ end
+ sourceinfo.sourcefiles = sourceinfo.sourcefiles or {}
+ table.insert(sourceinfo.sourcefiles, sourcefile)
+ end
+
+ -- use unit batch
+ local sourcefiles = {}
+ local objectfiles = {}
+ local dependfiles = {}
+ for sourcefile_unit, sourceinfo in pairs(unitbatch) do
+ table.insert(sourcefiles, sourcefile_unit)
+ table.insert(objectfiles, sourceinfo.objectfile)
+ table.insert(dependfiles, sourceinfo.dependfile)
+ end
+ sourcebatch.sourcefiles = sourcefiles
+ sourcebatch.objectfiles = objectfiles
+ sourcebatch.dependfiles = dependfiles
+
+ -- save unit batch
+ target:data_set("unit_build.unitbatch." .. sourcebatch.rulename, unitbatch)
+end
diff --git a/xmake/rules/c++/unit_build/xmake.lua b/xmake/rules/c++/unit_build/xmake.lua
index c6d0ea0bd..b0eb7b39a 100644
--- a/xmake/rules/c++/unit_build/xmake.lua
+++ b/xmake/rules/c++/unit_build/xmake.lua
@@ -19,3 +19,27 @@
--
rule("c++.unit_build")
+ after_load(function (target)
+ import("unit_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ for _, rulename in ipairs({"c.build", "c++.build"}) do
+ local sourcebatch = sourcebatches[rulename]
+ if sourcebatch then
+ unit_build(target, sourcebatch)
+ end
+ end
+ end
+ end)
+ before_build(function (target, opt)
+ import("unit_build")
+ local sourcebatches = target:sourcebatches()
+ if sourcebatches then
+ for _, rulename in ipairs({"c.build", "c++.build"}) do
+ local sourcebatch = sourcebatches[rulename]
+ if sourcebatch then
+ unit_build.generate_unitfiles(target, sourcebatch, opt)
+ end
+ end
+ end
+ end)