diff options
| author | ruki <[email protected]> | 2023-06-18 21:44:52 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2023-06-18 21:45:20 +0800 |
| commit | 4ae1b14bbc7979f2ac4989da0fe29e37547d9d41 (patch) | |
| tree | 764aece01de0d092e56e070477042dca19d14cac | |
| parent | a94427eb73b394a440ea1d291cefaf2fe78bba78 (diff) | |
improve compile_commands generator #3857
| -rw-r--r-- | xmake/plugins/project/clang/compile_commands.lua | 149 |
1 files changed, 44 insertions, 105 deletions
diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 24a580d34..ded2ad3c4 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -26,6 +26,8 @@ import("core.project.project") import("core.language.language") import("private.utils.batchcmds") import("private.utils.executable_path") +import("private.utils.rule_groups") +import("plugins.project.utils.target_cmds", {rootdir = os.programdir()}) -- escape path function _escape_path(p) @@ -165,101 +167,56 @@ function _make_arguments(jsonfile, arguments, sourcefile) map[key] = true end --- make commands for target -function _make_commands_for_targetrules(jsonfile, target, suffix) - for _, ruleinst in ipairs(target:orderules()) do - local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") - local script = ruleinst:script(scriptname) - if script then - local batchcmds_ = batchcmds.new({target = target}) - script(target, batchcmds_, {}) - 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 +-- add target custom commands +function _add_target_custom_commands(jsonfile, target, suffix, cmds) + for _, cmd in ipairs(cmds) do + if cmd.program then + _make_arguments(jsonfile, table.join(cmd.program, cmd.argv)) end end end --- make commands for object rules -function _make_commands_for_objectrules(jsonfile, target, sourcebatch, suffix) - - -- we ignore all built sourcebatches - if _sourcebatch_is_built(sourcebatch) then - return - end - - -- get rule - local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") - local ruleinst = assert(target:rule(rulename) or 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 +-- add target source commands +function _add_target_source_commands(jsonfile, target) + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind and _sourcebatch_is_built(sourcebatch) 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 end end end +-- add target commands +function _add_target_commands(jsonfile, target) + -- build sourcebatch groups first + local sourcegroups = rule_groups.build_sourcebatch_groups(target, target:sourcebatches()) --- make commands for objects -function _make_commands_for_objects(jsonfile, target, sourcebatch) - local sourcekind = sourcebatch.sourcekind - if sourcekind and _sourcebatch_is_built(sourcebatch) 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 + -- add before commands + -- we use irpairs(groups), because the last group that should be given the highest priority. + local cmds_before = {} + target_cmds.get_target_buildcmd(target, cmds_before, "before") + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, "before") + -- rule.on_buildcmd_files should also be executed before building the target, as cmake PRE_BUILD does not work. + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups) + _add_target_custom_commands(jsonfile, target, "before", cmds_before) --- make objects -function _make_objects(jsonfile, target, sourcebatch) - _make_commands_for_targetrules(jsonfile, target, "before") - _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") - _make_commands_for_targetrules(jsonfile, target, "after") + -- add target source commands + _add_target_source_commands(jsonfile, target) + + -- add after commands + local cmds_after = {} + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, "after") + target_cmds.get_target_buildcmd(target, cmds_after, "after") + _add_target_custom_commands(jsonfile, target, "after", cmds_after) end --- make target -function _make_target(jsonfile, target) +-- add target +function _add_target(jsonfile, target) -- https://github.com/xmake-io/xmake/issues/2337 target:data_set("plugin.project.kind", "compile_commands") @@ -274,30 +231,22 @@ function _make_target(jsonfile, target) target:set("pcxxheader", nil) end - -- build source batches - for _, sourcebatch in pairs(target:sourcebatches()) do - _make_objects(jsonfile, target, sourcebatch) - end + -- add target commands + _add_target_commands(jsonfile, target) -- restore package environments os.setenvs(oldenvs) end --- make all -function _make_all(jsonfile) - - -- make header +-- add targets +function _add_targets(jsonfile) jsonfile:print("[") - - -- make commands _g.firstline = true for _, target in pairs(project.targets()) do if not target:is_phony() then - _make_target(jsonfile, target) + _add_target(jsonfile, target) end end - - -- make tailer jsonfile:print("]") end @@ -309,19 +258,9 @@ end -- - http://eli.thegreenplace.net/2014/05/21/compilation-databases-for-clang-based-tools -- function make(outputdir) - - -- enter project directory local oldir = os.cd(os.projectdir()) - - -- open the jsonfile local jsonfile = io.open(path.join(outputdir, "compile_commands.json"), "w") - - -- make all - _make_all(jsonfile) - - -- close the jsonfile + _add_targets(jsonfile) jsonfile:close() - - -- leave project directory os.cd(oldir) end |
