diff options
| -rw-r--r-- | xmake/actions/build/build_files.lua | 168 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 2 |
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 |
