diff --git a/src/actions/vstudio/vs2010_vcxproj_filters.lua b/src/actions/vstudio/vs2010_vcxproj_filters.lua index 181219e1..17a69024 100644 --- a/src/actions/vstudio/vs2010_vcxproj_filters.lua +++ b/src/actions/vstudio/vs2010_vcxproj_filters.lua @@ -41,7 +41,7 @@ local fullpath = "" -- split the file's path into it's component parts - local folders = string.explode(file.fullpath, "/", true) + local folders = string.explode(file.vpath, "/", true) for i = 1, #folders - 1 do if numFilters == 0 then _p(1,'') @@ -78,7 +78,7 @@ if #files > 0 then _p(1,'') for _, file in ipairs(files) do - local filter = path.getdirectory(file.fullpath) + local filter = path.getdirectory(file.vpath) if filter ~= "." then _p(2,'<%s Include=\"%s\">', group, path.translate(file.fullpath)) _p(3,'%s', path.translate(filter)) diff --git a/src/project/project.lua b/src/project/project.lua index f9a861c2..b056b2c7 100755 --- a/src/project/project.lua +++ b/src/project/project.lua @@ -60,6 +60,7 @@ -- These file configurations contain: -- -- fullpath - the relative path from the project to the file +-- vpath - the file's virtual path, if specified, or fullpath if not -- function project.eachfile(prj) @@ -69,14 +70,17 @@ return function() i = i + 1 if i <= #files then - local fullpath = project.getrelative(prj, files[i]) - local fcfg = {} - fcfg.fullpath = fullpath - return fcfg + fcfg.fullpath = project.getrelative(prj, files[i]) - -- local fcfg = prj.__fileconfigs[t[i]] - -- fcfg.vpath = premake.project.getvpath(prj, fcfg.name) + local vpath = project.getvpath(prj, files[i]) + if vpath ~= files[i] then + fcfg.vpath = vpath + else + fcfg.vpath = fcfg.fullpath + end + + return fcfg end end end @@ -237,10 +241,70 @@ local tr = premake.tree.new(prj.name) for fcfg in project.eachfile(prj) do - local node = premake.tree.add(tr, fcfg.fullpath) + local node = premake.tree.add(tr, fcfg.vpath) node.cfg = fcfg end premake.tree.sort(tr) return tr end + + +-- +-- Given a source file path, return a corresponding virtual path based on +-- the vpath entries in the project. If no matching vpath entry is found, +-- the original path is returned. +-- + + function project.getvpath(prj, filename) + -- if there is no match, return the input filename + local vpath = filename + + -- file are always specified relative to the script, so the vpath + -- patterns do too. Get the script relative path + local relpath = path.getrelative(prj.basedir, filename) + + for replacement,patterns in pairs(prj.vpaths or {}) do + for _,pattern in ipairs(patterns) do + -- does the filename match this vpath pattern? + local i = relpath:find(path.wildcards(pattern)) + if i == 1 then + -- yes; trim the leading portion of the path + i = pattern:find("*", 1, true) or (pattern:len() + 1) + local leaf = relpath:sub(i) + if leaf:startswith("/") then + leaf = leaf:sub(2) + end + + -- check for (and remove) stars in the replacement pattern. + -- If there are none, then trim all path info from the leaf + -- and use just the filename in the replacement (stars should + -- really only appear at the end; I'm cheating here) + local stem = "" + if replacement:len() > 0 then + stem, stars = replacement:gsub("%*", "") + if stars == 0 then + leaf = path.getname(leaf) + end + end + + vpath = path.join(stem, leaf) + end + end + end + + -- remove any dot ("./", "../") patterns from the start of the path + local changed + repeat + changed = true + if vpath:startswith("./") then + vpath = vpath:sub(3) + elseif vpath:startswith("../") then + vpath = vpath:sub(4) + else + changed = false + end + until not changed + + return vpath + end diff --git a/tests/actions/vstudio/vc200x/test_files.lua b/tests/actions/vstudio/vc200x/test_files.lua index d70aae67..2ec60ccf 100644 --- a/tests/actions/vstudio/vc200x/test_files.lua +++ b/tests/actions/vstudio/vc200x/test_files.lua @@ -88,6 +88,28 @@ end +-- +-- Check the structure of a file with a virtual path. +-- + + function suite.file_onVpath() + files { "src/hello.cpp" } + vpaths { ["Source Files"] = "**.cpp" } + prepare() + test.capture [[ + + + + + ]] + end + + -- -- Make sure that the special "build a C code" logic only gets triggered -- by actual C source code files. diff --git a/tests/actions/vstudio/vc200x/test_filters.lua b/tests/actions/vstudio/vc200x/test_filters.lua deleted file mode 100644 index 4955b7cc..00000000 --- a/tests/actions/vstudio/vc200x/test_filters.lua +++ /dev/null @@ -1,50 +0,0 @@ --- --- tests/actions/vstudio/vc200x/test_filters.lua --- Validate generation of filter blocks in Visual Studio 200x C/C++ projects. --- Copyright (c) 2011 Jason Perkins and the Premake project --- - - T.vs200x_filters = { } - local suite = T.vs200x_filters - local vc200x = premake.vstudio.vc200x - - --- --- Setup/teardown --- - - local sln, prj - - function suite.setup() - _ACTION = "vs2008" - sln = test.createsolution() - end - - local function prepare() - premake.bake.buildconfigs() - sln.vstudio_configs = premake.vstudio.buildconfigs(sln) - prj = premake.solution.getproject(sln,1) - end - - --- --- File/filter assignment tests --- - - function suite.Filter_UsesVirtualForm_OnVpath() - files { "src/hello.cpp" } - vpaths { ["Source Files"] = "**.cpp" } - prepare() - vc200x.Files(prj) - test.capture [[ - - - - - ]] - end diff --git a/tests/premake4.lua b/tests/premake4.lua index 9cccd6ff..b6c0e195 100644 --- a/tests/premake4.lua +++ b/tests/premake4.lua @@ -105,7 +105,6 @@ dofile("actions/vstudio/vc200x/test_debug_settings.lua") dofile("actions/vstudio/vc200x/test_configuration.lua") dofile("actions/vstudio/vc200x/test_files.lua") - dofile("actions/vstudio/vc200x/test_filters.lua") dofile("actions/vstudio/vc200x/test_linker_block.lua") dofile("actions/vstudio/vc200x/test_manifest_block.lua") dofile("actions/vstudio/vc200x/test_mfc.lua") diff --git a/tests/project/test_eachfile.lua b/tests/project/test_eachfile.lua index 8ddf235d..bbb67b89 100644 --- a/tests/project/test_eachfile.lua +++ b/tests/project/test_eachfile.lua @@ -1,12 +1,12 @@ -- -- tests/project/test_eachfile.lua -- Automated test suite for the file iteration function. --- Copyright (c) 2011 Jason Perkins and the Premake project +-- Copyright (c) 2011-2012 Jason Perkins and the Premake project -- T.project_eachfile = { } local suite = T.project_eachfile - local project = premake.project + local project = premake5.project -- @@ -15,32 +15,55 @@ local sln, prj function suite.setup() - sln = test.createsolution() + sln, prj = test.createsolution() end - local function prepare() - premake.bake.buildconfigs() - prj = premake.solution.getproject(sln, 1) + local function prepare(field) + if not field then + field = "fullpath" + end + for file in project.eachfile(prj) do + _p(2, file[field]) + end end -- --- Tests +-- Sanity check that all files are returned, with project relative paths. -- - function suite.ReturnsAllFiles() + function suite.listsAllFiles() files { "hello.h", "hello.c" } prepare() - local iter = project.eachfile(prj) - test.isequal("hello.h", iter().name) - test.isequal("hello.c", iter().name) - test.isnil(iter()) + test.capture [[ + hello.h + hello.c + ]] end +-- +-- Ensure that the virtual path field defaults to the real file path. +-- - function suite.ReturnedObjectIncludesVpath() + function suite.vpathsAreNil_onNoVpaths() files { "hello.h", "hello.c" } - prepare() - local iter = project.eachfile(prj) - test.isequal("hello.h", iter().vpath) + prepare("vpath") + test.capture [[ + hello.h + hello.c + ]] + end + +-- +-- If a virtual path is specified, the vpath field should be set. +-- + + function suite.vpathSet_onVpath() + files { "hello.h", "hello.c" } + vpaths { Headers = "**.h" } + prepare("vpath") + test.capture [[ + Headers/hello.h + hello.c + ]] end diff --git a/tests/project/test_vpaths.lua b/tests/project/test_vpaths.lua index 8616907e..d1f3194d 100644 --- a/tests/project/test_vpaths.lua +++ b/tests/project/test_vpaths.lua @@ -1,12 +1,12 @@ -- -- tests/project/test_vpaths.lua -- Automated test suite for the project support functions. --- Copyright (c) 2011 Jason Perkins and the Premake project +-- Copyright (c) 2011-2012 Jason Perkins and the Premake project -- T.project_vpaths = { } local suite = T.project_vpaths - local project = premake.project + local project = premake5.project -- @@ -19,8 +19,7 @@ end local function prepare() - premake.bake.buildconfigs() - prj = premake.solution.getproject(sln, 1) + prj = premake.solution.getproject_ng(sln, 1) end