Path tokens in non-path fields (like custom build commands) are not expanded to project-relative paths
This commit is contained in:
parent
0cd9bac896
commit
b59850dd1b
@ -457,8 +457,8 @@
|
||||
local commands = table.concat(filecfg.buildcommands,'\r\n')
|
||||
_p(3,'<Command %s>%s</Command>', condition, premake.esc(commands))
|
||||
|
||||
local outputs = table.concat(filecfg.buildoutputs, ' ')
|
||||
_p(3,'<Outputs %s>%s</Outputs>', condition, premake.esc(outputs))
|
||||
local outputs = project.getrelative(prj, filecfg.buildoutputs)
|
||||
vc2010.element(3, "Outputs", condition, '%s', table.concat(outputs, " "))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,6 +40,14 @@
|
||||
ctx._filename = { filename } or {}
|
||||
ctx.terms = {}
|
||||
|
||||
-- This base directory is used when expanding path tokens encountered
|
||||
-- in non-path value; such values will be made relative to this value
|
||||
-- so the resulting projects will only contain relative paths. It is
|
||||
-- expected that the creator of the context will set this value using
|
||||
-- the setbasedir() function.
|
||||
|
||||
ctx._basedir = os.getcwd()
|
||||
|
||||
-- when a missing field is requested, fetch it from my config
|
||||
-- set, and then cache the value for future lookups
|
||||
setmetatable(ctx, context.__mt)
|
||||
@ -82,6 +90,26 @@
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Sets the base directory for path token expansion in non-path fields; such
|
||||
-- values will be made relative to this path.
|
||||
--
|
||||
-- @param ctx
|
||||
-- The context in which to set the value.
|
||||
-- @param basedir
|
||||
-- The new base directory for path token expansion. This should be
|
||||
-- provided as an absolute path. This may be left nil to simply fetch
|
||||
-- the current base directory.
|
||||
-- @return
|
||||
-- The context's base directory.
|
||||
--
|
||||
|
||||
function context.basedir(ctx, basedir)
|
||||
ctx._basedir = basedir or ctx._basedir
|
||||
return ctx._basedir
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Compiles the context for better performance. The list of context terms
|
||||
-- becomes locked down; any subsequent changes are ignored.
|
||||
@ -130,8 +158,8 @@
|
||||
local field = premake.fields[key]
|
||||
if field and field.tokens then
|
||||
local kind = field.kind
|
||||
local ispath = kind:startswith("path") or kind:startswith("mixed")
|
||||
value = premake.detoken.expand(value, ctx.environ, ispath)
|
||||
local ispath = kind:startswith("path") or kind:startswith("file") or kind:startswith("mixed")
|
||||
value = premake.detoken.expand(value, ctx.environ, ispath, ctx._basedir)
|
||||
end
|
||||
|
||||
-- store the result for later lookups
|
||||
|
@ -3,7 +3,7 @@
|
||||
--
|
||||
-- Expands tokens.
|
||||
--
|
||||
-- Copyright (c) 2011-2012 Jason Perkins and the Premake project
|
||||
-- Copyright (c) 2011-2013 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.detoken = {}
|
||||
@ -22,11 +22,14 @@
|
||||
-- @param ispath
|
||||
-- If true, the value treated as a file system path, and checks will be made
|
||||
-- for nested absolute paths from expanded tokens.
|
||||
-- @param basedir
|
||||
-- If provided, path tokens encountered in non-path fields (where the ispath
|
||||
-- parameter is set to false) will be made relative to this location.
|
||||
-- @return
|
||||
-- The value with any contained tokens expanded.
|
||||
--
|
||||
|
||||
function detoken.expand(value, environ, ispath)
|
||||
function detoken.expand(value, environ, ispath, basedir)
|
||||
-- enable access to the global environment
|
||||
setmetatable(environ, {__index = _G})
|
||||
|
||||
@ -36,20 +39,42 @@
|
||||
if not func then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
|
||||
-- give the function access to the project objects
|
||||
setfenv(func, environ)
|
||||
|
||||
|
||||
-- run it and return the result
|
||||
local result = func() or ""
|
||||
|
||||
-- if I'm replacing within a path value, and the replacement is
|
||||
-- itself and absolute path, insert a marker at the start of it.
|
||||
-- This will be my clue later to trim the path here.
|
||||
if ispath and path.isabsolute(result) then
|
||||
-- If the result is an absolute path, and it is being inserted into
|
||||
-- a path value, place a special marker at the start of it. After
|
||||
-- all results have been processed, I can look for these markers to
|
||||
-- find the last absolute path expanded.
|
||||
--
|
||||
-- Example: the value "/home/user/myprj/%{cfg.objdir}" expands to:
|
||||
-- "/home/user/myprj//home/user/myprj/obj/Debug".
|
||||
--
|
||||
-- By inserting a marker this becomes:
|
||||
-- "/home/user/myprj/[\0]/home/user/myprj/obj/Debug".
|
||||
--
|
||||
-- I can now trim everything before the marker to get the right
|
||||
-- result, which should always be the last absolute path specified:
|
||||
-- "/home/user/myprj/obj/Debug"
|
||||
|
||||
local isAbs = path.isabsolute(result)
|
||||
if isAbs and ispath then
|
||||
result = "\0" .. result
|
||||
end
|
||||
|
||||
|
||||
-- If the result is an absolute path, and it is being inserted into
|
||||
-- a NON-path value, I need to make it relative to the project that
|
||||
-- will contain it. Otherwise I ended up with an absolute path in
|
||||
-- the generated project, and it can no longer be moved around.
|
||||
|
||||
if isAbs and not ispath and basedir then
|
||||
result = path.getrelative(basedir, result)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
@ -64,7 +89,7 @@
|
||||
return result
|
||||
end)
|
||||
until count == 0
|
||||
|
||||
|
||||
-- if a path, look for a split out embedded absolute paths
|
||||
if ispath then
|
||||
local i, j
|
||||
@ -75,7 +100,7 @@
|
||||
end
|
||||
until not i
|
||||
end
|
||||
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
@ -89,7 +114,7 @@
|
||||
return expandvalue(value)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return recurse(value)
|
||||
end
|
||||
|
||||
|
@ -132,6 +132,10 @@
|
||||
})
|
||||
setmetatable(sln, getmetatable(result))
|
||||
|
||||
-- Specify the solution's file system location; when path tokens are
|
||||
-- expanded in solution values, they will be made relative to this path.
|
||||
|
||||
context.basedir(ctx, project.getlocation(sln))
|
||||
|
||||
-- bake all of the projects in the list, and store that result
|
||||
local projects = {}
|
||||
|
@ -263,6 +263,13 @@
|
||||
filecfg.config = cfg
|
||||
filecfg.project = cfg.project
|
||||
|
||||
-- Set the context's base directory the project's file system
|
||||
-- location. Any path tokens which are expanded in non-path fields
|
||||
-- (such as the custom build commands) will be made relative to
|
||||
-- this path, ensuring a portable generated project.
|
||||
|
||||
context.basedir(filecfg, project.getlocation(cfg.project))
|
||||
|
||||
-- and cache the result
|
||||
cfg.files[filename] = filecfg
|
||||
end
|
||||
|
@ -123,6 +123,12 @@
|
||||
})
|
||||
setmetatable(prj, getmetatable(result))
|
||||
|
||||
-- Set the context's base directory the project's file system
|
||||
-- location. Any path tokens which are expanded in non-path fields
|
||||
-- are made relative to this, ensuring a portable generated project.
|
||||
|
||||
context.basedir(ctx, project.getlocation(prj))
|
||||
|
||||
-- bake all configurations contained by the project
|
||||
local configs = {}
|
||||
for _, pairing in ipairs(result._cfglist) do
|
||||
@ -285,24 +291,8 @@
|
||||
cfg.solution = prj.solution
|
||||
cfg.project = prj
|
||||
cfg.context = ctx
|
||||
environ.cfg = cfg
|
||||
|
||||
-- File this under "too clever by half": I want path tokens (targetdir, etc.)
|
||||
-- to expand to relative paths, so they can be used in custom build rules and
|
||||
-- other places where it would be impractical to detect and convert them. So
|
||||
-- create a proxy object with an attached metatable that converts path fields
|
||||
-- on the fly as they are requested.
|
||||
local proxy = {}
|
||||
setmetatable(proxy, {
|
||||
__index = function(proxy, key)
|
||||
local field = premake.fields[key]
|
||||
if field and field.kind == "path" then
|
||||
return premake5.project.getrelative(cfg.project, cfg[key])
|
||||
end
|
||||
return cfg[key]
|
||||
end,
|
||||
})
|
||||
|
||||
environ.cfg = proxy
|
||||
|
||||
|
||||
-- TODO: HACK, TRANSITIONAL, REMOVE: pass requests for missing values
|
||||
|
@ -285,7 +285,7 @@
|
||||
|
||||
function suite.customBuildTool_onBuildRuleWithTokens()
|
||||
files { "hello.x" }
|
||||
objdir "../../../tmp"
|
||||
objdir "../tmp/%{cfg.name}"
|
||||
configuration "**.x"
|
||||
buildmessage "Compiling $(InputFile)"
|
||||
buildcommands {
|
||||
@ -303,8 +303,8 @@
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="cxc -c hello.x -o obj/Debug/hello.xo
c2o -c obj/Debug/hello.xo -o obj/Debug/hello.obj"
|
||||
Outputs="obj/Debug/hello.obj"
|
||||
CommandLine="cxc -c hello.x -o ../tmp/Debug/hello.xo
c2o -c ../tmp/Debug/hello.xo -o ../tmp/Debug/hello.obj"
|
||||
Outputs="../tmp/Debug/hello.obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
]]
|
||||
|
@ -4,8 +4,7 @@
|
||||
-- Copyright (c) 2011-2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.detoken = {}
|
||||
local suite = T.detoken
|
||||
local suite = test.declare("detoken")
|
||||
|
||||
local detoken = premake.detoken
|
||||
|
||||
@ -66,12 +65,25 @@
|
||||
--
|
||||
|
||||
function suite.canExpandToAbsPath()
|
||||
environ.cfg = { basedir=os.getcwd() }
|
||||
environ.cfg = { basedir = os.getcwd() }
|
||||
x = detoken.expand("bin/debug/%{cfg.basedir}", environ, true)
|
||||
test.isequal(os.getcwd(), x)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If a non-path field contains a token that expands to a path, that
|
||||
-- path should be converted to a relative value.
|
||||
--
|
||||
|
||||
function suite.canExpandToRelPath()
|
||||
local cwd = os.getcwd()
|
||||
environ.cfg = { basedir = path.getdirectory(cwd) }
|
||||
x = detoken.expand("cd %{cfg.basedir}", environ, false, cwd)
|
||||
test.isequal("cd ..", x)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the value being expanded is a table, iterate over all of its values.
|
||||
--
|
||||
@ -80,3 +92,4 @@
|
||||
x = detoken.expand({ "A%{1}", "B%{2}", "C%{3}" }, environ)
|
||||
test.isequal({ "A1", "B2", "C3" }, x)
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user