|
356 | 356 | context.addFilter(self, "architecture", self.architecture) |
357 | 357 | context.addFilter(self, "tags", self.tags) |
358 | 358 |
|
359 | | - self.usage = usage |
| 359 | + self.usage = self |
360 | 360 |
|
361 | 361 | self.environ = { |
362 | 362 | wks = prj.workspace, |
|
394 | 394 | local buildcfg = pairing[1] |
395 | 395 | local platform = pairing[2] |
396 | 396 | local cfg = oven.bakeConfig(wks, prj, buildcfg, platform, nil, self) |
| 397 | + cfg.usage = self |
| 398 | + cfg._isusage = true |
397 | 399 |
|
398 | 400 | if p.action.supportsconfig(p.action.current(), cfg) then |
399 | 401 | self.configs[(buildcfg or "*") .. (platform or "")] = cfg |
|
950 | 952 | end |
951 | 953 | end |
952 | 954 |
|
953 | | - local function applyUsage(prj, usage) |
954 | | - -- For each configuration in the project, apply the corresponding configuration from the usage block |
955 | | - for cfg in p.project.eachconfig(prj) do |
956 | | - -- Merge the usage block into the project configuration |
957 | | - -- If the type of a field contains files, ensure the files are applied relative to the usage block's location |
958 | | - -- instead of target configuration's location |
959 | | - |
960 | | - -- Find the usage configuration that corresponds to the project configuration |
961 | | - local match = p.project.findClosestMatch(usage, cfg.buildcfg, cfg.platform) |
962 | | - if match then |
963 | | - -- Merge the usage configuration into the project configuration |
964 | | - verbosef(' Applying usage %s:%s:%s to %s:%s', usage.project.name, usage.name, cfg.shortname, prj.name, cfg.shortname) |
965 | | - buildAppliedPropertyTable(prj, match) |
966 | | - end |
967 | | - end |
968 | | - end |
| 955 | + local function fetchPropertiesToApply(src, tgt) |
| 956 | + local properties = {} |
| 957 | + local srcprj = src.project |
969 | 958 |
|
| 959 | + verbosef('Applying properties from %s:%s to %s:%s', srcprj.name, src.name, tgt.project.name, tgt.shortname) |
970 | 960 |
|
971 | | - -- Build a table of all of the usage blocks in the workspace which are not a special |
972 | | - -- case (public, private, interface). |
| 961 | + for k, v in pairs(src) do |
| 962 | + verbosef('key = %s, value = %s', k, v) |
| 963 | + end |
973 | 964 |
|
974 | | - verbosef(' Baking usages...') |
975 | | - local usages = {} |
976 | | - for wks in p.global.eachWorkspace() do |
977 | | - for prj in p.workspace.eachproject(wks) do |
978 | | - for _, usage in ipairs(prj.usages or {}) do |
979 | | - verbosef(' Found usage %s:%s:%s', wks.name, prj.name, usage.name) |
980 | | - |
981 | | - if not p.usage.isSpecial(usage) then |
982 | | - -- Check if the usage block already exists in the table |
983 | | - local existing = usages[usage.name] |
984 | | - if not existing then |
985 | | - usages[usage.name] = usage |
986 | | - else |
987 | | - p.warn('Usage with name %s already exists in the workspace.') |
988 | | - end |
| 965 | + return properties |
| 966 | + end |
| 967 | + |
| 968 | + local function collectUsages(cfg) |
| 969 | + local uses = {} |
| 970 | + |
| 971 | + for _, use in ipairs(cfg.uses or {}) do |
| 972 | + -- Find a usage block that matches the usage name |
| 973 | + local namematch = p.usage.findglobal(use) |
| 974 | + for i = 1, #namematch do |
| 975 | + local usagecfg = p.project.findClosestMatch(namematch[i], cfg.buildcfg, cfg.platform) |
| 976 | + |
| 977 | + if usagecfg then |
| 978 | + -- Apply the usage block to the project configuration |
| 979 | + local children = collectUsages(usagecfg) |
| 980 | + uses = table.join(uses, children) |
| 981 | + else |
| 982 | + p.warnOnce('no-such-usage:' .. use, "Usage '%s' not found in project '%s'", use, cfg.project.name) |
989 | 983 | end |
990 | 984 | end |
| 985 | + |
| 986 | + if #namematch > 0 then |
| 987 | + table.insert(uses, use) -- Add use to the end, to preserve walking order |
| 988 | + else |
| 989 | + p.warnOnce('no-such-usage:' .. use, "Usage '%s' not found in project '%s'", use, cfg.project.name) |
| 990 | + end |
991 | 991 | end |
| 992 | + |
| 993 | + return uses |
992 | 994 | end |
993 | 995 |
|
| 996 | + local function collectSpecialUsages(usage, cfg) |
| 997 | + local usagecfg = p.project.findClosestMatch(usage, cfg.buildcfg, cfg.platform) |
| 998 | + if usagecfg then |
| 999 | + local result = {} |
| 1000 | + local children = collectUsages(usagecfg) |
| 1001 | + |
| 1002 | + local uses = table.translate(children, function(use) |
| 1003 | + return p.usage.findglobal(use) |
| 1004 | + end) |
| 1005 | + |
| 1006 | + result = table.join(result, uses) |
| 1007 | + result = table.insert(result, usage) |
| 1008 | + |
| 1009 | + return result |
| 1010 | + end |
| 1011 | + |
| 1012 | + return {} |
| 1013 | + end |
| 1014 | + |
| 1015 | + verbosef(' Baking usages...') |
| 1016 | + |
994 | 1017 | for wks in p.global.eachWorkspace() do |
995 | 1018 | for prj in p.workspace.eachproject(wks) do |
996 | | - -- Check if the project has a PRIVATE or PUBLIC block |
997 | | - -- PUBLIC is applied to all, PRIVATE is applied to the project only |
998 | | - local publicusage = p.project.findusage(prj, p.usage.PUBLIC) |
999 | | - local interfaceusage = p.project.findusage(prj, p.usage.INTERFACE) |
1000 | | - |
1001 | | - if publicusage then |
1002 | | - applyUsage(prj, publicusage) |
1003 | | - end |
| 1019 | + for cfg in p.project.eachconfig(prj) do |
| 1020 | + local usenames = collectUsages(cfg) |
| 1021 | + local uses = table.translate(usenames, function(use) |
| 1022 | + return p.usage.findglobal(use) |
| 1023 | + end) |
| 1024 | + |
| 1025 | + -- Find a public usage block for the current project |
| 1026 | + local publicusage = p.project.findusage(prj, p.usage.PUBLIC) |
| 1027 | + if publicusage then |
| 1028 | + local children = collectSpecialUsages(publicusage, cfg) |
| 1029 | + uses = table.join(uses, children) |
| 1030 | + end |
1004 | 1031 |
|
1005 | | - if interfaceusage then |
1006 | | - applyUsage(prj, interfaceusage) |
1007 | | - end |
| 1032 | + -- Find a private usage block for the current project |
| 1033 | + local privateusage = p.project.findusage(prj, p.usage.PRIVATE) |
| 1034 | + if privateusage then |
| 1035 | + local children = collectSpecialUsages(privateusage, cfg) |
| 1036 | + uses = table.join(uses, children) |
| 1037 | + end |
1008 | 1038 |
|
1009 | | - local uses = prj.uses or {} |
1010 | | - for _, usagename in ipairs(uses) do |
1011 | | - -- Search priority: |
1012 | | - -- 1. Search for a project with the same name as the usage |
1013 | | - -- 2. Search for a usage with the same name as the usage |
1014 | | - -- 3. Present a warning if no project or usage is found |
1015 | | - |
1016 | | - local tgt = p.workspace.findproject(wks, usagename) |
1017 | | - if tgt then |
1018 | | - -- In the case of a project, search for public and interface blocks |
1019 | | - local publicusage = p.project.findusage(tgt, p.usage.PUBLIC) -- public block |
1020 | | - local interfaceusage = p.project.findusage(tgt, p.usage.INTERFACE) -- interface block |
1021 | | - |
1022 | | - if publicusage then |
1023 | | - applyUsage(prj, publicusage) |
1024 | | - end |
| 1039 | + local allprops = {} |
1025 | 1040 |
|
1026 | | - if interfaceusage then |
1027 | | - applyUsage(prj, interfaceusage) |
1028 | | - end |
1029 | | - else |
1030 | | - local usage = usages[usagename] |
1031 | | - if usage then |
1032 | | - applyUsage(prj, usage) |
1033 | | - else |
1034 | | - -- Present a warning if no project or usage is found |
1035 | | - p.warn('Project %s uses %s, but no project or usage with that name was found', prj.name, usagename) |
| 1041 | + for _, usage in ipairs(uses) do |
| 1042 | + local props = fetchPropertiesToApply(usage[1], cfg) |
| 1043 | + |
| 1044 | + -- Handle duplicate properties |
| 1045 | + for key, value in pairs(props) do |
| 1046 | + allprops[key] = p.field.store(p.fields[key], allprops[key], value) |
1036 | 1047 | end |
1037 | 1048 | end |
1038 | 1049 | end |
1039 | 1050 | end |
1040 | | - |
1041 | 1051 | end |
1042 | 1052 | end |
0 commit comments