268 lines
7.2 KiB
Lua
268 lines
7.2 KiB
Lua
-- msvc-vscommon.lua - utility code for all versions of Visual Studio
|
|
|
|
module(..., package.seeall)
|
|
|
|
local native = require "tundra.native"
|
|
local os = require "os"
|
|
|
|
-- Visual Studio tooling layout
|
|
|
|
local vc_bin_map = {
|
|
["x86"] = {
|
|
["x86"] = "",
|
|
["x64"] = "x86_amd64",
|
|
["arm"] = "x86_arm",
|
|
},
|
|
["x64"] = {
|
|
["x86"] = "",
|
|
["x64"] = "amd64",
|
|
["arm"] = "x86_arm", -- is this really legal?
|
|
},
|
|
}
|
|
|
|
local vc_lib_map = {
|
|
["x86"] = {
|
|
["x86"] = "",
|
|
["x64"] = "amd64",
|
|
["arm"] = "arm",
|
|
},
|
|
["x64"] = {
|
|
["x86"] = "",
|
|
["x64"] = "amd64",
|
|
["arm"] = "arm",
|
|
},
|
|
}
|
|
|
|
-- Windows SDK layout
|
|
|
|
local pre_win8_sdk_dir = {
|
|
["bin"] = "bin",
|
|
["include"] = "include",
|
|
["lib"] = "lib",
|
|
}
|
|
|
|
local win8_sdk_dir = {
|
|
["bin"] = "bin",
|
|
["include"] = "include",
|
|
["lib"] = "lib\\win8\\um",
|
|
}
|
|
|
|
local win81_sdk_dir = {
|
|
["bin"] = "bin",
|
|
["include"] = "include",
|
|
["lib"] = "lib\\winv6.3\\um",
|
|
}
|
|
|
|
local pre_win8_sdk = {
|
|
["x86"] = {
|
|
["bin"] = "",
|
|
["include"] = "",
|
|
["lib"] = "",
|
|
},
|
|
["x64"] = {
|
|
["bin"] = "x64",
|
|
["include"] = "",
|
|
["lib"] = "x64",
|
|
},
|
|
}
|
|
|
|
local post_win8_sdk = {
|
|
["x86"] = {
|
|
["bin"] = "x86",
|
|
["include"] = { "shared", "um" },
|
|
["lib"] = "x86",
|
|
},
|
|
["x64"] = {
|
|
["bin"] = "x64",
|
|
["include"] = { "shared", "um" },
|
|
["lib"] = "x64",
|
|
},
|
|
["arm"] = {
|
|
["bin"] = "arm",
|
|
["include"] = { "shared", "um" },
|
|
["lib"] = "arm",
|
|
},
|
|
}
|
|
|
|
-- Each quadruplet specifies a registry key value that gets us the SDK location,
|
|
-- followed by a folder structure (for each supported target architecture)
|
|
-- and finally the corresponding bin, include and lib folder's relative location
|
|
|
|
local sdk_map = {
|
|
["9.0"] = { "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v6.0A", "InstallationFolder", pre_win8_sdk_dir, pre_win8_sdk },
|
|
["10.0"] = { "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.0A", "InstallationFolder", pre_win8_sdk_dir, pre_win8_sdk },
|
|
["11.0"] = { "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot", win8_sdk_dir, post_win8_sdk },
|
|
["12.0"] = { "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot81", win81_sdk_dir, post_win8_sdk },
|
|
}
|
|
|
|
local function get_host_arch()
|
|
local snative = native.getenv("PROCESSOR_ARCHITECTURE")
|
|
local swow = native.getenv("PROCESSOR_ARCHITEW6432", "")
|
|
if snative == "AMD64" or swow == "AMD64" then
|
|
return "x64"
|
|
elseif snative == "IA64" or swow == "IA64" then
|
|
return "itanium";
|
|
else
|
|
return "x86"
|
|
end
|
|
end
|
|
|
|
function path_combine(path, path_to_append)
|
|
if path == nil then
|
|
return path_to_append
|
|
end
|
|
if path:find("\\$") then
|
|
return path .. path_to_append
|
|
end
|
|
return path .. "\\" .. path_to_append
|
|
end
|
|
|
|
function path_it(maybe_list)
|
|
if type(maybe_list) == "table" then
|
|
return ipairs(maybe_list)
|
|
end
|
|
return ipairs({maybe_list})
|
|
end
|
|
|
|
function apply_msvc_visual_studio(version, env, options)
|
|
|
|
-- NOTE: don't make changes to `env` until you've asserted
|
|
-- that the requested version is in fact installed,
|
|
-- the `vs-wild` toolset will call this function
|
|
-- repeatedly with a the next version but the same `env`,
|
|
-- if a version fails (assert/error)
|
|
|
|
if native.host_platform ~= "windows" then
|
|
error("the msvc toolset only works on windows hosts")
|
|
end
|
|
|
|
-- Load basic MSVC environment setup first.
|
|
-- We're going to replace the paths to some tools.
|
|
tundra.unitgen.load_toolset('msvc', env)
|
|
|
|
options = options or {}
|
|
|
|
local target_arch = options.TargetArch or "x86"
|
|
local host_arch = options.HostArch or get_host_arch()
|
|
local sdk_version = options.SdkVersion or version -- we identify SDKs by VS version and fallback to current version
|
|
|
|
-- We'll find any edition of VS (including Express) here
|
|
local vs_root = native.reg_query("HKLM", "SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", version)
|
|
assert(vs_root, "The requested version of Visual Studio isn't installed")
|
|
vs_root = string.gsub(vs_root, "\\+$", "\\")
|
|
|
|
local vc_lib
|
|
local vc_bin
|
|
|
|
vc_bin = vc_bin_map[host_arch][target_arch]
|
|
if not vc_bin then
|
|
errorf("can't build target arch %s on host arch %s", target_arch, host_arch)
|
|
end
|
|
vc_bin = vs_root .. "vc\\bin\\" .. vc_bin
|
|
|
|
vc_lib = vs_root .. "vc\\lib\\" .. vc_lib_map[host_arch][target_arch]
|
|
|
|
--
|
|
-- Now fix up the SDK
|
|
--
|
|
|
|
local sdk_root
|
|
local sdk_bin
|
|
local sdk_include = {}
|
|
local sdk_lib
|
|
|
|
local sdk = sdk_map[sdk_version]
|
|
assert(sdk, "The requested version of Visual Studio isn't supported")
|
|
|
|
sdk_root = native.reg_query("HKLM", sdk[1], sdk[2])
|
|
assert(sdk_root, "The requested version of the SDK isn't installed")
|
|
sdk_root = string.gsub(sdk_root, "\\+$", "\\")
|
|
|
|
local sdk_dir_base = sdk[3]
|
|
|
|
local sdk_dir = sdk[4][target_arch]
|
|
assert(sdk_dir, "The target platform architecture isn't supported by the SDK")
|
|
|
|
sdk_bin = sdk_root .. sdk_dir_base["bin"] .. "\\" .. sdk_dir["bin"]
|
|
|
|
local sdk_dir_base_include = sdk_dir_base["include"]
|
|
for _, v in path_it(sdk_dir["include"]) do
|
|
sdk_include[#sdk_include + 1] = sdk_root .. sdk_dir_base_include .. "\\" .. v
|
|
end
|
|
|
|
sdk_lib = sdk_root .. sdk_dir_base["lib"] .. "\\" .. sdk_dir["lib"]
|
|
|
|
--
|
|
-- Tools
|
|
--
|
|
|
|
local cl_exe = '"' .. path_combine(vc_bin, "cl.exe") .. '"'
|
|
local lib_exe = '"' .. path_combine(vc_bin, "lib.exe") .. '"'
|
|
local link_exe = '"' .. path_combine(vc_bin, "link.exe") .. '"'
|
|
local rc_exe = '"' .. path_combine(sdk_bin, "rc.exe") .. '"' -- pickup the Resource Compiler from the SDK
|
|
|
|
env:set('CC', cl_exe)
|
|
env:set('CXX', cl_exe)
|
|
env:set('LIB', lib_exe)
|
|
env:set('LD', link_exe)
|
|
env:set('RC', rc_exe)
|
|
|
|
if sdk_version == "9.0" then
|
|
env:set("RCOPTS", "") -- clear the "/nologo" option (it was first added in VS2010)
|
|
end
|
|
|
|
if version == "12.0" then
|
|
-- Force MSPDBSRV.EXE
|
|
env:set("CCOPTS", "/FS")
|
|
env:set("CXXOPTS", "/FS")
|
|
end
|
|
|
|
-- Wire-up the external environment
|
|
|
|
env:set_external_env_var('VSINSTALLDIR', vs_root)
|
|
env:set_external_env_var('VCINSTALLDIR', vs_root .. "\\vc")
|
|
env:set_external_env_var('DevEnvDir', vs_root .. "Common7\\IDE")
|
|
|
|
local include = {}
|
|
|
|
for _, v in ipairs(sdk_include) do
|
|
include[#include + 1] = v
|
|
end
|
|
|
|
include[#include + 1] = vs_root .. "VC\\ATLMFC\\INCLUDE"
|
|
include[#include + 1] = vs_root .. "VC\\INCLUDE"
|
|
|
|
env:set_external_env_var("WindowsSdkDir", sdk_root)
|
|
env:set_external_env_var("INCLUDE", table.concat(include, ';'))
|
|
|
|
-- if MFC isn't installed with VS
|
|
-- the linker will throw an error when looking for libs
|
|
-- Lua does not have a "does directory exist function"
|
|
-- we could use one here
|
|
local lib_str = sdk_lib .. ";" .. vs_root .. "\\VC\\ATLMFC\\lib\\" .. vc_lib_map[host_arch][target_arch] .. ";" .. vc_lib
|
|
env:set_external_env_var("LIB", lib_str)
|
|
env:set_external_env_var("LIBPATH", lib_str)
|
|
|
|
-- Modify %PATH%
|
|
|
|
local path = {}
|
|
|
|
path[#path + 1] = sdk_root
|
|
path[#path + 1] = vs_root .. "Common7\\IDE"
|
|
|
|
if "x86" == host_arch then
|
|
path[#path + 1] = vs_root .. "\\VC\\Bin"
|
|
elseif "x64" == host_arch then
|
|
path[#path + 1] = vs_root .. "\\VC\\Bin\\amd64"
|
|
elseif "arm" == host_arch then
|
|
path[#path + 1] = vs_root .. "\\VC\\Bin\\arm"
|
|
end
|
|
|
|
path[#path + 1] = vs_root .. "\\Common7\\IDE"
|
|
|
|
path[#path + 1] = env:get_external_env_var('PATH')
|
|
|
|
env:set_external_env_var("PATH", table.concat(path, ';'))
|
|
|
|
end
|