diff options
Diffstat (limited to 'cc/src/windows_registry.rs')
-rw-r--r-- | cc/src/windows_registry.rs | 186 |
1 files changed, 124 insertions, 62 deletions
diff --git a/cc/src/windows_registry.rs b/cc/src/windows_registry.rs index 9099e0f..bbcbb09 100644 --- a/cc/src/windows_registry.rs +++ b/cc/src/windows_registry.rs @@ -65,11 +65,19 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> { return impl_::find_msbuild(target); } + if tool.contains("devenv") { + return impl_::find_devenv(target); + } + // If VCINSTALLDIR is set, then someone's probably already run vcvars and we // should just find whatever that indicates. if env::var_os("VCINSTALLDIR").is_some() { return env::var_os("PATH") - .and_then(|path| env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists())) + .and_then(|path| { + env::split_paths(&path) + .map(|p| p.join(tool)) + .find(|p| p.exists()) + }) .map(|path| Tool::new(path.into())); } @@ -119,19 +127,20 @@ pub fn find_vs_version() -> Result<VsVers, String> { use std::env; match env::var("VisualStudioVersion") { - Ok(version) => { - match &version[..] { - "15.0" => Ok(VsVers::Vs15), - "14.0" => Ok(VsVers::Vs14), - "12.0" => Ok(VsVers::Vs12), - vers => Err(format!("\n\n\ - unsupported or unknown VisualStudio version: {}\n\ - if another version is installed consider running \ - the appropriate vcvars script before building this \ - crate\n\ - ", vers)), - } - } + Ok(version) => match &version[..] { + "15.0" => Ok(VsVers::Vs15), + "14.0" => Ok(VsVers::Vs14), + "12.0" => Ok(VsVers::Vs12), + vers => Err(format!( + "\n\n\ + unsupported or unknown VisualStudio version: {}\n\ + if another version is installed consider running \ + the appropriate vcvars script before building this \ + crate\n\ + ", + vers + )), + }, _ => { // Check for the presense of a specific registry key // that indicates visual studio is installed. @@ -142,12 +151,14 @@ pub fn find_vs_version() -> Result<VsVers, String> { } else if impl_::has_msbuild_version("12.0") { Ok(VsVers::Vs12) } else { - Err(format!("\n\n\ - couldn't determine visual studio generator\n\ - if VisualStudio is installed, however, consider \ - running the appropriate vcvars script before building \ - this crate\n\ - ")) + Err(format!( + "\n\n\ + couldn't determine visual studio generator\n\ + if VisualStudio is installed, however, consider \ + running the appropriate vcvars script before building \ + this crate\n\ + " + )) } } } @@ -185,7 +196,12 @@ mod impl_ { } fn into_tool(self) -> Tool { - let MsvcTool { tool, libs, path, include } = self; + let MsvcTool { + tool, + libs, + path, + include, + } = self; let mut tool = Tool::new(tool.into()); add_env(&mut tool, "LIB", libs); add_env(&mut tool, "PATH", path); @@ -217,11 +233,13 @@ mod impl_ { None } - fn tool_from_vs15_instance(tool: &str, target: &str, - instance: &SetupInstance) -> Option<Tool> { - let (bin_path, host_dylib_path, lib_path, include_path) = otry!(vs15_vc_paths(target, instance)); + fn tool_from_vs15_instance(tool: &str, target: &str, instance: &SetupInstance) -> Option<Tool> { + let (bin_path, host_dylib_path, lib_path, include_path) = + otry!(vs15_vc_paths(target, instance)); let tool_path = bin_path.join(tool); - if !tool_path.exists() { return None }; + if !tool_path.exists() { + return None; + }; let mut tool = MsvcTool::new(tool_path); tool.path.push(host_dylib_path); @@ -238,9 +256,13 @@ mod impl_ { Some(tool.into_tool()) } - fn vs15_vc_paths(target: &str, instance: &SetupInstance) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> { + fn vs15_vc_paths( + target: &str, + instance: &SetupInstance, + ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> { let instance_path: PathBuf = otry!(instance.installation_path().ok()).into(); - let version_path = instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); + let version_path = + instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); let mut version_file = otry!(File::open(version_path).ok()); let mut version = String::new(); otry!(version_file.read_to_string(&mut version).ok()); @@ -255,11 +277,15 @@ mod impl_ { let path = instance_path.join(r"VC\Tools\MSVC").join(version); // This is the path to the toolchain for a particular target, running // on a given host - let bin_path = path.join("bin").join(&format!("Host{}", host)).join(&target); + let bin_path = path.join("bin") + .join(&format!("Host{}", host)) + .join(&target); // But! we also need PATH to contain the target directory for the host // architecture, because it contains dlls like mspdb140.dll compiled for // the host architecture. - let host_dylib_path = path.join("bin").join(&format!("Host{}", host)).join(&host.to_lowercase()); + let host_dylib_path = path.join("bin") + .join(&format!("Host{}", host)) + .join(&host.to_lowercase()); let lib_path = path.join("lib").join(&target); let include_path = path.join("include"); Some((bin_path, host_dylib_path, lib_path, include_path)) @@ -288,7 +314,8 @@ mod impl_ { let sub = otry!(lib_subdir(target)); let (ucrt, ucrt_version) = otry!(get_ucrt_dir()); - tool.path.push(ucrt.join("bin").join(&ucrt_version).join(sub)); + tool.path + .push(ucrt.join("bin").join(&ucrt_version).join(sub)); let ucrt_include = ucrt.join("include").join(&ucrt_version); tool.include.push(ucrt_include.join("ucrt")); @@ -302,6 +329,7 @@ mod impl_ { tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include").join(&version); tool.include.push(sdk_include.join("um")); + tool.include.push(sdk_include.join("cppwinrt")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } else if let Some(sdk) = get_sdk81_dir() { @@ -353,7 +381,8 @@ mod impl_ { let prev = env::var_os(env).unwrap_or(OsString::new()); let prev = env::split_paths(&prev); let new = paths.into_iter().chain(prev); - tool.env.push((env.to_string().into(), env::join_paths(new).unwrap())); + tool.env + .push((env.to_string().into(), env::join_paths(new).unwrap())); } // Given a possible MSVC installation directory, we look for the linker and @@ -361,7 +390,12 @@ mod impl_ { fn get_tool(tool: &str, path: &Path, target: &str) -> Option<MsvcTool> { bin_subdir(target) .into_iter() - .map(|(sub, host)| (path.join("bin").join(sub).join(tool), path.join("bin").join(host))) + .map(|(sub, host)| { + ( + path.join("bin").join(sub).join(tool), + path.join("bin").join(host), + ) + }) .filter(|&(ref path, _)| path.is_file()) .map(|(path, host)| { let mut tool = MsvcTool::new(path); @@ -402,16 +436,17 @@ mod impl_ { let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("KitsRoot10").ok()); let readdir = otry!(Path::new(&root).join("lib").read_dir().ok()); - let max_libdir = otry!(readdir.filter_map(|dir| dir.ok()) - .map(|dir| dir.path()) - .filter(|dir| { - dir.components() + let max_libdir = otry!( + readdir + .filter_map(|dir| dir.ok()) + .map(|dir| dir.path()) + .filter(|dir| dir.components() .last() .and_then(|c| c.as_os_str().to_str()) .map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir()) - .unwrap_or(false) - }) - .max()); + .unwrap_or(false)) + .max() + ); let version = max_libdir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) @@ -430,14 +465,17 @@ mod impl_ { let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("InstallationFolder").ok()); let readdir = otry!(Path::new(&root).join("lib").read_dir().ok()); - let mut dirs = readdir.filter_map(|dir| dir.ok()) + let mut dirs = readdir + .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .collect::<Vec<_>>(); dirs.sort(); - let dir = otry!(dirs.into_iter() - .rev() - .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file()) - .next()); + let dir = otry!( + dirs.into_iter() + .rev() + .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file()) + .next() + ); let version = dir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) @@ -485,8 +523,8 @@ mod impl_ { ("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")], ("x86_64", X86) => vec![("x86_amd64", "")], ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")], - ("arm", X86) => vec![("x86_arm", "")], - ("arm", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")], + ("arm", X86) | ("thumbv7a", X86) => vec![("x86_arm", "")], + ("arm", X86_64) | ("thumbv7a", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")], _ => vec![], } } @@ -496,7 +534,8 @@ mod impl_ { match arch { "i586" | "i686" => Some("x86"), "x86_64" => Some("x64"), - "arm" => Some("arm"), + "arm" | "thumbv7a" => Some("arm"), + "aarch64" => Some("arm64"), _ => None, } } @@ -507,7 +546,8 @@ mod impl_ { match arch { "i586" | "i686" => Some(""), "x86_64" => Some("amd64"), - "arm" => Some("arm"), + "arm" | "thumbv7a" => Some("arm"), + "aarch64" => Some("arm64"), _ => None, } } @@ -553,7 +593,8 @@ mod impl_ { let mut max_vers = 0; let mut max_key = None; for subkey in key.iter().filter_map(|k| k.ok()) { - let val = subkey.to_str() + let val = subkey + .to_str() .and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok()); let val = match val { Some(s) => s, @@ -572,18 +613,39 @@ mod impl_ { pub fn has_msbuild_version(version: &str) -> bool { match version { "15.0" => { - find_msbuild_vs15("x86_64-pc-windows-msvc").is_some() || - find_msbuild_vs15("i686-pc-windows-msvc").is_some() - } - "12.0" | "14.0" => { - LOCAL_MACHINE.open( - &OsString::from(format!("SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}", - version))).is_ok() + find_msbuild_vs15("x86_64-pc-windows-msvc").is_some() + || find_msbuild_vs15("i686-pc-windows-msvc").is_some() } - _ => false + "12.0" | "14.0" => LOCAL_MACHINE + .open(&OsString::from(format!( + "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}", + version + ))) + .is_ok(), + _ => false, } } + pub fn find_devenv(target: &str) -> Option<Tool> { + find_devenv_vs15(&target) + } + + fn find_devenv_vs15(target: &str) -> Option<Tool> { + let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"; + LOCAL_MACHINE + .open(key.as_ref()) + .ok() + .and_then(|key| key.query_str("15.0").ok()) + .map(|path| { + let path = PathBuf::from(path).join(r"Common7\IDE\devenv.exe"); + let mut tool = Tool::new(path); + if target.contains("x86_64") { + tool.env.push(("Platform".into(), "X64".into())); + } + tool + }) + } + // see http://stackoverflow.com/questions/328017/path-to-msbuild pub fn find_msbuild(target: &str) -> Option<Tool> { // VS 15 (2017) changed how to locate msbuild @@ -599,11 +661,10 @@ mod impl_ { // or that find_msvc_15 could just use this registry key // instead of the COM interface. let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"; - LOCAL_MACHINE.open(key.as_ref()) + LOCAL_MACHINE + .open(key.as_ref()) .ok() - .and_then(|key| { - key.query_str("15.0").ok() - }) + .and_then(|key| key.query_str("15.0").ok()) .map(|path| { let path = PathBuf::from(path).join(r"MSBuild\15.0\Bin\MSBuild.exe"); let mut tool = Tool::new(path); @@ -616,7 +677,8 @@ mod impl_ { fn find_old_msbuild(target: &str) -> Option<Tool> { let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions"; - LOCAL_MACHINE.open(key.as_ref()) + LOCAL_MACHINE + .open(key.as_ref()) .ok() .and_then(|key| { max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok()) |