summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-03-02 16:14:48 +0800
committerGitHub <[email protected]>2022-03-02 16:14:48 +0800
commitf46a4b4a6e5aa5146d46c89987859715f692c727 (patch)
treecad88ae6821223ef927c67a43323f72ac8341226
parent0a707bfb27db9d87a8063985f4623c0ed4a81a07 (diff)
parentf6a48a7481bffa3f8b97ac9cd509eb7f4c202559 (diff)
Merge pull request #2118 from xmake-io/export
add export symbols list rule
-rw-r--r--tests/modules/table/test.lua20
-rw-r--r--tests/projects/c/shared_library_export_all/xmake.lua2
-rw-r--r--tests/projects/c/shared_library_export_list/src/foo.c14
-rw-r--r--tests/projects/c/shared_library_export_list/src/foo.export.txt2
-rw-r--r--tests/projects/c/shared_library_export_list/src/foo.h9
-rw-r--r--tests/projects/c/shared_library_export_list/src/main.c8
-rw-r--r--tests/projects/c/shared_library_export_list/test.lua3
-rw-r--r--tests/projects/c/shared_library_export_list/xmake.lua21
-rw-r--r--xmake/core/base/interpreter.lua24
-rw-r--r--xmake/core/base/scopeinfo.lua24
-rw-r--r--xmake/core/base/table.lua42
-rw-r--r--xmake/rules/c++/modules/build_modules/msvc.lua2
-rw-r--r--xmake/rules/utils/symbols/export_list/xmake.lua107
13 files changed, 247 insertions, 31 deletions
diff --git a/tests/modules/table/test.lua b/tests/modules/table/test.lua
index 5ed17620c..569f18e50 100644
--- a/tests/modules/table/test.lua
+++ b/tests/modules/table/test.lua
@@ -9,3 +9,23 @@ function test_find_if(t)
t:are_equal(table.find({1, 2, 4, 4, 5, 6}, 4), {3, 4})
t:are_equal(table.find_first({1, 2, 3, 4, 5, 6}, 4), 4)
end
+
+function test_wrap(t)
+ t:are_equal(table.wrap(1), {1})
+ t:are_equal(table.wrap(nil), {})
+ t:are_equal(table.wrap({}), {})
+ t:are_equal(table.wrap({1}), {1})
+ t:are_equal(table.wrap({{}}), {{}})
+ local a = table.wraplock({1})
+ t:are_equal(table.wrap({a}), {a})
+end
+
+function test_unwrap(t)
+ t:are_equal(table.unwrap(1), 1)
+ t:are_equal(table.unwrap(nil), nil)
+ t:are_equal(table.unwrap({}), {})
+ t:are_equal(table.unwrap({1}), 1)
+ t:are_equal(table.unwrap({{}}), {})
+ local a = table.wraplock({1})
+ t:are_equal(table.unwrap(a), a)
+end
diff --git a/tests/projects/c/shared_library_export_all/xmake.lua b/tests/projects/c/shared_library_export_all/xmake.lua
index 6466a16fc..2797d2024 100644
--- a/tests/projects/c/shared_library_export_all/xmake.lua
+++ b/tests/projects/c/shared_library_export_all/xmake.lua
@@ -3,7 +3,7 @@ add_rules("mode.release", "mode.debug")
target("foo")
set_kind("shared")
add_files("src/foo.c", "src/bar.cpp")
- add_rules("utils.symbols.export_all", {class = true})
+ add_rules("utils.symbols.export_all", {export_classes = true})
target("test")
set_kind("binary")
diff --git a/tests/projects/c/shared_library_export_list/src/foo.c b/tests/projects/c/shared_library_export_list/src/foo.c
new file mode 100644
index 000000000..e068c1983
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/src/foo.c
@@ -0,0 +1,14 @@
+#include "foo.h"
+#include <stdio.h>
+
+void stub() {
+ printf("stub\n");
+}
+
+int sub(int a, int b) {
+ return a - b;
+}
+
+int add(int a, int b) {
+ return a + b;
+}
diff --git a/tests/projects/c/shared_library_export_list/src/foo.export.txt b/tests/projects/c/shared_library_export_list/src/foo.export.txt
new file mode 100644
index 000000000..f8c70f59e
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/src/foo.export.txt
@@ -0,0 +1,2 @@
+add
+sub
diff --git a/tests/projects/c/shared_library_export_list/src/foo.h b/tests/projects/c/shared_library_export_list/src/foo.h
new file mode 100644
index 000000000..d2506bca9
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/src/foo.h
@@ -0,0 +1,9 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int add(int a, int b);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/projects/c/shared_library_export_list/src/main.c b/tests/projects/c/shared_library_export_list/src/main.c
new file mode 100644
index 000000000..1e52e7a81
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/src/main.c
@@ -0,0 +1,8 @@
+#include "foo.h"
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+ printf("add(1, 2) = %d\n", add(1, 2));
+ return 0;
+}
diff --git a/tests/projects/c/shared_library_export_list/test.lua b/tests/projects/c/shared_library_export_list/test.lua
new file mode 100644
index 000000000..b57362078
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/test.lua
@@ -0,0 +1,3 @@
+function main(t)
+ t:build()
+end
diff --git a/tests/projects/c/shared_library_export_list/xmake.lua b/tests/projects/c/shared_library_export_list/xmake.lua
new file mode 100644
index 000000000..b48e131c2
--- /dev/null
+++ b/tests/projects/c/shared_library_export_list/xmake.lua
@@ -0,0 +1,21 @@
+add_rules("mode.release", "mode.debug")
+
+target("foo")
+ set_kind("shared")
+ add_files("src/foo.c")
+ add_rules("utils.symbols.export_list", {symbols = {
+ "add",
+ "sub"}})
+
+target("foo2")
+ set_kind("shared")
+ add_files("src/foo.c")
+ add_files("src/foo.export.txt")
+ add_rules("utils.symbols.export_list")
+
+target("test")
+ set_kind("binary")
+ add_deps("foo")
+ add_files("src/main.c")
+
+
diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua
index 8a4ed906c..07aa701dc 100644
--- a/xmake/core/base/interpreter.lua
+++ b/xmake/core/base/interpreter.lua
@@ -1059,8 +1059,16 @@ function interpreter:api_register_set_values(scope_kind, ...)
extra_config = nil
end
- -- expand values
- if not extra_config or extra_config.expand ~= false then
+ -- @note we need mark table value as meta object to avoid wrap/unwrap
+ -- if these values cannot be expanded, especially when there is only one value
+ --
+ -- e.g. set_shflags({"-Wl,-exported_symbols_list", exportfile}, {force = true, expand = false})
+ if extra_config and extra_config.expand == false then
+ for _, value in ipairs(values) do
+ table.wraplock(value)
+ end
+ else
+ -- expand values
values = table.join(table.unpack(values))
end
@@ -1101,8 +1109,16 @@ function interpreter:api_register_add_values(scope_kind, ...)
extra_config = nil
end
- -- expand values
- if not extra_config or extra_config.expand ~= false then
+ -- @note we need mark table value as meta object to avoid wrap/unwrap
+ -- if these values cannot be expanded, especially when there is only one value
+ --
+ -- e.g. add_shflags({"-Wl,-exported_symbols_list", exportfile}, {force = true, expand = false})
+ if extra_config and extra_config.expand == false then
+ for _, value in ipairs(values) do
+ table.wraplock(value)
+ end
+ else
+ -- expand values
values = table.join(table.unpack(values))
end
diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua
index 8a69a9299..b826ac648 100644
--- a/xmake/core/base/scopeinfo.lua
+++ b/xmake/core/base/scopeinfo.lua
@@ -113,8 +113,16 @@ function _instance:_api_set_values(name, ...)
extra_config = nil
end
- -- expand values
- if not extra_config or extra_config.expand ~= false then
+ -- @note we need mark table value as meta object to avoid wrap/unwrap
+ -- if these values cannot be expanded, especially when there is only one value
+ --
+ -- e.g. target:set("shflags", {"-Wl,-exported_symbols_list", exportfile}, {force = true, expand = false})
+ if extra_config and extra_config.expand == false then
+ for _, value in ipairs(values) do
+ table.wraplock(value)
+ end
+ else
+ -- expand values
values = table.join(table.unpack(values))
end
@@ -154,8 +162,16 @@ function _instance:_api_add_values(name, ...)
extra_config = nil
end
- -- expand values
- if not extra_config or extra_config.expand ~= false then
+ -- @note we need mark table value as meta object to avoid wrap/unwrap
+ -- if these values cannot be expanded, especially when there is only one value
+ --
+ -- e.g. target:add("shflags", {"-Wl,-exported_symbols_list", exportfile}, {force = true, expand = false})
+ if extra_config and extra_config.expand == false then
+ for _, value in ipairs(values) do
+ table.wraplock(value)
+ end
+ else
+ -- expand values
values = table.join(table.unpack(values))
end
diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua
index 9868c93d5..6c2b3aaf4 100644
--- a/xmake/core/base/table.lua
+++ b/xmake/core/base/table.lua
@@ -165,11 +165,7 @@ end
-- copy the table to self
function table.copy2(self, copied)
-
- -- clear self first
table.clear(self)
-
- -- copy it
copied = copied or {}
for k, v in pairs(table.wrap(copied)) do
self[k] = v
@@ -312,31 +308,35 @@ function table.to_array(iterator, state, var)
return result, count
end
--- unwrap object if be only one
-function table.unwrap(object)
- if type(object) == "table" then
- if #object == 1 then
- return object[1]
+-- unwrap array if be only one value
+function table.unwrap(array)
+ if type(array) == "table" and not array.__wraplocked__ then
+ if #array == 1 then
+ return array[1]
end
end
- return object
+ return array
end
--- wrap object to table
-function table.wrap(object)
-
- -- no object?
- if nil == object then
+-- wrap value to array
+function table.wrap(value)
+ if nil == value then
return {}
end
-
- -- wrap it if not table
- if type(object) ~= "table" then
- return {object}
+ if type(value) ~= "table" or value.__wraplocked__ then
+ return {value}
end
+ return value
+end
- -- ok
- return object
+-- lock table value to avoid unwrap
+--
+-- a = {1}, wrap(a): {1}, unwrap(a): 1
+-- a = wraplock({1}), wrap(a): {a}, unwrap(a): a
+function table.wraplock(value)
+ if type(value) == "table" then
+ value.__wraplocked__ = true
+ end
end
-- remove repeat from the given array
diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua
index dfaf56b41..cb81effd7 100644
--- a/xmake/rules/c++/modules/build_modules/msvc.lua
+++ b/xmake/rules/c++/modules/build_modules/msvc.lua
@@ -43,7 +43,7 @@ function load_parent(target, opt)
local sourcebatches = dep:sourcebatches()
if sourcebatches and sourcebatches["c++.build.modules"] then
local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache")
- target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = true})
+ target:add("cxxflags", {"/ifcSearchDir", cachedir}, {force = true, expand = false})
end
end
end
diff --git a/xmake/rules/utils/symbols/export_list/xmake.lua b/xmake/rules/utils/symbols/export_list/xmake.lua
new file mode 100644
index 000000000..4184432a4
--- /dev/null
+++ b/xmake/rules/utils/symbols/export_list/xmake.lua
@@ -0,0 +1,107 @@
+--!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, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file xmake.lua
+--
+
+-- export the given symbols list
+--
+--@code
+-- target("foo")
+-- set_kind("shared")
+-- add_files("src/foo.c")
+-- add_rules("utils.symbols.export_list", {symbols = {
+-- "add",
+-- "sub"}})
+--
+-- target("foo2")
+-- set_kind("shared")
+-- add_files("src/foo.c")
+-- add_files("src/foo.export.txt")
+-- add_rules("utils.symbols.export_list")
+--
+rule("utils.symbols.export_list")
+ set_extensions(".export.txt")
+ on_config(function (target)
+ assert(target:is_shared(), 'rule("utils.symbols.export_list"): only for shared target(%s)!', target:name())
+ local exportfile
+ local exportkind
+ local exportsymbols = target:extraconf("rules", "utils.symbols.export_list", "symbols")
+ if not exportsymbols then
+ local sourcebatch = target:sourcebatches()["utils.symbols.export_list"]
+ if sourcebatch then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local list = io.readfile(sourcefile)
+ if list then
+ exportsymbols = list:split("\n")
+ end
+ break
+ end
+ end
+ end
+ assert(exportsymbols and #exportsymbols > 0, 'rule("utils.symbols.export_list"): no exported symbols!')
+ if target:has_tool("ld", "link") then
+ exportkind = "def"
+ exportfile = path.join(target:autogendir(), "rules", "symbols", "export_list.def")
+ target:add("shflags", "/def:" .. exportfile, {force = true})
+ elseif target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then
+ exportkind = "apple"
+ exportfile = path.join(target:autogendir(), "rules", "symbols", "export_list.exp")
+ target:add("shflags", {"-Wl,-exported_symbols_list", exportfile}, {force = true, expand = false})
+ elseif target:has_tool("ld", "gcc", "gxx", "clang", "clangxx") or
+ target:has_tool("sh", "gcc", "gxx", "clang", "clangxx") then
+ exportkind = "ver"
+ exportfile = path.join(target:autogendir(), "rules", "symbols", "export_list.map")
+ target:add("shflags", "-Wl,--version-script=" .. exportfile, {force = true})
+ elseif target:has_tool("ld", "dmd") or target:has_tool("sh", "dmd") then
+ exportkind = "ver"
+ exportfile = path.join(target:autogendir(), "rules", "symbols", "export_list.map")
+ target:add("shflags", "-L--version-script=" .. exportfile, {force = true})
+ elseif target:has_tool("ld", "ld") or target:has_tool("sh", "ld") then
+ exportkind = "ver"
+ exportfile = path.join(target:autogendir(), "rules", "symbols", "export_list.map")
+ target:add("shflags", "--version-script=" .. exportfile, {force = true})
+ end
+ if exportfile and exportkind then
+ if exportkind == "ver" then
+ io.writefile(exportfile, ([[{
+ global:
+ %s
+
+ local:
+ *;
+};]]):format(table.concat(exportsymbols, ";\n ") .. ";"))
+ elseif exportkind == "apple" then
+ local file = io.open(exportfile, 'w')
+ for _, symbol in ipairs(exportsymbols) do
+ if not symbol:startswith("_") then
+ symbol = "_" .. symbol
+ end
+ file:print("%s", symbol)
+ end
+ file:close()
+ elseif exportkind == "def" then
+ local file = io.open(exportfile, 'w')
+ file:print("EXPORTS")
+ for _, symbol in ipairs(exportsymbols) do
+ file:print("%s", symbol)
+ end
+ file:close()
+ end
+ end
+ end)
+