summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-07-19 23:01:56 +0800
committerruki <[email protected]>2019-07-19 12:54:41 +0800
commit85c03562de5a5e2b28eefbb53cb28816f7b98d32 (patch)
tree023f7138eec7d56766b02f3791649eeaefc61a89
parent311a955a8e4fe8b68033426415258e6dc23b2e0c (diff)
match and build files
-rw-r--r--xmake/actions/build/build_files.lua168
-rw-r--r--xmake/core/base/os.lua2
2 files changed, 167 insertions, 3 deletions
diff --git a/xmake/actions/build/build_files.lua b/xmake/actions/build/build_files.lua
index ce7cf519a..6f6641dcb 100644
--- a/xmake/actions/build/build_files.lua
+++ b/xmake/actions/build/build_files.lua
@@ -23,15 +23,179 @@ import("core.base.option")
import("core.project.config")
import("core.project.project")
import("core.platform.environment")
+import("kinds.object")
+
+-- match source files
+function _match_sourcefiles(sourcefile, filepatterns)
+ for _, filepattern in ipairs(filepatterns) do
+ if sourcefile:match(filepattern.pattern) == sourcefile then
+ if filepattern.excludes then
+ if filepattern.rootdir and sourcefile:startswith(filepattern.rootdir) then
+ sourcefile = sourcefile:sub(#filepattern.rootdir + 2)
+ end
+ for _, exclude in ipairs(filepattern.excludes) do
+ if sourcefile:match(exclude) == sourcefile then
+ return false
+ end
+ end
+ end
+ return true
+ end
+ end
+end
+
+-- prepare jobs for target
+function _prepare_jobs_for_target(jobs, target, filepatterns)
+
+ local newbatches = {}
+ local sourcecount = 0
+ for sourcekind, sourcebatch in pairs(target:sourcebatches()) do
+ local objectfiles = sourcebatch.objectfiles
+ local dependfiles = sourcebatch.dependfiles
+ for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ if _match_sourcefiles(sourcefile, filepatterns) then
+ local newbatch = newbatches[sourcekind]
+ if not newbatch then
+ newbatch = {}
+ newbatch.sourcekind = sourcekind
+ newbatch.rulename = sourcebatch.rulename
+ newbatch.sourcefiles = {}
+ newbatch.objectfiles = {}
+ newbatch.dependfiles = {}
+ end
+ table.insert(newbatch.sourcefiles, sourcefile)
+ table.insert(newbatch.objectfiles, objectfiles[idx])
+ table.insert(newbatch.dependfiles, dependfiles[idx])
+ newbatches[sourcekind] = newbatch
+ sourcecount = sourcecount + 1
+ end
+ end
+ end
+ if sourcecount > 0 then
+ table.insert(jobs, {target = target, sourcecount = sourcecount, sourcebatches = newbatches})
+ end
+end
+
+-- prepare jobs for the given target and deps
+function _prepare_jobs_for_targetdeps(jobs, target, filepatterns)
+
+ -- this target have been finished?
+ if _g.finished[target:name()] then
+ return
+ end
+
+ -- make for all dependent targets
+ for _, depname in ipairs(target:get("deps")) do
+ _prepare_jobs_for_targetdeps(jobs, project.target(depname), filepatterns)
+ end
+
+ -- prepare jobs for target
+ _prepare_jobs_for_target(jobs, target, filepatterns)
+
+ -- finished
+ _g.finished[target:name()] = true
+end
+
+-- prepare jobs
+function _prepare_jobs(targetname, filepatterns)
+
+ -- clear finished states
+ _g.finished = {}
+
+ -- prepare jobs for the given target?
+ local jobs = {}
+ if targetname then
+ _prepare_jobs_for_targetdeps(jobs, project.target(targetname), filepatterns)
+ else
+ -- prepare jobs for default or all targets
+ for _, target in pairs(project.targets()) do
+ local default = target:get("default")
+ if default == nil or default == true or option.get("all") then
+ _prepare_jobs_for_targetdeps(jobs, target, filepatterns)
+ end
+ end
+ end
+
+ -- get source total count
+ local sourcecount = 0
+ for _, job in ipairs(jobs) do
+ sourcecount = sourcecount + job.sourcecount
+ end
+ return jobs, sourcecount
+end
+
+-- convert all sourcefiles to lua pattern
+function _get_file_patterns(sourcefiles)
+ local patterns = {}
+ for _, sourcefile in ipairs(path.splitenv(sourcefiles)) do
+
+ -- get the excludes
+ local pattern = sourcefile:trim()
+ local excludes = pattern:match("|.*$")
+ if excludes then excludes = excludes:split("|", {plain = true}) end
+
+ -- translate excludes
+ if excludes then
+ local _excludes = {}
+ for _, exclude in ipairs(excludes) do
+ exclude = path.translate(exclude)
+ exclude = exclude:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
+ exclude = exclude:gsub("%*%*", "\001")
+ exclude = exclude:gsub("%*", "\002")
+ exclude = exclude:gsub("\001", ".*")
+ exclude = exclude:gsub("\002", "[^/]*")
+ table.insert(_excludes, exclude)
+ end
+ excludes = _excludes
+ end
+
+ -- translate path and remove some repeat separators
+ pattern = path.translate(pattern:gsub("|.*$", ""))
+
+ -- remove "./" or '.\\' prefix
+ if pattern:sub(1, 2):find('%.[/\\]') then
+ pattern = pattern:sub(3)
+ end
+
+ -- get the root directory
+ local rootdir = pattern
+ local startpos = pattern:find("*", 1, true)
+ if startpos then
+ rootdir = rootdir:sub(1, startpos - 1)
+ end
+ rootdir = path.directory(rootdir)
+
+ -- convert to lua path pattern
+ pattern = path.pattern(pattern)
+ table.insert(patterns, {pattern = pattern, excludes = excludes, rootdir = rootdir})
+ end
+ return patterns
+end
-- the main entry
function main(targetname, sourcefiles)
+ -- convert all sourcefiles to lua pattern
+ local filepatterns = _get_file_patterns(sourcefiles)
+
+ -- prepare jobs
+ local jobs, sourcecount = _prepare_jobs(targetname, filepatterns)
+ if #jobs == 0 or sourcecount == 0 then
+ return
+ end
+
-- enter toolchains environment
environment.enter("toolchains")
- -- TODO
- print("target: %s, files: %s", targetname, sourcefiles)
+ -- build source files for all jobs
+ _g.finished = {}
+ _g.targetindex = 0
+ _g.targetcount = 1
+ _g.sourceindex = 1
+ _g.sourcecount = sourcecount
+ for _, job in ipairs(jobs) do
+ object.build_sourcefiles(job.target, _g, job.sourcebatches)
+ end
-- leave toolchains environment
environment.leave("toolchains")
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index 4c23ed0c4..2f17ebc27 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -208,7 +208,7 @@ function os.match(pattern, mode, callback)
-- get the excludes
local excludes = pattern:match("|.*$")
- if excludes then excludes = excludes:split("|") end
+ if excludes then excludes = excludes:split("|", {plain = true}) end
-- translate excludes
if excludes then