summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2024-05-20 07:44:24 +0800
committerGitHub <[email protected]>2024-05-20 07:44:24 +0800
commit782baf43d356e96ba8eb001e3218e625d5f1e44d (patch)
tree610cc5fb68689e2ab35fec5d61330ec9d6f159cb
parent0a965dfa5ad4c0ba34dab7624fbe1852e61782b6 (diff)
parentdad8fe9b2acda84bfbead2a05a8b0d4b504d6479 (diff)
Merge pull request #5119 from xmake-io/export
improve utils.symbols.export_all to support clang/objdump
-rw-r--r--tests/projects/c++/shared_library_export_all/src/bar.cpp5
-rw-r--r--tests/projects/c++/shared_library_export_all/src/bar.h4
-rw-r--r--tests/projects/c++/shared_library_export_all/src/foo.cpp3
-rw-r--r--tests/projects/c++/shared_library_export_all/src/foo.h3
-rw-r--r--tests/projects/c++/shared_library_export_all/src/main.cpp9
-rw-r--r--tests/projects/c++/shared_library_export_all/xmake.lua11
-rw-r--r--xmake/rules/utils/symbols/export_all/export_all.lua138
7 files changed, 127 insertions, 46 deletions
diff --git a/tests/projects/c++/shared_library_export_all/src/bar.cpp b/tests/projects/c++/shared_library_export_all/src/bar.cpp
new file mode 100644
index 000000000..a3065ed8b
--- /dev/null
+++ b/tests/projects/c++/shared_library_export_all/src/bar.cpp
@@ -0,0 +1,5 @@
+#include "bar.h"
+
+int bar::add(int a, int b) {
+ return a + b;
+}
diff --git a/tests/projects/c++/shared_library_export_all/src/bar.h b/tests/projects/c++/shared_library_export_all/src/bar.h
new file mode 100644
index 000000000..687386e0a
--- /dev/null
+++ b/tests/projects/c++/shared_library_export_all/src/bar.h
@@ -0,0 +1,4 @@
+class bar {
+public:
+ static int add(int a, int b);
+};
diff --git a/tests/projects/c++/shared_library_export_all/src/foo.cpp b/tests/projects/c++/shared_library_export_all/src/foo.cpp
index 3ab50856c..46635f458 100644
--- a/tests/projects/c++/shared_library_export_all/src/foo.cpp
+++ b/tests/projects/c++/shared_library_export_all/src/foo.cpp
@@ -1,6 +1,5 @@
#include "foo.h"
-int test::add(int a, int b)
-{
+int foo::add(int a, int b) {
return a + b;
}
diff --git a/tests/projects/c++/shared_library_export_all/src/foo.h b/tests/projects/c++/shared_library_export_all/src/foo.h
index f671c7d32..e27636b94 100644
--- a/tests/projects/c++/shared_library_export_all/src/foo.h
+++ b/tests/projects/c++/shared_library_export_all/src/foo.h
@@ -1,5 +1,4 @@
-class test
-{
+class foo {
public:
static int add(int a, int b);
};
diff --git a/tests/projects/c++/shared_library_export_all/src/main.cpp b/tests/projects/c++/shared_library_export_all/src/main.cpp
index e48f4730e..cc95897ee 100644
--- a/tests/projects/c++/shared_library_export_all/src/main.cpp
+++ b/tests/projects/c++/shared_library_export_all/src/main.cpp
@@ -1,10 +1,9 @@
#include "foo.h"
+#include "bar.h"
#include <iostream>
-using namespace std;
-
-int main(int argc, char** argv)
-{
- cout << "add(1, 2) = " << test::add(1, 2) << endl;
+int main(int argc, char** argv) {
+ std::cout << "foo::add(1, 2) = " << foo::add(1, 2) << std::endl;
+ std::cout << "bar::add(1, 2) = " << bar::add(1, 2) << std::endl;
return 0;
}
diff --git a/tests/projects/c++/shared_library_export_all/xmake.lua b/tests/projects/c++/shared_library_export_all/xmake.lua
index fa25fac50..73159d4b5 100644
--- a/tests/projects/c++/shared_library_export_all/xmake.lua
+++ b/tests/projects/c++/shared_library_export_all/xmake.lua
@@ -5,9 +5,18 @@ target("foo")
add_files("src/foo.cpp")
add_rules("utils.symbols.export_all", {export_classes = true})
+target("bar")
+ set_kind("shared")
+ add_files("src/bar.cpp")
+ add_rules("utils.symbols.export_all", {export_filter = function (symbol)
+ if symbol:find("add", 1, true) then
+ return true
+ end
+ end})
+
target("demo")
set_kind("binary")
- add_deps("foo")
+ add_deps("foo", "bar")
add_files("src/main.cpp")
diff --git a/xmake/rules/utils/symbols/export_all/export_all.lua b/xmake/rules/utils/symbols/export_all/export_all.lua
index 14ea99211..9376e557e 100644
--- a/xmake/rules/utils/symbols/export_all/export_all.lua
+++ b/xmake/rules/utils/symbols/export_all/export_all.lua
@@ -26,6 +26,90 @@ 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
+ local export_filter = opt.export_filter
+ 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 export_filter then
+ if export_filter(symbol) then
+ allsymbols:insert(symbol)
+ end
+ elseif 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
+
+-- use objdump to get all symbols from object files
+function _get_allsymbols_by_objdump(target, objdump, opt)
+ opt = opt or {}
+ local allsymbols = hashset.new()
+ local export_classes = opt.export_classes
+ local export_filter = opt.export_filter
+ for _, objectfile in ipairs(target:objectfiles()) do
+ local objectsymbols = try { function () return os.iorunv(objdump, {"--syms", objectfile}) end }
+ if objectsymbols then
+ for _, line in ipairs(objectsymbols:split('\n', {plain = true})) do
+ if line:find("(scl 2)", 1, true) then
+ local splitinfo = line:split("%s")
+ local symbol = splitinfo[#splitinfo]
+ if symbol then
+ if export_filter then
+ if export_filter(symbol) then
+ allsymbols:insert(symbol)
+ end
+ elseif 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 +127,29 @@ 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
+ -- the export filter
+ local export_filter = target:extraconf("rules", "utils.symbols.export_all", "export_filter")
+
+ -- 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,
+ export_filter = export_filter})
+ elseif target:has_tool("cc", "clang", "clang_cl", "clangxx", "gcc", "gxx") then
+ local objdump = assert(find_tool("llvm-objdump") or find_tool("objdump"), "objdump not found!")
+ allsymbols = _get_allsymbols_by_objdump(target, objdump.program, {
+ export_classes = export_classes,
+ export_filter = export_filter})
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
@@ -97,3 +162,4 @@ function main(target, opt)
end, {dependfile = dependfile, files = target:objectfiles(), changed = target:is_rebuilt()})
end
+