From 8ac69277488bb8ba906b59e2797997190b2e0ca2 Mon Sep 17 00:00:00 2001 From: John Leidegren Date: Wed, 15 Nov 2023 18:53:18 +0100 Subject: [PATCH] Rework of MSVC tools (#341) --- doc/manual.asciidoc | 83 +++++ scripts/tundra/tools/msvc-latest.lua | 349 ++++++++++++++++++++ scripts/tundra/tools/msvc-vs2017.lua | 8 +- scripts/tundra/tools/msvc-vs2019.lua | 8 +- scripts/tundra/tools/msvc-vs2022.lua | 8 +- scripts/tundra/tools/msvc-vscommon-next.lua | 220 ------------ scripts/tundra/tools/msvc-vswild.lua | 23 -- 7 files changed, 447 insertions(+), 252 deletions(-) create mode 100644 scripts/tundra/tools/msvc-latest.lua delete mode 100644 scripts/tundra/tools/msvc-vscommon-next.lua delete mode 100644 scripts/tundra/tools/msvc-vswild.lua diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index f7309a97..c9ebbdc1 100755 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -1262,6 +1262,89 @@ architecture: } ------------------------------------------------------------------------------- +=== msvc-latest + +This toolset is for use with the more recent versions of Visual Studio starting +with Visual Studio 2017. It is similar to the existing `msvc` toolsets but +because of how these new versions are installed this toolset can be customized +to select a particular version and product to use. You don't have to specify +anything but you have control over it. + +The behaviour outlined here should be very similar to the Developer Command +Prompt for VS (`VsDevCmd.bat`): + +- Starting with Visual Studio 2017 `msvc-vs20xx` is just an alias for +`{"msvc-latest", Version = "20xx" }`. If you use `msvc-latest` directly without +specifying a version it will fallback to the most recently tested version of +Visual Studio which is (as of writing) 2022. + +- If you don't specify product it will try all of them, in this order: +`BuildTools`, `Community`, `Professional`, `Enterprise` and use the first one +which has the *Desktop development with C++* workload installed. + +- If you don't specify Windows SDK version you will get the one installed with +the highest version number. + +- If you don't specify MSVC tools version you will get the default (as given by +`\\` followed by +`VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt`). + +- Path is just for completness and will default to either `C:\Program Files (x86)` or + `C:\Program Files` depending on `Version`. + +Here's a complete example of how this toolset can be configured: + +[source,lua] +------------------------------------------------------------------------------- + Tools = { + { + "msvc-latest", + Path = "C:\\Program Files (x86)\\Microsoft Visual Studio", + Version = "2019", + Product = "BuildTools", + HostArch = "x64", -- "x64" (default), "x86", "arm" or "arm64" + TargetArch = "x64", -- "x64" (default), "x86", "arm" or "arm64" + WindowsSdkVersion = "10.0.22621.0", + VcToolsVersion = "14.29.30133", + AppPlatform = "Desktop", -- "Desktop" (default), "UWP" or "OneCore" + AtlMfc = false + } + } +------------------------------------------------------------------------------- + +When you are not being explicit about the Windows SDK version or MSVC tools +version it will tell you what it ended up chosing during DAG generation. This is +done so that you can more easily lock your configuration to a specific version, +if you want to. + +[source,lua] +------------------------------------------------------------------------------- + > tundra2 -f -G + 3 valid build tuples + Generating DAG for win64-msvc-release-default + WindowsSdkVersion : 10.0.22621.0 + VcToolsVersion : 14.29.30133 + Generating DAG for win64-msvc-debug-default + WindowsSdkVersion : 10.0.22621.0 + VcToolsVersion : 14.29.30133 + Generating DAG for win64-msvc-production-default + WindowsSdkVersion : 10.0.22621.0 + VcToolsVersion : 14.29.30133 + save_dag_data: 3 bindings, 29 accessed files + compiling mmapable DAG data.. + *** Build success (0.05 seconds) +------------------------------------------------------------------------------- + +In Visual Studio 2017 and later, MFC and ATL are optional sub-components under +the Desktop development with C++ workload in the Visual Studio Installer +program. If you want to use MFC and ATL you have to install them and opt-in via +`AtlMfc = true`. + +The idea behind this toolset is that it will be compatible with future Visual +Studio releases and in the rare case that it isn't, it can be made to work by +simply changing the `Path`, `Version` and `Product` options to whatever you +need. + == Extending Tundra Tundra can be extended in three ways: diff --git a/scripts/tundra/tools/msvc-latest.lua b/scripts/tundra/tools/msvc-latest.lua new file mode 100644 index 00000000..e8e6612d --- /dev/null +++ b/scripts/tundra/tools/msvc-latest.lua @@ -0,0 +1,349 @@ +module(..., package.seeall) + +-- How does this work? +-- +-- Visual Studio is installed in one of two locations depending on version and product +-- 2017-2019 : C:\Program Files (x86)\Microsoft Visual Studio\\ +-- 2022- : C:\Program Files\Microsoft Visual Studio\\ +-- +-- This will be the value for the VSINSTALLDIR environment variable. +-- +-- Since it is possible to install any combination of Visual Studio products +-- we have to check all of them. The first product with a VC tools version +-- will be used unless you ask for a specific product and/or VC tools version. +-- +-- The VsDevCmd.bat script is used to initialize the Developer Command Prompt for VS. +-- It will unconditionally call the bat files inside "%VSINSTALLDIR%\Common7\Tools\vsdevcmd\core" +-- followed by "%VSINSTALLDIR%\Common7\Tools\vsdevcmd\ext" unless run with -no_ext. +-- +-- The only two bat files that we care about are: +-- "%VSINSTALLDIR%\Common7\Tools\vsdevcmd\core\winsdk.bat" +-- "%VSINSTALLDIR%\Common7\Tools\vsdevcmd\ext\vcvars.bat" +-- +-- And the rest of this is just reverse engineered from these bat scripts. + +local native = require "tundra.native" +local native_path = require "tundra.native.path" + +-- Note that while Community, Professional and Enterprise products are installed +-- in C:\Program Files while BuildTools are always installed in C:\Program Files (x86) +local vs_default_path = "C:\\Program Files (x86)\\Microsoft Visual Studio" + +-- Add new Visual Studio versions here and update vs_default_version +local vs_default_paths = { + ["2017"] = vs_default_path, + ["2019"] = vs_default_path, + ["2022"] = "C:\\Program Files\\Microsoft Visual Studio" +} + +local vs_default_version = "2022" + +local vs_products = { + "BuildTools", -- default + "Community", + "Professional", + "Enterprise" +} + +-- dump keys of table into sorted array +local function keys(tbl) + local ks, i = {}, 1 + for k, _ in pairs(tbl) do + ks[i] = k + i = i + 1 + end + table.sort(ks) + return ks +end + +local supported_arch_mappings = { + ["x86"] = "x86", + ["x64"] = "x64", + ["arm"] = "arm", + ["arm64"] = "arm64", + + -- alias + ["amd64"] = "x64" +} + +local function get_arch(arch) + local arch2 = supported_arch_mappings[arch:lower()] + return arch2 +end + +local function get_arch_tuple(host_arch, target_arch) + local host_arch2 = get_arch(host_arch) + local target_arch2 = get_arch(target_arch) + + if host_arch2 == nil then + error("unknown host architecture '" .. host_arch .. "' expected one of " .. + table.concat(keys(supported_arch_mappings), ", ")) + end + if target_arch2 == nil then + error("unknown target architecture '" .. target_arch .. "' expected one of " .. + table.concat(keys(supported_arch_mappings), ", ")) + end + + return host_arch2, target_arch2 +end + +local supported_app_platforms = { + ["desktop"] = "Desktop", -- default + ["uwp"] = "UWP", + ["onecore"] = "OneCore" +} + +local function get_app_platform(app_platform) + local app_platform2 = supported_app_platforms[app_platform:lower()] + if app_platform2 == nil then + error("unknown target architecture '" .. app_platform .. "' expected one of " .. + table.concat(keys(supported_app_platforms), ", ")) + end + return app_platform2 +end + +local function find_winsdk(target_winsdk_version, app_platform) + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/core/winsdk.bat#L63 + -- HKLM\SOFTWARE\Wow6432Node + -- HKCU\SOFTWARE\Wow6432Node (ignored) + -- HKLM\SOFTWARE (ignored) + -- HKCU\SOFTWARE (ignored) + local winsdk_key = "SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0" + local winsdk_dir = native.reg_query("HKLM", winsdk_key, "InstallationFolder") + local winsdk_versions = {} + + -- Due to the SDK installer changes beginning with the 10.0.15063.0 + local check_file = "winsdkver.h" + if app_platform == "UWP" then + check_file = "Windows.h" + end + + local dirs, _, _ = native.list_directory(native_path.join(winsdk_dir, "Include")) + for _, winsdk_version in ipairs(dirs) do + if winsdk_version:find("^10.") then + local testpath = native_path.join(winsdk_dir, "Include\\" .. winsdk_version .. "\\um\\" .. check_file) + local test = native.stat_file(testpath) + if not test.isdirectory and test.exists then + winsdk_versions[#winsdk_versions + 1] = winsdk_version + end + end + end + + if target_winsdk_version ~= nil then + for _, winsdk_version in ipairs(winsdk_versions) do + if winsdk_version == target_winsdk_version then + return winsdk_dir, target_winsdk_version + end + end + error("Windows SDK version '" .. target_winsdk_version .. "' not found.\n" .. + "You can try one of these Windows SDK versions " .. table.concat(winsdk_versions, ", ") .. + " or change the app platform to UWP") + end + + return winsdk_dir, winsdk_versions[#winsdk_versions] -- latest +end + +local function find_vc_tools(vs_path, vs_version, vs_product, target_vc_tools_version, search_set) + if vs_path == nil then + if vs_product == "BuildTools" then + vs_path = vs_default_path + else + vs_path = vs_default_paths[vs_version] or vs_default_paths[vs_default_version] + end + end + + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/ext/vcvars.bat#L729 + + -- we ignore Microsoft.VCToolsVersion.v143.default.txt and use Microsoft.VCToolsVersion.default.txt + -- unless a specific VC tools version was requested + + local vs_install_dir = native_path.join(vs_path, vs_version .. "\\" .. vs_product) + local vc_install_dir = native_path.join(vs_install_dir, "VC") + local vc_tools_version = nil + + if target_vc_tools_version == nil then + local f = io.open(vc_install_dir .. "\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt", "r") + if f ~= nil then + vc_tools_version = f:read("*l") + f:close() + end + else + vc_tools_version = target_vc_tools_version + end + + if vc_tools_version ~= nil then + local testpath = native_path.join(vc_install_dir, "Tools\\MSVC\\" .. vc_tools_version .. "\\include\\vcruntime.h") + local test = native.stat_file(testpath) + if not test.isdirectory and test.exists then + return vs_install_dir, vc_install_dir, vc_tools_version + end + end + + search_set[#search_set + 1] = vs_install_dir + return nil, nil, nil +end + +function apply(env, options, extra) + if native.host_platform ~= "windows" then + error("the msvc toolset only works on windows hosts") + end + + tundra.unitgen.load_toolset('msvc', env) + + options = options or {} + extra = extra or {} + + -- these control the environment + local vs_path = options.Path or options.InstallationPath + local vs_version = options.Version or extra.Version or vs_default_version + local vs_product = options.Product + local host_arch = options.HostArch or "x64" + local target_arch = options.TargetArch or "x64" + local app_platform = options.AppPlatform or options.PlatformType or "Desktop" -- Desktop, UWP or OneCore + local target_winsdk_version = options.WindowsSdkVersion or options.SdkVersion -- Windows SDK version + local target_vc_tools_version = options.VcToolsVersion -- Visual C++ tools version + local atl_mfc = options.AtlMfc or false + + if vs_default_paths[vs_version] == nil then + print("Warning: Visual Studio " .. vs_version .. " has not been tested and might not work out of the box") + end + + host_arch, target_arch = get_arch_tuple(host_arch, target_arch) + app_platform = get_app_platform(app_platform) + + local env_path = {} + local env_include = {} + local env_lib = {} + local env_lib_path = {} -- WinRT + + ----------------- + -- Windows SDK -- + ----------------- + + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/core/winsdk.bat#L513 + + local winsdk_dir, winsdk_version = find_winsdk(target_winsdk_version, app_platform) + + env_path[#env_path + 1] = native_path.join(winsdk_dir, "bin\\" .. winsdk_version .. "\\" .. host_arch) + + env_include[#env_include + 1] = native_path.join(winsdk_dir, "Include\\" .. winsdk_version .. "\\shared") + env_include[#env_include + 1] = native_path.join(winsdk_dir, "Include\\" .. winsdk_version .. "\\um") + env_include[#env_include + 1] = native_path.join(winsdk_dir, "Include\\" .. winsdk_version .. "\\winrt") -- WinRT (used by DirectX 12 headers) + -- env_include[#env_include + 1] = native_path.join(winsdk_dir, "Include\\" .. winsdk_version .. "\\cppwinrt") -- WinRT + + env_lib[#env_lib + 1] = native_path.join(winsdk_dir, "Lib\\" .. winsdk_version .. "\\um\\" .. target_arch) + + -- We assume that the Universal CRT isn't loaded from a different directory + local ucrt_sdk_dir = winsdk_dir + local ucrt_version = winsdk_version + + env_include[#env_include + 1] = native_path.join(ucrt_sdk_dir, "Include\\" .. ucrt_version .. "\\ucrt") + + env_lib[#env_lib + 1] = native_path.join(ucrt_sdk_dir, "Lib\\" .. ucrt_version .. "\\ucrt\\" .. target_arch) + + -- Skip if the Universal CRT is loaded from the same path as the Windows SDK + if ucrt_sdk_dir ~= winsdk_dir and ucrt_version ~= winsdk_version then + env_lib[#env_lib + 1] = native_path.join(ucrt_sdk_dir, "Lib\\" .. ucrt_version .. "\\um\\" .. target_arch) + end + + ---------------- + -- Visual C++ -- + ---------------- + + local search_set = {} + + local vs_install_dir = nil + local vc_install_dir = nil + local vc_tools_version = nil + + -- If product is unspecified search for a suitable product + if vs_product == nil then + for _, product in pairs(vs_products) do + vs_install_dir, vc_install_dir, vc_tools_version = find_vc_tools(vs_path, vs_version, product, + target_vc_tools_version, search_set) + if vc_tools_version ~= nil then + vs_product = product + break + end + end + else + vs_install_dir, vc_install_dir, vc_tools_version = find_vc_tools(vs_path, vs_version, vs_product, + target_vc_tools_version, search_set) + end + + if vc_tools_version == nil then + local vc_product = "Visual C++ tools" + local vc_product_version_disclaimer = "" + if target_vc_tools_version ~= nil then + vc_product = vc_product .. " [Version " .. target_vc_tools_version .. "]" + vc_product_version_disclaimer = + "Note that a specific version of the Visual C++ tools has been requested. Remove the setting VcToolsVersion if this was undesirable\n" + end + local vs_default_path = vs_default_paths[vs_default_version]:gsub("\\", "\\\\") + error(vc_product .. " not found\n\n" .. " Cannot find " .. vc_product .. + " in any of the following locations:\n " .. table.concat(search_set, "\n ") .. + "\n\n Check that 'Desktop development with C++' is installed together with the product version in Visual Studio Installer\n\n" .. + " If you want to use a specific version of Visual Studio you can try setting Path, Version and Product like this:\n\n" .. + " Tools = {\n { \"msvc-vs-latest\", Path = \"" .. vs_default_path .. "\", Version = \"" .. + vs_default_version .. "\", Product = \"" .. vs_products[1] .. "\" }\n }\n\n " .. + vc_product_version_disclaimer) + end + + -- to do: extension SDKs? + + -- VCToolsInstallDir + local vc_tools_dir = native_path.join(vc_install_dir, "Tools\\MSVC\\" .. vc_tools_version) + + -- VCToolsRedistDir + -- Ignored for now. Don't have a use case for this + + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/ext/vcvars.bat#L707 + + env_path[#env_path + 1] = native_path.join(vs_install_dir, "Common7\\IDE\\VC\\VCPackages") + + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/ext/vcvars.bat#L761 + + env_path[#env_path + 1] = native_path.join(vc_tools_dir, "bin\\Host" .. host_arch .. "\\" .. target_arch) + + -- to do: IFCPATH? C++ header/units and/or modules? + -- to do: LIBPATH? Fuse with #using C++/CLI + -- to do: https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/intro-to-using-cpp-with-winrt#sdk-support-for-cwinrt + + env_include[#env_include + 1] = native_path.join(vs_install_dir, "VC\\Auxiliary\\VS\\include") + env_include[#env_include + 1] = native_path.join(vc_tools_dir, "include") + + if app_platform == "Desktop" then + env_lib[#env_lib + 1] = native_path.join(vc_tools_dir, "lib\\" .. target_arch) + if atl_mfc then + env_include[#env_include + 1] = native_path.join(vc_tools_dir, "atlmfc\\include") + env_lib[#env_lib + 1] = native_path.join(vc_tools_dir, "atlmfc\\lib\\" .. target_arch) + end + elseif app_platform == "UWP" then + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/ext/vcvars.bat#825 + env_lib[#env_lib + 1] = native_path.join(vc_tools_dir, "store\\" .. target_arch) + elseif app_platform == "OneCore" then + -- file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio/2022/BuildTools/Common7/Tools/vsdevcmd/ext/vcvars.bat#830 + env_lib[#env_lib + 1] = native_path.join(vc_tools_dir, "lib\\onecore\\" .. target_arch) + end + + -- Force MSPDBSRV.EXE (fix for issue with cl.exe running in parallel and otherwise corrupting PDB files) + -- These options where added to Visual C++ in Visual Studio 2013. They do not exist in older versions. + env:set("CCOPTS", "/FS") + env:set("CXXOPTS", "/FS") + + env:set_external_env_var("VSINSTALLDIR", vs_install_dir) + env:set_external_env_var("VCINSTALLDIR", vc_install_dir) + env:set_external_env_var("INCLUDE", table.concat(env_include, ";")) + env:set_external_env_var("LIB", table.concat(env_lib, ";")) + env:set_external_env_var("LIBPATH", table.concat(env_lib_path, ";")) + env:set_external_env_var("PATH", table.concat(env_path, ";")) + + -- Since there's a bit of magic involved in finding these we log them once, at the end. + -- This also makes it easy to lock the SDK and C++ tools version if you want to do that. + if target_winsdk_version == nil then + print(" WindowsSdkVersion : " .. winsdk_version) -- verbose? + end + if target_vc_tools_version == nil then + print(" VcToolsVersion : " .. vc_tools_version) -- verbose? + end +end diff --git a/scripts/tundra/tools/msvc-vs2017.lua b/scripts/tundra/tools/msvc-vs2017.lua index bea11db3..6e86bbfe 100644 --- a/scripts/tundra/tools/msvc-vs2017.lua +++ b/scripts/tundra/tools/msvc-vs2017.lua @@ -1,8 +1,10 @@ - module(..., package.seeall) -local vscommon = require "tundra.tools.msvc-vscommon-next" +local vslatest = require "tundra.tools.msvc-latest" function apply(env, options) - vscommon.apply_msvc_visual_studio("2017", env, options) + local extra = { + Version = "2017" + } + vslatest.apply(env, options, extra) end diff --git a/scripts/tundra/tools/msvc-vs2019.lua b/scripts/tundra/tools/msvc-vs2019.lua index 2bb72581..a1c0dca9 100644 --- a/scripts/tundra/tools/msvc-vs2019.lua +++ b/scripts/tundra/tools/msvc-vs2019.lua @@ -1,8 +1,10 @@ - module(..., package.seeall) -local vscommon = require "tundra.tools.msvc-vscommon-next" +local vslatest = require "tundra.tools.msvc-latest" function apply(env, options) - vscommon.apply_msvc_visual_studio("2019", env, options) + local extra = { + Version = "2019" + } + vslatest.apply(env, options, extra) end diff --git a/scripts/tundra/tools/msvc-vs2022.lua b/scripts/tundra/tools/msvc-vs2022.lua index ff1a5263..0a9b029e 100644 --- a/scripts/tundra/tools/msvc-vs2022.lua +++ b/scripts/tundra/tools/msvc-vs2022.lua @@ -1,8 +1,10 @@ - module(..., package.seeall) -local vscommon = require "tundra.tools.msvc-vscommon-next" +local vslatest = require "tundra.tools.msvc-latest" function apply(env, options) - vscommon.apply_msvc_visual_studio("2022", env, options) + local extra = { + Version = "2022" + } + vslatest.apply(env, options, extra) end diff --git a/scripts/tundra/tools/msvc-vscommon-next.lua b/scripts/tundra/tools/msvc-vscommon-next.lua deleted file mode 100644 index 0d8a5ab4..00000000 --- a/scripts/tundra/tools/msvc-vscommon-next.lua +++ /dev/null @@ -1,220 +0,0 @@ --- for usage with Visual Studio 2017 and later, --- does not work with earlier versions of Visual Studio - --- see https://blogs.msdn.microsoft.com/vcblog/2016/10/07/compiler-tools-layout-in-visual-studio-15/ - -module(..., package.seeall) - -local native = require "tundra.native" -local native_path = require "tundra.native.path" - -local vs_products = { - "BuildTools", --default - "Community", - "Professional", - "Enterprise" -} - -local function find_vc_tools(installation_path, version, vs_product, search_set) - local path, stat - - path = native_path.join(installation_path, version) - path = native_path.join(path, vs_product) - path = native_path.join(path, "VC\\Auxiliary\\Build\\vcvarsall.bat") - - stat = native.stat_file(path) - if stat.exists then - return path - end - search_set[#search_set+1] = path - return nil -end - -local supported_arch_mappings = { - ["x86"] = "x86", - ["amd64"] = "amd64", - ["arm"] = "arm", - ["arm64"] = "arm64", - - --alias - ["x64"] = "amd64", -} - -local supported_arch_tuples = { - ["x86"] = true, - ["amd64"] = true, - ["x86_amd64"] = true, - ["x86_arm"] = true, - ["x86_arm64"] = true, - ["amd64_x86"] = true, - ["amd64_arm"] = true, - ["amd64_arm64"] = true, -} - -local function get_arch(arch) - local arch2 = supported_arch_mappings[arch:lower()] - return arch2 -end - --- dump keys of table into sorted array -local function keys(tbl) - local ks, i = {}, 1 - for k, _ in pairs(tbl) do - ks[i] = k - i = i + 1 - end - table.sort(ks) - return ks -end - -local function get_arch_tuple(host_arch, target_arch) - local host_arch2 = get_arch(host_arch) - local target_arch2 = get_arch(target_arch) - - if host_arch2 == nil then - error("unknown host architecture '" .. host_arch .. "' expected one of " .. table.concat(keys(supported_arch_mappings), ", ")) - end - if target_arch2 == nil then - error("unknown target architecture '" .. target_arch .. "' expected one of " .. table.concat(keys(supported_arch_mappings), ", ")) - end - - if host_arch2 == target_arch2 then - return host_arch2 - end - return host_arch2 .. "_" .. target_arch2 -end - -local vcvars_cache = {} - -function apply_msvc_visual_studio(version, env, options) - if native.host_platform ~= "windows" then - error("the msvc toolset only works on windows hosts") - end - - tundra.unitgen.load_toolset('msvc', env) - - options = options or {} - - -- these control how vcvarsall.bat is invoked - local target_arch = options.TargetArch or "x64" - local host_arch = options.HostArch or "x64" - local arch_tuple = get_arch_tuple(host_arch, target_arch) - local platform_type = options.PlatformType --default empty ({empty} | store | uwp) - local sdk_version = options.SdkVersion --default from vcvarsall.bat (otherwise request a specific version through this option) - local installation_path = options.InstallationPath or "C:\\Program Files (x86)\\Microsoft Visual Studio" - -- VS2022 is 64-bit and gets installed into Program Files. - if not options.InstallationPath and (version == "2022") then - installation_path = "C:\\Program Files\\Microsoft Visual Studio" - end - - local vs_product = options.Product - local vcvarsall_bat = options.VCVarsPath --override the search strategy and use a specific 'vcvars' bat file - local search_set = {} - - if arch_tuple == nil then - error("unsupported host/target architecture " .. arch_tuple) - end - - if vcvarsall_bat == nil then - -- don't assume that everyone is using the same edition of Visual Studio - -- unless a specific edition (i.e. product) has been requested, look for - -- the first setup that has Visual C++ compiler toolset installed - if vs_product == nil then - for _, vs_product in pairs(vs_products) do - vcvarsall_bat = find_vc_tools(installation_path, version, vs_product, search_set) - if vcvarsall_bat ~= nil then - break - end - end - else - vcvarsall_bat = find_vc_tools(installation_path, version, vs_product, search_set) - end - else - local stat = native.stat_file(vcvarsall_bat) - if not stat.exists then - error("cannot find the vcvars batch file: " .. vcvarsall_bat) - end - end - - if vcvarsall_bat == nil then - error("cannot find the Visual C++ compiler toolset in any of the following locations: \n " .. table.concat(search_set, "\n ") .. "\nCheck that either Desktop development with C++ or Visual C++ build tools is installed. You can customize the InstallationPath or Product options to load a specific instance of Visual Studio " .. version .. " from a specific location. If Product is not specified it will look for the first instance of the Visual C++ compiler toolset in the default installation path 'C:\\Program Files (x86)\\Microsoft Visual Studio' in the following order " .. table.concat(vs_products, ", ") .. " using the tripplet (InstallationPath, '" .. version .. "', Product)") - end - - -- now to the fun part, the vcvarsall.bat script is quite customizable - -- we can request the environment from it, let it do the hard part and - -- then diff and merge things back into our environment - - -- Syntax: - -- vcvarsall.bat [arch] [platform_type] [winsdk_version] [-vcvars_ver=vc_version] - -- where : - -- [arch]: x86 | amd64 | x86_amd64 | x86_arm | x86_arm64 | amd64_x86 | amd64_arm | amd64_arm64 - -- [platform_type]: {empty} | store | uwp - -- [winsdk_version] : full Windows 10 SDK number (e.g. 10.0.10240.0) or "8.1" to use the Windows 8.1 SDK. - -- [vc_version] : "14.0" for VC++ 2015 Compiler Toolset | {empty} for default VS 2017 VC++ compiler toolset - -- - -- The store parameter sets environment variables to support Universal Windows Platform application - -- development and is an alias for 'uwp'. - -- - -- For example: - -- vcvarsall.bat x86_amd64 - -- vcvarsall.bat x86_amd64 10.0.10240.0 - -- vcvarsall.bat x86_arm uwp 10.0.10240.0 - -- vcvarsall.bat x86_arm onecore 10.0.10240.0 -vcvars_ver=14.0 - -- vcvarsall.bat x64 8.1 - -- vcvarsall.bat x64 store 8.1 - - local vcvars_args = { arch_tuple } - - if platform_type ~= nil then - vcvars_args[#vcvars_args+1] = platform_type - end - - if sdk_version ~= nil then - vcvars_args[#vcvars_args+1] = sdk_version - end - - local vcvars = {} - - local vcvars_a = table.concat(vcvars_args, " ") - local vcvars_key = vcvarsall_bat .. vcvars_a - if not vcvars_cache[vcvars_key] then - local command = "\"" .. vcvarsall_bat .. "\" " .. vcvars_a .. " 1>NUL && set" - local vcvars_p = io.popen(command) - for ln in vcvars_p:lines() do - local split_at = ln:find("=") - local k = ln:sub(1, split_at-1):upper() - local v = ln:sub(split_at+1) - vcvars[k] = v - end - vcvars_p:close() - vcvars_cache[vcvars_key] = vcvars - else - vcvars = vcvars_cache[vcvars_key] - end - - --print(table.concat(keys(vcvars), " ")) - - -- Force MSPDBSRV.EXE (fixes issues with cl.exe running in parallel and corrupting PDB files) - env:set("CCOPTS", "/FS") - env:set("CXXOPTS", "/FS") - - local copy_env_vars = { - "VSINSTALLDIR", - "VCINSTALLDIR", - "INCLUDE", - "LIB", - "LIBPATH", - "PATH", - } - - for _, k in pairs(copy_env_vars) do - local v = vcvars[k] - if v == nil then - print("Warning: expected environment variable '" .. k .. "' but got nil") - else - env:set_external_env_var(k, v) - end - end - - -- OK done -end diff --git a/scripts/tundra/tools/msvc-vswild.lua b/scripts/tundra/tools/msvc-vswild.lua deleted file mode 100644 index ea215b6c..00000000 --- a/scripts/tundra/tools/msvc-vswild.lua +++ /dev/null @@ -1,23 +0,0 @@ - -module(..., package.seeall) - -local vscommon = require "tundra.tools.msvc-vscommon" - -function apply(env, options) - - local vsvs = options.VsVersions or { "14.0", "12.0", "11.0", "10.0", "9.0" } - - for _, v in ipairs(vsvs) do - local v1 = v - local success, result = xpcall(function() vscommon.apply_msvc_visual_studio(v1, env, options) end, function(err) return err end) - if success then - print("Visual Studio version " .. v1 .. " found ") - return - else - print("Visual Studio version " .. v1 .. " does not appear to be installed (" .. result .. ")") - end - end - - error("Unable to find suitable version of Visual Studio (please install either version " .. table.concat(vsvs, ", ") .. " of Visual Studio to continue)") - -end