diff options
| author | ruki <[email protected]> | 2025-03-28 00:37:04 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-04-08 15:31:56 +0800 |
| commit | 7e60e473a3d92d0706a4856c12f161c4d2df32a9 (patch) | |
| tree | b021e66c41b2494a237c7ae5dddc2a22335ae0f3 | |
| parent | 6582a3e7eb62f1c6ad4a8263bd14579e7a25c092 (diff) | |
mark as jobbatch as deprecated
16 files changed, 500 insertions, 460 deletions
diff --git a/xmake/actions/build/.DS_Store b/xmake/actions/build/.DS_Store Binary files differnew file mode 100644 index 000000000..b82482eba --- /dev/null +++ b/xmake/actions/build/.DS_Store diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index 05284490d..54827d354 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -22,242 +22,20 @@ import("core.base.option") import("core.project.config") import("core.project.project") -import("private.async.jobpool") -import("async.runjobs") -import("private.utils.batchcmds") -import("core.base.hashset") -import("private.service.remote_cache.client", {alias = "remote_cache_client"}) -import("private.service.distcc_build.client", {alias = "distcc_build_client"}) -import("prepare", {alias = "prepare_build"}) import("target_utils") +import("deprecated.build", {alias = "deprecated_build"}) --- clean target for rebuilding -function _clean_target(target) - if target:targetfile() then - os.tryrm(target:symbolfile()) - os.tryrm(target:targetfile()) - end -end - --- add builtin batch jobs -function _add_batchjobs_builtin(batchjobs, rootjob, target) - - -- uses the rules script? - local job, job_leaf - for _, r in irpairs(target:orderules()) do -- reverse rules order for batchjobs:addjob() - local script = r:script("build") - if script then - if r:extraconf("build", "batch") then - job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):on_build(): no returned job!", r:name()) - else - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total, opt) - script(target, {progress = opt.progress}) - end, {rootjob = job or rootjob}) - end - else - local buildcmd = r:script("buildcmd") - if buildcmd then - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total, opt) - local batchcmds_ = batchcmds.new({target = target}) - buildcmd(target, batchcmds_, {progress = opt.progress}) - batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) - end, {rootjob = job or rootjob}) - end - end - end - - -- uses the builtin target script - if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object() or target:is_moduleonly()) then - job, job_leaf = import("kinds." .. target:kind(), {anonymous = true})(batchjobs, rootjob, target) - end - job = job or rootjob - return job, job_leaf or job +function _prepare(targets_root, opt) + opt = opt or {} + opt.job_kind = "prepare" + target_utils.runjobs(targets_root, opt) end --- add batch jobs -function _add_batchjobs(batchjobs, rootjob, target) - - local job, job_leaf - local script = target:script("build") - if not script then - -- do builtin batch jobs - job, job_leaf = _add_batchjobs_builtin(batchjobs, rootjob, target) - elseif target:extraconf("build", "batch") then - -- do custom batch script - -- e.g. - -- target("test") - -- on_build(function (target, batchjobs, opt) - -- return batchjobs:addjob("test", function (idx, total) - -- print("build it") - -- end, {rootjob = opt.rootjob}) - -- end, {batch = true}) - -- - job, job_leaf = assert(script(target, batchjobs, {rootjob = rootjob}), "target(%s):on_build(): no returned job!", target:name()) - else - -- do custom script directly - -- e.g. - -- - -- target("test") - -- on_build(function (target, opt) - -- print("build it") - -- end) - -- - job = batchjobs:addjob(target:name() .. "/build", function (index, total, opt) - script(target, {progress = opt.progress}) - end, {rootjob = rootjob}) - end - return job, job_leaf or job -end - --- add batch jobs for the given target -function _add_batchjobs_for_target(batchjobs, rootjob, target) - - -- has been disabled? - if not target:is_enabled() then - return - end - - -- add after_build job for target - local pkgenvs = _g.pkgenvs or {} - _g.pkgenvs = pkgenvs - local job_build_after = batchjobs:addjob(target:name() .. "/after_build", function (index, total, opt) - - -- do after_build - local progress = opt.progress - local after_build = target:script("build_after") - if after_build then - after_build(target, {progress = progress}) - end - for _, r in ipairs(target:orderules()) do - local after_build = r:script("build_after") - if after_build then - after_build(target, {progress = progress}) - else - local after_buildcmd = r:script("buildcmd_after") - if after_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - after_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) - end - end - end - - -- restore environments - if target:pkgenvs() then - pkgenvs.oldenvs = pkgenvs.oldenvs or os.getenvs() - pkgenvs.newenvs = pkgenvs.newenvs or {} - pkgenvs.newenvs[target] = nil - local newenvs = pkgenvs.oldenvs - for _, envs in pairs(pkgenvs.newenvs) do - newenvs = os.joinenvs(envs, newenvs) - end - os.setenvs(newenvs) - end - - end, {rootjob = rootjob}) - - -- add batch jobs for target, @note only on_build script support batch jobs - local job_build, job_build_leaf = _add_batchjobs(batchjobs, job_build_after, target) - - -- add before_build job for target - local job_build_before = batchjobs:addjob(target:name() .. "/before_build", function (index, total, opt) - - -- enter package environments - -- https://github.com/xmake-io/xmake/issues/4033 - -- - -- maybe mixing envs isn't a great solution, - -- but it's the most efficient compromise compared to setting envs in every on_build_file. - -- - if target:pkgenvs() then - pkgenvs.oldenvs = pkgenvs.oldenvs or os.getenvs() - pkgenvs.newenvs = pkgenvs.newenvs or {} - pkgenvs.newenvs[target] = target:pkgenvs() - local newenvs = pkgenvs.oldenvs - for _, envs in pairs(pkgenvs.newenvs) do - newenvs = os.joinenvs(envs, newenvs) - end - os.setenvs(newenvs) - end - - -- clean target if rebuild - if target:is_rebuilt() and not option.get("dry-run") then - _clean_target(target) - end - - -- do before_build - -- we cannot add batchjobs for this rule scripts, @see https://github.com/xmake-io/xmake/issues/2684 - local progress = opt.progress - local before_build = target:script("build_before") - if before_build then - before_build(target, {progress = progress}) - end - for _, r in ipairs(target:orderules()) do - local before_build = r:script("build_before") - if before_build then - before_build(target, {progress = progress}) - else - local before_buildcmd = r:script("buildcmd_before") - if before_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - before_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) - end - end - end - end, {rootjob = job_build_leaf}) - return job_build_before, job_build, job_build_after -end - --- add batch jobs for the given target and deps -function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, target, jobrefs, jobrefs_before) - local targetjob_ref = jobrefs[target:name()] - if targetjob_ref then - batchjobs:add(targetjob_ref, rootjob) - else - local job_build_before, job_build, job_build_after = _add_batchjobs_for_target(batchjobs, rootjob, target) - if job_build_before and job_build and job_build_after then - jobrefs[target:name()] = job_build_after - jobrefs_before[target:name()] = job_build_before - for _, depname in ipairs(target:get("deps")) do - local dep = project.target(depname, {namespace = target:namespace()}) - local targetjob = job_build - -- @see https://github.com/xmake-io/xmake/discussions/2500 - if dep:policy("build.across_targets_in_parallel") == false then - targetjob = job_build_before - end - _add_batchjobs_for_target_and_deps(batchjobs, targetjob, dep, jobrefs, jobrefs_before) - end - end - end -end - --- get batch jobs -function _get_batchjobs(targets_root, opt) - - -- generate batch jobs for default or all targets - local jobrefs = {} - local jobrefs_before = {} - local batchjobs = jobpool.new() - for _, target in ipairs(targets_root) do - _add_batchjobs_for_target_and_deps(batchjobs, batchjobs:rootjob(), target, jobrefs, jobrefs_before) - end - - -- add fence jobs, @see https://github.com/xmake-io/xmake/issues/5003 - for _, target in ipairs(project.ordertargets()) do - local target_job_before = jobrefs_before[target:name()] - if target_job_before then - for _, dep in ipairs(target:orderdeps()) do - if dep:policy("build.fence") then - local fence_job = jobrefs[dep:name()] - if fence_job then - batchjobs:add(fence_job, target_job_before) - end - end - end - end - end - - return batchjobs +function _build(targets_root, opt) + --[[ + opt = opt or {} + opt.job_kind = "build" + target_utils.runjobs(targets_root, opt)]] end function main(targetnames, opt) @@ -266,24 +44,12 @@ function main(targetnames, opt) local targets_root = target_utils.get_root_targets(targetnames, opt) -- prepare to build - prepare_build(targets_root, opt) - - -- enable distcc? - local distcc - if distcc_build_client.is_connected() then - distcc = distcc_build_client.singleton() - end + _prepare(targets_root, opt) - -- build all jobs - local batchjobs = _get_batchjobs(targets_root, opt) - if batchjobs and batchjobs:size() > 0 then - local curdir = os.curdir() - runjobs("build", batchjobs, {on_exit = function (errors) - import("utils.progress") - if errors and progress.showing_without_scroll() then - print("") - end - end, comax = option.get("jobs") or 1, curdir = curdir, distcc = distcc}) - os.cd(curdir) + -- do build + if project.policy("build.jobgraph") then + _build(targets_root, opt) + else + deprecated_build(targets_root, opt) end end diff --git a/xmake/actions/build/build_files.lua b/xmake/actions/build/build_files.lua index 8d1383cbb..718390e0b 100644 --- a/xmake/actions/build/build_files.lua +++ b/xmake/actions/build/build_files.lua @@ -23,174 +23,28 @@ import("core.base.option") import("core.base.hashset") import("core.project.config") import("core.project.project") -import("private.async.jobpool") -import("async.runjobs") -import("kinds.object") import("target_utils") -import("prepare_files", {alias = "prepare_build_files"}) +import("deprecated.build_files", {alias = "deprecated_build_files"}) --- 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 - --- add batch jobs -function _add_batchjobs(batchjobs, rootjob, target, filepatterns) - local newbatches = {} - local sourcecount = 0 - for rulename, sourcebatch in pairs(target:sourcebatches()) do - local objectfiles = sourcebatch.objectfiles - local dependfiles = sourcebatch.dependfiles - local sourcekind = sourcebatch.sourcekind - for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do - if _match_sourcefiles(sourcefile, filepatterns) then - local newbatch = newbatches[rulename] - if not newbatch then - newbatch = {} - newbatch.sourcekind = sourcekind - newbatch.rulename = rulename - newbatch.sourcefiles = {} - end - table.insert(newbatch.sourcefiles, sourcefile) - if objectfiles then - newbatch.objectfiles = newbatch.objectfiles or {} - table.insert(newbatch.objectfiles, objectfiles[idx]) - end - if dependfiles then - newbatch.dependfiles = newbatch.dependfiles or {} - table.insert(newbatch.dependfiles, dependfiles[idx]) - end - newbatches[rulename] = newbatch - sourcecount = sourcecount + 1 - end - end - end - if sourcecount > 0 then - return object.add_batchjobs_for_sourcefiles(batchjobs, rootjob, target, newbatches) - end -end - --- add batch jobs for the given target -function _add_batchjobs_for_target(batchjobs, rootjob, target, filepatterns) - - -- has been disabled? - if not target:is_enabled() then - return - end - - -- add batch jobs for target - return _add_batchjobs(batchjobs, rootjob, target, filepatterns) -end - --- add batch jobs for the given target and deps -function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, jobrefs, target, filepatterns) - local targetjob_ref = jobrefs[target:name()] - if targetjob_ref then - batchjobs:add(targetjob_ref, rootjob) - else - local targetjob, targetjob_root = _add_batchjobs_for_target(batchjobs, rootjob, target, filepatterns) - if targetjob and targetjob_root then - jobrefs[target:name()] = targetjob_root - if not option.get("shallow") then - for _, depname in ipairs(target:get("deps")) do - _add_batchjobs_for_target_and_deps(batchjobs, targetjob, jobrefs, - project.target(depname, {namespace = target:namespace()}), filepatterns) - end - end - end - end +function _prepare_files(targets_root, opt) end --- get batch jobs -function _get_batchjobs(targets_root, opt) - - -- convert all sourcefiles to lua pattern - local filepatterns = _get_file_patterns(opt.sourcefiles) - - -- generate batch jobs for default or all targets - local jobrefs = {} - local batchjobs = jobpool.new() - for _, target in pairs(targets_root) do - _add_batchjobs_for_target_and_deps(batchjobs, batchjobs:rootjob(), jobrefs, target, filepatterns) - end - return batchjobs -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 = path.pattern(exclude) - 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 +function _build_files(targets_root, opt) end --- the main entry function main(targetnames, opt) -- get root targets local targets_root = target_utils.get_root_targets(targetnames, opt) -- prepare to build files - prepare_build_files(targets_root, opt) + _prepare_files(targets_root, opt) - -- build all jobs - local batchjobs = _get_batchjobs(targets_root, opt) - if batchjobs and batchjobs:size() > 0 then - local curdir = os.curdir() - runjobs("build_files", batchjobs, {comax = option.get("jobs") or 1, curdir = curdir}) - os.cd(curdir) + -- do build files + if project.policy("build.jobgraph") then + _build_files(targets_root, opt) else - wprint("%s not found!", opt.sourcefiles) + deprecated_build_files(targets_root, opt) end end diff --git a/xmake/actions/build/deprecated/.DS_Store b/xmake/actions/build/deprecated/.DS_Store Binary files differnew file mode 100644 index 000000000..a8ae5f9d6 --- /dev/null +++ b/xmake/actions/build/deprecated/.DS_Store diff --git a/xmake/actions/build/deprecated/build.lua b/xmake/actions/build/deprecated/build.lua new file mode 100644 index 000000000..1c8d47a18 --- /dev/null +++ b/xmake/actions/build/deprecated/build.lua @@ -0,0 +1,283 @@ +--!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.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") +import("private.async.jobpool") +import("async.runjobs") +import("private.utils.batchcmds") +import("core.base.hashset") +import("private.service.remote_cache.client", {alias = "remote_cache_client"}) +import("private.service.distcc_build.client", {alias = "distcc_build_client"}) + +-- clean target for rebuilding +function _clean_target(target) + if target:targetfile() then + os.tryrm(target:symbolfile()) + os.tryrm(target:targetfile()) + end +end + +-- add builtin batch jobs +function _add_batchjobs_builtin(batchjobs, rootjob, target) + + -- uses the rules script? + local job, job_leaf + for _, r in irpairs(target:orderules()) do -- reverse rules order for batchjobs:addjob() + local script = r:script("build") + if script then + if r:extraconf("build", "batch") then + job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):on_build(): no returned job!", r:name()) + elseif r:extraconf("build", "jobgraph") then + wprint("rule(%s) with jobgraph found, please enable `build.jobgraph` policy first!", r:name()) + else + job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total, opt) + script(target, {progress = opt.progress}) + end, {rootjob = job or rootjob}) + end + else + local buildcmd = r:script("buildcmd") + if buildcmd then + job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total, opt) + local batchcmds_ = batchcmds.new({target = target}) + buildcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) + end, {rootjob = job or rootjob}) + end + end + end + + -- uses the builtin target script + if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object() or target:is_moduleonly()) then + job, job_leaf = import("kinds." .. target:kind(), {anonymous = true})(batchjobs, rootjob, target) + end + job = job or rootjob + return job, job_leaf or job +end + +-- add batch jobs +function _add_batchjobs(batchjobs, rootjob, target) + + local job, job_leaf + local script = target:script("build") + if not script then + -- do builtin batch jobs + job, job_leaf = _add_batchjobs_builtin(batchjobs, rootjob, target) + elseif target:extraconf("build", "batch") then + -- do custom batch script + -- e.g. + -- target("test") + -- on_build(function (target, batchjobs, opt) + -- return batchjobs:addjob("test", function (idx, total) + -- print("build it") + -- end, {rootjob = opt.rootjob}) + -- end, {batch = true}) + -- + job, job_leaf = assert(script(target, batchjobs, {rootjob = rootjob}), "target(%s):on_build(): no returned job!", target:name()) + else + -- do custom script directly + -- e.g. + -- + -- target("test") + -- on_build(function (target, opt) + -- print("build it") + -- end) + -- + job = batchjobs:addjob(target:name() .. "/build", function (index, total, opt) + script(target, {progress = opt.progress}) + end, {rootjob = rootjob}) + end + return job, job_leaf or job +end + +-- add batch jobs for the given target +function _add_batchjobs_for_target(batchjobs, rootjob, target) + + -- has been disabled? + if not target:is_enabled() then + return + end + + -- add after_build job for target + local pkgenvs = _g.pkgenvs or {} + _g.pkgenvs = pkgenvs + local job_build_after = batchjobs:addjob(target:name() .. "/after_build", function (index, total, opt) + + -- do after_build + local progress = opt.progress + local after_build = target:script("build_after") + if after_build then + after_build(target, {progress = progress}) + end + for _, r in ipairs(target:orderules()) do + local after_build = r:script("build_after") + if after_build then + after_build(target, {progress = progress}) + else + local after_buildcmd = r:script("buildcmd_after") + if after_buildcmd then + local batchcmds_ = batchcmds.new({target = target}) + after_buildcmd(target, batchcmds_, {progress = progress}) + batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) + end + end + end + + -- restore environments + if target:pkgenvs() then + pkgenvs.oldenvs = pkgenvs.oldenvs or os.getenvs() + pkgenvs.newenvs = pkgenvs.newenvs or {} + pkgenvs.newenvs[target] = nil + local newenvs = pkgenvs.oldenvs + for _, envs in pairs(pkgenvs.newenvs) do + newenvs = os.joinenvs(envs, newenvs) + end + os.setenvs(newenvs) + end + + end, {rootjob = rootjob}) + + -- add batch jobs for target, @note only on_build script support batch jobs + local job_build, job_build_leaf = _add_batchjobs(batchjobs, job_build_after, target) + + -- add before_build job for target + local job_build_before = batchjobs:addjob(target:name() .. "/before_build", function (index, total, opt) + + -- enter package environments + -- https://github.com/xmake-io/xmake/issues/4033 + -- + -- maybe mixing envs isn't a great solution, + -- but it's the most efficient compromise compared to setting envs in every on_build_file. + -- + if target:pkgenvs() then + pkgenvs.oldenvs = pkgenvs.oldenvs or os.getenvs() + pkgenvs.newenvs = pkgenvs.newenvs or {} + pkgenvs.newenvs[target] = target:pkgenvs() + local newenvs = pkgenvs.oldenvs + for _, envs in pairs(pkgenvs.newenvs) do + newenvs = os.joinenvs(envs, newenvs) + end + os.setenvs(newenvs) + end + + -- clean target if rebuild + if target:is_rebuilt() and not option.get("dry-run") then + _clean_target(target) + end + + -- do before_build + -- we cannot add batchjobs for this rule scripts, @see https://github.com/xmake-io/xmake/issues/2684 + local progress = opt.progress + local before_build = target:script("build_before") + if before_build then + before_build(target, {progress = progress}) + end + for _, r in ipairs(target:orderules()) do + local before_build = r:script("build_before") + if before_build then + before_build(target, {progress = progress}) + else + local before_buildcmd = r:script("buildcmd_before") + if before_buildcmd then + local batchcmds_ = batchcmds.new({target = target}) + before_buildcmd(target, batchcmds_, {progress = progress}) + batchcmds_:runcmds({changed = target:is_rebuilt(), dryrun = option.get("dry-run")}) + end + end + end + end, {rootjob = job_build_leaf}) + return job_build_before, job_build, job_build_after +end + +-- add batch jobs for the given target and deps +function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, target, jobrefs, jobrefs_before) + local targetjob_ref = jobrefs[target:name()] + if targetjob_ref then + batchjobs:add(targetjob_ref, rootjob) + else + local job_build_before, job_build, job_build_after = _add_batchjobs_for_target(batchjobs, rootjob, target) + if job_build_before and job_build and job_build_after then + jobrefs[target:name()] = job_build_after + jobrefs_before[target:name()] = job_build_before + for _, depname in ipairs(target:get("deps")) do + local dep = project.target(depname, {namespace = target:namespace()}) + local targetjob = job_build + -- @see https://github.com/xmake-io/xmake/discussions/2500 + if dep:policy("build.across_targets_in_parallel") == false then + targetjob = job_build_before + end + _add_batchjobs_for_target_and_deps(batchjobs, targetjob, dep, jobrefs, jobrefs_before) + end + end + end +end + +-- get batch jobs +function _get_batchjobs(targets_root, opt) + + -- generate batch jobs for default or all targets + local jobrefs = {} + local jobrefs_before = {} + local batchjobs = jobpool.new() + for _, target in ipairs(targets_root) do + _add_batchjobs_for_target_and_deps(batchjobs, batchjobs:rootjob(), target, jobrefs, jobrefs_before) + end + + -- add fence jobs, @see https://github.com/xmake-io/xmake/issues/5003 + for _, target in ipairs(project.ordertargets()) do + local target_job_before = jobrefs_before[target:name()] + if target_job_before then + for _, dep in ipairs(target:orderdeps()) do + if dep:policy("build.fence") then + local fence_job = jobrefs[dep:name()] + if fence_job then + batchjobs:add(fence_job, target_job_before) + end + end + end + end + end + + return batchjobs +end + +function main(targets_root, opt) + + -- enable distcc? + local distcc + if distcc_build_client.is_connected() then + distcc = distcc_build_client.singleton() + end + + -- build all jobs + local batchjobs = _get_batchjobs(targets_root, opt) + if batchjobs and batchjobs:size() > 0 then + local curdir = os.curdir() + runjobs("build", batchjobs, {on_exit = function (errors) + import("utils.progress") + if errors and progress.showing_without_scroll() then + print("") + end + end, comax = option.get("jobs") or 1, curdir = curdir, distcc = distcc}) + os.cd(curdir) + end +end diff --git a/xmake/actions/build/deprecated/build_files.lua b/xmake/actions/build/deprecated/build_files.lua new file mode 100644 index 000000000..db58385cb --- /dev/null +++ b/xmake/actions/build/deprecated/build_files.lua @@ -0,0 +1,188 @@ +--!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_files.lua +-- + +-- imports +import("core.base.option") +import("core.base.hashset") +import("core.project.config") +import("core.project.project") +import("private.async.jobpool") +import("async.runjobs") +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 + +-- add batch jobs +function _add_batchjobs(batchjobs, rootjob, target, filepatterns) + local newbatches = {} + local sourcecount = 0 + for rulename, sourcebatch in pairs(target:sourcebatches()) do + local objectfiles = sourcebatch.objectfiles + local dependfiles = sourcebatch.dependfiles + local sourcekind = sourcebatch.sourcekind + for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do + if _match_sourcefiles(sourcefile, filepatterns) then + local newbatch = newbatches[rulename] + if not newbatch then + newbatch = {} + newbatch.sourcekind = sourcekind + newbatch.rulename = rulename + newbatch.sourcefiles = {} + end + table.insert(newbatch.sourcefiles, sourcefile) + if objectfiles then + newbatch.objectfiles = newbatch.objectfiles or {} + table.insert(newbatch.objectfiles, objectfiles[idx]) + end + if dependfiles then + newbatch.dependfiles = newbatch.dependfiles or {} + table.insert(newbatch.dependfiles, dependfiles[idx]) + end + newbatches[rulename] = newbatch + sourcecount = sourcecount + 1 + end + end + end + if sourcecount > 0 then + return object.add_batchjobs_for_sourcefiles(batchjobs, rootjob, target, newbatches) + end +end + +-- add batch jobs for the given target +function _add_batchjobs_for_target(batchjobs, rootjob, target, filepatterns) + + -- has been disabled? + if not target:is_enabled() then + return + end + + -- add batch jobs for target + return _add_batchjobs(batchjobs, rootjob, target, filepatterns) +end + +-- add batch jobs for the given target and deps +function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, jobrefs, target, filepatterns) + local targetjob_ref = jobrefs[target:name()] + if targetjob_ref then + batchjobs:add(targetjob_ref, rootjob) + else + local targetjob, targetjob_root = _add_batchjobs_for_target(batchjobs, rootjob, target, filepatterns) + if targetjob and targetjob_root then + jobrefs[target:name()] = targetjob_root + if not option.get("shallow") then + for _, depname in ipairs(target:get("deps")) do + _add_batchjobs_for_target_and_deps(batchjobs, targetjob, jobrefs, + project.target(depname, {namespace = target:namespace()}), filepatterns) + end + end + end + end +end + +-- get batch jobs +function _get_batchjobs(targets_root, opt) + + -- convert all sourcefiles to lua pattern + local filepatterns = _get_file_patterns(opt.sourcefiles) + + -- generate batch jobs for default or all targets + local jobrefs = {} + local batchjobs = jobpool.new() + for _, target in pairs(targets_root) do + _add_batchjobs_for_target_and_deps(batchjobs, batchjobs:rootjob(), jobrefs, target, filepatterns) + end + return batchjobs +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 = path.pattern(exclude) + 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 + +function main(targets_root, opt) + + -- build all jobs + local batchjobs = _get_batchjobs(targets_root, opt) + if batchjobs and batchjobs:size() > 0 then + local curdir = os.curdir() + runjobs("build_files", batchjobs, {comax = option.get("jobs") or 1, curdir = curdir}) + os.cd(curdir) + else + wprint("%s not found!", opt.sourcefiles) + end +end + + diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/deprecated/kinds/binary.lua index 3f67232f7..3f67232f7 100644 --- a/xmake/actions/build/kinds/binary.lua +++ b/xmake/actions/build/deprecated/kinds/binary.lua diff --git a/xmake/actions/build/kinds/linkdepfiles.lua b/xmake/actions/build/deprecated/kinds/linkdepfiles.lua index f96e532fc..f96e532fc 100644 --- a/xmake/actions/build/kinds/linkdepfiles.lua +++ b/xmake/actions/build/deprecated/kinds/linkdepfiles.lua diff --git a/xmake/actions/build/kinds/moduleonly.lua b/xmake/actions/build/deprecated/kinds/moduleonly.lua index d177b8b97..d177b8b97 100644 --- a/xmake/actions/build/kinds/moduleonly.lua +++ b/xmake/actions/build/deprecated/kinds/moduleonly.lua diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/deprecated/kinds/object.lua index b5359f79e..b5359f79e 100644 --- a/xmake/actions/build/kinds/object.lua +++ b/xmake/actions/build/deprecated/kinds/object.lua diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/deprecated/kinds/shared.lua index cc7aa010c..cc7aa010c 100644 --- a/xmake/actions/build/kinds/shared.lua +++ b/xmake/actions/build/deprecated/kinds/shared.lua diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/deprecated/kinds/static.lua index abb6c5f72..abb6c5f72 100644 --- a/xmake/actions/build/kinds/static.lua +++ b/xmake/actions/build/deprecated/kinds/static.lua diff --git a/xmake/actions/build/prepare.lua b/xmake/actions/build/prepare.lua deleted file mode 100644 index 30207d614..000000000 --- a/xmake/actions/build/prepare.lua +++ /dev/null @@ -1,28 +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 prepare.lua --- - --- imports -import("target_utils") - -function main(targets_root, opt) - opt = opt or {} - opt.job_kind = "prepare" - target_utils.runjobs(targets_root, opt) -end diff --git a/xmake/actions/build/prepare_files.lua b/xmake/actions/build/prepare_files.lua deleted file mode 100644 index 3abb3ef31..000000000 --- a/xmake/actions/build/prepare_files.lua +++ /dev/null @@ -1,26 +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 prepare_files.lua --- - --- imports -import("core.base.option") -import("core.project.config") - -function main(targets_root, opt) -end diff --git a/xmake/actions/build/target_utils.lua b/xmake/actions/build/target_utils.lua index dd6328b23..0c1c64abf 100644 --- a/xmake/actions/build/target_utils.lua +++ b/xmake/actions/build/target_utils.lua @@ -38,7 +38,8 @@ end -- add jobs for the builtin script function _add_jobs_for_builtin_script(jobgraph, target, job_kind) if target:is_static() or target:is_binary() or target:is_shared() or target:is_object() or target:is_moduleonly() then - local script = import("kinds." .. target:kind(), {anonymous = true})[job_kind] + -- TODO + local script = import("deprecated.kinds." .. target:kind(), {anonymous = true})[job_kind] if script then script(jobgraph, target) end @@ -59,7 +60,7 @@ function _add_jobs_for_script(jobgraph, instance, script_name, scriptcmd_name) if instance:extraconf(script_name, "jobgraph") then script(target, jobgraph) elseif instance:extraconf(script_name, "batch") then - wprint("%s.%s: the batch mode is deprecated, please use jobgraph mode instead of it.", instance:fullname(), script_name) + wprint("%s.%s: the batch mode is deprecated, please use jobgraph mode instead of it, or disable `build.jobgraph` policy to use it.", instance:fullname(), script_name) else -- call custom script directly -- e.g. diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index c3754d540..76016e164 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -94,6 +94,8 @@ function policy.policies() ["build.c++.gcc.modules.cxx11abi"] = {description = "Force to enable new cxx11 abi in C++ modules for gcc.", type = "boolean"}, -- Enable cuda device link ["build.cuda.devlink"] = {description = "Enable Cuda devlink.", type = "boolean"}, + -- Enable build jobgraph + ["build.jobgraph"] = {description = "Enable build jobgraph.", default = false, type = "boolean"}, -- Enable windows UAC and set level, e.g. invoker, admin, highest ["windows.manifest.uac"] = {description = "Enable windows manifest UAC.", type = "string"}, -- Enable ui access for windows UAC |
