summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-07-08 21:49:56 +0800
committerGitHub <[email protected]>2026-07-08 21:49:56 +0800
commit03e4bc9076d6cd9e642f4a9c565c85757db72ce2 (patch)
treeb7ff177a4734ea7634cf739ea9b2deaa34b7674e
parent0a2255cc281327f60a53d321705f607ab3c72e8f (diff)
parent4e518789d0509056bbdcd9165af03ea8bbfebfb8 (diff)
Merge pull request #7629 from xmake-io/vsxmake
Improve custom source types in Solution Explorer
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua10
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua12
-rw-r--r--xmake/plugins/project/vstudio/impl/vsutils.lua41
-rw-r--r--xmake/plugins/project/vsxmake/vsxmake.lua51
-rw-r--r--xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/#target#.vcxproj.filters3
-rw-r--r--xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/File.none(filenone)3
-rw-r--r--xmake/scripts/vsxmake/vsproj/templates/vcxproj/#target#.vcxproj3
-rw-r--r--xmake/scripts/vsxmake/vsproj/templates/vcxproj/File.none(filenone)1
8 files changed, 112 insertions, 12 deletions
diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
index f1f44c3a8..24e1a70ac 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
@@ -1438,6 +1438,16 @@ function _make_source_files(vcxprojfile, vsinfo, target)
end
end
vcxprojfile:leave("</ItemGroup>")
+
+ -- add other files (e.g. files added by add_files but handled by a custom rule), for display only
+ local otherfiles = vsutils.otherfiles(target)
+ if #otherfiles > 0 then
+ vcxprojfile:enter("<ItemGroup>")
+ for _, otherfile in ipairs(otherfiles) do
+ vcxprojfile:print("<None Include=\"%s\" />", path.relative(path.absolute(otherfile), target.project_dir))
+ end
+ vcxprojfile:leave("</ItemGroup>")
+ end
end
-- make vcxproj
diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua
index ed9002662..6c4c0ea8d 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj_filters.lua
@@ -23,8 +23,10 @@
--
-- imports
+import("core.base.hashset")
import("core.tool.compiler")
import("vsfile")
+import("vsutils")
-- make header
function _make_header(filtersfile, vsinfo)
@@ -147,14 +149,20 @@ end
-- make sources
function _make_sources(filtersfile, vsinfo, target, vcxprojdir)
+ -- the source files that are not natively built by VS, list them as <None> for display only
+ local otherfiles = hashset.from(vsutils.otherfiles(target))
+ -- the files displayed as include files (e.g. also added by add_extrafiles), skip them to avoid duplicate
+ local includefiles = hashset.from(table.join(target.headerfiles or {}, target.extrafiles or {}))
+
-- and sources
filtersfile:enter("<ItemGroup>")
for _, sourcefile in ipairs(target.sourcefiles) do
local filter = _make_filter(sourcefile, target, vcxprojdir)
- if filter then
+ if filter and not includefiles:has(sourcefile) then
local nodename
local ext = path.extension(sourcefile)
- if ext == "asm" then nodename = "CustomBuild"
+ if otherfiles:has(sourcefile) then nodename = "None"
+ elseif ext == "asm" then nodename = "CustomBuild"
elseif ext == "cu" then nodename = "CudaCompile"
else nodename = "ClCompile"
end
diff --git a/xmake/plugins/project/vstudio/impl/vsutils.lua b/xmake/plugins/project/vstudio/impl/vsutils.lua
index 30832ae3f..2cf5e7bdb 100644
--- a/xmake/plugins/project/vstudio/impl/vsutils.lua
+++ b/xmake/plugins/project/vstudio/impl/vsutils.lua
@@ -20,6 +20,7 @@
-- imports
import("core.base.option")
+import("core.base.hashset")
import("core.project.config")
import("core.project.project")
import("core.cache.memcache")
@@ -64,6 +65,46 @@ function translate_path(filepath)
return (filepath:gsub("::", "#"))
end
+-- get the source files that are not natively built by VS, e.g. files added by add_files but handled
+-- by a custom rule. we list them as <None> in the project for display only (like add_extrafiles).
+-- this must be consistent with vs201x_vcxproj._make_source_files.
+-- @see https://github.com/xmake-io/xmake/issues/7619
+function otherfiles(target)
+
+ -- collect the source files that are natively built by VS
+ local builtfiles = hashset.new()
+ for _, targetinfo in ipairs(target.info or {}) do
+ for _, sourcebatch in pairs(targetinfo.sourcebatches or {}) do
+ local sourcekind = sourcebatch.sourcekind
+ local rulename = sourcebatch.rulename
+ if rulename == "c.build" or rulename == "c++.build" or rulename == "c++.build.modules"
+ or sourcekind == "as" or sourcekind == "mrc" or sourcekind == "cu" then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ builtfiles:insert(sourcefile)
+ end
+ end
+ end
+ end
+
+ -- exclude the header/extra files and the precompiled header to avoid duplicate display
+ local excludefiles = hashset.from(table.join(target.headerfiles or {}, target.extrafiles or {}))
+ if target.pcheader then
+ excludefiles:insert(target.pcheader)
+ end
+ if target.pcxxheader then
+ excludefiles:insert(target.pcxxheader)
+ end
+
+ -- the remaining source files are the custom files
+ local results = {}
+ for _, sourcefile in ipairs(target.sourcefiles or {}) do
+ if not builtfiles:has(sourcefile) and not excludefiles:has(sourcefile) then
+ table.insert(results, sourcefile)
+ end
+ end
+ return results
+end
+
function reset_config_and_caches(mode, arch)
-- reload config, project and platform
-- modify config
diff --git a/xmake/plugins/project/vsxmake/vsxmake.lua b/xmake/plugins/project/vsxmake/vsxmake.lua
index cd61dfcbf..99584e789 100644
--- a/xmake/plugins/project/vsxmake/vsxmake.lua
+++ b/xmake/plugins/project/vsxmake/vsxmake.lua
@@ -39,6 +39,21 @@ local template_targets = path.join(template_root, "Xmake.Custom.targets")
local template_items = path.join(template_root, "Xmake.Custom.items")
local template_itemfil = path.join(template_root, "Xmake.Custom.items.filters")
+-- the source file extensions natively supported by the vsxmake project, keyed by the template import name
+-- the `filenone` group collects everything else (e.g. files added by add_files but handled by a custom rule)
+local _source_exts = {
+ filec = {".c"},
+ filecxx = {".cpp", ".cc", ".cxx"},
+ filempp = {".mpp", ".mxx", ".cppm", ".ixx"},
+ filecu = {".cu"},
+ fileobj = {".obj", ".o"},
+ filerc = {".rc"},
+ fileui = {".ui"},
+ fileqrc = {".qrc"},
+ filets = {".ts"},
+ filecs = {".cs"}
+}
+
function _filter_files(files, includeexts, excludeexts)
local positive = not excludeexts
local extset = hashset.from(positive and includeexts or excludeexts)
@@ -122,34 +137,50 @@ function _buildparams(info, target, default)
end
if args.filec then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".c"}))
+ table.insert(r, _filter_files(files, _source_exts.filec))
elseif args.filecxx then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".cpp", ".cc", ".cxx"}))
+ table.insert(r, _filter_files(files, _source_exts.filecxx))
elseif args.filempp then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".mpp", ".mxx", ".cppm", ".ixx"}))
+ table.insert(r, _filter_files(files, _source_exts.filempp))
elseif args.filecu then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".cu"}))
+ table.insert(r, _filter_files(files, _source_exts.filecu))
elseif args.fileobj then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".obj", ".o"}))
+ table.insert(r, _filter_files(files, _source_exts.fileobj))
elseif args.filerc then
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".rc"}))
+ table.insert(r, _filter_files(files, _source_exts.filerc))
elseif args.fileui then -- for qt/.ui
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".ui"}))
+ table.insert(r, _filter_files(files, _source_exts.fileui))
elseif args.fileqrc then -- for qt/.qrc
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".qrc"}))
+ table.insert(r, _filter_files(files, _source_exts.fileqrc))
elseif args.filets then -- for qt/.ts
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".ts"}))
+ table.insert(r, _filter_files(files, _source_exts.filets))
elseif args.filecs then -- for c#
local files = info._targets[target].sourcefiles
- table.insert(r, _filter_files(files, {".cs"}))
+ table.insert(r, _filter_files(files, _source_exts.filecs))
+ elseif args.filenone then -- for custom build steps, e.g. files added by add_files but handled by a custom rule
+ -- collect the source files not natively supported by vsxmake, and exclude the header/extra files
+ -- to avoid duplicate display with the include group (add_extrafiles)
+ local _target = info._targets[target]
+ local excludeexts = {}
+ for _, exts in table.orderpairs(_source_exts) do
+ table.join2(excludeexts, exts)
+ end
+ local excludefiles = hashset.from(table.join(_target.headerfiles or {}, _target.extrafiles or {}))
+ local files = {}
+ for _, file in ipairs(_target.sourcefiles) do
+ if not excludefiles:has(file) then
+ table.insert(files, file)
+ end
+ end
+ table.insert(r, _filter_files(files, nil, excludeexts))
elseif args.incc then
local files = table.join(info._targets[target].headerfiles or {}, info._targets[target].extrafiles)
table.insert(r, _filter_files(files, nil, {".natvis"}))
diff --git a/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/#target#.vcxproj.filters b/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/#target#.vcxproj.filters
index 998c8af83..7d8131262 100644
--- a/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/#target#.vcxproj.filters
+++ b/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/#target#.vcxproj.filters
@@ -50,6 +50,9 @@
#Import(File.qrc)#
#Import(File.ts)#
</ItemGroup>
+ <ItemGroup>
+#Import(File.none)#
+ </ItemGroup>
<Import Condition="Exists('$(MSBuildThisFileDirectory)\Xmake.Custom.files.filters')"
Project="$(MSBuildThisFileDirectory)\Xmake.Custom.files.filters" />
</Project>
diff --git a/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/File.none(filenone) b/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/File.none(filenone)
new file mode 100644
index 000000000..9aee25191
--- /dev/null
+++ b/xmake/scripts/vsxmake/vsproj/templates/vcxproj.filters/File.none(filenone)
@@ -0,0 +1,3 @@
+ <None Include="#path#">
+ <Filter>#dir#</Filter>
+ </None>
diff --git a/xmake/scripts/vsxmake/vsproj/templates/vcxproj/#target#.vcxproj b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/#target#.vcxproj
index 21a7eb99a..a01ae9554 100644
--- a/xmake/scripts/vsxmake/vsproj/templates/vcxproj/#target#.vcxproj
+++ b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/#target#.vcxproj
@@ -52,6 +52,9 @@
#Import(File.qrc)#
#Import(File.ts)#
</ItemGroup>
+ <ItemGroup>
+#Import(File.none)#
+ </ItemGroup>
<!-- <ItemGroup>
#Import(ProjectRef)#
</ItemGroup> -->
diff --git a/xmake/scripts/vsxmake/vsproj/templates/vcxproj/File.none(filenone) b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/File.none(filenone)
new file mode 100644
index 000000000..6429fe3e9
--- /dev/null
+++ b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/File.none(filenone)
@@ -0,0 +1 @@
+ <None Include="#path#" />