summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-02-20 23:38:39 +0800
committerGitHub <[email protected]>2021-02-20 23:38:39 +0800
commit1180e3decfcbdfb6be8ef9a1567465d489e7f278 (patch)
tree903af9262c58298f0023bf2e17391b61332a8b9a
parentc830852b9acbfa5cc6b14ddb41e6328c63860c2e (diff)
parentb038b2b86af516d3d49d7cc3fd6226ad23944564 (diff)
Merge pull request #1245 from xmake-io/generator
improve rules and generators
-rw-r--r--.gitignore3
-rw-r--r--xmake/actions/build/kinds/object.lua37
-rw-r--r--xmake/core/project/rule.lua9
-rw-r--r--xmake/modules/private/action/require/impl/install_packages.lua2
-rw-r--r--xmake/modules/private/utils/batchcmds.lua343
-rw-r--r--xmake/modules/private/utils/progress.lua10
-rw-r--r--xmake/plugins/project/clang/compile_commands.lua96
-rw-r--r--xmake/rules/lex_yacc/lex/xmake.lua89
-rw-r--r--xmake/rules/lex_yacc/yacc/xmake.lua92
-rw-r--r--xmake/rules/protobuf/proto.lua86
-rw-r--r--xmake/rules/protobuf/xmake.lua17
11 files changed, 535 insertions, 249 deletions
diff --git a/.gitignore b/.gitignore
index 43b458963..1631dd04d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,9 @@ winenv/
*.7z
*.run
+# for compiler
+compile_commands.json
+
# Makefile generation
/core/xmake.config.h
/core/.config.mak
diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua
index baf2d2f11..866c9680c 100644
--- a/xmake/actions/build/kinds/object.lua
+++ b/xmake/actions/build/kinds/object.lua
@@ -24,6 +24,7 @@ import("core.project.rule")
import("core.project.config")
import("core.project.project")
import("private.async.runjobs")
+import("private.utils.batchcmds")
-- add batch jobs for the custom rule
function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix)
@@ -32,7 +33,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!")
local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename)
- -- add batch jobs
+ -- add batch jobs for xx_build_files
local scriptname = "build_files" .. (suffix and ("_" .. suffix) or "")
local script = ruleinst:script(scriptname)
if script then
@@ -43,7 +44,10 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
script(target, sourcebatch, {progress = (index * 100) / total})
end, rootjob)
end
- else
+ end
+
+ -- add batch jobs for xx_build_file
+ if not script then
scriptname = "build_file" .. (suffix and ("_" .. suffix) or "")
script = ruleinst:script(scriptname)
if script then
@@ -55,6 +59,35 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
end
end
end
+
+ -- add batch jobs for xx_buildcmd_files
+ if not script then
+ scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "")
+ script = ruleinst:script(scriptname)
+ if script then
+ batchjobs:addjob("rule/" .. rulename .. "/" .. scriptname, function (index, total)
+ local batchcmds_ = batchcmds.new({target = target})
+ script(target, batchcmds_, sourcebatch, {progress = (index * 100) / total})
+ batchcmds_:runcmds({dryrun = option.get("dry-run")})
+ end, rootjob)
+ end
+ end
+
+ -- add batch jobs for xx_buildcmd_file
+ if not script then
+ scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "")
+ script = ruleinst:script(scriptname)
+ if script then
+ local sourcekind = sourcebatch.sourcekind
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ batchjobs:addjob(sourcefile, function (index, total)
+ local batchcmds_ = batchcmds.new({target = target})
+ script(target, batchcmds_, sourcefile, {sourcekind = sourcekind, progress = (index * 100) / total})
+ batchcmds_:runcmds({dryrun = option.get("dry-run")})
+ end, rootjob)
+ end
+ end
+ end
end
-- add batch jobs for target
diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua
index 53c1a9854..81ef99148 100644
--- a/xmake/core/project/rule.lua
+++ b/xmake/core/project/rule.lua
@@ -173,6 +173,9 @@ function rule.apis()
, "rule.on_package"
, "rule.on_install"
, "rule.on_uninstall"
+ , "rule.on_buildcmd"
+ , "rule.on_buildcmd_file"
+ , "rule.on_buildcmd_files"
-- rule.before_xxx
, "rule.before_run"
, "rule.before_load"
@@ -184,6 +187,9 @@ function rule.apis()
, "rule.before_package"
, "rule.before_install"
, "rule.before_uninstall"
+ , "rule.before_buildcmd"
+ , "rule.before_buildcmd_file"
+ , "rule.before_buildcmd_files"
-- rule.after_xxx
, "rule.after_run"
, "rule.after_load"
@@ -195,6 +201,9 @@ function rule.apis()
, "rule.after_package"
, "rule.after_install"
, "rule.after_uninstall"
+ , "rule.after_buildcmd"
+ , "rule.after_buildcmd_file"
+ , "rule.after_buildcmd_files"
}
}
end
diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua
index aa94e8682..b7adf5400 100644
--- a/xmake/modules/private/action/require/impl/install_packages.lua
+++ b/xmake/modules/private/action/require/impl/install_packages.lua
@@ -422,7 +422,7 @@ function main(requires, opt)
-- fetch and register packages (with system) from local first
runjobs("fetch_packages", function (index)
local instance = packages[index]
- if instance and (not option.get("force") or (option.get("shallow") and instance:is_toplevel())) then
+ if instance and (not option.get("force") or (option.get("shallow") and not instance:is_toplevel())) then
instance:envs_enter()
instance:fetch()
instance:envs_leave()
diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua
new file mode 100644
index 000000000..371735321
--- /dev/null
+++ b/xmake/modules/private/utils/batchcmds.lua
@@ -0,0 +1,343 @@
+--!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 batchcmds.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.object")
+import("core.base.tty")
+import("core.base.colors")
+import("core.project.depend")
+import("core.theme.theme")
+import("core.tool.linker")
+import("core.tool.compiler")
+import("core.language.language")
+import("private.utils.progress", {alias = "progress_utils"})
+
+-- define module
+local batchcmds = batchcmds or object { _init = {"_TARGET", "_CMDS", "_DEPS", "_tip"}}
+
+-- show text
+function _show(showtext, progress)
+ if option.get("verbose") then
+ cprint(showtext)
+ else
+ local is_scroll = _g.is_scroll
+ if is_scroll == nil then
+ is_scroll = theme.get("text.build.progress_style") == "scroll"
+ _g.is_scroll = is_scroll
+ end
+ if is_scroll then
+ cprint(showtext)
+ else
+ tty.erase_line_to_start().cr()
+ local msg = showtext
+ local msg_plain = colors.translate(msg, {plain = true})
+ local maxwidth = os.getwinsize().width
+ if #msg_plain <= maxwidth then
+ cprintf(msg)
+ else
+ -- windows width is too small? strip the partial message in middle
+ local partlen = math.floor(maxwidth / 2) - 3
+ local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1)
+ local split = msg:split(sep, {plain = true, strict = true})
+ cprintf(table.concat(split, "..."))
+ end
+ if math.floor(progress) == 100 then
+ print("")
+ _g.showing_without_scroll = false
+ else
+ _g.showing_without_scroll = true
+ end
+ io.flush()
+ end
+ end
+end
+
+-- run command: show
+function _runcmd_show(cmd, opt)
+ local showtext = cmd.showtext
+ if showtext then
+ _show(showtext, cmd.progress)
+ end
+end
+
+-- run command: os.runv
+function _runcmd_runv(cmd, opt)
+ if cmd.program then
+ if not opt.dryrun then
+ os.runv(cmd.program, cmd.argv, cmd.opt)
+ end
+ end
+end
+
+-- run command: os.vrunv
+function _runcmd_vrunv(cmd, opt)
+ if cmd.program then
+ if opt.dryrun then
+ vprint(os.args(table.join(cmd.program, cmd.argv)))
+ else
+ os.vrunv(cmd.program, cmd.argv, cmd.opt)
+ end
+ end
+end
+
+-- run command: os.execv
+function _runcmd_execv(cmd, opt)
+ if cmd.program then
+ if opt.dryrun then
+ print(os.args(table.join(cmd.program, cmd.argv)))
+ else
+ os.execv(cmd.program, cmd.argv, cmd.opt)
+ end
+ end
+end
+
+-- run command: os.mkdir
+function _runcmd_mkdir(cmd, opt)
+ local dir = cmd.dir
+ if not opt.dryrun and not os.isdir(dir) then
+ os.mkdir(dir)
+ end
+end
+
+-- run command: os.rm
+function _runcmd_rm(cmd, opt)
+ local filepath = cmd.filepath
+ if not opt.dryrun then
+ os.tryrm(filepath)
+ end
+end
+
+-- run command: os.cp
+function _runcmd_cp(cmd, opt)
+ if not opt.dryrun then
+ os.cp(opt.srcpath, opt.dstpath, opt.opt)
+ end
+end
+
+-- run command: os.mv
+function _runcmd_mv(cmd, opt)
+ if not opt.dryrun then
+ os.mv(opt.srcpath, opt.dstpath, opt.opt)
+ end
+end
+
+-- run command: os.ln
+function _runcmd_ln(cmd, opt)
+ if not opt.dryrun then
+ os.ln(opt.srcpath, opt.dstpath, opt.opt)
+ end
+end
+
+-- run command
+function _runcmd(cmd, opt)
+ local kind = cmd.kind
+ local maps = _g.maps
+ if not maps then
+ maps =
+ {
+ show = _runcmd_show,
+ runv = _runcmd_runv,
+ vrunv = _runcmd_vrunv,
+ execv = _runcmd_execv,
+ mkdir = _runcmd_mkdir,
+ rm = _runcmd_rm,
+ cp = _runcmd_cp,
+ mv = _runcmd_mv,
+ ln = _runcmd_ln
+ }
+ _g.maps = maps
+ end
+ local script = maps[kind]
+ if script then
+ script(cmd, opt)
+ end
+end
+
+-- run commands
+function _runcmds(cmds, opt)
+ for _, cmd in ipairs(cmds) do
+ _runcmd(cmd, opt)
+ end
+end
+
+-- is empty? no commands
+function batchcmds:empty()
+ return #self:cmds() == 0
+end
+
+-- get commands
+function batchcmds:cmds()
+ return self._CMDS
+end
+
+-- add command: os.runv
+function batchcmds:runv(program, argv, opt)
+ table.insert(self:cmds(), {kind = "runv", program = program, argv = argv, opt = opt})
+ self:add_depvalues(program, argv)
+end
+
+-- add command: os.vrunv
+function batchcmds:vrunv(program, argv, opt)
+ table.insert(self:cmds(), {kind = "vrunv", program = program, argv = argv, opt = opt})
+ self:add_depvalues(program, argv)
+end
+
+-- add command: os.execv
+function batchcmds:execv(program, argv, opt)
+ table.insert(self:cmds(), {kind = "execv", program = program, argv = argv, opt = opt})
+ self:add_depvalues(program, argv)
+end
+
+-- add command: compiler.compile
+function batchcmds:compile(sourcefiles, objectfile, opt)
+
+ -- bind target if exists
+ opt = opt or {}
+ opt.target = self._TARGET
+
+ -- load compiler and get compilation command
+ local sourcekind = opt.sourcekind
+ if not sourcekind and type(sourcefiles) == "string" then
+ sourcekind = language.sourcekind_of(sourcefiles)
+ end
+ local compiler_inst = compiler.load(sourcekind, opt)
+ local program, argv = compiler_inst:compargv(sourcefiles, objectfile, opt)
+
+ -- add compilation command and bind run environments of compiler
+ self:mkdir(path.directory(objectfile))
+ self:vrunv(program, argv, {envs = table.join(compiler_inst:runenvs(), opt.envs)})
+end
+
+-- add command: linker.link
+function batchcmds:link(objectfiles, targetfile, opt)
+
+ -- bind target if exists
+ local target = self._TARGET
+ opt = opt or {}
+ opt.target = target
+
+ -- load linker and get link command
+ local linker_inst = target and target:linker() or linker.load(opt.targetkind, opt.sourcekinds, opt)
+ local program, argv = linker_inst:linkargv(objectfiles, targetfile, opt)
+
+ -- add link command and bind run environments of linker
+ self:mkdir(path.directory(targetfile))
+ self:vrunv(program, argv, {envs = table.join(linker_inst:runenvs(), opt.envs)})
+end
+
+-- add command: os.mkdir
+function batchcmds:mkdir(dir)
+ table.insert(self:cmds(), {kind = "mkdir", dir = dir})
+end
+
+-- add command: os.rm
+function batchcmds:rm(filepath)
+ table.insert(self:cmds(), {kind = "rm", filepath = filepath})
+end
+
+-- add command: os.cp
+function batchcmds:cp(srcpath, dstpath, opt)
+ table.insert(self:cmds(), {kind = "cp", srcpath = srcpath, dstpath = dstpath, opt = opt})
+end
+
+-- add command: os.mv
+function batchcmds:mv(srcpath, dstpath, opt)
+ table.insert(self:cmds(), {kind = "mv", srcpath = srcpath, dstpath = dstpath, opt = opt})
+end
+
+-- add command: os.ln
+function batchcmds:ln(srcpath, dstpath, opt)
+ table.insert(self:cmds(), {kind = "ln", srcpath = srcpath, dstpath = dstpath, opt = opt})
+end
+
+-- add command: show
+function batchcmds:show(format, ...)
+ local showtext = string.format(format, ...)
+ table.insert(self:cmds(), {kind = "show", showtext = showtext})
+end
+
+-- add command: show progress
+function batchcmds:show_progress(progress, format, ...)
+ if progress then
+ local showtext = progress_utils.text(progress, format, ...)
+ table.insert(self:cmds(), {kind = "show", showtext = showtext, progress = progress})
+ end
+end
+
+-- get deps
+function batchcmds:deps()
+ return self._DEPS
+end
+
+-- add dependent files
+function batchcmds:add_depfiles(...)
+ local deps = self._DEPS or {}
+ deps.files = deps.files or {}
+ table.join2(deps.files, ...)
+ self._DEPS = deps
+end
+
+-- add dependent values
+function batchcmds:add_depvalues(...)
+ local deps = self._DEPS or {}
+ deps.values = deps.values or {}
+ table.join2(deps.values, ...)
+ self._DEPS = deps
+end
+
+-- set the last mtime of dependent files and values
+function batchcmds:set_depmtime(lastmtime)
+ local deps = self._DEPS or {}
+ deps.lastmtime = lastmtime
+ self._DEPS = deps
+end
+
+-- set cache file of depend info
+function batchcmds:set_depcache(cachefile)
+ local deps = self._DEPS or {}
+ deps.dependfile = cachefile
+ self._DEPS = deps
+end
+
+-- run cmds
+function batchcmds:runcmds(opt)
+ opt = opt or {}
+ if self:empty() then
+ return
+ end
+ local deps = self:deps()
+ if deps and deps.files then
+ depend.on_changed(function ()
+ _runcmds(self:cmds(), opt)
+ end, self:deps())
+ else
+ _runcmds(self:cmds(), opt)
+ end
+end
+
+-- new a batch commands for rule/xx_xxcmd_xxx()
+--
+-- @params opt options, e.g. {target = ..}
+--
+function new(opt)
+ opt = opt or {}
+ return batchcmds {_TARGET = opt.target, _CMDS = {}}
+end
diff --git a/xmake/modules/private/utils/progress.lua b/xmake/modules/private/utils/progress.lua
index e00b4ab57..5c08cbf8f 100644
--- a/xmake/modules/private/utils/progress.lua
+++ b/xmake/modules/private/utils/progress.lua
@@ -111,6 +111,16 @@ function show(progress, format, ...)
end
end
+-- get the message text with process
+function text(progress, format, ...)
+ local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
+ if option.get("verbose") then
+ return string.format(progress_prefix .. "${dim}" .. format, progress, ...)
+ else
+ return string.format(progress_prefix .. format, progress, ...)
+ end
+end
+
-- build a progress indicator
-- @params stream - stream to write to, will use io.stdout if not provided
-- @params opt - options
diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua
index ba257bb35..41d83bd57 100644
--- a/xmake/plugins/project/clang/compile_commands.lua
+++ b/xmake/plugins/project/clang/compile_commands.lua
@@ -20,8 +20,10 @@
-- imports
import("core.tool.compiler")
+import("core.project.rule")
import("core.project.project")
import("core.language.language")
+import("private.utils.batchcmds")
-- escape path
function _escape_path(p)
@@ -47,20 +49,23 @@ function _translate_arguments(arguments)
return args
end
--- make the object
-function _make_object(jsonfile, target, sourcefile, objectfile)
+-- make command
+function _make_arguments(jsonfile, arguments, sourcefile)
- -- get the source file kind
- local sourcekind = language.sourcekind_of(sourcefile)
-
- -- make the object for the *.o/obj? ignore it directly
- if sourcekind == "obj" or sourcekind == "lib" then
- return
+ -- attempt to get source file from arguments
+ if not sourcefile then
+ for _, arg in ipairs(arguments) do
+ local sourcekind = try {function () return language.sourcekind_of(path.filename(arg)) end}
+ if sourcekind and os.isfile(arg) then
+ sourcefile = arg
+ break
+ end
+ end
+ if not sourcefile then
+ return
+ end
end
- -- get compile arguments
- local arguments = table.join(compiler.compargv(sourcefile, objectfile, {target = target, sourcekind = sourcekind}))
-
-- translate some unsupported arguments
arguments = _translate_arguments(arguments)
@@ -82,11 +87,69 @@ function _make_object(jsonfile, target, sourcefile, objectfile)
_g.firstline = false
end
+-- make commands for object rules
+function _make_commands_for_objectrules(jsonfile, target, sourcebatch, suffix)
+
+ -- get rule
+ local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!")
+ local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename)
+
+ -- generate commands for xx_buildcmd_files
+ local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "")
+ local script = ruleinst:script(scriptname)
+ if script then
+ local batchcmds_ = batchcmds.new({target = target})
+ script(target, batchcmds_, sourcebatch, {})
+ if not batchcmds_:empty() then
+ for _, cmd in ipairs(batchcmds_:cmds()) do
+ if cmd.program then
+ _make_arguments(jsonfile, table.join(cmd.program, cmd.argv))
+ end
+ end
+ end
+ end
+
+ -- generate commands for xx_buildcmd_file
+ if not script then
+ scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "")
+ script = ruleinst:script(scriptname)
+ if script then
+ local sourcekind = sourcebatch.sourcekind
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local batchcmds_ = batchcmds.new({target = target})
+ script(target, batchcmds_, sourcefile, {})
+ if not batchcmds_:empty() then
+ for _, cmd in ipairs(batchcmds_:cmds()) do
+ if cmd.program then
+ _make_arguments(jsonfile, table.join(cmd.program, cmd.argv))
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+-- make commands for objects
+function _make_commands_for_objects(jsonfile, target, sourcebatch)
+ local sourcekind = sourcebatch.sourcekind
+ if sourcekind then
+ for index, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local objectfile = sourcebatch.objectfiles[index]
+ local arguments = table.join(compiler.compargv(sourcefile, objectfile, {target = target, sourcekind = sourcekind}))
+ _make_arguments(jsonfile, arguments, sourcefile)
+ end
+ return true
+ end
+end
+
-- make objects
-function _make_objects(jsonfile, target, sourcekind, sourcebatch)
- for index, objectfile in ipairs(sourcebatch.objectfiles) do
- _make_object(jsonfile, target, sourcebatch.sourcefiles[index], objectfile)
+function _make_objects(jsonfile, target, sourcebatch)
+ _make_commands_for_objectrules(jsonfile, target, sourcebatch, "before")
+ if not _make_commands_for_objects(jsonfile, target, sourcebatch) then
+ _make_commands_for_objectrules(jsonfile, target, sourcebatch)
end
+ _make_commands_for_objectrules(jsonfile, target, sourcebatch, "after")
end
-- make target
@@ -99,10 +162,7 @@ function _make_target(jsonfile, target)
-- build source batches
for _, sourcebatch in pairs(target:sourcebatches()) do
- local sourcekind = sourcebatch.sourcekind
- if sourcekind then
- _make_objects(jsonfile, target, sourcekind, sourcebatch)
- end
+ _make_objects(jsonfile, target, sourcebatch)
end
end
diff --git a/xmake/rules/lex_yacc/lex/xmake.lua b/xmake/rules/lex_yacc/lex/xmake.lua
index 0e28a2ad7..cbdb766e4 100644
--- a/xmake/rules/lex_yacc/lex/xmake.lua
+++ b/xmake/rules/lex_yacc/lex/xmake.lua
@@ -20,93 +20,32 @@
-- define rule: lex
rule("lex")
-
- -- set extension
set_extensions(".l", ".ll")
-
- -- load lex/flex
- before_load(function (target)
- import("core.project.config")
- import("lib.detect.find_tool")
- local lex = config.get("__lex")
- if not lex then
- lex = find_tool("flex") or find_tool("lex")
- if lex and lex.program then
- config.set("__lex", lex.program)
- cprint("checking for Lex ... ${color.success}%s", lex.program)
- else
- cprint("checking for Lex ... ${color.nothing}${text.nothing}")
- raise("lex/flex not found!")
- end
- end
- end)
-
- -- build lex file
- on_build_file(function (target, sourcefile_lex, opt)
+ on_buildcmd_file(function (target, batchcmds, sourcefile_lex, opt)
-- imports
- import("core.base.option")
- import("core.theme.theme")
- import("core.project.config")
- import("core.project.depend")
- import("core.tool.compiler")
- import("private.utils.progress")
+ import("lib.detect.find_tool")
-- get lex
- local lex = assert(config.get("__lex"), "lex not found!")
-
- -- get extension: .l/.ll
- local extension = path.extension(sourcefile_lex)
+ local lex = assert(find_tool("flex") or find_tool("lex"), "lex not found!")
-- get c/c++ source file for lex
+ local extension = path.extension(sourcefile_lex)
local sourcefile_cx = path.join(target:autogendir(), "rules", "lex_yacc", path.basename(sourcefile_lex) .. (extension == ".ll" and ".cpp" or ".c"))
- local sourcefile_dir = path.directory(sourcefile_cx)
-
- -- get object file
- local objectfile = target:objectfile(sourcefile_cx)
-
- -- load compiler
- local compinst = compiler.load((extension == ".ll" and "cxx" or "cc"), {target = target})
-
- -- get compile flags
- local compflags = compinst:compflags({target = target, sourcefile = sourcefile_cx})
-- add objectfile
+ local objectfile = target:objectfile(sourcefile_cx)
table.insert(target:objectfiles(), objectfile)
- -- load dependent info
- local dependfile = target:dependfile(objectfile)
- local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
-
- -- need build this object?
- local depvalues = {compinst:program(), compflags}
- if not depend.is_changed(dependinfo, {lastmtime = os.mtime(objectfile), values = depvalues}) then
- return
- end
-
- -- trace progress info
- progress.show(opt.progress, "${color.build.object}compiling.lex %s", sourcefile_lex)
-
- -- ensure the source file directory
- if not os.isdir(sourcefile_dir) then
- os.mkdir(sourcefile_dir)
- end
-
- -- compile lex
- os.vrunv(lex, {"-o", sourcefile_cx, sourcefile_lex})
-
- -- trace
- if option.get("verbose") then
- print(compinst:compcmd(sourcefile_cx, objectfile, {compflags = compflags}))
- end
-
- -- compile c/c++ source file for lex
- dependinfo.files = {}
- assert(compinst:compile(sourcefile_cx, objectfile, {dependinfo = dependinfo, compflags = compflags}))
+ -- add commands
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.lex %s", sourcefile_lex)
+ batchcmds:mkdir(path.directory(sourcefile_cx))
+ batchcmds:vrunv(lex.program, {"-o", sourcefile_cx, sourcefile_lex})
+ batchcmds:compile(sourcefile_cx, objectfile)
- -- update files and values to the dependent file
- dependinfo.values = depvalues
- table.insert(dependinfo.files, sourcefile_lex)
- depend.save(dependinfo, dependfile)
+ -- add deps
+ batchcmds:add_depfiles(sourcefile_lex)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
end)
diff --git a/xmake/rules/lex_yacc/yacc/xmake.lua b/xmake/rules/lex_yacc/yacc/xmake.lua
index a93f458c0..f93db2ccb 100644
--- a/xmake/rules/lex_yacc/yacc/xmake.lua
+++ b/xmake/rules/lex_yacc/yacc/xmake.lua
@@ -20,96 +20,36 @@
-- define rule: yacc
rule("yacc")
-
- -- set extension
set_extensions(".y", ".yy")
-
- -- load yacc/bison
- before_load(function (target)
- import("core.project.config")
- import("lib.detect.find_tool")
- local yacc = config.get("__yacc")
- if not yacc then
- yacc = find_tool("bison") or find_tool("yacc")
- if yacc and yacc.program then
- config.set("__yacc", yacc.program)
- cprint("checking for Yacc ... ${color.success}%s", yacc.program)
- else
- cprint("checking for Yacc ... ${color.nothing}${text.nothing}")
- raise("yacc/bison not found!")
- end
- end
- end)
-
- -- build yacc file
- before_build_file(function (target, sourcefile_yacc, opt)
+ before_buildcmd_file(function (target, batchcmds, sourcefile_yacc, opt)
-- imports
- import("core.base.option")
- import("core.theme.theme")
- import("core.project.config")
- import("core.project.depend")
- import("core.tool.compiler")
- import("private.utils.progress")
+ import("lib.detect.find_tool")
-- get yacc
- local yacc = assert(config.get("__yacc"), "yacc not found!")
-
- -- get extension: .l/.ll
- local extension = path.extension(sourcefile_yacc)
+ local yacc = assert(find_tool("bison") or find_tool("yacc"), "yacc/bison not found!")
-- get c/c++ source file for yacc
- local sourcefile_cx = path.join(target:autogendir(), "rules", "lex_yacc", path.basename(sourcefile_yacc) .. ".tab" .. (extension == ".yy" and ".cpp" or ".c"))
- local sourcefile_dir = path.directory(sourcefile_cx)
-
- -- get object file
- local objectfile = target:objectfile(sourcefile_cx)
-
- -- load compiler
- local compinst = compiler.load((extension == ".yy" and "cxx" or "cc"), {target = target})
-
- -- get compile flags
- local compflags = compinst:compflags({target = target, sourcefile = sourcefile_cx})
+ local extension = path.extension(sourcefile_yacc)
+ local sourcefile_cx = path.join(target:autogendir(), "rules", "yacc_yacc", path.basename(sourcefile_yacc) .. ".tab" .. (extension == ".yy" and ".cpp" or ".c"))
-- add objectfile
+ local objectfile = target:objectfile(sourcefile_cx)
table.insert(target:objectfiles(), objectfile)
-- add includedirs
+ local sourcefile_dir = path.directory(sourcefile_cx)
target:add("includedirs", sourcefile_dir)
- -- load dependent info
- local dependfile = target:dependfile(objectfile)
- local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
-
- -- need build this object?
- local depvalues = {compinst:program(), compflags}
- if not depend.is_changed(dependinfo, {lastmtime = os.mtime(objectfile), values = depvalues}) then
- return
- end
-
- -- trace progress info
- progress.show(opt.progress, "${color.build.object}compiling.yacc %s", sourcefile_yacc)
-
- -- ensure the source file directory
- if not os.isdir(sourcefile_dir) then
- os.mkdir(sourcefile_dir)
- end
-
- -- compile yacc
- os.vrunv(yacc, {"-d", "-o", sourcefile_cx, sourcefile_yacc})
-
- -- trace
- if option.get("verbose") then
- print(compinst:compcmd(sourcefile_cx, objectfile, {compflags = compflags}))
- end
-
- -- compile c/c++ source file for yacc
- dependinfo.files = {}
- assert(compinst:compile(sourcefile_cx, objectfile, {dependinfo = dependinfo, compflags = compflags}))
+ -- add commands
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.yacc %s", sourcefile_yacc)
+ batchcmds:mkdir(sourcefile_dir)
+ batchcmds:vrunv(yacc.program, {"-d", "-o", sourcefile_cx, sourcefile_yacc})
+ batchcmds:compile(sourcefile_cx, objectfile)
- -- update files and values to the dependent file
- dependinfo.values = depvalues
- table.insert(dependinfo.files, sourcefile_yacc)
- depend.save(dependinfo, dependfile)
+ -- add deps
+ batchcmds:add_depfiles(sourcefile_yacc)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
end)
diff --git a/xmake/rules/protobuf/proto.lua b/xmake/rules/protobuf/proto.lua
index f899e91c5..7a29d8b4a 100644
--- a/xmake/rules/protobuf/proto.lua
+++ b/xmake/rules/protobuf/proto.lua
@@ -19,16 +19,10 @@
--
-- imports
-import("core.base.option")
-import("core.theme.theme")
-import("core.project.config")
-import("core.project.depend")
-import("core.tool.compiler")
import("lib.detect.find_tool")
-import("private.utils.progress")
--- build protobuf file
-function main(target, sourcekind, sourcefile_proto, opt)
+-- get protoc
+function _get_protoc(target, sourcekind)
-- find protoc
local protoc = target:data("protobuf.protoc")
@@ -49,7 +43,14 @@ function main(target, sourcekind, sourcefile_proto, opt)
end
-- get protoc
- protoc = assert(target:data(sourcekind == "cxx" and "protobuf.protoc" or "protobuf.protoc-c"), "protoc not found!")
+ return assert(target:data(sourcekind == "cxx" and "protobuf.protoc" or "protobuf.protoc-c"), "protoc not found!")
+end
+
+-- generate build commands
+function buildcmd(target, batchcmds, sourcefile_proto, opt, sourcekind)
+
+ -- get protoc
+ local protoc = _get_protoc(target, sourcekind)
-- get c/c++ source file for protobuf
local prefixdir
@@ -65,64 +66,21 @@ function main(target, sourcekind, sourcefile_proto, opt)
-- add includedirs
target:add("includedirs", sourcefile_dir)
- -- get object file
- local objectfile = target:objectfile(sourcefile_cx)
-
- -- load compiler
- local compinst = compiler.load(sourcekind, {target = target})
-
- -- get compile flags
- local configs = {includedirs = sourcefile_dir}
- if sourcekind == "cxx" then
- configs.languages = "c++11"
- end
- local compflags = compinst:compflags({target = target, sourcefile = sourcefile_cx, configs = configs})
-
-- add objectfile
+ local objectfile = target:objectfile(sourcefile_cx)
table.insert(target:objectfiles(), objectfile)
- -- load dependent info
- local dependfile = target:dependfile(objectfile)
- local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
-
- -- need build this object?
- local depvalues = {compinst:program(), compflags}
- if not depend.is_changed(dependinfo, {lastmtime = os.mtime(objectfile), values = depvalues}) then
- return
- end
-
- -- trace progress info
- progress.show(opt.progress, "${color.build.object}compiling.proto %s", sourcefile_proto)
-
- -- ensure the source file directory
- if not os.isdir(sourcefile_dir) then
- os.mkdir(sourcefile_dir)
- end
-
- -- get compilation flags
- local argv = {sourcefile_proto}
- if prefixdir then
- table.insert(argv, "-I" .. prefixdir)
- else
- table.insert(argv, "-I" .. path.directory(sourcefile_proto))
- end
- table.insert(argv, (sourcekind == "cxx" and "--cpp_out=" or "--c_out=") .. sourcefile_dir)
-
- -- do compile
- os.vrunv(protoc, argv)
-
- -- trace
- if option.get("verbose") then
- print(compinst:compcmd(sourcefile_cx, objectfile, {compflags = compflags}))
- end
-
- -- compile c/c++ source file for protobuf
- dependinfo.files = {}
- assert(compinst:compile(sourcefile_cx, objectfile, {dependinfo = dependinfo, compflags = compflags}))
+ -- add commands
+ batchcmds:mkdir(sourcefile_dir)
+ batchcmds:show_progress(opt.progress, "${color.build.object}compiling.proto %s", sourcefile_proto)
+ batchcmds:vrunv(protoc, {sourcefile_proto,
+ "-I" .. (prefixdir and prefixdir or path.directory(sourcefile_proto)),
+ (sourcekind == "cxx" and "--cpp_out=" or "--c_out=") .. sourcefile_dir})
+ batchcmds:compile(sourcefile_cx, objectfile, {configs = {includedirs = sourcefile_dir, languages = (sourcekind == "cxx" and "c++11")}})
- -- update files and values to the dependent file
- dependinfo.values = depvalues
- table.insert(dependinfo.files, sourcefile_proto)
- depend.save(dependinfo, dependfile)
+ -- add deps
+ batchcmds:add_depfiles(sourcefile_proto)
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
end
diff --git a/xmake/rules/protobuf/xmake.lua b/xmake/rules/protobuf/xmake.lua
index 1abaa2447..e28a9cbb6 100644
--- a/xmake/rules/protobuf/xmake.lua
+++ b/xmake/rules/protobuf/xmake.lua
@@ -20,23 +20,14 @@
-- define rule: protobuf.cpp
rule("protobuf.cpp")
-
- -- set extension
set_extensions(".proto")
-
- -- build protobuf file
- before_build_file(function (target, sourcefile_proto, opt)
- import("proto")(target, "cxx", sourcefile_proto, opt)
+ before_buildcmd_file(function (target, batchcmds, sourcefile_proto, opt)
+ return import("proto").buildcmd(target, batchcmds, sourcefile_proto, opt, "cxx")
end)
-
-- define rule: protobuf.c
rule("protobuf.c")
-
- -- set extension
set_extensions(".proto")
-
- -- build protobuf file
- before_build_file(function (target, sourcefile_proto, opt)
- import("proto")(target, "cc", sourcefile_proto, opt)
+ before_buildcmd_file(function (target, batchcmds, sourcefile_proto, opt)
+ return import("proto").buildcmd(target, batchcmds, sourcefile_proto, opt, "cc")
end)