vpaths matching doesn't use anchors and therefore ends up matching .clang-format with *.c or .hgignore with *.h
assarbad opened this issue · 0 comments
I noticed this because .hgignore
always ended up in the ["Header Files/*"] = { "*.hpp", "*.h", },
vpaths-mapping, despite there being another mapping with which I attempted to map .hgignore
without any wildcard characters. The same evidently happens/happened for .clang-format
.
The path.wilcards()
function returns a match string that isn't anchored to the beginning and end of the string respectively, so returning matches when it would not be expected.
I think the appropriate way would be (or rather have been) to have path.wildcards()
return patterns anchored between ^
and $
, i.e. the beginning and end of a string respectively. But in this particular case it's rather finicky to work around this from the outside.
The issue with that seems to be that -- for obvious reasons -- the name path.wildcards
is already bound by the time I try to manipulate it.
Essentially I have replace this single line by something along the lines of (not knowing, however, how much else this may influence or how many existing premake4.lua
files it'd break):
local wildcards = "^" .. path.wildcards(pattern) .. "$"
local i = abspath:find(wildcards)
... to get my proverbial foot in the door. Still, only thanks to the way Premake4 was designed, it's possible without having to patch the C part of it.
This does not happen when replacement
(the key in the vpaths
table) is an empty string, btw.
The workaround
Somewhere in your premake4.lua
place this code:
do
local orig_getvpath = premake.project.getvpath
premake.project.getvpath = function(prj, abspath)
for replacement, patterns in pairs(prj.vpaths or {}) do
for _, pattern in ipairs(patterns) do
if abspath == pattern then
local stem, _ = replacement:gsub("%*", "")
return path.join(stem, abspath)
end
end
end
return orig_getvpath(prj, abspath)
end
end
What it does is to replace premake.project.getvpath()
with our own code, retaining a "function pointer" to the original function.
Then it goes through all replacements and respective patterns, looking for exact matches between patterns and path -- which should reasonably only happen whenever the pattern (and path) contain no wildcard characters anyway -- and if that was found uses a stripped down version of the logic in the original getvpath()
and returns its result at the first match. This is exactly the behavior I would have expected when there are no wildcard characters in the pattern, but which wasn't the case due to using string.find
without anchors.
FYI: I don't expect anyone but myself to fix/address this. However, perhaps it helps someone else who still uses Premake4 or raises awareness on that issue for Premake5 (I don't know how related the code bases truly are).
Here's one failed attempt:
do
if premake.project.getvpath then
local orig_getvpath = premake.project.getvpath
premake.project.getvpath = function(prj, abspath)
local orig_wildcards = path.wildcards
-- just for a single call, fix up the wildcards() function
path.wildcards = function(pattern)
return "^" .. orig_wildcards(pattern) .. ""
end
local retval = orig_getvpath(prj, abspath)
path.wildcards = orig_wildcards -- reset back to the original value
return retval
end
end
end
This method also fails (filteridgroup
and getfilegroup
respectively use the premake.project.eachfile
function, which I hoped to influence this way):
do
local orig_wildcards = path.wildcards
local orig_filteridgroup = premake.vstudio.vc2010.filteridgroup
local orig_getfilegroup = premake.vstudio.vc2010.getfilegroup
local replacement_wildcards = function(pattern)
return "^" .. orig_wildcards(pattern) .. ""
end
premake.vstudio.vc2010.filteridgroup = function(prj)
path.wildcards = replacement_wildcards -- just for a single call, fix up the wildcards() function
local retval = orig_filteridgroup(prj)
path.wildcards = orig_wildcards -- reset back to the original value
return retval
end
premake.vstudio.vc2010.getfilegroup = function(prj, group)
path.wildcards = replacement_wildcards -- just for a single call, fix up the wildcards() function
local retval = orig_getfilegroup(prj, group)
path.wildcards = orig_wildcards -- reset back to the original value
return retval
end
end