Skip to content

Commit 62b9bc7

Browse files
Merge pull request #2432 from nickclark2016/feature/better-dependencies
Usages and Uses API
2 parents 446ad5e + 0b23f92 commit 62b9bc7

13 files changed

+615
-12
lines changed

src/_manifest.lua

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"base/config.lua",
5050
"base/fileconfig.lua",
5151
"base/rule.lua",
52+
"base/usage.lua",
5253

5354
-- project script processing
5455
"base/oven.lua",

src/_premake_init.lua

+6
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,12 @@
11821182
end
11831183
end
11841184

1185+
api.register {
1186+
name = "uses",
1187+
scope = "config",
1188+
kind = "list:string",
1189+
}
1190+
11851191

11861192
-----------------------------------------------------------------------------
11871193
--

src/base/configset.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@
462462
function configset.compile(cset, filter)
463463
-- always start with the parent
464464
local result
465-
if cset.parent then
465+
if cset.parent and not cset.noinherit then
466466
result = configset.compile(cset.parent, filter)
467467
else
468468
result = configset.new()

src/base/global.lua

-8
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,6 @@
1717
return p.container.new(p.global, name)
1818
end
1919

20-
---
21-
-- Bakes the global scope.
22-
---
23-
function global.bake(self)
24-
p.container.bakeChildren(self)
25-
end
26-
27-
2820
---
2921
-- Iterate over the collection of rules in a session.
3022
--

src/base/oven.lua

+220-3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@
8080
context.addFilter(self, "options", options)
8181
end
8282

83+
---
84+
-- Bakes the global scope.
85+
---
86+
87+
function p.global.bake(self)
88+
p.container.bakeChildren(self)
89+
90+
-- now we can post process the projects for 'uses' entries and apply the
91+
-- corresponding 'usage' block to the project.
92+
oven.applyUsages()
93+
end
94+
8395
---
8496
-- Bakes a specific workspace object.
8597
---
@@ -322,6 +334,86 @@
322334
end
323335

324336

337+
---
338+
-- Bakes a specific usage object.
339+
--
340+
-- @param self
341+
-- The usage object to bake.
342+
---
343+
function p.usage.bake(self)
344+
verbosef(' Baking %s:%s...', self.project.name, self.name)
345+
346+
local prj = self.project
347+
local wks = prj.workspace
348+
349+
-- Add filtering terms to the context to make it as specific as I can.
350+
context.copyFilters(self, prj)
351+
352+
self.system = self.system or os.target()
353+
context.addFilter(self, "system", os.getSystemTags(self.system))
354+
context.addFilter(self, "host", os.getSystemTags(os.host()))
355+
context.addFilter(self, "architecture", self.architecture)
356+
context.addFilter(self, "tags", self.tags)
357+
358+
self.usage = self
359+
self.configurations = prj.configurations
360+
self.platforms = prj.platforms
361+
362+
self.environ = {
363+
wks = prj.workspace,
364+
sln = prj.workspace,
365+
prj = prj,
366+
usage = self,
367+
}
368+
369+
-- Mark the children blocks of the usage as originating from usage
370+
-- so they can be distinguished from the project's own blocks.
371+
self._isusage = true
372+
373+
for _, block in ipairs(self._cfgset.blocks) do
374+
-- Mark the block as originating from usage
375+
block._isusage = true
376+
end
377+
378+
context.compile(self)
379+
380+
p.container.bakeChildren(self)
381+
382+
self.location = self.location or self.basedir
383+
context.basedir(self, self.location)
384+
385+
local cfgs = table.fold(self.configurations or {}, self.platforms or {})
386+
oven.bubbleFields(self, self, cfgs)
387+
self._cfglist = oven.bakeConfigList(self, cfgs)
388+
389+
local usageSystem = self.system
390+
self.system = nil
391+
392+
self.configs = {}
393+
394+
for _, pairing in ipairs(self._cfglist) do
395+
local buildcfg = pairing[1]
396+
local platform = pairing[2]
397+
local cfg = oven.bakeConfig(wks, prj, buildcfg, platform, nil, self)
398+
cfg.usage = self
399+
cfg._isusage = true
400+
401+
if p.action.supportsconfig(p.action.current(), cfg) then
402+
self.configs[(buildcfg or "*") .. (platform or "")] = cfg
403+
end
404+
end
405+
406+
self._ = {}
407+
self._.files = oven.bakeFiles(self)
408+
409+
if p.project.isnative(self) then
410+
oven.assignObjectSequences(self)
411+
end
412+
413+
self.system = usageSystem
414+
end
415+
416+
325417

326418
--
327419
-- Assigns a unique objects directory to every configuration of every project
@@ -526,9 +618,11 @@
526618
-- @param extraFilters
527619
-- Optional. Any extra filter terms to use when retrieving the data for
528620
-- this configuration
621+
-- @param usage
622+
-- Optional. The usage block to apply to the configuration.
529623
---
530624

531-
function oven.bakeConfig(wks, prj, buildcfg, platform, extraFilters)
625+
function oven.bakeConfig(wks, prj, buildcfg, platform, extraFilters, usage)
532626

533627
-- Set the default system and architecture values; if the platform's
534628
-- name matches a known system or architecture, use that as the default.
@@ -554,10 +648,12 @@
554648
wks = wks,
555649
sln = wks,
556650
prj = prj,
651+
usage = usage,
557652
}
558653

559-
local ctx = context.new(prj or wks, environ)
654+
local ctx = context.new(usage or prj or wks, environ)
560655

656+
ctx.usage = usage
561657
ctx.project = prj
562658
ctx.workspace = wks
563659
ctx.solution = wks
@@ -782,11 +878,132 @@
782878
cfg.name = cfg.longname
783879

784880
-- compute build and link targets
785-
if cfg.project and cfg.kind then
881+
-- usages do not have build or link targets
882+
if cfg.project and cfg.kind and not cfg.usage then
786883
cfg.buildtarget = p.config.gettargetinfo(cfg)
787884
cfg.buildtarget.relpath = p.project.getrelative(cfg.project, cfg.buildtarget.abspath)
788885

789886
cfg.linktarget = p.config.getlinkinfo(cfg)
790887
cfg.linktarget.relpath = p.project.getrelative(cfg.project, cfg.linktarget.abspath)
791888
end
792889
end
890+
891+
892+
--
893+
-- Post-process the projects for 'uses' entries and apply the corresponding
894+
-- 'usage' block to the project.
895+
--
896+
function oven.applyUsages()
897+
local function fetchConfigSetBlocks(cfg)
898+
return cfg._cfgset.blocks
899+
end
900+
901+
local function fetchPropertiesToApply(src, tgt)
902+
local properties = {}
903+
local srcprj = src.project
904+
905+
local blocks = fetchConfigSetBlocks(src)
906+
local n = #blocks
907+
local srccfgpath = src.basedir
908+
local tgtcfgpath = tgt.basedir
909+
910+
for i = 1, n do
911+
local block = blocks[i]
912+
for k, v in pairs(block) do
913+
local f = p.field.get(k)
914+
if f then
915+
properties[k] = p.field.store(f, properties[k], v)
916+
end
917+
end
918+
end
919+
920+
return properties
921+
end
922+
923+
local function collectUsages(cfg)
924+
local uses = {}
925+
926+
for _, use in ipairs(cfg.uses or {}) do
927+
if p.usage.isSpecialName(use) then
928+
-- Explicitly providing special names is not allowed
929+
p.error("Special names are not allowed in 'uses' list. Found '%s' requested in project '%s'", use, cfg.project.name)
930+
end
931+
932+
-- Find a usage block that matches the usage name
933+
local namematch = p.usage.findglobal(use)
934+
for i = 1, #namematch do
935+
local usagecfg = p.project.findClosestMatch(namematch[i], cfg.buildcfg, cfg.platform)
936+
937+
if usagecfg then
938+
-- Apply the usage block to the project configuration
939+
local children = collectUsages(usagecfg)
940+
uses = table.join(uses, children)
941+
table.insert(uses, usagecfg)
942+
else
943+
p.warnOnce('no-such-usage:' .. use, "Usage '%s' not found in project '%s'", use, cfg.project.name)
944+
end
945+
end
946+
947+
if #namematch == 0 then
948+
p.warnOnce('no-such-usage:' .. use, "Usage '%s' not found in project '%s'", use, cfg.project.name)
949+
end
950+
end
951+
952+
return uses
953+
end
954+
955+
local function collectSpecialUsages(usage, cfg)
956+
local usagecfg = p.project.findClosestMatch(usage, cfg.buildcfg, cfg.platform)
957+
if usagecfg then
958+
local result = {}
959+
local uses = collectUsages(usagecfg)
960+
961+
result = table.join(result, uses)
962+
table.insert(result, usagecfg)
963+
964+
return result
965+
end
966+
967+
return {}
968+
end
969+
970+
verbosef(' Baking usages...')
971+
972+
for wks in p.global.eachWorkspace() do
973+
for prj in p.workspace.eachproject(wks) do
974+
for cfg in p.project.eachconfig(prj) do
975+
local toconsume = collectUsages(cfg)
976+
977+
-- Find a public usage block for the current project
978+
local publicusage = p.project.findusage(prj, p.usage.PUBLIC)
979+
if publicusage then
980+
local children = collectSpecialUsages(publicusage, cfg)
981+
toconsume = table.join(toconsume, children)
982+
end
983+
984+
-- Find a private usage block for the current project
985+
local privateusage = p.project.findusage(prj, p.usage.PRIVATE)
986+
if privateusage then
987+
local children = collectSpecialUsages(privateusage, cfg)
988+
toconsume = table.join(toconsume, children)
989+
end
990+
991+
toconsume = table.unique(toconsume)
992+
993+
local allprops = {}
994+
995+
for _, usage in ipairs(toconsume) do
996+
local props = fetchPropertiesToApply(usage, cfg)
997+
for k, v in pairs(props) do
998+
local field = p.field.get(k)
999+
if field then
1000+
allprops[k] = p.field.store(field, allprops[k], v)
1001+
end
1002+
end
1003+
end
1004+
1005+
table.insert(cfg._cfgset.blocks, allprops)
1006+
end
1007+
end
1008+
end
1009+
end

src/base/project.lua

+19
Original file line numberDiff line numberDiff line change
@@ -570,3 +570,22 @@
570570
return values[1], values[2]
571571
end
572572
end
573+
574+
575+
---
576+
-- Retrieve the project's usage information for a particular usage.
577+
-- @param name
578+
-- The name of the usage to retrieve.
579+
-- @return
580+
-- The usage object with the specified name or nil if not found.
581+
---
582+
583+
function project.findusage(self, name)
584+
for _, usage in ipairs(self.usages or self.project.usages) do
585+
if name == usage.name then
586+
return usage
587+
end
588+
end
589+
590+
return nil
591+
end

0 commit comments

Comments
 (0)