]> git.tdb.fi Git - builder.git/blob - plugins/msvc/microsofttools.cpp
Move the VS project and solution generators to the MSVC plugin
[builder.git] / plugins / msvc / microsofttools.cpp
1 #include <msp/builder/builder.h>
2 #include <msp/builder/externaltask.h>
3 #include <msp/builder/logger.h>
4 #include <msp/builder/sysutils.h>
5 #include <msp/core/algorithm.h>
6 #include <msp/fs/dir.h>
7 #include <msp/fs/stat.h>
8 #include <msp/strings/utils.h>
9 #include "microsofttools.h"
10 #include "msvcarchiver.h"
11 #include "msvccompiler.h"
12 #include "msvclinker.h"
13 #include "vcxprojectgenerator.h"
14 #include "vssolutiongenerator.h"
15
16 using namespace std;
17 using namespace Msp;
18
19 MicrosoftTools::MicrosoftTools(Builder &builder, const Architecture &arch):
20         Toolchain("msvc", get_priority(arch))
21 {
22         find_vc_bin_dir(builder, arch);
23         if(!vc_base_dir.empty())
24                 find_windows_sdk_dir(builder);
25
26         add_tool(new MsvcCompiler(builder, arch, "CC", *this));
27         add_tool(new MsvcCompiler(builder, arch, "CXX", *this));
28         add_tool(new MsvcLinker(builder, arch, *this));
29         add_tool(new MsvcArchiver(builder, arch, *this));
30
31         add_tool(new VcxProjectGenerator(builder));
32         add_tool(new VsSolutionGenerator(builder));
33 }
34
35 void MicrosoftTools::find_vc_bin_dir(Builder &builder, const Architecture &arch)
36 {
37         FS::Path program_files_x86 = get_program_files_x86_dir();
38
39         FS::Path vswhere = program_files_x86/"Microsoft Visual Studio"/"Installer"/"vswhere.exe";
40         if(!FS::exists(vswhere))
41                 return;
42
43         ExternalTask::Arguments argv;
44         argv.push_back(vswhere.str());
45         argv.push_back("-latest");
46         argv.push_back("-property");
47         argv.push_back("installationPath");
48
49         builder.get_logger().log("auxcommands", "Running %s", join(argv.begin(), argv.end()));
50
51         string output = ExternalTask::run_and_capture_output(argv, FS::Path(), true);
52         FS::Path vs_path = strip(output);
53         if(!vs_path.is_absolute())
54         {
55                 string drive = vs_path[1];
56                 if(drive.size()==2 && drive[0]>='A' && drive[0]<='Z' && drive[1]==':')
57                         vs_path = FS::Path("/mnt")/string(1, tolower(drive[0]))/vs_path.subpath(2);
58         }
59
60         builder.get_logger().log("tools", "Visual Studio found in %s", vs_path);
61
62         FS::Path vc_aux_build_dir = vs_path/"VC"/"Auxiliary"/"Build";
63         builder.get_logger().log("files", "Traversing %s", vc_aux_build_dir);
64         vector<string> vc_version_files = FS::list_filtered(vc_aux_build_dir, "^Microsoft\\.VCToolsVersion\\.");
65         if(vc_version_files.empty())
66         {
67                 builder.get_logger().log("problems", "MSVC tools version not found");
68                 return;
69         }
70
71         sort(vc_version_files);
72         FS::Path vc_version_fn = vc_aux_build_dir/vc_version_files.back();
73         builder.get_logger().log("files", "Reading %s", vc_version_fn);
74         char buffer[256];
75         unsigned len = IO::File(vc_version_fn.str()).read(buffer, sizeof(buffer));
76         string vc_version = strip(string(buffer, len));
77
78         builder.get_logger().log("tools", "Detected MSVC version %s", vc_version);
79
80         const Architecture &native_arch = builder.get_native_arch();
81         string host = (native_arch.get_bits()==64 ? "Hostx64" : "Hostx86");
82         string target = (arch.get_bits()==64 ? "x64" : "x86");
83
84         vc_base_dir = vs_path/"VC"/"Tools"/"MSVC"/vc_version;
85         vc_bin_dir = vc_base_dir/"bin"/host/target;
86 }
87
88 void MicrosoftTools::find_windows_sdk_dir(Builder &builder)
89 {
90         win_sdk_dir = get_registry_value<string>("HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0\\InstallationFolder");
91         if(win_sdk_dir.empty())
92                 win_sdk_dir = get_program_files_x86_dir()/"Windows Kits"/"10";
93
94         builder.get_logger().log("files", "Traversing %s", win_sdk_dir/"include");
95         vector<string> sdk_versions = FS::list_filtered(win_sdk_dir/"include", "^10\\.");
96         if(sdk_versions.empty())
97         {
98                 builder.get_logger().log("problems", "No Windows SDK versions found");
99                 return;
100         }
101
102         sort(sdk_versions);
103         win_sdk_version = sdk_versions.back();
104
105         builder.get_logger().log("tools", "Windows SDK version %s found in %s", win_sdk_version, win_sdk_dir);
106 }
107
108 int MicrosoftTools::get_priority(const Architecture &arch)
109 {
110         if(arch.get_toolchain()=="msvc")
111                 return 20;
112         else if(arch.get_system()=="windows")
113                 return 10;
114         else
115                 return 0;
116 }