summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-03-28 00:37:04 +0800
committerruki <[email protected]>2025-04-08 15:31:56 +0800
commit7e60e473a3d92d0706a4856c12f161c4d2df32a9 (patch)
treeb021e66c41b2494a237c7ae5dddc2a22335ae0f3
parent6582a3e7eb62f1c6ad4a8263bd14579e7a25c092 (diff)
mark as jobbatch as deprecated
-rw-r--r--xmake/actions/build/.DS_Storebin0 -> 6148 bytes
-rw-r--r--xmake/actions/build/build.lua266
-rw-r--r--xmake/actions/build/build_files.lua162
-rw-r--r--xmake/actions/build/deprecated/.DS_Storebin0 -> 6148 bytes
-rw-r--r--xmake/actions/build/deprecated/build.lua283
-rw-r--r--xmake/actions/build/deprecated/build_files.lua188
-rw-r--r--xmake/actions/build/deprecated/kinds/binary.lua (renamed from xmake/actions/build/kinds/binary.lua)0
-rw-r--r--xmake/actions/build/deprecated/kinds/linkdepfiles.lua (renamed from xmake/actions/build/kinds/linkdepfiles.lua)0
-rw-r--r--xmake/actions/build/deprecated/kinds/moduleonly.lua (renamed from xmake/actions/build/kinds/moduleonly.lua)0
-rw-r--r--xmake/actions/build/deprecated/kinds/object.lua (renamed from xmake/actions/build/kinds/object.lua)0
-rw-r--r--xmake/actions/build/deprecated/kinds/shared.lua (renamed from xmake/actions/build/kinds/shared.lua)0
-rw-r--r--xmake/actions/build/deprecated/kinds/static.lua (renamed from xmake/actions/build/kinds/static.lua)0
-rw-r--r--xmake/actions/build/prepare.lua28
-rw-r--r--xmake/actions/build/prepare_files.lua26
-rw-r--r--xmake/actions/build/target_utils.lua5
-rw-r--r--xmake/core/project/policy.lua2
16 files changed, 500 insertions, 460 deletions
diff --git a/xmake/actions/build/.DS_Store b/xmake/actions/build/.DS_Store
new file mode 100644
index 000000000..b82482eba
--- /dev/null
+++ b/xmake/actions/build/.DS_Store
Binary files differ
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
new file mode 100644
index 000000000..a8ae5f9d6
--- /dev/null
+++ b/xmake/actions/build/deprecated/.DS_Store
Binary files differ
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