diff options
| author | ruki <[email protected]> | 2025-12-11 23:35:23 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 09:00:44 +0800 |
| commit | 4ccb8514f37fdf7108b41dbcd8ca77143841e1cd (patch) | |
| tree | ff1b1ae7433fa16acb2bfccffcf4bebc4e9b8b98 | |
| parent | 409b21826872503ef479848321003d7ca4c1aad8 (diff) | |
set plain as default
| -rw-r--r-- | core/src/xmake/binutils/extractlib.c | 17 | ||||
| -rw-r--r-- | core/src/xmake/binutils/mslib/extractlib.c | 88 | ||||
| -rw-r--r-- | xmake/core/base/binutils.lua | 6 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/binutils.lua | 4 | ||||
| -rw-r--r-- | xmake/modules/utils/binary/extractlib.lua | 11 |
5 files changed, 112 insertions, 14 deletions
diff --git a/core/src/xmake/binutils/extractlib.c b/core/src/xmake/binutils/extractlib.c index d5e8b3759..ec588f213 100644 --- a/core/src/xmake/binutils/extractlib.c +++ b/core/src/xmake/binutils/extractlib.c @@ -36,7 +36,7 @@ * forward declarations */ extern tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outputdir); -extern tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t const *outputdir); +extern tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t const *outputdir, tb_bool_t plain); /* ////////////////////////////////////////////////////////////////////////////////////// * implementation @@ -46,6 +46,11 @@ extern tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t co * Supports AR format (.a) and MSVC lib format (.lib) * * @param lua the lua state + * + * libraryfile = lua[1] + * outputdir = lua[2] + * plain = lua[3] (optional, default: true) + * * @return 1 on success, 2 on failure (with error message) */ tb_int_t xm_binutils_extractlib(lua_State *lua) { @@ -59,6 +64,12 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) { tb_char_t const *outputdir = luaL_checkstring(lua, 2); tb_check_return_val(outputdir, 0); + // get the plain mode (optional) + tb_bool_t plain = tb_true; + if (lua_gettop(lua) >= 3 && !lua_isnil(lua, 3)) { + plain = lua_toboolean(lua, 3); + } + // open library file tb_stream_ref_t istream = tb_stream_init_from_file(libraryfile, TB_FILE_MODE_RO); if (!istream) { @@ -88,7 +99,7 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) { // if the file extension is .lib, we use the msvc lib extractor to support long paths and subdirectories tb_size_t n = tb_strlen(libraryfile); if (n > 4 && !tb_strnicmp(libraryfile + n - 4, ".lib", 4)) { - if (!xm_binutils_mslib_extract(istream, outputdir)) { + if (!xm_binutils_mslib_extract(istream, outputdir, plain)) { error_msg = "extract MSVC lib failed"; break; } @@ -105,7 +116,7 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) { // MSVC lib files can be: // 1. Import libraries (different format) // 2. Static libraries (COFF archive format, similar to AR but different) - if (!xm_binutils_mslib_extract(istream, outputdir)) { + if (!xm_binutils_mslib_extract(istream, outputdir, plain)) { error_msg = "extract MSVC lib failed"; break; } diff --git a/core/src/xmake/binutils/mslib/extractlib.c b/core/src/xmake/binutils/mslib/extractlib.c index f56d3eb3e..5dec97f3e 100644 --- a/core/src/xmake/binutils/mslib/extractlib.c +++ b/core/src/xmake/binutils/mslib/extractlib.c @@ -34,13 +34,49 @@ * implementation */ +/* generate unique name for output file + * + * @param base_name the base name + * @param id the unique id + * @param output output buffer + * @param output_size output buffer size + * @param output_len output: actual output length + * @return tb_true on success, tb_false on failure + */ +static tb_bool_t xm_binutils_mslib_generate_unique_name(tb_char_t const *base_name, tb_uint32_t id, tb_char_t *output, tb_size_t output_size, tb_size_t* output_len) { + tb_assert_and_check_return_val(base_name && output && output_size > 0 && output_len, tb_false); + + // find the last dot for extension + tb_char_t const *ext = tb_strrchr(base_name, '.'); + tb_long_t n = -1; + if (ext) { + tb_size_t base_len = (tb_size_t)(ext - base_name); + tb_size_t ext_len = tb_strlen(ext); + if (base_len + ext_len + 16 < output_size) { + n = tb_snprintf(output, output_size, "%.*s_%u%s", (tb_int_t)base_len, base_name, id, ext); + } + } else { + // no extension + if (tb_strlen(base_name) + 16 < output_size) { + n = tb_snprintf(output, output_size, "%s_%u", base_name, id); + } + } + + if (n >= 0) { + *output_len = (tb_size_t)n; + return tb_true; + } + return tb_false; +} + /* extract MSVC lib archive to directory * * @param istream the input stream * @param outputdir the output directory + * @param plain extract all object files to the same directory * @return tb_true on success, tb_false on failure */ -tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t const *outputdir) { +tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t const *outputdir, tb_bool_t plain) { tb_assert_and_check_return_val(istream && outputdir, tb_false); // check magic (!<arch>\n) @@ -158,11 +194,53 @@ tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t const *ou // check output path length tb_char_t output_path[1024]; - if (tb_strlen(outputdir) + 1 + name_len >= sizeof(output_path)) { - ok = tb_false; - break; + if (plain) { + // get filename only + tb_char_t const* name = tb_strrchr(member_name, '/'); + if (name) name++; + else name = member_name; + + // check conflicts + tb_char_t output_name[512]; + tb_size_t output_name_len = tb_strlen(name); + tb_size_t outputdir_len = tb_strlen(outputdir); + + if (outputdir_len + 1 + output_name_len >= sizeof(output_path)) { + ok = tb_false; + break; + } + tb_snprintf(output_path, sizeof(output_path), "%s/%s", outputdir, name); + + if (tb_file_info(output_path, tb_null)) { + // name conflict, try different IDs + tb_uint32_t conflict_id = 1; + while (conflict_id < 10000) { + if (!xm_binutils_mslib_generate_unique_name(name, conflict_id, output_name, sizeof(output_name), &output_name_len)) { + ok = tb_false; + break; + } + if (outputdir_len + 1 + output_name_len >= sizeof(output_path)) { + ok = tb_false; + break; + } + tb_snprintf(output_path, sizeof(output_path), "%s/%s", outputdir, output_name); + if (!tb_file_info(output_path, tb_null)) { + break; + } + conflict_id++; + } + if (!ok || conflict_id >= 10000) { + ok = tb_false; + break; + } + } + } else { + if (tb_strlen(outputdir) + 1 + name_len >= sizeof(output_path)) { + ok = tb_false; + break; + } + tb_snprintf(output_path, sizeof(output_path), "%s/%s", outputdir, member_name); } - tb_snprintf(output_path, sizeof(output_path), "%s/%s", outputdir, member_name); // ensure directory exists tb_char_t const* p = tb_strrchr(output_path, '/'); diff --git a/xmake/core/base/binutils.lua b/xmake/core/base/binutils.lua index ea5d04ba8..9ddcfcf0c 100644 --- a/xmake/core/base/binutils.lua +++ b/xmake/core/base/binutils.lua @@ -105,10 +105,12 @@ end -- Supports AR format (.a) and MSVC lib format (.lib) -- @param libraryfile the static library file path (.a or .lib) -- @param outputdir the output directory to extract object files +-- @param opt the options (optional) +-- - plain: extract all object files to the same directory (default: true) -- @return true on success, false and error message on failure -function binutils.extractlib(libraryfile, outputdir) +function binutils.extractlib(libraryfile, outputdir, opt) if binutils._extractlib then - local ok, errors = binutils._extractlib(libraryfile, outputdir) + local ok, errors = binutils._extractlib(libraryfile, outputdir, opt and opt.plain) if ok then return true else diff --git a/xmake/core/sandbox/modules/import/core/base/binutils.lua b/xmake/core/sandbox/modules/import/core/base/binutils.lua index e2306a2da..5bc0e4f72 100644 --- a/xmake/core/sandbox/modules/import/core/base/binutils.lua +++ b/xmake/core/sandbox/modules/import/core/base/binutils.lua @@ -53,8 +53,8 @@ function sandbox_core_base_binutils.readsyms(binaryfile) end -- extract static library to directory -function sandbox_core_base_binutils.extractlib(libraryfile, outputdir) - local ok, errors = binutils.extractlib(libraryfile, outputdir) +function sandbox_core_base_binutils.extractlib(libraryfile, outputdir, opt) + local ok, errors = binutils.extractlib(libraryfile, outputdir, opt) if not ok then raise("extractlib: %s", errors or "unknown errors") end diff --git a/xmake/modules/utils/binary/extractlib.lua b/xmake/modules/utils/binary/extractlib.lua index 9097db73a..818d343bc 100644 --- a/xmake/modules/utils/binary/extractlib.lua +++ b/xmake/modules/utils/binary/extractlib.lua @@ -21,7 +21,14 @@ -- imports import("core.base.binutils") -function main(libraryfile, outputdir) +-- extract static library to directory +-- +-- @param libraryfile the static library file path (.a or .lib) +-- @param outputdir the output directory to extract object files +-- @param opt the options (optional) +-- - plain: extract all object files to the same directory (default: true) +-- +function main(libraryfile, outputdir, opt) -- init paths libraryfile = path.absolute(libraryfile) outputdir = path.absolute(outputdir) @@ -36,7 +43,7 @@ function main(libraryfile, outputdir) print("extracting static library %s to %s ..", libraryfile, outputdir) -- do extraction - binutils.extractlib(libraryfile, outputdir) + binutils.extractlib(libraryfile, outputdir, opt) -- trace cprint("${bright}extraction completed!") |
