summaryrefslogtreecommitdiff
path: root/xmake/plugins/project
diff options
context:
space:
mode:
authorJérôme Leclercq <[email protected]>2021-12-22 20:56:39 +0100
committerJérôme Leclercq <[email protected]>2021-12-22 20:56:39 +0100
commit01b29068ec1effab05be538ed9df3e05727ae181 (patch)
treee03fe3f0cc26ca2de3547e1ee8adf5e1cfa34f3b /xmake/plugins/project
parent9d5658ade35f41bb2c8a348e4d835c52eb33cf5d (diff)
projects/vstudio: add support for runenvs
Diffstat (limited to 'xmake/plugins/project')
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x.lua104
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua57
2 files changed, 131 insertions, 30 deletions
diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua
index bf76b13dc..759789fda 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x.lua
@@ -33,10 +33,69 @@ import("vs201x_vcxproj_filters")
import("core.cache.memcache")
import("core.cache.localcache")
import("private.action.require.install", {alias = "install_requires"})
+import("private.action.run.make_runenvs")
import("actions.config.configfiles", {alias = "generate_configfiles", rootdir = os.programdir()})
import("actions.config.configheader", {alias = "generate_configheader", rootdir = os.programdir()})
import("private.utils.batchcmds")
+-- escape special chars in msbuild file
+function _escape(str)
+ if not str then
+ return nil
+ end
+
+ local map =
+ {
+ ["%"] = "%25" -- Referencing metadata
+ , ["$"] = "%24" -- Referencing properties
+ , ["@"] = "%40" -- Referencing item lists
+ , ["'"] = "%27" -- Conditions and other expressions
+ , [";"] = "%3B" -- List separator
+ , ["?"] = "%3F" -- Wildcard character for file names in Include and Exclude attributes
+ , ["*"] = "%2A" -- Wildcard character for use in file names in Include and Exclude attributes
+ -- html entities
+ , ["\""] = "&quot;"
+ , ["<"] = "&lt;"
+ , [">"] = "&gt;"
+ , ["&"] = "&amp;"
+ }
+
+ return (string.gsub(str, "[%%%$@';%?%*\"<>&]", function (c) return assert(map[c]) end))
+end
+
+function _make_dirs(dir, vcxprojdir)
+ if dir == nil then
+ return ""
+ end
+ if type(dir) == "string" then
+ dir = path.translate(dir)
+ if dir == "" then
+ return ""
+ end
+ if path.is_absolute(dir) then
+ print("absolute")
+ print(dir)
+ print("projectdir", project.directory())
+ if dir:startswith(project.directory()) then
+ print("relative to ", vcxprojdir)
+ print(dir)
+ return _escape(path.relative(dir, vcxprojdir))
+ end
+ return _escape(dir)
+ else
+ print("relative")
+ print(dir)
+ return _escape(path.relative(path.absolute(dir), vcxprojdir))
+ end
+ end
+ local r = {}
+ for k, v in ipairs(dir) do
+ r[k] = _make_dirs(v, vcxprojdir)
+ end
+ r = table.unique(r)
+ return path.joinenv(r)
+end
+
-- clear cache configuration
function _clear_cacheconf()
config.clear()
@@ -180,7 +239,7 @@ function _make_custom_commands(target)
end
-- make target info
-function _make_targetinfo(mode, arch, target)
+function _make_targetinfo(mode, arch, target, vcxprojdir)
-- init target info
local targetinfo = { mode = mode, arch = (arch == "x86" and "Win32" or "x64") }
@@ -246,6 +305,44 @@ function _make_targetinfo(mode, arch, target)
-- save execution dir (when executed from VS)
targetinfo.rundir = target:rundir()
+ -- save runenvs
+ local runenvs = {}
+ local addrunenvs, setrunenvs = make_runenvs(target)
+ for k, v in pairs(target:pkgenvs()) do
+ addrunenvs = addrunenvs or {}
+ addrunenvs[k] = table.join(table.wrap(addrunenvs[k]), path.splitenv(v))
+ end
+ for _, dep in ipairs(target:orderdeps()) do
+ for k, v in pairs(dep:pkgenvs()) do
+ addrunenvs = addrunenvs or {}
+ addrunenvs[k] = table.join(table.wrap(addrunenvs[k]), path.splitenv(v))
+ end
+ end
+ for k, v in pairs(addrunenvs) do
+ if k:upper() == "PATH" then
+ runenvs[k] = format("%s;$([System.Environment]::GetEnvironmentVariable('%s'))", _make_dirs(v, vcxprojdir), k)
+ else
+ runenvs[k] = format("%s;$([System.Environment]::GetEnvironmentVariable('%s'))", path.joinenv(v), k)
+ end
+ end
+ for k, v in pairs(setrunenvs) do
+ if #v == 1 then
+ v = v[1]
+ if path.is_absolute(v) and v:startswith(project.directory()) then
+ runenvs[k] = _make_dirs(v, vcxprojdir)
+ else
+ runenvs[k] = v[1]
+ end
+ else
+ runenvs[k] = path.joinenv(v)
+ end
+ end
+ local runenvstr = {}
+ for k, v in pairs(runenvs) do
+ table.insert(runenvstr, k .. "=" .. v)
+ end
+ targetinfo.runenvs = table.concat(runenvstr, "\n")
+
-- use mfc? save the mfc runtime kind
if target:rule("win.sdk.mfc.shared_app") or target:rule("win.sdk.mfc.shared") then
targetinfo.usemfc = "Dynamic"
@@ -462,6 +559,9 @@ function make(outputdir, vsinfo)
-- make target with the given mode and arch
targets[targetname] = targets[targetname] or {}
local _target = targets[targetname]
+
+ -- the vcxproj directory
+ _target.project_dir = path.join(vsinfo.solution_dir, targetname)
-- save c/c++ precompiled header
_target.pcheader = target:pcheaderfile("c") -- header.h
@@ -472,7 +572,7 @@ function make(outputdir, vsinfo)
_target.kind = target:kind()
_target.scriptdir = target:scriptdir()
_target.info = _target.info or {}
- table.insert(_target.info, _make_targetinfo(mode, arch, target))
+ table.insert(_target.info, _make_targetinfo(mode, arch, target, _target.project_dir))
-- save all sourcefiles and headerfiles
_target.sourcefiles = table.unique(table.join(_target.sourcefiles or {}, (target:sourcefiles())))
diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
index 154e0763b..0d3d06da5 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
@@ -166,7 +166,7 @@ function _make_tailer(vcxprojfile, vsinfo)
end
-- make Configurations
-function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir)
+function _make_configurations(vcxprojfile, vsinfo, target)
-- the target name
local targetname = target.name
@@ -233,8 +233,8 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir)
-- make OutputDirectory and IntermediateDirectory
for _, targetinfo in ipairs(target.info) do
vcxprojfile:enter("<PropertyGroup Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">", targetinfo.mode, targetinfo.arch)
- vcxprojfile:print("<OutDir>%s\\</OutDir>", _make_dirs(targetinfo.targetdir, vcxprojdir))
- vcxprojfile:print("<IntDir>%s\\</IntDir>", _make_dirs(targetinfo.objectdir, vcxprojdir))
+ vcxprojfile:print("<OutDir>%s\\</OutDir>", _make_dirs(targetinfo.targetdir, target.project_dir))
+ vcxprojfile:print("<IntDir>%s\\</IntDir>", _make_dirs(targetinfo.objectdir, target.project_dir))
vcxprojfile:print("<TargetName>%s</TargetName>", path.basename(targetinfo.targetfile))
vcxprojfile:print("<TargetExt>%s</TargetExt>", path.extension(targetinfo.targetfile))
@@ -247,7 +247,8 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir)
-- make Debugger
for _, targetinfo in ipairs(target.info) do
vcxprojfile:enter("<PropertyGroup Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\" Label=\"Debugger\">", targetinfo.mode, targetinfo.arch)
- vcxprojfile:print("<LocalDebuggerWorkingDirectory>%s</LocalDebuggerWorkingDirectory>", _make_dirs(targetinfo.rundir, vcxprojdir))
+ vcxprojfile:print("<LocalDebuggerWorkingDirectory>%s</LocalDebuggerWorkingDirectory>", _make_dirs(targetinfo.rundir, target.project_dir))
+ vcxprojfile:print("<LocalDebuggerEnvironment>%s;$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>", targetinfo.runenvs)
vcxprojfile:leave("</PropertyGroup>")
end
end
@@ -530,7 +531,7 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir)
end
-- make common items
-function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir)
+function _make_common_items(vcxprojfile, vsinfo, target)
-- for each mode and arch
for _, targetinfo in ipairs(target.info) do
@@ -546,7 +547,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir)
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
-- make compiler flags
- local flags = _make_compflags(sourcefile, targetinfo, vcxprojdir)
+ local flags = _make_compflags(sourcefile, targetinfo, target.project_dir)
-- no common flags for asm
if sourcekind ~= "as" then
@@ -591,7 +592,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir)
targetinfo.sourceflags = sourceflags
-- make common item
- _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir)
+ _make_common_item(vcxprojfile, vsinfo, target, targetinfo, target.project_dir)
end
end
@@ -601,7 +602,7 @@ function _make_header_file(vcxprojfile, includefile, vcxprojdir)
end
-- make source file for all modes
-function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir)
+function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo)
-- get object file and source kind
local sourcekind = nil
@@ -612,7 +613,7 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc
-- enter it
local nodename = (sourcekind == "as" and "CustomBuild" or (sourcekind == "mrc" and "ResourceCompile" or "ClCompile"))
- sourcefile = path.relative(path.absolute(sourcefile), vcxprojdir)
+ sourcefile = path.relative(path.absolute(sourcefile), target.project_dir)
vcxprojfile:enter("<%s Include=\"%s\">", nodename, sourcefile)
-- for *.asm files
@@ -620,8 +621,8 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc
vcxprojfile:print("<ExcludedFromBuild>false</ExcludedFromBuild>")
vcxprojfile:print("<FileType>Document</FileType>")
for _, info in ipairs(sourceinfo) do
- local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir)
- local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, vcxprojdir)
+ local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir)
+ local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, target.project_dir)
vcxprojfile:print("<Outputs Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s\'\">%s</Outputs>", info.mode .. '|' .. info.arch, objectfile)
vcxprojfile:print("<Command Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s\'\">%s</Command>", info.mode .. '|' .. info.arch, compcmd)
end
@@ -630,7 +631,7 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc
-- for *.rc files
elseif sourcekind == "mrc" then
for _, info in ipairs(sourceinfo) do
- local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir)
+ local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir)
vcxprojfile:print("<ResourceOutputFileName Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">%s</ResourceOutputFileName>", info.mode, info.arch, objectfile)
end
@@ -717,10 +718,10 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc
end
-- make source file for specific modes
-function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir)
+function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo)
-- add source file
- sourcefile = path.relative(path.absolute(sourcefile), vcxprojdir)
+ sourcefile = path.relative(path.absolute(sourcefile), target.project_dir)
for _, info in ipairs(sourceinfo) do
-- enter it
@@ -728,9 +729,9 @@ function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sour
vcxprojfile:enter("<%s Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\" Include=\"%s\">", nodename, info.mode, info.arch, sourcefile)
-- for *.asm files
- local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir)
+ local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir)
if info.sourcekind == "as" then
- local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, vcxprojdir)
+ local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, target.project_dir)
vcxprojfile:print("<ExcludedFromBuild>false</ExcludedFromBuild>")
vcxprojfile:print("<FileType>Document</FileType>")
vcxprojfile:print("<Outputs>%s</Outputs>", objectfile)
@@ -757,12 +758,12 @@ function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sour
end
-- make source file for precompiled header
-function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir)
+function _make_source_file_forpch(vcxprojfile, vsinfo, target)
-- add precompiled source file
local pcheader = target.pcxxheader or target.pcheader
if pcheader then
- local sourcefile = path.relative(path.absolute(pcheader), vcxprojdir)
+ local sourcefile = path.relative(path.absolute(pcheader), target.project_dir)
vcxprojfile:enter("<ClCompile Include=\"%s\">", sourcefile)
vcxprojfile:print("<PrecompiledHeader>Create</PrecompiledHeader>")
vcxprojfile:print("<PrecompiledHeaderFile></PrecompiledHeaderFile>")
@@ -776,7 +777,7 @@ function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir)
-- add object file
local pcoutputfile = info.pcxxoutputfile or info.pcoutputfile
if pcoutputfile then
- local objectfile = path.relative(path.absolute(pcoutputfile .. ".obj"), vcxprojdir)
+ local objectfile = path.relative(path.absolute(pcoutputfile .. ".obj"), target.project_dir)
vcxprojfile:print("<ObjectFileName Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">%s</ObjectFileName>", info.mode, info.arch, objectfile)
end
end
@@ -785,7 +786,7 @@ function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir)
end
-- make source files
-function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir)
+function _make_source_files(vcxprojfile, vsinfo, target)
-- add source files
vcxprojfile:enter("<ItemGroup>")
@@ -810,14 +811,14 @@ function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir)
-- make source files
for sourcefile, sourceinfo in pairs(sourceinfos) do
if #sourceinfo == #target.info then
- _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir)
+ _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo)
else
- _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir)
+ _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo)
end
end
-- make precompiled source file
- _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir)
+ _make_source_file_forpch(vcxprojfile, vsinfo, target)
vcxprojfile:leave("</ItemGroup>")
@@ -827,7 +828,7 @@ function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir)
for _, includefile in ipairs(target.headerfiles) do
-- we need ignore pcheader file to fix https://github.com/xmake-io/xmake/issues/1171
if not pcheader or includefile ~= pcheader then
- _make_header_file(vcxprojfile, includefile, vcxprojdir)
+ _make_header_file(vcxprojfile, includefile, target.project_dir)
end
end
vcxprojfile:leave("</ItemGroup>")
@@ -840,7 +841,7 @@ function make(vsinfo, target)
local targetname = target.name
-- the vcxproj directory
- local vcxprojdir = path.join(vsinfo.solution_dir, targetname)
+ local vcxprojdir = target.project_dir
-- open vcxproj file
local vcxprojpath = path.join(vcxprojdir, targetname .. ".vcxproj")
@@ -853,13 +854,13 @@ function make(vsinfo, target)
_make_header(vcxprojfile, vsinfo)
-- make Configurations
- _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir)
+ _make_configurations(vcxprojfile, vsinfo, target)
-- make common items
- _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir)
+ _make_common_items(vcxprojfile, vsinfo, target)
-- make source files
- _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir)
+ _make_source_files(vcxprojfile, vsinfo, target)
-- make tailer
_make_tailer(vcxprojfile, vsinfo)