|
80 | 80 | context.addFilter(self, "options", options)
|
81 | 81 | end
|
82 | 82 |
|
| 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 | + |
83 | 95 | ---
|
84 | 96 | -- Bakes a specific workspace object.
|
85 | 97 | ---
|
|
322 | 334 | end
|
323 | 335 |
|
324 | 336 |
|
| 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 | + |
325 | 417 |
|
326 | 418 | --
|
327 | 419 | -- Assigns a unique objects directory to every configuration of every project
|
|
526 | 618 | -- @param extraFilters
|
527 | 619 | -- Optional. Any extra filter terms to use when retrieving the data for
|
528 | 620 | -- this configuration
|
| 621 | +-- @param usage |
| 622 | +-- Optional. The usage block to apply to the configuration. |
529 | 623 | ---
|
530 | 624 |
|
531 |
| - function oven.bakeConfig(wks, prj, buildcfg, platform, extraFilters) |
| 625 | + function oven.bakeConfig(wks, prj, buildcfg, platform, extraFilters, usage) |
532 | 626 |
|
533 | 627 | -- Set the default system and architecture values; if the platform's
|
534 | 628 | -- name matches a known system or architecture, use that as the default.
|
|
554 | 648 | wks = wks,
|
555 | 649 | sln = wks,
|
556 | 650 | prj = prj,
|
| 651 | + usage = usage, |
557 | 652 | }
|
558 | 653 |
|
559 |
| - local ctx = context.new(prj or wks, environ) |
| 654 | + local ctx = context.new(usage or prj or wks, environ) |
560 | 655 |
|
| 656 | + ctx.usage = usage |
561 | 657 | ctx.project = prj
|
562 | 658 | ctx.workspace = wks
|
563 | 659 | ctx.solution = wks
|
|
782 | 878 | cfg.name = cfg.longname
|
783 | 879 |
|
784 | 880 | -- 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 |
786 | 883 | cfg.buildtarget = p.config.gettargetinfo(cfg)
|
787 | 884 | cfg.buildtarget.relpath = p.project.getrelative(cfg.project, cfg.buildtarget.abspath)
|
788 | 885 |
|
789 | 886 | cfg.linktarget = p.config.getlinkinfo(cfg)
|
790 | 887 | cfg.linktarget.relpath = p.project.getrelative(cfg.project, cfg.linktarget.abspath)
|
791 | 888 | end
|
792 | 889 | 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 |
0 commit comments