diff --git a/xmake/plugins/project/vstudio/impl/vs200x.lua b/xmake/plugins/project/vstudio/impl/vs200x.lua index d1f220c8aac..409d73a4930 100644 --- a/xmake/plugins/project/vstudio/impl/vs200x.lua +++ b/xmake/plugins/project/vstudio/impl/vs200x.lua @@ -22,6 +22,7 @@ import("core.project.project") import("vs200x_solution") import("vs200x_vcproj") +import("vs_csproj") -- make vstudio project function make(outputdir, vsinfo) @@ -44,8 +45,17 @@ function make(outputdir, vsinfo) -- make vsprojs for _, target in pairs(project.targets()) do - if not target:is_phony() then - vs200x_vcproj.make(vsinfo, target) + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind == "cc" or sourcekind == "cxx" then + if not target:is_phony() then + vs200x_vcproj.make(vsinfo, target) + end + break + elseif sourcekind == "cs" then + vs_csproj.make(vsinfo, target) + break + end end end diff --git a/xmake/plugins/project/vstudio/impl/vs200x_solution.lua b/xmake/plugins/project/vstudio/impl/vs200x_solution.lua index 48b10445f57..b0a0987979f 100644 --- a/xmake/plugins/project/vstudio/impl/vs200x_solution.lua +++ b/xmake/plugins/project/vstudio/impl/vs200x_solution.lua @@ -31,15 +31,29 @@ end -- make projects function _make_projects(slnfile, vsinfo) - -- the vstudio tool uuid for vc project - local vctool = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" - -- make all targets for targetname, target in pairs(project.targets()) do + + tool_id = "" -- the vstudio tool uuid for project + proj_extension = "" + + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind == "cc" or sourcekind == "cxx" then + tool_id = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" + proj_extension = "vcxproj" + break + elseif sourcekind == "cs" then + tool_id = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" + proj_extension = "csproj" + break + end + end + if not target:is_phony() then -- enter project - slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcproj\", \"{%s}\"", vctool, targetname, targetname, targetname, hash.uuid4(targetname)) + slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.%s\", \"{%s}\"", tool_id, targetname, targetname, targetname, proj_extension, hash.uuid4(targetname)) -- add dependences for _, dep in ipairs(target:get("deps")) do diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index a8b48dada5f..0d071270010 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -32,6 +32,7 @@ import("core.tool.toolchain") import("vs201x_solution") import("vs201x_vcxproj") import("vs201x_vcxproj_filters") +import("vs_csproj") import("vsutils") import("core.cache.memcache") import("core.cache.localcache") @@ -288,7 +289,7 @@ function _make_targetinfo(mode, arch, target, vcxprojdir) for _, sourcebatch in table.orderpairs(sourcebatches) do local sourcekind = sourcebatch.sourcekind local rulename = sourcebatch.rulename - if sourcekind then + if sourcekind and sourcekind ~= "cs" then -- TODO: temp, delete it when cs flags are done for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do local compflags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) if not firstcompflags and (rulename == "c.build" or rulename == "c++.build" or rulename == "cuda.build") then @@ -567,10 +568,18 @@ function make(outputdir, vsinfo) -- make solution vs201x_solution.make(vsinfo) - -- make .vcxproj + -- make .vcxproj and .csproj for _, target in table.orderpairs(targets) do - vs201x_vcxproj.make(vsinfo, target) - vs201x_vcxproj_filters.make(vsinfo, target) + for _, targetinfo in ipairs(target.info) do + if targetinfo.sourcekinds and table.contains(targetinfo.sourcekinds, "cc", "cxx") then + vs201x_vcxproj.make(vsinfo, target) + vs201x_vcxproj_filters.make(vsinfo, target) + break + elseif targetinfo.sourcekinds and table.contains(targetinfo.sourcekinds, "cs") then + vs_csproj.make(vsinfo, target) + break + end + end end -- clear local cache diff --git a/xmake/plugins/project/vstudio/impl/vs201x_solution.lua b/xmake/plugins/project/vstudio/impl/vs201x_solution.lua index 82ede489a75..4f8b5d14360 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_solution.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_solution.lua @@ -35,7 +35,6 @@ function _make_projects(slnfile, vsinfo) -- make all targets local groups = {} local targets = {} - local vctool = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" for targetname, target in table.orderpairs(project.targets()) do -- we need to set startup project for default or binary target -- @see https://github.com/xmake-io/xmake/issues/1249 @@ -53,8 +52,23 @@ function _make_projects(slnfile, vsinfo) end end for _, target in ipairs(targets) do + tool_id = "" + proj_extension = "" + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind == "cc" or sourcekind == "cxx" then + tool_id = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" + proj_extension = "vcxproj" + break + elseif sourcekind == "cs" then + tool_id = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" + proj_extension = "csproj" + break + end + end + local targetname = target:name() - slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.vcxproj\", \"{%s}\"", vctool, targetname, targetname, targetname, hash.uuid4(targetname)) + slnfile:enter("Project(\"{%s}\") = \"%s\", \"%s\\%s.%s\", \"{%s}\"", tool_id, targetname, targetname, targetname, proj_extension, hash.uuid4(targetname)) for _, dep in ipairs(target:get("deps")) do slnfile:enter("ProjectSection(ProjectDependencies) = postProject") slnfile:print("{%s} = {%s}", hash.uuid4(dep), hash.uuid4(dep)) diff --git a/xmake/plugins/project/vstudio/impl/vs_csproj.lua b/xmake/plugins/project/vstudio/impl/vs_csproj.lua new file mode 100644 index 00000000000..cff20ca687d --- /dev/null +++ b/xmake/plugins/project/vstudio/impl/vs_csproj.lua @@ -0,0 +1,214 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author Kethers +-- @file vs_csproj.lua +-- + +-- imports +import("core.base.option") +import("core.base.hashset") +import("core.project.rule") +import("core.project.config") +import("core.project.project") +import("core.language.language") +import("core.tool.toolchain") +import("private.utils.batchcmds") +import("vsfile") +import("vsutils") +import("plugins.project.vsxmake.getinfo", {rootdir = os.programdir()}) + + +function _make_dirs(dir, csprojdir) + dir = dir:trim() + if #dir == 0 then + return "" + end + dir = path.translate(dir) + if not path.is_absolute(dir) then + dir = path.relative(path.absolute(dir), csprojdir) + end + return dir +end + +-- make header +function _make_header(csprojfile, vsinfo) + csprojfile:print("") + csprojfile:enter("", assert(vsinfo.project_version)) +end + +function _make_configurations(csprojfile, vsinfo, target) + -- the target name + local targetname = target.name + + -- init configuration type + local output_types = + { + binary = "Exe" + -- , winexe = "WinExe" TODO: this kind doesn't exist yet + , shared = "Library" + } + + -- import Microsoft.Common.props + csprojfile:print("") + + -- make Globals + csprojfile:enter("") + csprojfile:print("debug") + csprojfile:print("x64") + csprojfile:print("{%s}", hash.uuid4(targetname)) + csprojfile:print("%s", output_types[target.kind] or "Unknown") + csprojfile:print("Properties") + csprojfile:print("%s", targetname) + csprojfile:print("%s", targetname) + csprojfile:print("v%s", vsinfo.dotnetframework_version) + csprojfile:print("512") + csprojfile:print("true") + csprojfile:leave("") + + -- make Configuration + for _, targetinfo in ipairs(target.info) do + local mode = targetinfo.mode + local arch = targetinfo.arch + + symbols = vsinfo._targets[targetname]._targets[mode][arch].symbols or "" + optimize = vsinfo._targets[targetname]._targets[mode][arch].optimize or "" + + debugtype = "portable" + debugsymbols = "true" + if (symbols == "debug") then + debugtype = "full" + debugsymbols = "true" + elseif (symbols == "hidden") then + debugtype = "none" + debugsymbols = "false" + elseif (string.find(symbols, "debug") and string.find(symbols, "embed")) then + debugtype = "embedded" + debugsymbols = "true" + end + + if optimize == "" or optimize == "none" then + optimize = "false" + else + optimize = "true" + end + + csprojfile:enter("", mode, arch) + csprojfile:print("%s", debugtype) + csprojfile:print("%s", debugsymbols) + csprojfile:print("%s", optimize) + csprojfile:print("%s", _make_dirs(targetinfo.targetdir, target.project_dir)) + csprojfile:print("%s", _make_dirs(targetinfo.objectdir, target.project_dir)) + csprojfile:print("%$(BaseIntermediateOutputPath)") + csprojfile:print("%s", vsinfo._targets[targetname]._targets[mode][arch].defines) + csprojfile:print("prompt") + csprojfile:print("4") + csprojfile:leave("") + end +end + +-- make source files +function _make_source_files(csprojfile, vsinfo, target) + -- make source file infos + local sourceinfos = {} + for _, targetinfo in ipairs(target.info) do + for _, sourcebatch in pairs(targetinfo.sourcebatches) do + local sourcekind = sourcebatch.sourcekind + local rulename = sourcebatch.rulename + if (sourcekind == "cs") then + local objectfiles = sourcebatch.objectfiles + for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = objectfiles[idx] + -- local flags = targetinfo.sourceflags[sourcefile] -- TODO: cs flags doesn't exist yet + sourceinfos[sourcefile] = sourceinfos[sourcefile] or {} + table.insert(sourceinfos[sourcefile], {targetinfo = targetinfo, mode = targetinfo.mode, arch = targetinfo.arch, sourcekind = sourcekind, objectfile = objectfile, flags = flags, compargv = targetinfo.compargvs[sourcefile]}) + end + end + end + end + + -- make source files + csprojfile:enter("") + for sourcefile, sourceinfo in table.orderpairs(sourceinfos) do + if #sourceinfo == #target.info then + csprojfile:print("", path.relative(path.absolute(sourcefile), target.project_dir)) + end + end + csprojfile:leave("") +end + +-- make project references +function _make_project_references(csprojfile, vsinfo, target) + local deps = vsinfo._targets[target.name]._deps + + csprojfile:enter("") + + for depname, dep in table.orderpairs(deps) do + proj_extension = dep.proj_extension + csprojfile:enter(" ", depname, depname, proj_extension) + csprojfile:print("{%s}", dep.target_id) + csprojfile:print("%s", depname) + csprojfile:leave("") + end + + csprojfile:leave("") +end + +-- make tailer +function _make_tailer(csprojfile, vsinfo, target) + -- import Microsoft.CSharp.targets + csprojfile:print("") + + csprojfile:leave("") +end + +-- make csproj +function make(vsinfo, target) + + -- TODO: getinfo will leads to repeat MSVC checking output, try not to use it + local info = getinfo(option.get("outputdir"), vsinfo) + + -- the target name + local targetname = target.name + + -- the csproj directory + local csprojdir = target.project_dir + + -- open csproj file + local csprojpath = path.join(csprojdir, targetname .. ".csproj") + local csprojfile = vsfile.open(csprojpath, "w") + + -- init indent character + vsfile.indentchar(' ') + + -- make headers + _make_header(csprojfile, info) + + -- make Configurations + _make_configurations(csprojfile, info, target) + + -- make source files + _make_source_files(csprojfile, info, target) + + -- make project references + _make_project_references(csprojfile, info, target) + + -- make tailer + _make_tailer(csprojfile, info, target) + + -- exit solution file + csprojfile:close() +end \ No newline at end of file diff --git a/xmake/scripts/vsxmake/vsproj/templates/csproj/#target#.csproj b/xmake/scripts/vsxmake/vsproj/templates/csproj/#target#.csproj index 6c85432b633..cf4a87b85c0 100644 --- a/xmake/scripts/vsxmake/vsproj/templates/csproj/#target#.csproj +++ b/xmake/scripts/vsxmake/vsproj/templates/csproj/#target#.csproj @@ -10,7 +10,7 @@ See https://github.com/xmake-io/xmake/pull/472 for more infomation. --> - + $(XMAKE_PROGRAM_DIR) #programdir# diff --git a/xmake/scripts/vsxmake/vsproj/templates/csproj/ProjectRef(dep) b/xmake/scripts/vsxmake/vsproj/templates/csproj/ProjectRef(dep) index dfccc2095bd..52deb3110b7 100644 --- a/xmake/scripts/vsxmake/vsproj/templates/csproj/ProjectRef(dep) +++ b/xmake/scripts/vsxmake/vsproj/templates/csproj/ProjectRef(dep) @@ -1,4 +1,4 @@ {#target_id#} - {#target#} + #target# diff --git a/xmake/scripts/vsxmake/vsproj/templates/vcxproj/ProjectRef(dep) b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/ProjectRef(dep) index dfccc2095bd..52deb3110b7 100644 --- a/xmake/scripts/vsxmake/vsproj/templates/vcxproj/ProjectRef(dep) +++ b/xmake/scripts/vsxmake/vsproj/templates/vcxproj/ProjectRef(dep) @@ -1,4 +1,4 @@ {#target_id#} - {#target#} + #target#