--!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, Xmake Open Source Community.
--
-- @author ruki
-- @file vs200x_vcproj.lua
--
-- imports
import("core.tool.linker")
import("core.tool.compiler")
import("core.project.config")
import("vsfile")
-- make compiling flags
function _make_compflags(sourcefile, target, vcprojdir)
-- make the compiling flags
local compflags = compiler.compflags(sourcefile, {target = target})
-- replace -Idir or /Idir, -Fdsymbol.pdb or /Fdsymbol.pdb
local flags = {}
for _, flag in ipairs(compflags) do
local flag = flag
-- replace -Idir or /Idir
flag = flag:gsub("[%-|/]I(.*)", function (dir)
dir = path.translate(dir:trim())
if not path.is_absolute(dir) then
dir = path.relative(path.absolute(dir), vcprojdir)
end
return "/I" .. dir
end)
-- replace -Fdsymbol.pdb or /Fdsymbol.pdb
flag = flag:gsub("[%-|/]Fd(.*)", function (dir)
dir = path.translate(dir:trim())
if not path.is_absolute(dir) then
dir = path.relative(path.absolute(dir), vcprojdir)
end
return "/Fd" .. dir
end)
-- save flag
table.insert(flags, flag)
end
-- make flags string
flags = os.args(flags)
-- replace " => "
flags = flags:gsub("\"", """)
-- ok?
return flags
end
-- make linking flags
function _make_linkflags(target, vcprojdir)
-- make the linking flags
local linkflags = linker.linkflags(target:kind(), target:sourcekinds(), {target = target})
-- replace -libpath:dir or /libpath:dir, -pdb:symbol.pdb or /pdb:symbol.pdb
local flags = {}
for _, flag in ipairs(linkflags) do
local flag = flag
-- replace -libpath:dir or /libpath:dir
flag = flag:gsub("[%-|/]libpath:(.*)", function (dir)
dir = path.translate(dir:trim())
if not path.is_absolute(dir) then
dir = path.relative(path.absolute(dir), vcprojdir)
end
return "/libpath:" .. dir
end)
-- replace -pdb:symbol.pdb or /pdb:symbol.pdb
flag = flag:gsub("[%-|/]pdb:(.*)", function (dir)
dir = path.translate(dir:trim())
if not path.is_absolute(dir) then
dir = path.relative(path.absolute(dir), vcprojdir)
end
return "/pdb:" .. dir
end)
-- save flag
table.insert(flags, flag)
end
-- make flags string
flags = os.args(flags)
-- replace " => "
flags = flags:gsub("\"", """)
-- ok?
return flags
end
-- make header
function _make_header(vcprojfile, vsinfo, target)
-- the target name
local targetname = target:name()
-- make header
vcprojfile:print("")
vcprojfile:enter("")
end
-- make tailer
function _make_tailer(vcprojfile, vsinfo, target)
vcprojfile:leave("")
end
-- make platforms
function _make_platforms(vcprojfile, vsinfo, target)
-- add Win32 platform
vcprojfile:enter("")
vcprojfile:enter("")
vcprojfile:leave("")
end
-- make toolfiles
function _make_toolfiles(vcprojfile, vsinfo, target)
-- empty toolfiles
vcprojfile:enter("")
vcprojfile:leave("")
end
-- make VCCLCompilerTool
--
-- e.g.
--
--
function _make_VCCLCompilerTool(vcprojfile, vsinfo, target, compflags)
vcprojfile:enter("")
end
-- make VCLinkerTool
--
-- e.g.
--
function _make_VCLinkerTool(vcprojfile, vsinfo, target, vcprojdir)
-- need not linker?
local kind = target:kind()
if kind ~= "binary" and kind ~= "shared" then
vcprojfile:enter("")
return
end
-- generate debug infomation?
local debug = false
for _, symbol in ipairs(target:get("symbols")) do
if symbol == "debug" then
debug = true
break
end
end
-- subsystem, console: 1, windows: 2
local subsystem = 1
local flags = _make_linkflags(target, vcprojdir)
if flags:lower():find("[%-/]subsystem:windows") then
subsystem = 2
end
-- make it
vcprojfile:enter("")
end
-- make configurations
function _make_configurations(vcprojfile, vsinfo, target, vcprojdir)
-- init configuration type
local configuration_types =
{
binary = 1
, shared = 2
, static = 4
}
-- save compiler flags
local compflags=nil
for _, sourcebatch in pairs(target:sourcebatches()) do
local sourcekind = sourcebatch.sourcekind
if sourcekind then
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
local flags = compiler.compflags(sourcefile, {target = target})
if sourcekind == "cc" or sourcekind == "cxx" then
compflags = flags
break
end
end
end
if compflags then
break
end
end
-- use mfc? not used: 0, static: 1, shared: 2
local usemfc = 0
if target:rule("win.sdk.mfc.shared_app") or target:rule("win.sdk.mfc.shared") then
usemfc = 2
elseif target:rule("win.sdk.mfc.static_app") or target:rule("win.sdk.mfc.static") then
usemfc = 1
end
-- set unicode
local unicode = false
for _, flag in ipairs(compflags) do
if flag:find("[%-|/]DUNICODE") then
unicode = true
break
end
end
-- enter configurations
vcprojfile:enter("")
-- make configuration for the current mode
vcprojfile:enter("")
-- make VCPreBuildEventTool
vcprojfile:enter("")
-- make VCCustomBuildTool
vcprojfile:enter("")
-- make VCXMLDataGeneratorTool
vcprojfile:enter("")
-- make VCWebServiceProxyGeneratorTool
vcprojfile:enter("")
-- make VCMIDLTool
vcprojfile:enter("")
-- make VCCLCompilerTool
_make_VCCLCompilerTool(vcprojfile, vsinfo, target, compflags)
-- make VCManagedResourceCompilerTool
vcprojfile:enter("")
-- make VCResourceCompilerTool
vcprojfile:enter("")
-- make VCPreLinkEventTool
vcprojfile:enter("")
-- make VCLinkerTool
_make_VCLinkerTool(vcprojfile, vsinfo, target, vcprojdir)
-- make VCALinkTool
vcprojfile:enter("")
-- make VCManifestTool
vcprojfile:enter("")
-- make VCXDCMakeTool
vcprojfile:enter("")
-- make VCBscMakeTool
vcprojfile:enter("")
-- make VCFxCopTool
vcprojfile:enter("")
-- make VCAppVerifierTool
vcprojfile:enter("")
-- make VCPostBuildEventTool
vcprojfile:enter("")
-- leave configuration
vcprojfile:leave("")
-- leave configurations
vcprojfile:leave("")
end
-- make references
function _make_references(vcprojfile, vsinfo, target)
vcprojfile:enter("")
vcprojfile:leave("")
end
-- make cxfile
--
-- e.g.
--
--
--
--
--
function _make_cxfile(vcprojfile, vsinfo, target, sourcefile, objectfile, vcprojdir)
-- get the target key
local key = target:cachekey()
-- make flags cache
_g.flags = _g.flags or {}
-- make flags
local flags = _g.flags[key] or _make_compflags(sourcefile, target, vcprojdir)
_g.flags[key] = flags
-- enter file
vcprojfile:enter("")
-- add file configuration
vcprojfile:enter("")
-- add compiling options
vcprojfile:enter("")
vcprojfile:leave("")
-- leave file
vcprojfile:leave("")
end
-- make rcfile
--
-- e.g.
--
--
--
--
--
function _make_rcfile(vcprojfile, vsinfo, target, sourcefile, objectfile, vcprojdir)
-- enter file
vcprojfile:enter("")
-- add file configuration
vcprojfile:enter("")
-- add compiling options
vcprojfile:enter("")
vcprojfile:leave("")
-- leave file
vcprojfile:leave("")
end
-- make files
--
-- e.g.
--
--
--
--
--
--
--
--
--
--
--
--
--
function _make_files(vcprojfile, vsinfo, target, vcprojdir)
-- enter files
vcprojfile:enter("")
local sourcebatches = target:sourcebatches()
-- c/cxx files
vcprojfile:enter("")
for _, sourcebatch in pairs(sourcebatches) do
local sourcekind = sourcebatch.sourcekind
if sourcekind ~= "mrc" then
local objectfiles = sourcebatch.objectfiles
for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
_make_cxfile(vcprojfile, vsinfo, target, sourcefile, objectfiles[idx], vcprojdir)
end
end
end
-- leave c/cxx files
vcprojfile:leave("")
-- *.rc files
vcprojfile:enter("")
for _, sourcebatch in pairs(sourcebatches) do
local sourcekind = sourcebatch.sourcekind
if sourcekind == "mrc" then
local objectfiles = sourcebatch.objectfiles
for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
_make_rcfile(vcprojfile, vsinfo, target, sourcefile, objectfiles[idx], vcprojdir)
end
end
end
-- leave *.rc files
vcprojfile:leave("")
vcprojfile:leave("")
end
-- make globals
function _make_globals(vcprojfile, vsinfo, target)
vcprojfile:enter("")
vcprojfile:leave("")
end
-- make vcproj
function make(vsinfo, target)
-- the target name
local targetname = target:name()
-- the vcproj directory
local vcprojdir = path.join(vsinfo.solution_dir, targetname)
-- open vcproj file
local vcprojfile = vsfile.open(path.join(vcprojdir, targetname .. ".vcproj"), "w")
-- init indent character
vsfile.indentchar('\t')
-- make header
_make_header(vcprojfile, vsinfo, target)
-- make platforms
_make_platforms(vcprojfile, vsinfo, target)
-- make toolfiles
_make_toolfiles(vcprojfile, vsinfo, target)
-- make configurations
_make_configurations(vcprojfile, vsinfo, target, vcprojdir)
-- make references
_make_references(vcprojfile, vsinfo, target)
-- make files
_make_files(vcprojfile, vsinfo, target, vcprojdir)
-- make globals
_make_globals(vcprojfile, vsinfo, target)
-- make tailer
_make_tailer(vcprojfile, vsinfo, target)
-- exit solution file
vcprojfile:close()
end