From a5cf8c2bb716632c27f75aff173d1684ea5c679b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 19 May 2024 22:28:21 +0800 Subject: improve to export symbols --- .../rules/utils/symbols/export_all/export_all.lua | 81 ++++++++++++---------- 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'xmake/rules/utils') diff --git a/xmake/rules/utils/symbols/export_all/export_all.lua b/xmake/rules/utils/symbols/export_all/export_all.lua index 14ea99211..b67a415c8 100644 --- a/xmake/rules/utils/symbols/export_all/export_all.lua +++ b/xmake/rules/utils/symbols/export_all/export_all.lua @@ -26,6 +26,44 @@ import("core.base.hashset") import("core.project.depend") import("utils.progress") +-- use dumpbin to get all symbols from object files +function _get_allsymbols_by_dumpbin(target, dumpbin, opt) + opt = opt or {} + local allsymbols = hashset.new() + local export_classes = opt.export_classes + for _, objectfile in ipairs(target:objectfiles()) do + local objectsymbols = try { function () return os.iorunv(dumpbin, {"/symbols", "/nologo", objectfile}) end } + if objectsymbols then + for _, line in ipairs(objectsymbols:split('\n', {plain = true})) do + -- https://docs.microsoft.com/en-us/cpp/build/reference/symbols + -- 008 00000000 SECT3 notype () External | add + if line:find("External") and not line:find("UNDEF") then + local symbol = line:match(".*External%s+| (.*)") + if symbol then + symbol = symbol:split('%s')[1] + if not symbol:startswith("__") then + -- we need ignore DllMain, https://github.com/xmake-io/xmake/issues/3992 + if target:is_arch("x86") and symbol:startswith("_") and not symbol:startswith("_DllMain@") then + symbol = symbol:sub(2) + end + if export_classes or not symbol:startswith("?") then + if export_classes then + if not symbol:startswith("??_G") and not symbol:startswith("??_E") then + allsymbols:insert(symbol) + end + else + allsymbols:insert(symbol) + end + end + end + end + end + end + end + end + return allsymbols +end + -- export all symbols for dynamic library function main(target, opt) @@ -43,48 +81,19 @@ function main(target, opt) -- trace progress info progress.show(opt.progress, "${color.build.target}exporting.$(mode) %s", path.filename(target:targetfile())) - -- get dumpbin - local msvc = toolchain.load("msvc", {plat = target:plat(), arch = target:arch()}) - local dumpbin = assert(find_tool("dumpbin", {envs = msvc:runenvs()}), "dumpbin not found!") - -- export c++ class? local export_classes = target:extraconf("rules", "utils.symbols.export_all", "export_classes") - -- get all symbols from object files - local allsymbols = hashset.new() - for _, objectfile in ipairs(target:objectfiles()) do - local objectsymbols = try { function () return os.iorunv(dumpbin.program, {"/symbols", "/nologo", objectfile}) end } - if objectsymbols then - for _, line in ipairs(objectsymbols:split('\n', {plain = true})) do - -- https://docs.microsoft.com/en-us/cpp/build/reference/symbols - -- 008 00000000 SECT3 notype () External | add - if line:find("External") and not line:find("UNDEF") then - local symbol = line:match(".*External%s+| (.*)") - if symbol then - symbol = symbol:split('%s')[1] - if not symbol:startswith("__") then - -- we need ignore DllMain, https://github.com/xmake-io/xmake/issues/3992 - if target:is_arch("x86") and symbol:startswith("_") and not symbol:startswith("_DllMain@") then - symbol = symbol:sub(2) - end - if export_classes or not symbol:startswith("?") then - if export_classes then - if not symbol:startswith("??_G") and not symbol:startswith("??_E") then - allsymbols:insert(symbol) - end - else - allsymbols:insert(symbol) - end - end - end - end - end - end - end + -- get all symbols + local allsymbols + local msvc = toolchain.load("msvc", {plat = target:plat(), arch = target:arch()}) + if msvc:check() then + local dumpbin = assert(find_tool("dumpbin", {envs = msvc:runenvs()}), "dumpbin not found!") + allsymbols = _get_allsymbols_by_dumpbin(target, dumpbin.program, {export_classes = export_classes}) end -- export all symbols - if allsymbols:size() > 0 then + if allsymbols and allsymbols:size() > 0 then local allsymbols_file = io.open(allsymbols_filepath, 'w') allsymbols_file:print("EXPORTS") for _, symbol in allsymbols:keys() do -- cgit v1.3.1