summaryrefslogtreecommitdiff
path: root/xmake/rules
diff options
context:
space:
mode:
authorruki <[email protected]>2026-04-01 18:02:50 +0800
committerGitHub <[email protected]>2026-04-01 18:02:50 +0800
commit75b084fa57f2fe00f369d9cac3878c03da43a68a (patch)
tree8ea62a9f04b88e9ae72a59a2fd58d1f7b976797e /xmake/rules
parentd7fcddd12197d427ad89d8967515f2e7afd16790 (diff)
parent57ef7e0332355a091abe1ee9eefe2a359aeb6f1a (diff)
Merge pull request #7443 from xmake-io/replace
add utils.replace rules
Diffstat (limited to 'xmake/rules')
-rw-r--r--xmake/rules/utils/replace/xmake.lua111
1 files changed, 111 insertions, 0 deletions
diff --git a/xmake/rules/utils/replace/xmake.lua b/xmake/rules/utils/replace/xmake.lua
new file mode 100644
index 000000000..8b865b750
--- /dev/null
+++ b/xmake/rules/utils/replace/xmake.lua
@@ -0,0 +1,111 @@
+--!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, Xmake Open Source Community.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- @usage
+--
+-- e.g. replace with lua pattern (default)
+--
+-- add_files("src/foo.c", {rules = "utils.replace", replaces = {{"RDKCONST%);", "VDKREG);"}}})
+--
+-- e.g. replace with plain text
+--
+-- add_files("src/foo.c", {rules = "utils.replace", replaces = {{"RDKCONST);", "VDKREG);"}}, replace_plain = true})
+--
+-- e.g. replace with custom function
+--
+-- add_files("src/foo.c", {rules = "utils.replace", replaces = function (content)
+-- content = content:gsub("old", "new")
+-- return content
+-- end})
+--
+rule("utils.replace")
+ on_prepare_file(function (target, sourcefile, opt)
+ import("utils.progress")
+ import("core.base.option")
+ import("core.project.depend")
+
+ -- get replace config from fileconfig
+ local fileconfig = target:fileconfig(sourcefile)
+ if not fileconfig or not fileconfig.replaces then
+ return
+ end
+ local replaces = fileconfig.replaces
+ local use_plain = fileconfig.replace_plain
+
+ -- get the replaced file path
+ local replacefile = target:autogenfile(sourcefile)
+
+ -- add the original source directory as includedir,
+ -- so that relative #include paths still work after replacing
+ local sourcedir = path.directory(path.absolute(sourcefile))
+ target:add("includedirs", sourcedir)
+
+ -- replace the sourcefile in the build sourcebatch,
+ -- so that the compiler uses the replaced file instead of the original
+ for _, sourcebatch in pairs(target:sourcebatches()) do
+ if sourcebatch.rulename ~= "utils.replace" then
+ for i, sf in ipairs(sourcebatch.sourcefiles) do
+ if sf == sourcefile then
+ sourcebatch.sourcefiles[i] = replacefile
+ end
+ end
+ end
+ end
+
+ -- build values list from replace config for change detection
+ local depvalues = {}
+ local is_function = type(replaces) == "function"
+ if not is_function then
+ for _, item in ipairs(replaces) do
+ table.insert(depvalues, item[1])
+ table.insert(depvalues, item[2])
+ end
+ if use_plain then
+ table.insert(depvalues, "plain")
+ end
+ end
+
+ -- do replace if source file or replace config is changed
+ depend.on_changed(function ()
+ progress.show(opt.progress, "${color.build.object}replacing.$(mode) %s", sourcefile)
+ vprint("replace %s to %s", sourcefile, replacefile)
+ local content = io.readfile(sourcefile)
+ if is_function then
+ content = replaces(content)
+ else
+ if option.get("diagnosis") then
+ for _, item in ipairs(replaces) do
+ cprint("${dim} > \"%s\" -> \"%s\"%s", item[1], item[2], use_plain and " (plain)" or "")
+ end
+ end
+ for _, item in ipairs(replaces) do
+ if use_plain then
+ content = content:replace(item[1], item[2], {plain = true})
+ else
+ content = content:gsub(item[1], item[2])
+ end
+ end
+ end
+ io.writefile(replacefile, content)
+ end, {dependfile = target:dependfile(replacefile),
+ files = {sourcefile},
+ values = depvalues,
+ changed = target:is_rebuilt()})
+ end)