diff options
| author | ruki <[email protected]> | 2026-07-08 21:49:56 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-08 21:49:56 +0800 |
| commit | 03e4bc9076d6cd9e642f4a9c565c85757db72ce2 (patch) | |
| tree | b7ff177a4734ea7634cf739ea9b2deaa34b7674e | |
| parent | 0a2255cc281327f60a53d321705f607ab3c72e8f (diff) | |
| parent | 4e518789d0509056bbdcd9165af03ea8bbfebfb8 (diff) | |
Merge pull request #7629 from xmake-io/vsxmake
Improve custom source types in Solution Explorer
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#" /> |
