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
149
|
--!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 module_parser.lua
--
-- imports
import("core.project.depend")
import("core.base.hashset")
-- get depend file of module source file
function _get_dependfile_of_modulesource(target, sourcefile)
return target:dependfile(sourcefile)
end
-- get depend file of module object file, compiler will rewrite it
function _get_dependfile_of_moduleobject(target, sourcefile)
local objectfile = target:objectfile(sourcefile)
return target:dependfile(objectfile)
end
-- generate module deps for the given file
function _generate_moduledeps(target, sourcefile, opt)
local dependfile = _get_dependfile_of_modulesource(target, sourcefile)
depend.on_changed(function ()
-- trace
vprint("generating.moduledeps %s", sourcefile)
-- generating deps
local module_name
local module_deps
local sourcecode = io.readfile(sourcefile)
sourcecode = sourcecode:gsub("//.-\n", "\n")
sourcecode = sourcecode:gsub("/%*.-%*/", "")
for _, line in ipairs(sourcecode:split("\n", {plain = true})) do
if not module_name then
module_name = line:match("export%s+module%s+(.+)%s*;")
end
local module_depname = line:match("import%s+(.+)%s*;")
if module_depname then
-- partition? import :xxx;
if module_depname:startswith(":") then
module_depname = module_name .. module_depname
end
module_deps = module_deps or {}
table.insert(module_deps, module_depname)
end
end
-- save depend data
if module_name then
local dependinfo = {moduleinfo = {name = module_name, deps = module_deps, file = sourcefile}}
return dependinfo
end
end, {dependfile = dependfile, files = {sourcefile}})
end
-- build batch jobs with deps
function _build_batchjobs_with_deps(moduledeps, batchjobs, rootjob, jobrefs, moduleinfo)
local targetjob_ref = jobrefs[moduleinfo.name]
if targetjob_ref then
batchjobs:add(targetjob_ref, rootjob)
else
local modulejob = batchjobs:add(moduleinfo.job, rootjob)
if modulejob then
jobrefs[moduleinfo.name] = modulejob
for _, depname in ipairs(moduleinfo.deps) do
local dep = moduledeps[depname]
if dep then -- maybe nil, e.g. `import <string>;`
_build_batchjobs_with_deps(moduledeps, batchjobs, modulejob, jobrefs, dep)
end
end
end
end
end
-- generate module deps
function generate(target, sourcebatch, opt)
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
_generate_moduledeps(target, sourcefile, opt)
end
end
-- load module deps
function load(target, sourcebatch, opt)
-- do generate first
generate(target, sourcebatch, opt)
-- load deps
local moduledeps
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
local dependfile = _get_dependfile_of_modulesource(target, sourcefile)
if os.isfile(dependfile) then
local data = io.load(dependfile)
if data then
local moduleinfo = data.moduleinfo
if moduleinfo then
moduledeps = moduledeps or {}
moduledeps[moduleinfo.name] = moduleinfo
end
end
end
end
-- get moduledeps with file map
local moduledeps_files = {}
for _, moduleinfo in pairs(moduledeps) do
moduledeps_files[moduleinfo.file] = moduleinfo
end
return moduledeps, moduledeps_files
end
-- build batch jobs
function build_batchjobs(moduledeps, batchjobs, rootjob)
local depset = hashset.new()
for _, moduleinfo in pairs(moduledeps) do
assert(moduleinfo.job)
for _, depname in ipairs(moduleinfo.deps) do
depset:insert(depname)
end
end
local moduledeps_root = {}
for _, moduleinfo in pairs(moduledeps) do
if not depset:has(moduleinfo.name) then
table.insert(moduledeps_root, moduleinfo)
end
end
local jobrefs = {}
for _, moduleinfo in pairs(moduledeps_root) do
_build_batchjobs_with_deps(moduledeps, batchjobs, rootjob, jobrefs, moduleinfo)
end
end
|