From 0e2574300271cdb454db610b36466dd27ea7cfa3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 00:00:46 +0800 Subject: add bin2obj rule and test --- xmake/rules/utils/bin2obj/xmake.lua | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 xmake/rules/utils/bin2obj/xmake.lua (limited to 'xmake/rules/utils/bin2obj') diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua new file mode 100644 index 000000000..13feba930 --- /dev/null +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -0,0 +1,69 @@ +--!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 +-- + +rule("utils.bin2obj") + set_extensions(".bin") + add_orders("utils.bin2obj", "c++.build.modules.builder") + on_preparecmd_file(function (target, batchcmds, sourcefile_bin, opt) + + -- get object file + local objectfile = path.join(target:objectdir(), path.basename(sourcefile_bin) .. ".o") + target:add("objectfiles", objectfile) + + -- add commands + batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2obj %s", sourcefile_bin) + batchcmds:mkdir(path.directory(objectfile)) + + -- get format (default: auto-detect from platform) + local format = target:extraconf("rules", "utils.bin2obj", "format") + if not format then + if target:is_plat("windows", "mingw", "msys", "cygwin") then + format = "coff" + elseif target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then + format = "macho" + else + format = "elf" + end + end + + -- get symbol prefix (default: _binary_) + local symbol_prefix = target:extraconf("rules", "utils.bin2obj", "symbol_prefix") or "_binary_" + + -- get architecture + local arch = target:arch() + + -- convert binary file to object file + local argv = { + "-i", path(sourcefile_bin), + "-o", path(objectfile), + "-f", format, + "-a", arch + } + if symbol_prefix ~= "_binary_" then + table.insert(argv, "--symbol-prefix") + table.insert(argv, symbol_prefix) + end + batchcmds:vlua("private.utils.bin2obj", argv) + + -- add deps + batchcmds:add_depfiles(sourcefile_bin) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + end) -- cgit v1.3.1 From d0293d9d840a71b64e5622350fa2e1df0ecff92f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 00:04:22 +0800 Subject: fix bin2obj rule --- xmake/rules/utils/bin2obj/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index 13feba930..df76c42a3 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -21,11 +21,11 @@ rule("utils.bin2obj") set_extensions(".bin") add_orders("utils.bin2obj", "c++.build.modules.builder") - on_preparecmd_file(function (target, batchcmds, sourcefile_bin, opt) + on_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) -- get object file local objectfile = path.join(target:objectdir(), path.basename(sourcefile_bin) .. ".o") - target:add("objectfiles", objectfile) + table.insert(target:objectfiles(), objectfile) -- add commands batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2obj %s", sourcefile_bin) -- cgit v1.3.1 From 2bbcf01a43b170d346d6776964ea0d5847c822aa Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 00:06:55 +0800 Subject: fix bin2obj ext --- xmake/rules/utils/bin2obj/xmake.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index df76c42a3..2bdd9c3a8 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -23,14 +23,6 @@ rule("utils.bin2obj") add_orders("utils.bin2obj", "c++.build.modules.builder") on_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) - -- get object file - local objectfile = path.join(target:objectdir(), path.basename(sourcefile_bin) .. ".o") - table.insert(target:objectfiles(), objectfile) - - -- add commands - batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2obj %s", sourcefile_bin) - batchcmds:mkdir(path.directory(objectfile)) - -- get format (default: auto-detect from platform) local format = target:extraconf("rules", "utils.bin2obj", "format") if not format then @@ -43,6 +35,15 @@ rule("utils.bin2obj") end end + -- get object file (use .obj for COFF, .o for others) + local objext = (format == "coff") and ".obj" or ".o" + local objectfile = path.join(target:objectdir(), path.basename(sourcefile_bin) .. objext) + table.insert(target:objectfiles(), objectfile) + + -- add commands + batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2obj %s", sourcefile_bin) + batchcmds:mkdir(path.directory(objectfile)) + -- get symbol prefix (default: _binary_) local symbol_prefix = target:extraconf("rules", "utils.bin2obj", "symbol_prefix") or "_binary_" -- cgit v1.3.1 From cae5b0a17dc7d0eb5599c0d5a92fab69d39983d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 11:17:46 +0800 Subject: support for iphoneos in bin2macho --- core/src/xmake/utils/bin2macho.c | 38 +++++++++++++++++++++++++++------ xmake/core/sandbox/modules/utils.lua | 4 ++-- xmake/modules/private/utils/bin2obj.lua | 19 +++++++++++------ xmake/rules/utils/bin2obj/xmake.lua | 6 +++++- 4 files changed, 52 insertions(+), 15 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/core/src/xmake/utils/bin2macho.c b/core/src/xmake/utils/bin2macho.c index 4d69d0656..b5a97c21f 100644 --- a/core/src/xmake/utils/bin2macho.c +++ b/core/src/xmake/utils/bin2macho.c @@ -54,6 +54,11 @@ #define XM_MACHO_LC_SYMTAB 0x2 #define XM_MACHO_LC_BUILD_VERSION 0x32 +#define XM_MACHO_PLATFORM_MACOS 1 +#define XM_MACHO_PLATFORM_IOS 2 +#define XM_MACHO_PLATFORM_TVOS 3 +#define XM_MACHO_PLATFORM_WATCHOS 4 + #define XM_MACHO_SECT_TYPE_REGULAR 0x0 #define XM_MACHO_SECT_ATTR_SOME_INITS 0x400 #define XM_MACHO_SECT_ATTR_PURE_INSTRUCTIONS 0x80000000 @@ -234,9 +239,26 @@ static tb_uint32_t xm_utils_bin2macho_align(tb_uint32_t value, tb_uint32_t align return ((value + align - 1) & ~(align - 1)); } +static tb_uint32_t xm_utils_bin2macho_get_platform(tb_char_t const *platform) { + if (!platform) { + return XM_MACHO_PLATFORM_MACOS; + } + if (tb_strcmp(platform, "macosx") == 0 || tb_strcmp(platform, "macos") == 0) { + return XM_MACHO_PLATFORM_MACOS; + } else if (tb_strcmp(platform, "iphoneos") == 0 || tb_strcmp(platform, "ios") == 0) { + return XM_MACHO_PLATFORM_IOS; + } else if (tb_strcmp(platform, "appletvos") == 0 || tb_strcmp(platform, "tvos") == 0) { + return XM_MACHO_PLATFORM_TVOS; + } else if (tb_strcmp(platform, "watchos") == 0) { + return XM_MACHO_PLATFORM_WATCHOS; + } + return XM_MACHO_PLATFORM_MACOS; +} + static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, + tb_char_t const *plat, tb_char_t const *arch, tb_char_t const *basename) { tb_assert_and_check_return_val(istream && ostream, tb_false); @@ -364,7 +386,7 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_memset(&build_version, 0, sizeof(build_version)); build_version.cmd = XM_MACHO_LC_BUILD_VERSION; build_version.cmdsize = build_version_cmd_size; - build_version.platform = 1; // PLATFORM_MACOS + build_version.platform = xm_utils_bin2macho_get_platform(plat); build_version.minos = 0x000a0000; // 10.0.0 build_version.sdk = 0x000a0000; // 10.0.0 build_version.ntools = 0; @@ -473,10 +495,11 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, static tb_bool_t xm_utils_bin2macho_dump(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, + tb_char_t const *plat, tb_char_t const *arch, tb_char_t const *basename) { if (xm_utils_bin2macho_is_64bit(arch)) { - return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, arch, basename); + return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, plat, arch, basename); } else { // 32-bit not implemented yet return tb_false; @@ -489,7 +512,7 @@ static tb_bool_t xm_utils_bin2macho_dump(tb_stream_ref_t istream, /* generate Mach-O object file from binary file * - * local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, arch, basename) + * local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename) */ tb_int_t xm_utils_bin2macho(lua_State *lua) { tb_assert_and_check_return_val(lua, 0); @@ -505,11 +528,14 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { // get symbol prefix (optional) tb_char_t const *symbol_prefix = lua_isstring(lua, 3) ? lua_tostring(lua, 3) : tb_null; + // get plat (optional) + tb_char_t const *plat = lua_isstring(lua, 4) ? lua_tostring(lua, 4) : tb_null; + // get arch (optional) - tb_char_t const *arch = lua_isstring(lua, 4) ? lua_tostring(lua, 4) : tb_null; + tb_char_t const *arch = lua_isstring(lua, 5) ? lua_tostring(lua, 5) : tb_null; // get basename (optional) - tb_char_t const *basename = lua_isstring(lua, 5) ? lua_tostring(lua, 5) : tb_null; + tb_char_t const *basename = lua_isstring(lua, 6) ? lua_tostring(lua, 6) : tb_null; // do dump tb_bool_t ok = tb_false; @@ -529,7 +555,7 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { break; } - if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, arch, basename)) { + if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, plat, arch, basename)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2macho: dump data failed"); break; diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index 694447924..b6dfedd45 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -170,8 +170,8 @@ end -- generate Mach-O object file from the binary file if utils.bin2macho then - function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, arch, basename) - local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, arch, basename) + function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename) + local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename) if not ok then os.raise(errors) end diff --git a/xmake/modules/private/utils/bin2obj.lua b/xmake/modules/private/utils/bin2obj.lua index 2221adf3c..a27f5c5dc 100644 --- a/xmake/modules/private/utils/bin2obj.lua +++ b/xmake/modules/private/utils/bin2obj.lua @@ -26,15 +26,19 @@ local options = { {'o', "outputpath", "kv", nil, "Set the output object file path."}, {'f', "format", "kv", nil, "Set the object file format (coff, elf, macho)."}, {nil, "symbol-prefix", "kv", nil, "Set the symbol prefix (default: _binary_)."}, - {'a', "arch", "kv", nil, "Set the target architecture."} + {'a', "arch", "kv", nil, "Set the target architecture."}, + {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."} } function _do_bin2obj_coff(binarypath, outputpath, opt) -- get symbol prefix local symbol_prefix = opt["symbol-prefix"] or "_binary_" - -- get architecture - local arch = opt.arch + -- get architecture (default: x86_64) + local arch = opt.arch or "x86_64" + + -- get platform (not used for COFF, but passed for consistency) + local platform = opt.plat -- get filename from binary path (with extension, dots replaced with underscores) local filename = path.filename(binarypath) @@ -63,8 +67,11 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- get symbol prefix local symbol_prefix = opt["symbol-prefix"] or "_binary_" - -- get architecture - local arch = opt.arch + -- get platform (default: macosx) + local plat = opt.plat or "macosx" + + -- get architecture (default: x86_64) + local arch = opt.arch or "x86_64" -- get filename from binary path (with extension, dots replaced with underscores) local filename = path.filename(binarypath) @@ -76,7 +83,7 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- do dump if utils.bin2macho then - utils.bin2macho(binarypath, outputpath, symbol_prefix, arch, basename) + utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename) else raise("bin2obj: utils.bin2macho not available (C implementation not compiled)") end diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index 2bdd9c3a8..def3f56e8 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -50,12 +50,16 @@ rule("utils.bin2obj") -- get architecture local arch = target:arch() + -- get platform + local plat = target:plat() + -- convert binary file to object file local argv = { "-i", path(sourcefile_bin), "-o", path(objectfile), "-f", format, - "-a", arch + "-a", arch, + "-p", plat } if symbol_prefix ~= "_binary_" then table.insert(argv, "--symbol-prefix") -- cgit v1.3.1 From 1ef6dddad4c6a3a2e3b3b79667e7f4568f7cfda0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 11:36:02 +0800 Subject: improve minos and sdkver --- core/src/xmake/utils/bin2macho.c | 72 ++++++++++++++++++++++++++++----- xmake/core/sandbox/modules/utils.lua | 4 +- xmake/modules/private/utils/bin2obj.lua | 18 ++++++--- xmake/rules/utils/bin2obj/xmake.lua | 20 ++++++++- 4 files changed, 94 insertions(+), 20 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/core/src/xmake/utils/bin2macho.c b/core/src/xmake/utils/bin2macho.c index b5a97c21f..5499ee103 100644 --- a/core/src/xmake/utils/bin2macho.c +++ b/core/src/xmake/utils/bin2macho.c @@ -67,6 +67,10 @@ #define XM_MACHO_N_TYPE_SECT 0x0e #define XM_MACHO_N_EXT 0x01 +#define XM_MACHO_VM_PROT_READ 1 +#define XM_MACHO_VM_PROT_WRITE 2 +#define XM_MACHO_VM_PROT_EXECUTE 4 + /* ////////////////////////////////////////////////////////////////////////////////////// * types */ @@ -255,12 +259,48 @@ static tb_uint32_t xm_utils_bin2macho_get_platform(tb_char_t const *platform) { return XM_MACHO_PLATFORM_MACOS; } +// parse version string (e.g., "10.0" or "18.2") to Mach-O format (0x000a0000) +// format: (major << 16) | (minor << 8) | patch +static tb_uint32_t xm_utils_bin2macho_parse_version(tb_char_t const *version_str) { + if (!version_str || !version_str[0]) { + return 0x000a0000; // default: 10.0.0 + } + tb_uint32_t major = 0; + tb_uint32_t minor = 0; + tb_uint32_t patch = 0; + tb_char_t const *p = version_str; + // parse major + while (*p && tb_isdigit(*p)) { + major = major * 10 + (*p - '0'); + p++; + } + if (*p == '.') { + p++; + // parse minor + while (*p && tb_isdigit(*p)) { + minor = minor * 10 + (*p - '0'); + p++; + } + if (*p == '.') { + p++; + // parse patch + while (*p && tb_isdigit(*p)) { + patch = patch * 10 + (*p - '0'); + p++; + } + } + } + return (major << 16) | (minor << 8) | patch; +} + static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, tb_char_t const *plat, tb_char_t const *arch, - tb_char_t const *basename) { + tb_char_t const *basename, + tb_uint32_t minos, + tb_uint32_t sdk) { tb_assert_and_check_return_val(istream && ostream, tb_false); // get file size @@ -339,13 +379,13 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_memset(&segment, 0, sizeof(segment)); segment.cmd = XM_MACHO_LC_SEGMENT_64; segment.cmdsize = segment_cmd_total_size; - tb_strncpy(segment.segname, "__DATA", 16); + tb_strncpy(segment.segname, "__TEXT", 16); segment.vmaddr = 0; segment.vmsize = data_size; segment.fileoff = data_offset; segment.filesize = data_size; - segment.maxprot = 1; // VM_PROT_READ - segment.initprot = 1; // VM_PROT_READ + segment.maxprot = XM_MACHO_VM_PROT_READ; // VM_PROT_READ (read-only) + segment.initprot = XM_MACHO_VM_PROT_READ; // VM_PROT_READ (read-only) segment.nsects = 1; segment.flags = 0; if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&segment, sizeof(segment))) { @@ -355,8 +395,8 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, // write section xm_macho_section_64_t section; tb_memset(§ion, 0, sizeof(section)); - tb_strncpy(section.sectname, "__data", 16); - tb_strncpy(section.segname, "__DATA", 16); + tb_strncpy(section.sectname, "__const", 16); + tb_strncpy(section.segname, "__TEXT", 16); section.addr = 0; section.size = data_size; section.offset = data_offset; @@ -387,8 +427,8 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, build_version.cmd = XM_MACHO_LC_BUILD_VERSION; build_version.cmdsize = build_version_cmd_size; build_version.platform = xm_utils_bin2macho_get_platform(plat); - build_version.minos = 0x000a0000; // 10.0.0 - build_version.sdk = 0x000a0000; // 10.0.0 + build_version.minos = minos; + build_version.sdk = sdk; build_version.ntools = 0; if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&build_version, sizeof(build_version))) { return tb_false; @@ -497,9 +537,11 @@ static tb_bool_t xm_utils_bin2macho_dump(tb_stream_ref_t istream, tb_char_t const *symbol_prefix, tb_char_t const *plat, tb_char_t const *arch, - tb_char_t const *basename) { + tb_char_t const *basename, + tb_uint32_t minos, + tb_uint32_t sdk) { if (xm_utils_bin2macho_is_64bit(arch)) { - return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, plat, arch, basename); + return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk); } else { // 32-bit not implemented yet return tb_false; @@ -537,6 +579,14 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { // get basename (optional) tb_char_t const *basename = lua_isstring(lua, 6) ? lua_tostring(lua, 6) : tb_null; + // get minos version string (optional) + tb_char_t const *minos_str = lua_isstring(lua, 7) ? lua_tostring(lua, 7) : tb_null; + tb_uint32_t minos = xm_utils_bin2macho_parse_version(minos_str); + + // get sdk version string (optional) + tb_char_t const *sdk_str = lua_isstring(lua, 8) ? lua_tostring(lua, 8) : tb_null; + tb_uint32_t sdk = xm_utils_bin2macho_parse_version(sdk_str); + // do dump tb_bool_t ok = tb_false; tb_stream_ref_t istream = tb_stream_init_from_file(binaryfile, TB_FILE_MODE_RO); @@ -555,7 +605,7 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { break; } - if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, plat, arch, basename)) { + if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2macho: dump data failed"); break; diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index b6dfedd45..b3453cb92 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -170,8 +170,8 @@ end -- generate Mach-O object file from the binary file if utils.bin2macho then - function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename) - local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename) + function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) + local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) if not ok then os.raise(errors) end diff --git a/xmake/modules/private/utils/bin2obj.lua b/xmake/modules/private/utils/bin2obj.lua index a27f5c5dc..a41c919fe 100644 --- a/xmake/modules/private/utils/bin2obj.lua +++ b/xmake/modules/private/utils/bin2obj.lua @@ -25,14 +25,16 @@ local options = { {'i', "binarypath", "kv", nil, "Set the binary file path."}, {'o', "outputpath", "kv", nil, "Set the output object file path."}, {'f', "format", "kv", nil, "Set the object file format (coff, elf, macho)."}, - {nil, "symbol-prefix", "kv", nil, "Set the symbol prefix (default: _binary_)."}, + {nil, "symbol_prefix", "kv", nil, "Set the symbol prefix (default: _binary_)."}, {'a', "arch", "kv", nil, "Set the target architecture."}, - {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."} + {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."}, + {nil, "target_minver", "kv", nil, "Set the target minimum version (e.g., 10.0, 18.2)."}, + {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."} } function _do_bin2obj_coff(binarypath, outputpath, opt) -- get symbol prefix - local symbol_prefix = opt["symbol-prefix"] or "_binary_" + local symbol_prefix = opt.symbol_prefix or "_binary_" -- get architecture (default: x86_64) local arch = opt.arch or "x86_64" @@ -65,7 +67,7 @@ end function _do_bin2obj_macho(binarypath, outputpath, opt) -- get symbol prefix - local symbol_prefix = opt["symbol-prefix"] or "_binary_" + local symbol_prefix = opt.symbol_prefix or "_binary_" -- get platform (default: macosx) local plat = opt.plat or "macosx" @@ -73,6 +75,12 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- get architecture (default: x86_64) local arch = opt.arch or "x86_64" + -- get target minimum version (default: nil, will use default 10.0.0 in C) + local target_minver = opt.target_minver + + -- get xcode sdk version (default: nil, will use default 10.0.0 in C) + local xcode_sdkver = opt.xcode_sdkver + -- get filename from binary path (with extension, dots replaced with underscores) local filename = path.filename(binarypath) -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) @@ -83,7 +91,7 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- do dump if utils.bin2macho then - utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename) + utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) else raise("bin2obj: utils.bin2macho not available (C implementation not compiled)") end diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index def3f56e8..1f8e6e0b2 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -53,6 +53,17 @@ rule("utils.bin2obj") -- get platform local plat = target:plat() + -- get target_minver and xcode_sdkver from xcode toolchain (if available) + local target_minver = nil + local xcode_sdkver = nil + if format == "macho" then + local toolchain = target:toolchain("xcode") + if toolchain then + target_minver = toolchain:config("target_minver") + xcode_sdkver = toolchain:config("xcode_sdkver") + end + end + -- convert binary file to object file local argv = { "-i", path(sourcefile_bin), @@ -62,8 +73,13 @@ rule("utils.bin2obj") "-p", plat } if symbol_prefix ~= "_binary_" then - table.insert(argv, "--symbol-prefix") - table.insert(argv, symbol_prefix) + table.insert(argv, "--symbol_prefix=" .. symbol_prefix) + end + if target_minver then + table.insert(argv, "--target_minver=" .. target_minver) + end + if xcode_sdkver then + table.insert(argv, "--xcode_sdkver=" .. xcode_sdkver) end batchcmds:vlua("private.utils.bin2obj", argv) -- cgit v1.3.1 From 774c5110ef60f2878d3a2f503c7a55db4943a1cb Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 12:06:33 +0800 Subject: add zeroend --- core/src/xmake/utils/bin2coff.c | 25 +++++++++++++++++++++++-- core/src/xmake/utils/bin2macho.c | 27 +++++++++++++++++++++++---- tests/projects/other/bin2obj/xmake.lua | 1 - xmake/core/sandbox/modules/utils.lua | 8 ++++---- xmake/modules/private/utils/bin2obj.lua | 13 ++++++++++--- xmake/rules/utils/bin2obj/xmake.lua | 6 ++++++ 6 files changed, 66 insertions(+), 14 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/core/src/xmake/utils/bin2coff.c b/core/src/xmake/utils/bin2coff.c index be8a313ad..58c05cd33 100644 --- a/core/src/xmake/utils/bin2coff.c +++ b/core/src/xmake/utils/bin2coff.c @@ -155,7 +155,8 @@ static tb_bool_t xm_utils_bin2coff_dump(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, tb_char_t const *arch, - tb_char_t const *basename) { + tb_char_t const *basename, + tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); // get file size @@ -164,6 +165,13 @@ static tb_bool_t xm_utils_bin2coff_dump(tb_stream_ref_t istream, return tb_false; } tb_uint32_t datasize = (tb_uint32_t)filesize; + // add null terminator if zeroend is true + if (zeroend) { + if (datasize >= 0xffffffffU) { + return tb_false; // would overflow + } + datasize++; + } // generate symbol names from filename tb_char_t symbol_name[256] = {0}; @@ -254,6 +262,13 @@ static tb_bool_t xm_utils_bin2coff_dump(tb_stream_ref_t istream, } left -= to_read; } + // append null terminator if zeroend is true + if (zeroend) { + tb_byte_t zero = 0; + if (!tb_stream_bwrit(ostream, &zero, 1)) { + return tb_false; + } + } // align to 4 bytes tb_uint32_t padding = (4 - (section_data_size & 3)) & 3; @@ -351,6 +366,12 @@ tb_int_t xm_utils_bin2coff(lua_State *lua) { // get basename (optional) tb_char_t const *basename = lua_isstring(lua, 5) ? lua_tostring(lua, 5) : tb_null; + // get platform (optional, not used but passed for consistency) + tb_char_t const *plat = lua_isstring(lua, 6) ? lua_tostring(lua, 6) : tb_null; + + // get zeroend (optional, default: false) + tb_bool_t zeroend = lua_toboolean(lua, 7); + // do dump tb_bool_t ok = tb_false; tb_stream_ref_t istream = tb_stream_init_from_file(binaryfile, TB_FILE_MODE_RO); @@ -369,7 +390,7 @@ tb_int_t xm_utils_bin2coff(lua_State *lua) { break; } - if (!xm_utils_bin2coff_dump(istream, ostream, symbol_prefix, arch, basename)) { + if (!xm_utils_bin2coff_dump(istream, ostream, symbol_prefix, arch, basename, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2coff: dump data failed"); break; diff --git a/core/src/xmake/utils/bin2macho.c b/core/src/xmake/utils/bin2macho.c index 5499ee103..c0798fa02 100644 --- a/core/src/xmake/utils/bin2macho.c +++ b/core/src/xmake/utils/bin2macho.c @@ -300,7 +300,8 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_char_t const *arch, tb_char_t const *basename, tb_uint32_t minos, - tb_uint32_t sdk) { + tb_uint32_t sdk, + tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); // get file size @@ -309,6 +310,13 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, return tb_false; } tb_uint32_t datasize = (tb_uint32_t)filesize; + // add null terminator if zeroend is true + if (zeroend) { + if (datasize >= 0xffffffffU) { + return tb_false; // would overflow + } + datasize++; + } // generate symbol names from filename tb_char_t symbol_name[256] = {0}; @@ -458,6 +466,13 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, } left -= to_read; } + // append null terminator if zeroend is true + if (zeroend) { + tb_byte_t zero = 0; + if (!tb_stream_bwrit(ostream, &zero, 1)) { + return tb_false; + } + } // align to 8 bytes padding = symtab_offset - data_end_offset; @@ -539,9 +554,10 @@ static tb_bool_t xm_utils_bin2macho_dump(tb_stream_ref_t istream, tb_char_t const *arch, tb_char_t const *basename, tb_uint32_t minos, - tb_uint32_t sdk) { + tb_uint32_t sdk, + tb_bool_t zeroend) { if (xm_utils_bin2macho_is_64bit(arch)) { - return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk); + return xm_utils_bin2macho_dump_64(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk, zeroend); } else { // 32-bit not implemented yet return tb_false; @@ -587,6 +603,9 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { tb_char_t const *sdk_str = lua_isstring(lua, 8) ? lua_tostring(lua, 8) : tb_null; tb_uint32_t sdk = xm_utils_bin2macho_parse_version(sdk_str); + // get zeroend (optional, default: false) + tb_bool_t zeroend = lua_toboolean(lua, 9); + // do dump tb_bool_t ok = tb_false; tb_stream_ref_t istream = tb_stream_init_from_file(binaryfile, TB_FILE_MODE_RO); @@ -605,7 +624,7 @@ tb_int_t xm_utils_bin2macho(lua_State *lua) { break; } - if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk)) { + if (!xm_utils_bin2macho_dump(istream, ostream, symbol_prefix, plat, arch, basename, minos, sdk, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2macho: dump data failed"); break; diff --git a/tests/projects/other/bin2obj/xmake.lua b/tests/projects/other/bin2obj/xmake.lua index bcd64fff5..e20a329e1 100644 --- a/tests/projects/other/bin2obj/xmake.lua +++ b/tests/projects/other/bin2obj/xmake.lua @@ -6,4 +6,3 @@ target("test") add_files("src/*.c") add_files("src/*.bin") add_files("src/*.png") - diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index b3453cb92..3601c1470 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -160,8 +160,8 @@ end -- generate COFF object file from the binary file if utils.bin2coff then - function sandbox_utils.bin2coff(binaryfile, outputfile, symbol_prefix, arch, basename) - local ok, errors = utils.bin2coff(binaryfile, outputfile, symbol_prefix, arch, basename) + function sandbox_utils.bin2coff(binaryfile, outputfile, symbol_prefix, arch, basename, plat, zeroend) + local ok, errors = utils.bin2coff(binaryfile, outputfile, symbol_prefix, arch, basename, plat, zeroend) if not ok then os.raise(errors) end @@ -170,8 +170,8 @@ end -- generate Mach-O object file from the binary file if utils.bin2macho then - function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) - local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) + function sandbox_utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver, zeroend) + local ok, errors = utils.bin2macho(binaryfile, outputfile, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver, zeroend) if not ok then os.raise(errors) end diff --git a/xmake/modules/private/utils/bin2obj.lua b/xmake/modules/private/utils/bin2obj.lua index a41c919fe..2e2e4bd94 100644 --- a/xmake/modules/private/utils/bin2obj.lua +++ b/xmake/modules/private/utils/bin2obj.lua @@ -29,7 +29,8 @@ local options = { {'a', "arch", "kv", nil, "Set the target architecture."}, {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."}, {nil, "target_minver", "kv", nil, "Set the target minimum version (e.g., 10.0, 18.2)."}, - {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."} + {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."}, + {nil, "zeroend", "k", nil, "Append a null terminator ('\\0') at the end of data."} } function _do_bin2obj_coff(binarypath, outputpath, opt) @@ -42,6 +43,9 @@ function _do_bin2obj_coff(binarypath, outputpath, opt) -- get platform (not used for COFF, but passed for consistency) local platform = opt.plat + -- get zeroend (default: false) + local zeroend = opt.zeroend or false + -- get filename from binary path (with extension, dots replaced with underscores) local filename = path.filename(binarypath) -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) @@ -52,7 +56,7 @@ function _do_bin2obj_coff(binarypath, outputpath, opt) -- do dump if utils.bin2coff then - utils.bin2coff(binarypath, outputpath, symbol_prefix, arch, basename) + utils.bin2coff(binarypath, outputpath, symbol_prefix, arch, basename, platform, zeroend) else raise("bin2obj: utils.bin2coff not available (C implementation not compiled)") end @@ -81,6 +85,9 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- get xcode sdk version (default: nil, will use default 10.0.0 in C) local xcode_sdkver = opt.xcode_sdkver + -- get zeroend (default: false) + local zeroend = opt.zeroend or false + -- get filename from binary path (with extension, dots replaced with underscores) local filename = path.filename(binarypath) -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) @@ -91,7 +98,7 @@ function _do_bin2obj_macho(binarypath, outputpath, opt) -- do dump if utils.bin2macho then - utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver) + utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver, zeroend) else raise("bin2obj: utils.bin2macho not available (C implementation not compiled)") end diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index 1f8e6e0b2..53ceb6a51 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -47,6 +47,9 @@ rule("utils.bin2obj") -- get symbol prefix (default: _binary_) local symbol_prefix = target:extraconf("rules", "utils.bin2obj", "symbol_prefix") or "_binary_" + -- get zeroend (default: false) + local zeroend = target:extraconf("rules", "utils.bin2obj", "zeroend") or false + -- get architecture local arch = target:arch() @@ -81,6 +84,9 @@ rule("utils.bin2obj") if xcode_sdkver then table.insert(argv, "--xcode_sdkver=" .. xcode_sdkver) end + if zeroend then + table.insert(argv, "--zeroend") + end batchcmds:vlua("private.utils.bin2obj", argv) -- add deps -- cgit v1.3.1 From 282349621e4e7c02fa3cb7a6df2d523fbba3c9d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 12:19:22 +0800 Subject: add file zeroend support --- core/src/xmake/utils/bin2macho.c | 2 +- tests/projects/other/bin2obj/xmake.lua | 2 +- xmake/rules/utils/bin2obj/xmake.lua | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'xmake/rules/utils/bin2obj') diff --git a/core/src/xmake/utils/bin2macho.c b/core/src/xmake/utils/bin2macho.c index c0798fa02..07c6fc347 100644 --- a/core/src/xmake/utils/bin2macho.c +++ b/core/src/xmake/utils/bin2macho.c @@ -534,7 +534,7 @@ static tb_bool_t xm_utils_bin2macho_dump_64(tb_stream_ref_t istream, tb_stream_bwrit(ostream, &null, 1); // align string table to 8 bytes - padding = strtab_size - (4 + start_len + 1 + end_len + 1); + padding = strtab_size - (4 + (tb_uint32_t)start_len + 1 + (tb_uint32_t)end_len + 1); if (padding > 0) { tb_byte_t zero = 0; while (padding-- > 0) { diff --git a/tests/projects/other/bin2obj/xmake.lua b/tests/projects/other/bin2obj/xmake.lua index e20a329e1..3f00aebf9 100644 --- a/tests/projects/other/bin2obj/xmake.lua +++ b/tests/projects/other/bin2obj/xmake.lua @@ -4,5 +4,5 @@ target("test") set_kind("binary") add_rules("utils.bin2obj", {extensions = {".bin", ".png"}}) add_files("src/*.c") - add_files("src/*.bin") + add_files("src/data.bin", {zeroend = true}) add_files("src/*.png") diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index 53ceb6a51..d35e50606 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -48,7 +48,9 @@ rule("utils.bin2obj") local symbol_prefix = target:extraconf("rules", "utils.bin2obj", "symbol_prefix") or "_binary_" -- get zeroend (default: false) - local zeroend = target:extraconf("rules", "utils.bin2obj", "zeroend") or 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 -- get architecture local arch = target:arch() -- cgit v1.3.1 From 35aeaac3f956f26f188ebab40c443b64d2cb2f95 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Dec 2025 15:27:27 +0800 Subject: move bin2obj and bin2c modules --- xmake/modules/private/utils/bin2c.lua | 129 ------------------------ xmake/modules/private/utils/bin2obj.lua | 170 -------------------------------- xmake/modules/utils/binary/bin2c.lua | 130 ++++++++++++++++++++++++ xmake/modules/utils/binary/bin2obj.lua | 170 ++++++++++++++++++++++++++++++++ xmake/rules/utils/bin2c/xmake.lua | 2 +- xmake/rules/utils/bin2obj/xmake.lua | 2 +- xmake/rules/utils/glsl2spv/xmake.lua | 2 +- xmake/rules/utils/hlsl2spv/xmake.lua | 2 +- xmake/rules/xmake_cli/xmake.lua | 2 +- 9 files changed, 305 insertions(+), 304 deletions(-) delete mode 100644 xmake/modules/private/utils/bin2c.lua delete mode 100644 xmake/modules/private/utils/bin2obj.lua create mode 100644 xmake/modules/utils/binary/bin2c.lua create mode 100644 xmake/modules/utils/binary/bin2obj.lua (limited to 'xmake/rules/utils/bin2obj') diff --git a/xmake/modules/private/utils/bin2c.lua b/xmake/modules/private/utils/bin2c.lua deleted file mode 100644 index 0d6f06a1d..000000000 --- a/xmake/modules/private/utils/bin2c.lua +++ /dev/null @@ -1,129 +0,0 @@ ---!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 bin2c.lua --- - --- imports -import("core.base.bytes") -import("core.base.option") - -local options = { - {'w', "linewidth", "kv", nil, "Set the line width"}, - {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"}, - {'i', "binarypath", "kv", nil, "Set the binary file path."}, - {'o', "outputpath", "kv", nil, "Set the output file path."} -} - -function _do_dump(binarydata, outputfile, opt) - local i = 0 - local n = 147 - local p = 0 - local e = binarydata:size() - local line = nil - local linewidth = opt.linewidth or 32 - local first = true - while p < e do - line = "" - if p + linewidth <= e then - for i = 0, linewidth - 1 do - if first then - first = false - line = line .. " " - else - line = line .. "," - end - line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) - end - outputfile:print(line) - p = p + linewidth - elseif p < e then - local left = e - p - for i = 0, left - 1 do - if first then - first = false - line = line .. " " - else - line = line .. "," - end - line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) - end - outputfile:print(line) - p = p + left - else - break - end - end -end - -function _do_bin2c(binarypath, outputpath, opt) - - -- init source directory and options - opt = opt or {} - binarypath = path.absolute(binarypath) - outputpath = path.absolute(outputpath) - assert(os.isfile(binarypath), "%s not found!", binarypath) - - -- trace - print("generating code data file from %s ..", binarypath) - - -- optimize the default linewidth for reading large file - if not opt.linewidth then - local filesize = os.filesize(binarypath) - if filesize > 1024 * 1024 * 1024 then - opt.linewidth = 512 - elseif filesize > 100 * 1024 * 1024 then - opt.linewidth = 256 - elseif filesize > 10 * 1024 * 1024 then - opt.linewidth = 128 - elseif filesize > 1024 * 1024 then - opt.linewidth = 64 - else - opt.linewidth = 32 - end - end - - -- do dump - if utils.bin2c then - utils.bin2c(binarypath, outputpath, opt) - else - local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) - local outputfile = io.open(outputpath, 'w') - if outputfile then - if not opt.nozeroend then - binarydata = binarydata .. bytes('\0') - end - _do_dump(binarydata, outputfile, opt) - outputfile:close() - end - end - - -- trace - cprint("${bright}%s generated!", outputpath) -end - -function main(...) - - -- parse arguments - local argv = {...} - local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." - , "" - , "Usage: xmake l private.utils.bin2c [options]") - - -- do bin2c - _do_bin2c(opt.binarypath, opt.outputpath, opt) -end diff --git a/xmake/modules/private/utils/bin2obj.lua b/xmake/modules/private/utils/bin2obj.lua deleted file mode 100644 index caa8b2e22..000000000 --- a/xmake/modules/private/utils/bin2obj.lua +++ /dev/null @@ -1,170 +0,0 @@ ---!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 bin2obj.lua --- - --- imports -import("core.base.option") - -local options = { - {'i', "binarypath", "kv", nil, "Set the binary file path."}, - {'o', "outputpath", "kv", nil, "Set the output object file path."}, - {'f', "format", "kv", nil, "Set the object file format (coff, elf, macho)."}, - {nil, "symbol_prefix", "kv", nil, "Set the symbol prefix (default: _binary_)."}, - {'a', "arch", "kv", nil, "Set the target architecture."}, - {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."}, - {nil, "target_minver", "kv", nil, "Set the target minimum version (e.g., 10.0, 18.2)."}, - {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."}, - {nil, "zeroend", "k", nil, "Append a null terminator ('\\0') at the end of data."} -} - -function _do_bin2obj_coff(binarypath, outputpath, opt) - -- get symbol prefix - local symbol_prefix = opt.symbol_prefix or "_binary_" - - -- get architecture (default: x86_64) - local arch = opt.arch or "x86_64" - - -- get zeroend (default: false) - local zeroend = opt.zeroend or false - - -- get filename from binary path (with extension, dots replaced with underscores) - local filename = path.filename(binarypath) - -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) - local basename = filename:gsub("%.", "_") - - -- trace - print("converting binary file %s to COFF object file %s ..", binarypath, outputpath) - - -- do dump - if utils.bin2coff then - utils.bin2coff(binarypath, outputpath, symbol_prefix, arch, basename, zeroend) - else - raise("bin2obj: utils.bin2coff not available (C implementation not compiled)") - end - - -- trace - cprint("${bright}%s generated!", outputpath) -end - -function _do_bin2obj_elf(binarypath, outputpath, opt) - -- get symbol prefix - local symbol_prefix = opt.symbol_prefix or "_binary_" - - -- get architecture (default: x86_64) - local arch = opt.arch or "x86_64" - - -- get zeroend (default: false) - local zeroend = opt.zeroend or false - - -- get filename from binary path (with extension, dots replaced with underscores) - local filename = path.filename(binarypath) - -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) - local basename = filename:gsub("%.", "_") - - -- trace - print("converting binary file %s to ELF object file %s ..", binarypath, outputpath) - - -- do dump - if utils.bin2elf then - utils.bin2elf(binarypath, outputpath, symbol_prefix, arch, basename, zeroend) - else - raise("bin2obj: utils.bin2elf not available (C implementation not compiled)") - end - - -- trace - cprint("${bright}%s generated!", outputpath) -end - -function _do_bin2obj_macho(binarypath, outputpath, opt) - -- get symbol prefix - local symbol_prefix = opt.symbol_prefix or "_binary_" - - -- get platform (default: macosx) - local plat = opt.plat or "macosx" - - -- get architecture (default: x86_64) - local arch = opt.arch or "x86_64" - - -- get target minimum version (default: nil, will use default 10.0.0 in C) - local target_minver = opt.target_minver - - -- get xcode sdk version (default: nil, will use default 10.0.0 in C) - local xcode_sdkver = opt.xcode_sdkver - - -- get zeroend (default: false) - local zeroend = opt.zeroend or false - - -- get filename from binary path (with extension, dots replaced with underscores) - local filename = path.filename(binarypath) - -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) - local basename = filename:gsub("%.", "_") - - -- trace - print("converting binary file %s to Mach-O object file %s ..", binarypath, outputpath) - - -- do dump - if utils.bin2macho then - utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver, zeroend) - else - raise("bin2obj: utils.bin2macho not available (C implementation not compiled)") - end - - -- trace - cprint("${bright}%s generated!", outputpath) -end - -function _do_bin2obj(binarypath, outputpath, opt) - - -- init source directory and options - opt = opt or {} - binarypath = path.absolute(binarypath) - outputpath = path.absolute(outputpath) - assert(os.isfile(binarypath), "%s not found!", binarypath) - - -- get format (default: coff) - local format = opt.format or "coff" - format = format:lower() - - -- validate format - if format ~= "coff" and format ~= "elf" and format ~= "macho" then - raise("bin2obj: unsupported format '%s' (supported: coff, elf, macho)", format) - end - - -- do conversion based on format - if format == "coff" then - _do_bin2obj_coff(binarypath, outputpath, opt) - elseif format == "elf" then - _do_bin2obj_elf(binarypath, outputpath, opt) - elseif format == "macho" then - _do_bin2obj_macho(binarypath, outputpath, opt) - end -end - -function main(...) - - -- parse arguments - local argv = {...} - local opt = option.parse(argv, options, "Convert binary file to object file for direct linking." - , "" - , "Usage: xmake l private.utils.bin2obj [options]") - - -- do bin2obj - _do_bin2obj(opt.binarypath, opt.outputpath, opt) -end - diff --git a/xmake/modules/utils/binary/bin2c.lua b/xmake/modules/utils/binary/bin2c.lua new file mode 100644 index 000000000..ce7336e36 --- /dev/null +++ b/xmake/modules/utils/binary/bin2c.lua @@ -0,0 +1,130 @@ +--!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 bin2c.lua +-- + +-- imports +import("core.base.bytes") +import("core.base.option") + +local options = { + {'w', "linewidth", "kv", nil, "Set the line width"}, + {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"}, + {'i', "binarypath", "kv", nil, "Set the binary file path."}, + {'o', "outputpath", "kv", nil, "Set the output file path."} +} + +function _do_dump(binarydata, outputfile, opt) + local i = 0 + local n = 147 + local p = 0 + local e = binarydata:size() + local line = nil + local linewidth = opt.linewidth or 32 + local first = true + while p < e do + line = "" + if p + linewidth <= e then + for i = 0, linewidth - 1 do + if first then + first = false + line = line .. " " + else + line = line .. "," + end + line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) + end + outputfile:print(line) + p = p + linewidth + elseif p < e then + local left = e - p + for i = 0, left - 1 do + if first then + first = false + line = line .. " " + else + line = line .. "," + end + line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) + end + outputfile:print(line) + p = p + left + else + break + end + end +end + +function _do_bin2c(binarypath, outputpath, opt) + + -- init source directory and options + opt = opt or {} + binarypath = path.absolute(binarypath) + outputpath = path.absolute(outputpath) + assert(os.isfile(binarypath), "%s not found!", binarypath) + + -- trace + print("generating code data file from %s ..", binarypath) + + -- optimize the default linewidth for reading large file + if not opt.linewidth then + local filesize = os.filesize(binarypath) + if filesize > 1024 * 1024 * 1024 then + opt.linewidth = 512 + elseif filesize > 100 * 1024 * 1024 then + opt.linewidth = 256 + elseif filesize > 10 * 1024 * 1024 then + opt.linewidth = 128 + elseif filesize > 1024 * 1024 then + opt.linewidth = 64 + else + opt.linewidth = 32 + end + end + + -- do dump + if utils.bin2c then + utils.bin2c(binarypath, outputpath, opt) + else + local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) + local outputfile = io.open(outputpath, 'w') + if outputfile then + if not opt.nozeroend then + binarydata = binarydata .. bytes('\0') + end + _do_dump(binarydata, outputfile, opt) + outputfile:close() + end + end + + -- trace + cprint("${bright}%s generated!", outputpath) +end + +function main(...) + + -- parse arguments + local argv = {...} + local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." + , "" + , "Usage: xmake l utils.binary.bin2c [options]") + + -- do bin2c + _do_bin2c(opt.binarypath, opt.outputpath, opt) +end + diff --git a/xmake/modules/utils/binary/bin2obj.lua b/xmake/modules/utils/binary/bin2obj.lua new file mode 100644 index 000000000..afb04dc3b --- /dev/null +++ b/xmake/modules/utils/binary/bin2obj.lua @@ -0,0 +1,170 @@ +--!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 bin2obj.lua +-- + +-- imports +import("core.base.option") + +local options = { + {'i', "binarypath", "kv", nil, "Set the binary file path."}, + {'o', "outputpath", "kv", nil, "Set the output object file path."}, + {'f', "format", "kv", nil, "Set the object file format (coff, elf, macho)."}, + {nil, "symbol_prefix", "kv", nil, "Set the symbol prefix (default: _binary_)."}, + {'a', "arch", "kv", nil, "Set the target architecture."}, + {'p', "plat", "kv", nil, "Set the target platform (macosx, iphoneos, etc.)."}, + {nil, "target_minver", "kv", nil, "Set the target minimum version (e.g., 10.0, 18.2)."}, + {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."}, + {nil, "zeroend", "k", nil, "Append a null terminator ('\\0') at the end of data."} +} + +function _do_bin2obj_coff(binarypath, outputpath, opt) + -- get symbol prefix + local symbol_prefix = opt.symbol_prefix or "_binary_" + + -- get architecture (default: x86_64) + local arch = opt.arch or "x86_64" + + -- get zeroend (default: false) + local zeroend = opt.zeroend or false + + -- get filename from binary path (with extension, dots replaced with underscores) + local filename = path.filename(binarypath) + -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) + local basename = filename:gsub("%.", "_") + + -- trace + print("converting binary file %s to COFF object file %s ..", binarypath, outputpath) + + -- do dump + if utils.bin2coff then + utils.bin2coff(binarypath, outputpath, symbol_prefix, arch, basename, zeroend) + else + raise("bin2obj: utils.bin2coff not available (C implementation not compiled)") + end + + -- trace + cprint("${bright}%s generated!", outputpath) +end + +function _do_bin2obj_elf(binarypath, outputpath, opt) + -- get symbol prefix + local symbol_prefix = opt.symbol_prefix or "_binary_" + + -- get architecture (default: x86_64) + local arch = opt.arch or "x86_64" + + -- get zeroend (default: false) + local zeroend = opt.zeroend or false + + -- get filename from binary path (with extension, dots replaced with underscores) + local filename = path.filename(binarypath) + -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) + local basename = filename:gsub("%.", "_") + + -- trace + print("converting binary file %s to ELF object file %s ..", binarypath, outputpath) + + -- do dump + if utils.bin2elf then + utils.bin2elf(binarypath, outputpath, symbol_prefix, arch, basename, zeroend) + else + raise("bin2obj: utils.bin2elf not available (C implementation not compiled)") + end + + -- trace + cprint("${bright}%s generated!", outputpath) +end + +function _do_bin2obj_macho(binarypath, outputpath, opt) + -- get symbol prefix + local symbol_prefix = opt.symbol_prefix or "_binary_" + + -- get platform (default: macosx) + local plat = opt.plat or "macosx" + + -- get architecture (default: x86_64) + local arch = opt.arch or "x86_64" + + -- get target minimum version (default: nil, will use default 10.0.0 in C) + local target_minver = opt.target_minver + + -- get xcode sdk version (default: nil, will use default 10.0.0 in C) + local xcode_sdkver = opt.xcode_sdkver + + -- get zeroend (default: false) + local zeroend = opt.zeroend or false + + -- get filename from binary path (with extension, dots replaced with underscores) + local filename = path.filename(binarypath) + -- replace dots with underscores for symbol name (e.g., data.bin -> data_bin) + local basename = filename:gsub("%.", "_") + + -- trace + print("converting binary file %s to Mach-O object file %s ..", binarypath, outputpath) + + -- do dump + if utils.bin2macho then + utils.bin2macho(binarypath, outputpath, symbol_prefix, plat, arch, basename, target_minver, xcode_sdkver, zeroend) + else + raise("bin2obj: utils.bin2macho not available (C implementation not compiled)") + end + + -- trace + cprint("${bright}%s generated!", outputpath) +end + +function _do_bin2obj(binarypath, outputpath, opt) + + -- init source directory and options + opt = opt or {} + binarypath = path.absolute(binarypath) + outputpath = path.absolute(outputpath) + assert(os.isfile(binarypath), "%s not found!", binarypath) + + -- get format (default: coff) + local format = opt.format or "coff" + format = format:lower() + + -- validate format + if format ~= "coff" and format ~= "elf" and format ~= "macho" then + raise("bin2obj: unsupported format '%s' (supported: coff, elf, macho)", format) + end + + -- do conversion based on format + if format == "coff" then + _do_bin2obj_coff(binarypath, outputpath, opt) + elseif format == "elf" then + _do_bin2obj_elf(binarypath, outputpath, opt) + elseif format == "macho" then + _do_bin2obj_macho(binarypath, outputpath, opt) + end +end + +function main(...) + + -- parse arguments + local argv = {...} + local opt = option.parse(argv, options, "Convert binary file to object file for direct linking." + , "" + , "Usage: xmake l utils.binary.bin2obj [options]") + + -- do bin2obj + _do_bin2obj(opt.binarypath, opt.outputpath, opt) +end + diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index fc05ecf4e..7be711af1 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -54,7 +54,7 @@ rule("utils.bin2c") if nozeroend then table.insert(argv, "--nozeroend") end - batchcmds:vlua("private.utils.bin2c", argv) + batchcmds:vlua("utils.binary.bin2c", argv) -- add deps batchcmds:add_depfiles(sourcefile_bin) diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index d35e50606..69fd9e717 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -89,7 +89,7 @@ rule("utils.bin2obj") if zeroend then table.insert(argv, "--zeroend") end - batchcmds:vlua("private.utils.bin2obj", argv) + batchcmds:vlua("utils.binary.bin2obj", argv) -- add deps batchcmds:add_depfiles(sourcefile_bin) diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua index dfd1779fe..a6c4a2aef 100644 --- a/xmake/rules/utils/glsl2spv/xmake.lua +++ b/xmake/rules/utils/glsl2spv/xmake.lua @@ -86,7 +86,7 @@ rule("utils.glsl2spv") -- add commands local argv = {"--nozeroend", "-i", path(spvfilepath), "-o", path(headerfile)} - batchcmds:vlua("private.utils.bin2c", argv) + batchcmds:vlua("utils.binary.bin2c", argv) end -- add deps diff --git a/xmake/rules/utils/hlsl2spv/xmake.lua b/xmake/rules/utils/hlsl2spv/xmake.lua index 2b285d893..4af520420 100644 --- a/xmake/rules/utils/hlsl2spv/xmake.lua +++ b/xmake/rules/utils/hlsl2spv/xmake.lua @@ -86,7 +86,7 @@ rule("utils.hlsl2spv") -- add commands local argv = {"--nozeroend", "-i", path(spvfilepath), "-o", path(headerfile)} - batchcmds:vlua("private.utils.bin2c", argv) + batchcmds:vlua("utils.binary.bin2c", argv) end batchcmds:add_depfiles(sourcefile_hlsl) diff --git a/xmake/rules/xmake_cli/xmake.lua b/xmake/rules/xmake_cli/xmake.lua index d3a4b6f26..7c543cb36 100644 --- a/xmake/rules/xmake_cli/xmake.lua +++ b/xmake/rules/xmake_cli/xmake.lua @@ -55,7 +55,7 @@ rule("xmake.cli") local headerfile = path.join(headerdir, "luafiles.xmz.h") target:add("includedirs", headerdir) argv = {"--nozeroend", "-i", path(archivefile), "-o", path(headerfile)} - batchcmds:vlua("private.utils.bin2c", argv) + batchcmds:vlua("utils.binary.bin2c", argv) batchcmds:add_depfiles(sourcefiles) batchcmds:set_depmtime(os.mtime(dependfile)) -- cgit v1.3.1