diff options
| author | ruki <[email protected]> | 2021-02-20 23:38:39 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-02-20 23:38:39 +0800 |
| commit | 1180e3decfcbdfb6be8ef9a1567465d489e7f278 (patch) | |
| tree | 903af9262c58298f0023bf2e17391b61332a8b9a | |
| parent | c830852b9acbfa5cc6b14ddb41e6328c63860c2e (diff) | |
| parent | b038b2b86af516d3d49d7cc3fd6226ad23944564 (diff) | |
Merge pull request #1245 from xmake-io/generator
improve rules and generators
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | xmake/actions/build/kinds/object.lua | 37 | ||||
| -rw-r--r-- | xmake/core/project/rule.lua | 9 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/install_packages.lua | 2 | ||||
| -rw-r--r-- | xmake/modules/private/utils/batchcmds.lua | 343 | ||||
| -rw-r--r-- | xmake/modules/private/utils/progress.lua | 10 | ||||
| -rw-r--r-- | xmake/plugins/project/clang/compile_commands.lua | 96 | ||||
| -rw-r--r-- | xmake/rules/lex_yacc/lex/xmake.lua | 89 | ||||
| -rw-r--r-- | xmake/rules/lex_yacc/yacc/xmake.lua | 92 | ||||
| -rw-r--r-- | xmake/rules/protobuf/proto.lua | 86 | ||||
| -rw-r--r-- | xmake/rules/protobuf/xmake.lua | 17 |
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) |
