1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
--!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_archive.lua
--
-- imports
import("core.base.option")
import("core.theme.theme")
import("core.project.depend")
import("core.project.target", {alias = "project_target"})
import("private.utils.progress")
import("core.tool.toolchain")
import("private.tools.vstool")
-- extract the static library for ar
function _extract_for_ar(program, libraryfile, objectdir)
-- make the object directory first
os.mkdir(objectdir)
-- get the absolute path of this library
libraryfile = path.absolute(libraryfile)
-- extract it
os.runv(program, {"-x", libraryfile}, {curdir = objectdir})
-- check repeat object name
local repeats = {}
local objectfiles = os.iorunv(program, {"-t", libraryfile})
for _, objectfile in ipairs(objectfiles:split('\n')) do
if repeats[objectfile] then
raise("object name(%s) conflicts in library: %s", objectfile, libraryfile)
end
repeats[objectfile] = true
end
end
-- extract the static library for msvc/lib
function _extract_for_msvclib(program, libraryfile, objectdir)
-- make the object directory first
os.mkdir(objectdir)
-- get runenvs for msvc
local runenvs
local msvc = toolchain.load("msvc")
if msvc then
runenvs = msvc:runenvs()
end
-- list object files
local objectfiles = vstool.iorunv(program, {"-nologo", "-list", libraryfile}, {envs = runenvs})
-- extrace all object files
for _, objectfile in ipairs(objectfiles:split('\n')) do
-- is object file?
if objectfile:find("%.obj") then
-- make the outputfile
local outputfile = path.translate(format("%s\\%s", objectdir, path.filename(objectfile)))
-- repeat? rename it
if os.isfile(outputfile) then
for i = 0, 10 do
outputfile = path.translate(format("%s\\%d_%s", objectdir, i, path.filename(objectfile)))
if not os.isfile(outputfile) then
break
end
end
end
-- extract it
vstool.runv(program, {"-nologo", "-extract:" .. objectfile, "-out:" .. outputfile, libraryfile}, {envs = runenvs})
end
end
end
-- do extract
function _extract(target, libraryfile, objectdir)
local program, toolname = target:tool("ex")
if program and toolname then
if toolname:find("ar") then
_extract_for_ar(program, libraryfile, objectdir)
elseif toolname == "lib" then
_extract_for_msvclib(program, libraryfile, objectdir)
end
else
raise("cannot extract %s, extractor not found!", libraryfile)
end
end
-- main entry
function main (target, sourcebatch, opt)
-- @note we cannot process archives in parallel because the current directory may be changed
for i = 1, #sourcebatch.sourcefiles do
-- get library source file
local sourcefile_lib = sourcebatch.sourcefiles[i]
-- get object directory of the archive file
local objectdir = target:objectfile(sourcefile_lib) .. ".dir"
-- load dependent info
local dependfile = target:dependfile(objectdir)
local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
-- need build this object?
if not depend.is_changed(dependinfo, {lastmtime = os.mtime(objectdir)}) then
local objectfiles = os.files(path.join(objectdir, "**" .. project_target.filename("", "object")))
table.join2(target:objectfiles(), objectfiles)
return
end
-- trace progress info
progress.show(opt.progress, "${color.build.object}inserting.$(mode) %s", sourcefile_lib)
-- extract the archive library
os.tryrm(objectdir)
_extract(target, sourcefile_lib, objectdir)
-- add objectfiles
local objectfiles = os.files(path.join(objectdir, "**" .. project_target.filename("", "object")))
table.join2(target:objectfiles(), objectfiles)
-- update files to the dependent file
dependinfo.files = {}
table.insert(dependinfo.files, sourcefile_lib)
depend.save(dependinfo, dependfile)
end
end
|