diff options
| author | ruki <[email protected]> | 2026-07-18 18:37:41 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-18 18:37:41 +0800 |
| commit | 108eaa6d115e03f44bd1f105328dbe90a7747b30 (patch) | |
| tree | 8f98ca03c2355a6f4acc934e0924324e3dd4a73a | |
| parent | c4f4ad6aec62c15fdff13721716a577690e0db81 (diff) | |
| parent | c48de38142edcb99b47bf72b0b54fe025f112fdf (diff) | |
Merge pull request #7654 from xmake-io/bin2obj
Add transform support for bin2obj/bin2c
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 |
