summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-07-18 18:37:41 +0800
committerGitHub <[email protected]>2026-07-18 18:37:41 +0800
commit108eaa6d115e03f44bd1f105328dbe90a7747b30 (patch)
tree8f98ca03c2355a6f4acc934e0924324e3dd4a73a
parentc4f4ad6aec62c15fdff13721716a577690e0db81 (diff)
parentc48de38142edcb99b47bf72b0b54fe025f112fdf (diff)
Merge pull request #7654 from xmake-io/bin2obj
Add transform support for bin2obj/bin2c
-rw-r--r--core/src/xmake/engine_pool.c21
-rw-r--r--tests/projects/other/bin2c/src/asset.bin1
-rw-r--r--tests/projects/other/bin2c/src/asset2.bin1
-rw-r--r--tests/projects/other/bin2c/src/main.c29
-rw-r--r--tests/projects/other/bin2c/test.lua2
-rw-r--r--tests/projects/other/bin2c/transform.lua5
-rw-r--r--tests/projects/other/bin2c/xmake.lua10
-rw-r--r--tests/projects/other/bin2obj/src/asset.bin1
-rw-r--r--tests/projects/other/bin2obj/src/asset2.bin1
-rw-r--r--tests/projects/other/bin2obj/src/main.c50
-rw-r--r--tests/projects/other/bin2obj/test.lua2
-rw-r--r--tests/projects/other/bin2obj/transform.lua5
-rw-r--r--tests/projects/other/bin2obj/xmake.lua8
-rw-r--r--xmake/core/base/task.lua6
-rw-r--r--xmake/core/base/thread.lua2
-rw-r--r--xmake/core/language/language.lua2
-rw-r--r--xmake/core/package/component.lua2
-rw-r--r--xmake/core/platform/platform.lua2
-rw-r--r--xmake/core/project/option.lua10
-rw-r--r--xmake/core/project/target.lua6
-rw-r--r--xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua13
-rw-r--r--xmake/core/sandbox/modules/import/core/tool/compiler.lua4
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_directory.lua2
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_file.lua2
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_path.lua2
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_program.lua4
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_programver.lua4
-rw-r--r--xmake/core/sandbox/sandbox.lua95
-rw-r--r--xmake/core/tool/compiler.lua4
-rw-r--r--xmake/core/tool/linker.lua2
-rw-r--r--xmake/core/tool/tool.lua6
-rw-r--r--xmake/core/tool/toolchain.lua4
-rw-r--r--xmake/modules/private/utils/batchcmds.lua30
-rw-r--r--xmake/plugins/project/utils/target_cmds.lua3
-rw-r--r--xmake/rules/utils/bin2c/utils.lua12
-rw-r--r--xmake/rules/utils/bin2c/xmake.lua2
-rw-r--r--xmake/rules/utils/bin2obj/utils.lua14
-rw-r--r--xmake/rules/utils/bin2obj/xmake.lua6
38 files changed, 273 insertions, 102 deletions
diff --git a/core/src/xmake/engine_pool.c b/core/src/xmake/engine_pool.c
index 39bdb1339..b9df842eb 100644
--- a/core/src/xmake/engine_pool.c
+++ b/core/src/xmake/engine_pool.c
@@ -43,6 +43,18 @@
#define XM_ENGINE_POOL (TB_SINGLETON_TYPE_USER + 4)
/* //////////////////////////////////////////////////////////////////////////////////////
+ * globals
+ */
+
+/* the engine pool lock
+ *
+ * the pool is a singleton shared by all worker threads, which may alloc/free engines
+ * concurrently (e.g. parallel batchcmds:lua/vlua jobs run in native threads), so we must
+ * protect the underlying list against data races, otherwise it will be corrupted and crash.
+ */
+static tb_spinlock_t g_engine_pool_lock = TB_SPINLOCK_INIT;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_handle_t xm_engine_pool_instance_init(tb_cpointer_t *ppriv) {
@@ -83,17 +95,22 @@ tb_void_t xm_engine_pool_exit(xm_engine_pool_ref_t engine_pool) {
xm_engine_ref_t xm_engine_pool_alloc(xm_engine_pool_ref_t engine_pool) {
xm_engine_ref_t engine = tb_null;
+ tb_spinlock_enter(&g_engine_pool_lock);
if (tb_single_list_size(engine_pool) > 0) {
engine = (xm_engine_ref_t)tb_single_list_head(engine_pool);
tb_single_list_remove_head(engine_pool);
}
+ tb_spinlock_leave(&g_engine_pool_lock);
return engine;
}
tb_bool_t xm_engine_pool_free(xm_engine_pool_ref_t engine_pool, xm_engine_ref_t engine) {
+ tb_bool_t ok = tb_false;
+ tb_spinlock_enter(&g_engine_pool_lock);
if (tb_single_list_size(engine_pool) < XM_ENGINE_POOL_MAXN) {
tb_single_list_insert_tail(engine_pool, engine);
- return tb_true;
+ ok = tb_true;
}
- return tb_false;
+ tb_spinlock_leave(&g_engine_pool_lock);
+ return ok;
}
diff --git a/tests/projects/other/bin2c/src/asset.bin b/tests/projects/other/bin2c/src/asset.bin
new file mode 100644
index 000000000..db1331f22
--- /dev/null
+++ b/tests/projects/other/bin2c/src/asset.bin
@@ -0,0 +1 @@
+hello transform! \ No newline at end of file
diff --git a/tests/projects/other/bin2c/src/asset2.bin b/tests/projects/other/bin2c/src/asset2.bin
new file mode 100644
index 000000000..d7ffc4b96
--- /dev/null
+++ b/tests/projects/other/bin2c/src/asset2.bin
@@ -0,0 +1 @@
+hello luafile! \ No newline at end of file
diff --git a/tests/projects/other/bin2c/src/main.c b/tests/projects/other/bin2c/src/main.c
index 74898132c..d85e9934e 100644
--- a/tests/projects/other/bin2c/src/main.c
+++ b/tests/projects/other/bin2c/src/main.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
+#include <string.h>
static unsigned char g_bin_data[] = {
#include "data.bin.h"
@@ -10,6 +11,14 @@ static unsigned char g_ico_data[] = {
#include "xmake.ico.h"
};
+static unsigned char g_asset_data[] = {
+ #include "asset.bin.h"
+};
+
+static unsigned char g_asset2_data[] = {
+ #include "asset2.bin.h"
+};
+
static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
printf("%s: size: %u bytes\n", name, (unsigned int)size);
if (size == 0) {
@@ -94,5 +103,25 @@ int main(int argc, char** argv)
hexdump("data.bin", g_bin_data, (uint32_t)sizeof(g_bin_data));
printf("\n");
hexdump("xmake.ico", g_ico_data, (uint32_t)sizeof(g_ico_data));
+ printf("\n");
+ hexdump("asset.bin (transformed)", g_asset_data, (uint32_t)sizeof(g_asset_data));
+ printf("\n");
+ hexdump("asset2.bin (transformed by lua file)", g_asset2_data, (uint32_t)sizeof(g_asset2_data));
+
+ // verify the function transform: asset.bin must be the reverse of "hello transform!" (+ zeroend '\0')
+ const char* expected = "!mrofsnart olleh";
+ if (sizeof(g_asset_data) != 17 || memcmp(g_asset_data, expected, 16) != 0) {
+ printf("asset.bin: transform verification failed!\n");
+ return 1;
+ }
+ printf("asset.bin: transform verification ok\n");
+
+ // verify the lua-file transform: asset2.bin must be the reverse of "hello luafile!" (+ zeroend '\0')
+ const char* expected2 = "!elifaul olleh";
+ if (sizeof(g_asset2_data) != 15 || memcmp(g_asset2_data, expected2, 14) != 0) {
+ printf("asset2.bin: transform verification failed!\n");
+ return 1;
+ }
+ printf("asset2.bin: transform verification ok\n");
return 0;
}
diff --git a/tests/projects/other/bin2c/test.lua b/tests/projects/other/bin2c/test.lua
index b57362078..a23bb98a3 100644
--- a/tests/projects/other/bin2c/test.lua
+++ b/tests/projects/other/bin2c/test.lua
@@ -1,3 +1,5 @@
function main(t)
t:build()
+ -- run the target, main.c verifies the transformed asset.bin and exits non-zero on mismatch
+ os.exec("xmake run test")
end
diff --git a/tests/projects/other/bin2c/transform.lua b/tests/projects/other/bin2c/transform.lua
new file mode 100644
index 000000000..54cf1f394
--- /dev/null
+++ b/tests/projects/other/bin2c/transform.lua
@@ -0,0 +1,5 @@
+function main(inputfile, outputfile)
+ import("core.base.bytes")
+ local data = io.readfile(inputfile, {encoding = "binary"})
+ io.writefile(outputfile, data:reverse(), {encoding = "binary"})
+end
diff --git a/tests/projects/other/bin2c/xmake.lua b/tests/projects/other/bin2c/xmake.lua
index b00dedb65..d60aea710 100644
--- a/tests/projects/other/bin2c/xmake.lua
+++ b/tests/projects/other/bin2c/xmake.lua
@@ -4,7 +4,15 @@ target("test")
set_kind("binary")
add_rules("utils.bin2c", {linewidth = 16, extensions = {".bin", ".ico"}})
add_files("src/*.c")
- add_files("src/*.bin")
+ add_files("src/data.bin")
add_files("src/xmake.ico", {nozeroend = true})
+ add_files("src/asset.bin", {transform = function (inputfile, outputfile, opt)
+ import("core.base.bytes")
+ assert(bytes and opt.target)
+ local data = io.readfile(inputfile, {encoding = "binary"})
+ io.writefile(outputfile, data:reverse(), {encoding = "binary"})
+ end})
+ -- transform can also be a lua script file (supported by the project generators)
+ add_files("src/asset2.bin", {transform = path.join(os.projectdir(), "transform.lua")})
diff --git a/tests/projects/other/bin2obj/src/asset.bin b/tests/projects/other/bin2obj/src/asset.bin
new file mode 100644
index 000000000..db1331f22
--- /dev/null
+++ b/tests/projects/other/bin2obj/src/asset.bin
@@ -0,0 +1 @@
+hello transform! \ No newline at end of file
diff --git a/tests/projects/other/bin2obj/src/asset2.bin b/tests/projects/other/bin2obj/src/asset2.bin
new file mode 100644
index 000000000..d7ffc4b96
--- /dev/null
+++ b/tests/projects/other/bin2obj/src/asset2.bin
@@ -0,0 +1 @@
+hello luafile! \ No newline at end of file
diff --git a/tests/projects/other/bin2obj/src/main.c b/tests/projects/other/bin2obj/src/main.c
index bc1d2442f..03c50352d 100644
--- a/tests/projects/other/bin2obj/src/main.c
+++ b/tests/projects/other/bin2obj/src/main.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
+#include <string.h>
extern const uint8_t _binary_data_bin_start[];
extern const uint8_t _binary_data_bin_end[];
@@ -8,30 +9,39 @@ extern const uint8_t _binary_data_bin_end[];
extern const uint8_t _binary_xmake_ico_start[];
extern const uint8_t _binary_xmake_ico_end[];
+extern const uint8_t _binary_asset_bin_start[];
+extern const uint8_t _binary_asset_bin_end[];
+
+extern const uint8_t _binary_asset2_bin_start[];
+extern const uint8_t _binary_asset2_bin_end[];
+
+extern const uint8_t _binary_asset2_bin_start[];
+extern const uint8_t _binary_asset2_bin_end[];
+
static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
printf("%s: size: %u bytes\n", name, (unsigned int)size);
if (size == 0) {
return;
}
-
+
// if file is larger than 128 bytes, only dump first 64 and last 64 bytes
uint32_t dump_size = size;
uint32_t start_offset = 0;
uint32_t end_offset = 0;
uint32_t skip_size = 0;
-
+
if (size > 128) {
dump_size = 64;
start_offset = 0;
end_offset = size - 64;
skip_size = end_offset - start_offset - dump_size;
}
-
+
// dump start
for (uint32_t offset = start_offset; offset < start_offset + dump_size; offset += 16) {
// print offset
printf("%08x ", (unsigned int)offset);
-
+
// print hex bytes (8 bytes, space, 8 bytes)
for (uint32_t i = 0; i < 16; i++) {
if (offset + i < size) {
@@ -43,7 +53,7 @@ static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
printf(" ");
}
}
-
+
// print ASCII representation
printf(" |");
for (uint32_t i = 0; i < 16 && offset + i < size; i++) {
@@ -52,18 +62,18 @@ static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
}
printf("|\n");
}
-
+
// print skip indicator if needed
if (skip_size > 0) {
printf(" ... (skipped %u bytes) ...\n", (unsigned int)skip_size);
}
-
+
// dump end if needed
if (size > 128) {
for (uint32_t offset = end_offset; offset < size; offset += 16) {
// print offset
printf("%08x ", (unsigned int)offset);
-
+
// print hex bytes (8 bytes, space, 8 bytes)
for (uint32_t i = 0; i < 16; i++) {
if (offset + i < size) {
@@ -75,7 +85,7 @@ static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
printf(" ");
}
}
-
+
// print ASCII representation
printf(" |");
for (uint32_t i = 0; i < 16 && offset + i < size; i++) {
@@ -90,9 +100,31 @@ static void hexdump(const char* name, const uint8_t* data, uint32_t size) {
int main(int argc, char** argv) {
const uint32_t _binary_data_bin_size = (uint32_t)(_binary_data_bin_end - _binary_data_bin_start);
const uint32_t _binary_xmake_ico_size = (uint32_t)(_binary_xmake_ico_end - _binary_xmake_ico_start);
+ const uint32_t _binary_asset_bin_size = (uint32_t)(_binary_asset_bin_end - _binary_asset_bin_start);
+ const uint32_t _binary_asset2_bin_size = (uint32_t)(_binary_asset2_bin_end - _binary_asset2_bin_start);
hexdump("data.bin", _binary_data_bin_start, _binary_data_bin_size);
printf("\n");
hexdump("xmake.ico", _binary_xmake_ico_start, _binary_xmake_ico_size);
+ printf("\n");
+ hexdump("asset.bin (transformed)", _binary_asset_bin_start, _binary_asset_bin_size);
+ printf("\n");
+ hexdump("asset2.bin (transformed by lua file)", _binary_asset2_bin_start, _binary_asset2_bin_size);
+
+ // verify the function transform: asset.bin must be the reverse of "hello transform!" (+ zeroend '\0')
+ const char* expected = "!mrofsnart olleh";
+ if (_binary_asset_bin_size != 17 || memcmp(_binary_asset_bin_start, expected, 16) != 0) {
+ printf("asset.bin: transform verification failed!\n");
+ return 1;
+ }
+ printf("asset.bin: transform verification ok\n");
+
+ // verify the lua-file transform: asset2.bin must be the reverse of "hello luafile!" (+ zeroend '\0')
+ const char* expected2 = "!elifaul olleh";
+ if (_binary_asset2_bin_size != 15 || memcmp(_binary_asset2_bin_start, expected2, 14) != 0) {
+ printf("asset2.bin: transform verification failed!\n");
+ return 1;
+ }
+ printf("asset2.bin: transform verification ok\n");
return 0;
}
diff --git a/tests/projects/other/bin2obj/test.lua b/tests/projects/other/bin2obj/test.lua
index 7f2050b62..a75aa7e40 100644
--- a/tests/projects/other/bin2obj/test.lua
+++ b/tests/projects/other/bin2obj/test.lua
@@ -1,4 +1,6 @@
function main(t)
t:build()
+ -- run the target, main.c verifies the transformed asset.bin and exits non-zero on mismatch
+ os.exec("xmake run test")
end
diff --git a/tests/projects/other/bin2obj/transform.lua b/tests/projects/other/bin2obj/transform.lua
new file mode 100644
index 000000000..54cf1f394
--- /dev/null
+++ b/tests/projects/other/bin2obj/transform.lua
@@ -0,0 +1,5 @@
+function main(inputfile, outputfile)
+ import("core.base.bytes")
+ local data = io.readfile(inputfile, {encoding = "binary"})
+ io.writefile(outputfile, data:reverse(), {encoding = "binary"})
+end
diff --git a/tests/projects/other/bin2obj/xmake.lua b/tests/projects/other/bin2obj/xmake.lua
index 9541e17ae..d383bb1bb 100644
--- a/tests/projects/other/bin2obj/xmake.lua
+++ b/tests/projects/other/bin2obj/xmake.lua
@@ -6,3 +6,11 @@ target("test")
add_files("src/*.c")
add_files("src/data.bin", {zeroend = true})
add_files("src/xmake.ico", {zeroend = false})
+ add_files("src/asset.bin", {zeroend = true, transform = function (inputfile, outputfile, opt)
+ import("core.base.bytes")
+ assert(bytes and opt.target)
+ local data = io.readfile(inputfile, {encoding = "binary"})
+ io.writefile(outputfile, data:reverse(), {encoding = "binary"})
+ end})
+ -- transform can also be a lua script file (supported by the project generators)
+ add_files("src/asset2.bin", {zeroend = true, transform = path.join(os.projectdir(), "transform.lua")})
diff --git a/xmake/core/base/task.lua b/xmake/core/base/task.lua
index 27ad5023a..a51b1dbb5 100644
--- a/xmake/core/base/task.lua
+++ b/xmake/core/base/task.lua
@@ -96,7 +96,7 @@ function task._translate_menu(taskname, menu)
local options_full = {}
for _, opt in ipairs(options) do
if type(opt) == "function" then
- local ok, results = sandbox.load(opt)
+ local ok, results = sandbox.call(opt)
if ok then
if results then
for _, opt in ipairs(results) do
@@ -141,7 +141,7 @@ function task._translate_menu(taskname, menu)
opt[i] = function ()
-- call it in the sandbox
- local ok, results = sandbox.load(description)
+ local ok, results = sandbox.call(description)
if not ok then
return nil, string.format("taskmenu: %s", results)
end
@@ -508,7 +508,7 @@ function task:run(...)
local curdir = os.curdir()
-- run task
- local ok, errors = sandbox.load(on_run, ...)
+ local ok, errors = sandbox.call(on_run, ...)
-- restore the current directory
os.cd(curdir)
diff --git a/xmake/core/base/thread.lua b/xmake/core/base/thread.lua
index 187f98d53..6c3fc5169 100644
--- a/xmake/core/base/thread.lua
+++ b/xmake/core/base/thread.lua
@@ -942,7 +942,7 @@ function thread._run_thread(callback_str, callinfo_str)
end
-- do callback
- local ok, errors = sandbox.load(sandbox_inst:script(), table.unpack(argv or {}))
+ local ok, errors = sandbox.call(sandbox_inst:script(), table.unpack(argv or {}))
-- thread is finished, we need to notify the waited thread
if wpipe then
diff --git a/xmake/core/language/language.lua b/xmake/core/language/language.lua
index 8c6846819..1ea960807 100644
--- a/xmake/core/language/language.lua
+++ b/xmake/core/language/language.lua
@@ -50,7 +50,7 @@ function _instance:get(name)
end
if self._g == nil and info.load ~= nil then
- local ok, results = sandbox.load(info.load)
+ local ok, results = sandbox.call(info.load)
if not ok then
os.raise(results)
end
diff --git a/xmake/core/package/component.lua b/xmake/core/package/component.lua
index c55dc4a73..bdf1ff061 100644
--- a/xmake/core/package/component.lua
+++ b/xmake/core/package/component.lua
@@ -135,7 +135,7 @@ function _instance:_load()
if not loaded then
local script = self:_on_component()
if script then
- local ok, errors = sandbox.load(script, self:package(), self)
+ local ok, errors = sandbox.call(script, self:package(), self)
if not ok then
os.raise("load component(%s) failed, %s", self:name(), errors or "unknown errors")
end
diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua
index f5eb9ab94..cd6c7722e 100644
--- a/xmake/core/platform/platform.lua
+++ b/xmake/core/platform/platform.lua
@@ -109,7 +109,7 @@ function _instance:get(name)
if not self._LOADED and not self:_is_builtin_conf(name) then
local on_load = self._INFO:get("load")
if on_load then
- local ok, errors = sandbox.load(on_load, self)
+ local ok, errors = sandbox.call(on_load, self)
if not ok then
os.raise(errors)
end
diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua
index 62687a106..43ba10f05 100644
--- a/xmake/core/project/option.lua
+++ b/xmake/core/project/option.lua
@@ -142,7 +142,7 @@ function _instance:_do_check_cxsnippets(snippets)
-- check snippets (run with output)
if #table.keys(snippets_output) > 0 then
- local ok, results_or_errors, output = sandbox.load(self._check_cxsnippets, snippets_output, {
+ local ok, results_or_errors, output = sandbox.call(self._check_cxsnippets, snippets_output, {
target = self,
sourcekind = sourcekind,
types = types,
@@ -165,7 +165,7 @@ function _instance:_do_check_cxsnippets(snippets)
-- check snippets (run only)
if passed == 0 and #table.keys(snippets_tryrun) > 0 then
- local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_tryrun, {
+ local ok, results_or_errors = sandbox.call(self._check_cxsnippets, snippets_tryrun, {
target = self,
sourcekind = sourcekind,
types = types,
@@ -187,7 +187,7 @@ function _instance:_do_check_cxsnippets(snippets)
-- check snippets (run with binary_match)
if #table.keys(snippets_binary_match) > 0 then
- local ok, results_or_errors, output = sandbox.load(self._check_cxsnippets, snippets_binary_match, {
+ local ok, results_or_errors, output = sandbox.call(self._check_cxsnippets, snippets_binary_match, {
target = self,
sourcekind = sourcekind,
types = types,
@@ -209,7 +209,7 @@ function _instance:_do_check_cxsnippets(snippets)
-- check snippets (build only)
if passed == 0 or #table.keys(snippets_build) > 0 then
- local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_build, {
+ local ok, results_or_errors = sandbox.call(self._check_cxsnippets, snippets_build, {
target = self,
sourcekind = sourcekind,
types = types,
@@ -296,7 +296,7 @@ function _instance:_on_check()
-- get check script
local check = self:script("check")
if check then
- return sandbox.load(check, self)
+ return sandbox.call(check, self)
else
return self:_do_check()
end
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index cc5df14d4..81b95cc96 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -84,7 +84,7 @@ function _instance:_load_rule(ruleinst, suffix)
if cache[key] == nil then
local on_load = ruleinst:script("load" .. (suffix and ("_" .. suffix) or ""))
if on_load then
- local ok, errors = sandbox.load(on_load, self)
+ local ok, errors = sandbox.call(on_load, self)
cache[key] = {ok, errors}
else
cache[key] = {true}
@@ -129,7 +129,7 @@ function _instance:_load()
-- do load for target
local on_load = self:script("load")
if on_load then
- ok, errors = sandbox.load(on_load, self)
+ ok, errors = sandbox.call(on_load, self)
if not ok then
return false, errors
end
@@ -159,7 +159,7 @@ function _instance:_load_after()
-- do load for target
local after_load = self:script("load_after")
if after_load then
- local ok, errors = sandbox.load(after_load, self)
+ local ok, errors = sandbox.call(after_load, self)
if not ok then
return false, errors
end
diff --git a/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua b/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua
index 0a9cae170..7303e901e 100644
--- a/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua
+++ b/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua
@@ -134,6 +134,19 @@ function sandbox_core_sandbox.filter(script)
return instance:filter()
end
+-- fork a new sandbox and bind a raw script
+function sandbox_core_sandbox.fork(script)
+ local instance = sandbox.instance()
+ if not instance then
+ raise("cannot get sandbox instance!")
+ end
+ local newinst, errors = instance:fork(script)
+ if not newinst then
+ raise(errors)
+ end
+ return newinst
+end
+
-- get all builtin modules
function sandbox_core_sandbox.builtin_modules()
return sandbox.builtin_modules()
diff --git a/xmake/core/sandbox/modules/import/core/tool/compiler.lua b/xmake/core/sandbox/modules/import/core/tool/compiler.lua
index 71de70d2a..28a3d4d92 100644
--- a/xmake/core/sandbox/modules/import/core/tool/compiler.lua
+++ b/xmake/core/sandbox/modules/import/core/tool/compiler.lua
@@ -207,7 +207,7 @@ function sandbox_core_tool_compiler.features(langkind, opt)
local flags = instance:compflags(opt)
-- get features
- local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._features, instance:name(), {flags = flags, program = instance:program(), envs = instance:runenvs()})
+ local ok, results_or_errors = sandbox.call(sandbox_core_tool_compiler._features, instance:name(), {flags = flags, program = instance:program(), envs = instance:runenvs()})
if not ok then
raise(results_or_errors)
end
@@ -259,7 +259,7 @@ function sandbox_core_tool_compiler.has_features(features, opt)
for sourcekind, features in pairs(features_by_kind) do
local instance = sandbox_core_tool_compiler.load(sourcekind, opt)
local flags = instance:compflags(opt)
- local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._has_features, instance:name(), features, {flags = flags, program = instance:program(), envs = instance:runenvs()})
+ local ok, results_or_errors = sandbox.call(sandbox_core_tool_compiler._has_features, instance:name(), features, {flags = flags, program = instance:program(), envs = instance:runenvs()})
if not ok then
raise(results_or_errors)
end
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua
index 63392a751..ad48cff73 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua
@@ -36,7 +36,7 @@ function sandbox_lib_detect_find_directory._expand_paths(paths)
for _, _path in ipairs(table.wrap(paths)) do
local _path = _path
if type(_path) == "function" then
- local ok, result_or_errors = sandbox.load(_path)
+ local ok, result_or_errors = sandbox.call(_path)
if ok then
_path = result_or_errors or ""
else
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua
index e642f45b7..67db6c443 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua
@@ -37,7 +37,7 @@ function sandbox_lib_detect_find_file._expand_paths(paths)
for _, _path in ipairs(table.wrap(paths)) do
local _path = _path
if type(_path) == "function" then
- local ok, result_or_errors = sandbox.load(_path)
+ local ok, result_or_errors = sandbox.call(_path)
if ok then
_path = result_or_errors or ""
else
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua
index 159d7dbdc..6dd775752 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua
@@ -36,7 +36,7 @@ function sandbox_lib_detect_find_path._expand_paths(paths)
for _, _path in ipairs(table.wrap(paths)) do
local _path = _path
if type(_path) == "function" then
- local ok, result_or_errors = sandbox.load(_path)
+ local ok, result_or_errors = sandbox.call(_path)
if ok then
_path = result_or_errors or ""
else
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
index 0ca3f8d19..eee1d13b6 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
@@ -64,7 +64,7 @@ function sandbox_lib_detect_find_program._do_check(program, opt)
elseif type(opt.check) == "table" then
ok, errors = os.runv(program, opt.check, {envs = opt.envs, shell = opt.shell})
else
- ok, errors = sandbox.load(opt.check, program)
+ ok, errors = sandbox.call(opt.check, program)
end
-- check failed? print verbose error info
@@ -112,7 +112,7 @@ function sandbox_lib_detect_find_program._find_from_paths(name, paths, opt)
-- format path for builtin variables
if type(_path) == "function" then
- local ok, results = sandbox.load(_path)
+ local ok, results = sandbox.call(_path)
if ok then
_path = results or ""
else
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua b/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua
index 0d76526e5..2a8629855 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua
@@ -79,7 +79,7 @@ function sandbox_lib_detect_find_programver.main(program, opt)
local outdata = nil
local command = opt.command
if type(command) == "function" then
- ok, outdata = sandbox.load(command)
+ ok, outdata = sandbox.call(command)
if not ok and outdata and option.get("diagnosis") then
utils.cprint("${color.warning}checkinfo: ${clear dim}" .. outdata)
end
@@ -94,7 +94,7 @@ function sandbox_lib_detect_find_programver.main(program, opt)
if ok and outdata and #outdata > 0 then
local parse = opt.parse
if type(parse) == "function" then
- ok, result = sandbox.load(parse, outdata)
+ ok, result = sandbox.call(parse, outdata)
if not ok and result and option.get("diagnosis") then
utils.cprint("${color.warning}checkinfo: ${clear dim}" .. result)
result = nil
diff --git a/xmake/core/sandbox/sandbox.lua b/xmake/core/sandbox/sandbox.lua
index 758a48030..13e598b73 100644
--- a/xmake/core/sandbox/sandbox.lua
+++ b/xmake/core/sandbox/sandbox.lua
@@ -105,43 +105,13 @@ function sandbox._new()
instance:_api_register_builtin(module_name, module)
end
- -- bind instance to the public script envirnoment
- instance:bind(instance._PUBLIC)
+ -- bind the public script envirnoment
+ instance:_bindenv(instance._PUBLIC)
return instance
end
--- new a sandbox instance with the given script
-function sandbox.new(script, opt)
- opt = opt or {}
-
- -- new instance
- local self = sandbox._new()
- assert(self and self._PUBLIC and self._PRIVATE)
-
- self._PRIVATE._FILTER = opt.filter
- self._PRIVATE._ROOTDIR = opt.rootdir
- self._PRIVATE._NAMESPACE = opt.namespace
-
- -- invalid script?
- if type(script) ~= "function" then
- return nil, "invalid script!"
- end
-
- -- bind public scope
- setfenv(script, self._PUBLIC)
-
- -- save script
- self._PRIVATE._SCRIPT = script
- return self
-end
-
--- load script in the sandbox
-function sandbox.load(script, ...)
- return utils.trycall(script, sandbox._traceback, ...)
-end
-
--- bind self instance to the given script or envirnoment
-function sandbox:bind(script_or_env)
+-- bind the given script or envirnoment and the self instance
+function sandbox:_bindenv(script_or_env)
-- get envirnoment
local env = script_or_env
@@ -150,20 +120,18 @@ function sandbox:bind(script_or_env)
end
-- bind instance to the script envirnoment
- setmetatable(env, { __index = function (tbl, key)
- if type(key) == "string" and key == "_SANDBOX" and rawget(tbl, "_SANDBOX_READABLE") then
- return self
- end
- return rawget(tbl, key)
+ setmetatable(env, { __index = function (tbl, key)
+ if type(key) == "string" and key == "_SANDBOX" and rawget(tbl, "_SANDBOX_READABLE") then
+ return self
end
- , __newindex = function (tbl, key, val)
- if type(key) == "string" and (key == "_SANDBOX" or key == "_SANDBOX_READABLE") then
- return
- end
- rawset(tbl, key, val)
- end})
-
- -- ok
+ return rawget(tbl, key)
+ end,
+ __newindex = function (tbl, key, val)
+ if type(key) == "string" and (key == "_SANDBOX" or key == "_SANDBOX_READABLE") then
+ return
+ end
+ rawset(tbl, key, val)
+ end})
return script_or_env
end
@@ -205,7 +173,7 @@ function sandbox:module()
table.copy2(scope_backup, scope_public)
-- load module with sandbox
- local ok, errors = sandbox.load(self:script())
+ local ok, errors = sandbox.call(self:script())
if not ok then
return nil, errors
end
@@ -250,6 +218,36 @@ function sandbox:api_register_builtin(name, func)
sandbox._api_register_builtin(self, name, func)
end
+-- new a sandbox instance with the given script
+function sandbox.new(script, opt)
+ opt = opt or {}
+
+ -- new instance
+ local self = sandbox._new()
+ assert(self and self._PUBLIC and self._PRIVATE)
+
+ self._PRIVATE._FILTER = opt.filter
+ self._PRIVATE._ROOTDIR = opt.rootdir
+ self._PRIVATE._NAMESPACE = opt.namespace
+
+ -- invalid script?
+ if type(script) ~= "function" then
+ return nil, "invalid script!"
+ end
+
+ -- bind public scope
+ setfenv(script, self._PUBLIC)
+
+ -- save script
+ self._PRIVATE._SCRIPT = script
+ return self
+end
+
+-- call script in the sandbox
+function sandbox.call(script, ...)
+ return utils.trycall(script, sandbox._traceback, ...)
+end
+
-- get current instance in the sandbox modules
function sandbox.instance(script)
@@ -331,6 +329,5 @@ function sandbox.builtin_modules()
return builtin_modules
end
-
-- return module
return sandbox
diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua
index e00505a4f..44349de5f 100644
--- a/xmake/core/tool/compiler.lua
+++ b/xmake/core/tool/compiler.lua
@@ -238,7 +238,7 @@ function compiler:build(sourcefiles, targetfile, opt)
if not targetkind and opt.target and opt.target.targetkind then
targetkind = opt.target:kind()
end
- return sandbox.load(self:_tool().build, self:_tool(), sourcefiles, targetkind or "binary", targetfile, flags, opt)
+ return sandbox.call(self:_tool().build, self:_tool(), sourcefiles, targetkind or "binary", targetfile, flags, opt)
end
-- get the build arguments list (compile and link)
@@ -297,7 +297,7 @@ function compiler:compile(sourcefiles, objectfile, opt)
opt = table.copy(opt)
opt.target = self:target()
profiler:enter(self:name(), "compile", sourcefiles)
- local ok, errors = sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags, opt)
+ local ok, errors = sandbox.call(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags, opt)
profiler:leave(self:name(), "compile", sourcefiles)
return ok, errors
end
diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua
index 9cdff8840..7eaecc666 100644
--- a/xmake/core/tool/linker.lua
+++ b/xmake/core/tool/linker.lua
@@ -242,7 +242,7 @@ function linker:link(objectfiles, targetfile, opt)
opt = opt or {}
local linkflags = opt.linkflags or self:linkflags(opt)
profiler:enter(self:name(), "link", targetfile)
- local ok, errors = sandbox.load(self:_tool().link, self:_tool(),
+ local ok, errors = sandbox.call(self:_tool().link, self:_tool(),
table.wrap(objectfiles), self:_targetkind(), targetfile, linkflags,
table.join(opt, {target = self:target()}))
profiler:leave(self:name(), "link", targetfile)
diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua
index c54e24c93..9d0dfa0d6 100644
--- a/xmake/core/tool/tool.lua
+++ b/xmake/core/tool/tool.lua
@@ -62,7 +62,7 @@ function _instance.new(kind, name, program, plat, arch, toolchain_inst)
-- init instance
if instance.init then
- local ok, errors = sandbox.load(instance.init, instance)
+ local ok, errors = sandbox.call(instance.init, instance)
if not ok then
return nil, errors
end
@@ -176,7 +176,7 @@ end
function _instance:_load_once()
if not self._LOADED then
if self.load then
- local ok, errors = sandbox.load(self.load, self)
+ local ok, errors = sandbox.call(self.load, self)
if not ok then
return false, errors
end
@@ -274,7 +274,7 @@ function tool.load(kind, opt)
tool._find_toolname = tool._find_toolname or import("lib.detect.find_toolname")
-- get the tool name from the program
- local ok, name_or_errors = sandbox.load(tool._find_toolname, toolname or program, {program = program})
+ local ok, name_or_errors = sandbox.call(tool._find_toolname, toolname or program, {program = program})
if not ok then
return nil, name_or_errors
end
diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua
index 3bca7e37a..7d19dfc7d 100644
--- a/xmake/core/tool/toolchain.lua
+++ b/xmake/core/tool/toolchain.lua
@@ -356,7 +356,7 @@ function _instance:check()
if checked == nil then
local on_check = self:_on_check()
if on_check then
- local ok, results_or_errors = sandbox.load(on_check, self)
+ local ok, results_or_errors = sandbox.call(on_check, self)
if ok then
checked = results_or_errors
else
@@ -449,7 +449,7 @@ function _instance:_load()
local on_load = self:_on_load()
if on_load then
info:set("__loading", true)
- local ok, errors = sandbox.load(on_load, self)
+ local ok, errors = sandbox.call(on_load, self)
info:set("__loading", false)
if not ok then
os.raise(errors)
diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua
index 3f584b286..349e31efe 100644
--- a/xmake/modules/private/utils/batchcmds.lua
+++ b/xmake/modules/private/utils/batchcmds.lua
@@ -28,6 +28,7 @@ import("core.theme.theme")
import("core.tool.linker")
import("core.tool.compiler")
import("core.language.language")
+import("core.sandbox.sandbox")
import("utils.run_script")
import("utils.progress", {alias = "progress_utils"})
import("utils.binary.rpath", {alias = "rpath_utils"})
@@ -126,6 +127,20 @@ function _runcmd_vlua(cmd, opt)
end
end
+-- run command: call
+function _runcmd_call(cmd, opt)
+ local func = cmd.func
+ if func then
+ if not opt.dryrun then
+ local argv = table.clone(cmd.argv)
+ if cmd.opt then
+ table.insert(argv, cmd.opt)
+ end
+ func(table.unpack(argv))
+ end
+ end
+end
+
-- run command: os.mkdir
function _runcmd_mkdir(cmd, opt)
local dir = cmd.dir
@@ -222,6 +237,7 @@ function _runcmd(cmd, opt)
vexecv = _runcmd_vexecv,
lua = _runcmd_lua,
vlua = _runcmd_vlua,
+ call = _runcmd_call,
mkdir = _runcmd_mkdir,
rmdir = _runcmd_rmdir,
cd = _runcmd_cd,
@@ -305,11 +321,23 @@ function batchcmds:lua(script, argv, opt)
table.insert(self:cmds(), {kind = "lua", script = script, argv = argv, opt = opt})
end
--- add command: run lua script file, command or module
+-- add command: run lua script, command or module
function batchcmds:vlua(script, argv, opt)
table.insert(self:cmds(), {kind = "vlua", script = script, argv = argv, opt = opt})
end
+-- add command: call lua function
+function batchcmds:call(func, argv, opt)
+ local functype = type(func)
+ if functype == "string" then
+ self:lua(func, argv, opt)
+ else
+ assert(functype == "function")
+ sandbox.fork(func)
+ table.insert(self:cmds(), {kind = "call", func = func, argv = argv, opt = opt})
+ end
+end
+
-- add command: compile source files
--
-- @param sourcefiles the source file paths
diff --git a/xmake/plugins/project/utils/target_cmds.lua b/xmake/plugins/project/utils/target_cmds.lua
index 7ea3a13a0..1c5fed7c8 100644
--- a/xmake/plugins/project/utils/target_cmds.lua
+++ b/xmake/plugins/project/utils/target_cmds.lua
@@ -87,6 +87,9 @@ function get_target_buildcmds(target, opt)
cmd.program = os.programfile()
cmd.argv = table.join("lua", cmd.script, cmd.argv)
cmd.script = nil
+ elseif cmd.func and kind == "call" then
+ local name = cmd.opt and cmd.opt.name or "unknown"
+ wprint("%s: batchcmds:call() is not supported by the project generator and will be ignored!", name)
end
end
return buildcmds:cmds()
diff --git a/xmake/rules/utils/bin2c/utils.lua b/xmake/rules/utils/bin2c/utils.lua
index 405c2ed62..156752576 100644
--- a/xmake/rules/utils/bin2c/utils.lua
+++ b/xmake/rules/utils/bin2c/utils.lua
@@ -36,6 +36,7 @@ function generate_headerfile(target, batchcmds, binaryfile, opt)
opt = opt or {}
local rulename = opt.rulename or "utils.bin2c"
local progress = opt.progress
+ local fileconfig = target:fileconfig(binaryfile)
-- get header directory and file
local headerdir = opt.headerdir
@@ -52,6 +53,16 @@ function generate_headerfile(target, batchcmds, binaryfile, opt)
-- add includedirs
target:add("includedirs", headerdir)
+ -- transform binary data first
+ -- @see https://github.com/xmake-io/xmake/issues/7513
+ local transform = opt.transform or (fileconfig and fileconfig.transform) or target:extraconf("rules", rulename, "transform")
+ if transform then
+ batchcmds:show_progress(progress, "${color.build.object}transforming.bin2c %s", binaryfile)
+ local transformed_file = target:autogenfile(binaryfile)
+ batchcmds:call(transform, {binaryfile, transformed_file}, {name = "bin2c/transform", target = target})
+ binaryfile = transformed_file
+ end
+
-- add commands
if progress then
batchcmds:show_progress(progress, "${color.build.object}generating.bin2c %s", binaryfile)
@@ -69,7 +80,6 @@ function generate_headerfile(target, batchcmds, binaryfile, opt)
end
-- get nozeroend/zeroend (check file-level config first, then rule-level config, then opt)
- local fileconfig = target:fileconfig(binaryfile)
local nozeroend = nil
if fileconfig then
if fileconfig.nozeroend ~= nil then
diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua
index 9f6338758..0d2745b60 100644
--- a/xmake/rules/utils/bin2c/xmake.lua
+++ b/xmake/rules/utils/bin2c/xmake.lua
@@ -33,7 +33,7 @@ rule("utils.bin2c")
-- generate header file
local headerfile = bin2c_utils.generate_headerfile(target, batchcmds, sourcefile_bin, {
- progress = opt.progress
+ progress = opt.progress,
})
-- add deps
diff --git a/xmake/rules/utils/bin2obj/utils.lua b/xmake/rules/utils/bin2obj/utils.lua
index 3e8802e97..bcee334f0 100644
--- a/xmake/rules/utils/bin2obj/utils.lua
+++ b/xmake/rules/utils/bin2obj/utils.lua
@@ -35,6 +35,7 @@ function generate_objectfile(target, batchcmds, binaryfile, opt)
opt = opt or {}
local rulename = opt.rulename or "utils.bin2obj"
local progress = opt.progress
+ local fileconfig = target:fileconfig(binaryfile)
-- check for cosmocc toolchain
local is_cosmocc = target:toolchain("cosmocc") or (target:has_tool("cc", "cosmocc") and target:has_tool("ar", "cosmoar"))
@@ -53,6 +54,16 @@ function generate_objectfile(target, batchcmds, binaryfile, opt)
end
end
+ -- transform binary data first
+ -- @see https://github.com/xmake-io/xmake/issues/7513
+ local transform = opt.transform or (fileconfig and fileconfig.transform) or target:extraconf("rules", rulename, "transform")
+ if transform then
+ batchcmds:show_progress(progress, "${color.build.object}transforming.bin2obj %s", binaryfile)
+ local transformed_file = target:autogenfile(binaryfile)
+ batchcmds:call(transform, {binaryfile, transformed_file}, {name = "bin2obj/transform", target = target})
+ binaryfile = transformed_file
+ end
+
-- get object file
local objectfile = opt.objectfile
if not objectfile then
@@ -75,6 +86,9 @@ function generate_objectfile(target, batchcmds, binaryfile, opt)
-- get zeroend (default: false, but can be overridden)
local zeroend = opt.zeroend
if zeroend == nil then
+ zeroend = fileconfig and fileconfig.zeroend
+ end
+ if zeroend == nil then
zeroend = target:extraconf("rules", rulename, "zeroend") or false
end
diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua
index 760b9d536..58ec87a90 100644
--- a/xmake/rules/utils/bin2obj/xmake.lua
+++ b/xmake/rules/utils/bin2obj/xmake.lua
@@ -24,15 +24,9 @@ rule("utils.bin2obj")
on_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt)
import("rules.utils.bin2obj.utils", {alias = "bin2obj_utils", rootdir = os.programdir()})
- -- get zeroend (default: false)
- -- check file-level config first, then rule-level config
- local fileconfig = target:fileconfig(sourcefile_bin)
- local zeroend = (fileconfig and fileconfig.zeroend) or target:extraconf("rules", "utils.bin2obj", "zeroend") or false
-
-- convert binary file to object file
local objectfile = bin2obj_utils.generate_objectfile(target, batchcmds, sourcefile_bin, {
progress = opt.progress,
- zeroend = zeroend
})
-- add deps