summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-09-05 00:27:39 +0800
committerGitHub <[email protected]>2021-09-05 00:27:39 +0800
commit58ab15fca9879617a5a3f31d7cdfa9b6dbbc87cd (patch)
tree20b52ad45af51fdfc5324344078b3af9a56f8a51
parentf1494df1cf0a7cbeb6c5f63d13f8e4699804fe9f (diff)
parent06b0a3c599b1cfb681dbbd89b4784190aadd2f8a (diff)
Merge pull request #1639 from xmake-io/mergelib
Improve to merge static library
-rw-r--r--CHANGELOG.md2
-rw-r--r--tests/projects/other/merge_archive2/src/add.c4
-rw-r--r--tests/projects/other/merge_archive2/src/main.c17
-rw-r--r--tests/projects/other/merge_archive2/src/mul.c4
-rw-r--r--tests/projects/other/merge_archive2/src/sub.c4
-rw-r--r--tests/projects/other/merge_archive2/src/subdir/add.c4
-rw-r--r--tests/projects/other/merge_archive2/src/subdir/sub.c4
-rw-r--r--tests/projects/other/merge_archive2/test.lua6
-rw-r--r--tests/projects/other/merge_archive2/xmake.lua21
-rw-r--r--xmake/core/project/policy.lua2
-rw-r--r--xmake/modules/utils/archive/merge_staticlib.lua73
-rw-r--r--xmake/rules/utils/merge_archive/xmake.lua30
12 files changed, 166 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4524d2b69..d83e6378c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
* [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings
* Improve Qt rules to support Qt 4.x
* Improve `set_symbols("debug")` to generate pdb file for clang on windows
+* [#1638](https://github.com/xmake-io/xmake/issues/1638): Improve to merge static library
## v2.5.7
@@ -1079,6 +1080,7 @@
* [#1618](https://github.com/xmake-io/xmake/issues/1618): 改进 vala 支持构建动态库和静态库程序
* 改进 Qt 规则去支持 Qt 4.x
* 改进 `set_symbols("debug")` 支持 clang/windows 生成 pdb 文件
+* [#1638](https://github.com/xmake-io/xmake/issues/1638): 改进合并静态库
## v2.5.7
diff --git a/tests/projects/other/merge_archive2/src/add.c b/tests/projects/other/merge_archive2/src/add.c
new file mode 100644
index 000000000..be1e084fc
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/add.c
@@ -0,0 +1,4 @@
+int add(int a, int b)
+{
+ return a + b;
+}
diff --git a/tests/projects/other/merge_archive2/src/main.c b/tests/projects/other/merge_archive2/src/main.c
new file mode 100644
index 000000000..927c9173e
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/main.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+int add(int a, int b);
+int sub(int a, int b);
+int mul(int a, int b);
+int subdir_add(int a, int b);
+int subdir_sub(int a, int b);
+
+int main(int argc, char** argv)
+{
+ printf("%d\n", add(1, 1));
+ printf("%d\n", sub(1, 1));
+ printf("%d\n", mul(1, 1));
+ printf("%d\n", subdir_add(1, 1));
+ printf("%d\n", subdir_sub(1, 1));
+ return 0;
+}
diff --git a/tests/projects/other/merge_archive2/src/mul.c b/tests/projects/other/merge_archive2/src/mul.c
new file mode 100644
index 000000000..c4292f9aa
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/mul.c
@@ -0,0 +1,4 @@
+int mul(int a, int b)
+{
+ return a * b;
+}
diff --git a/tests/projects/other/merge_archive2/src/sub.c b/tests/projects/other/merge_archive2/src/sub.c
new file mode 100644
index 000000000..b151ec4bc
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/sub.c
@@ -0,0 +1,4 @@
+int sub(int a, int b)
+{
+ return a - b;
+}
diff --git a/tests/projects/other/merge_archive2/src/subdir/add.c b/tests/projects/other/merge_archive2/src/subdir/add.c
new file mode 100644
index 000000000..318ed98f8
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/subdir/add.c
@@ -0,0 +1,4 @@
+int subdir_add(int a, int b)
+{
+ return a + b;
+}
diff --git a/tests/projects/other/merge_archive2/src/subdir/sub.c b/tests/projects/other/merge_archive2/src/subdir/sub.c
new file mode 100644
index 000000000..68c4d13ae
--- /dev/null
+++ b/tests/projects/other/merge_archive2/src/subdir/sub.c
@@ -0,0 +1,4 @@
+int subdir_sub(int a, int b)
+{
+ return a - b;
+}
diff --git a/tests/projects/other/merge_archive2/test.lua b/tests/projects/other/merge_archive2/test.lua
new file mode 100644
index 000000000..b76241be2
--- /dev/null
+++ b/tests/projects/other/merge_archive2/test.lua
@@ -0,0 +1,6 @@
+-- main entry
+function main(t)
+
+ -- build project
+ t:build()
+end
diff --git a/tests/projects/other/merge_archive2/xmake.lua b/tests/projects/other/merge_archive2/xmake.lua
new file mode 100644
index 000000000..be1f45de0
--- /dev/null
+++ b/tests/projects/other/merge_archive2/xmake.lua
@@ -0,0 +1,21 @@
+add_rules("mode.debug", "mode.release")
+
+target("add")
+ set_kind("static")
+ add_files("src/add.c")
+ add_files("src/subdir/add.c")
+
+target("sub")
+ set_kind("static")
+ add_files("src/sub.c")
+ add_files("src/subdir/sub.c")
+
+target("mul")
+ set_kind("static")
+ add_deps("add", "sub")
+ add_files("src/mul.c")
+ set_policy("build.merge_archive", true)
+
+target("test")
+ add_deps("mul")
+ add_files("src/main.c")
diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua
index c624aed96..8491e6883 100644
--- a/xmake/core/project/policy.lua
+++ b/xmake/core/project/policy.lua
@@ -43,6 +43,8 @@ function policy.policies()
["check.target_package_licenses"] = {description = "Enable check the compatibility of target and package licenses.", default = true, type = "boolean"},
-- we can compile the source files for each target in parallel
["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"},
+ -- merge archive intead of linking for all dependent targets
+ ["build.merge_archive"] = {description = "Enable merge archive intead of linking for all dependent targets.", default = false, type = "boolean"},
-- we need enable longpaths when building target or installing package
["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"},
-- lock required packages
diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua
new file mode 100644
index 000000000..dc0130219
--- /dev/null
+++ b/xmake/modules/utils/archive/merge_staticlib.lua
@@ -0,0 +1,73 @@
+--!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 merge_staticlib.lua
+--
+
+-- imports
+import("core.base.option")
+import("private.tools.vstool")
+
+-- merge *.a archive libraries for ar
+function _merge_for_ar(target, program, outputfile, libraryfiles, opt)
+ opt = opt or {}
+ if target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then
+ os.vrunv("libtool", table.join("-static", "-o", outputfile, libraryfiles))
+ else
+ local tmpfile = os.tmpfile()
+ local mrifile = io.open(tmpfile, "w")
+ mrifile:print("create %s", outputfile)
+ for _, libraryfile in ipairs(libraryfiles) do
+ mrifile:print("addlib %s", libraryfile)
+ end
+ mrifile:print("save")
+ mrifile:print("end")
+ mrifile:close()
+ os.vrunv(program, {"-M"}, {stdin = tmpfile})
+ os.rm(tmpfile)
+ end
+end
+
+-- merge *.a archive libraries for msvc/lib.exe
+function _merge_for_msvclib(target, program, outputfile, libraryfiles, opt)
+ opt = opt or {}
+ vstool.runv(program, table.join("-nologo", "-out:" .. outputfile, libraryfiles), {envs = opt.runenvs})
+end
+
+-- merge *.a archive libraries
+function main(target, outputfile, libraryfiles)
+ local program, toolname = target:tool("ar")
+ if program and toolname then
+ if toolname:find("ar") then
+ _merge_for_ar(target, program, outputfile, libraryfiles)
+ elseif toolname == "link" and target:is_plat("windows") then
+ local msvc
+ for _, toolchain_inst in ipairs(target:toolchains()) do
+ if toolchain_inst:name() == "msvc" then
+ msvc = toolchain_inst
+ break
+ end
+ end
+ _merge_for_msvclib(target, (program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {runenvs = msvc and msvc:runenvs()})
+ else
+ raise("cannot merge (%s): unknown ar tool %s!", table.concat(libraryfiles, ", "), toolname)
+ end
+ else
+ raise("cannot merge (%s): ar not found!", table.concat(libraryfiles, ", "))
+ end
+end
+
diff --git a/xmake/rules/utils/merge_archive/xmake.lua b/xmake/rules/utils/merge_archive/xmake.lua
index 6d57f55bb..62e3900ff 100644
--- a/xmake/rules/utils/merge_archive/xmake.lua
+++ b/xmake/rules/utils/merge_archive/xmake.lua
@@ -18,12 +18,32 @@
-- @file xmake.lua
--
--- define rule: utils.merge.archive
rule("utils.merge.archive")
-
- -- set extensions
set_extensions(".a", ".lib")
-
- -- on build file
on_build_files("merge_archive")
+ after_link(function (target, opt)
+ if target:policy("build.merge_archive") and target:is_static() then
+ import("utils.archive.merge_staticlib")
+ import("core.project.depend")
+ import("private.utils.progress")
+ local libraryfiles = {}
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:is_static() then
+ table.insert(libraryfiles, dep:targetfile())
+ end
+ end
+ if #libraryfiles > 0 then
+ table.insert(libraryfiles, target:targetfile())
+ end
+ depend.on_changed(function ()
+ progress.show(opt.progress, "${color.build.target}merging.$(mode) %s", path.filename(target:targetfile()))
+ if #libraryfiles > 0 then
+ local tmpfile = os.tmpfile() .. path.extension(target:targetfile())
+ merge_staticlib(target, tmpfile, libraryfiles)
+ os.cp(tmpfile, target:targetfile())
+ os.rm(tmpfile)
+ end
+ end, {dependfile = target:dependfile(target:targetfile() .. ".merge_archive"), files = libraryfiles})
+ end
+ end)