]> git.tdb.fi Git - builder.git/blob - source/msvccompiler.cpp
Add gcc's private library directory to ClangLinker's system path
[builder.git] / source / msvccompiler.cpp
1 #include <msp/core/environ.h>
2 #include <msp/core/maputils.h>
3 #include <msp/fs/utils.h>
4 #include <msp/strings/format.h>
5 #include <msp/strings/utils.h>
6 #include "builder.h"
7 #include "component.h"
8 #include "csourcefile.h"
9 #include "microsofttools.h"
10 #include "msvccompiler.h"
11 #include "objectfile.h"
12 #include "sourcepackage.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 MsvcCompiler::MsvcCompiler(Builder &b, const Architecture &a, const string &t, const MicrosoftTools &m):
18         Tool(b, &a, t),
19         ms_tools(m)
20 {
21         if(tag=="CC")
22         {
23                 input_suffixes.push_back(".c");
24                 aux_suffixes.push_back(".h");
25         }
26         else if(tag=="CXX")
27         {
28                 input_suffixes.push_back(".cpp");
29                 input_suffixes.push_back(".cc");
30                 aux_suffixes.push_back(".hpp");
31         }
32         else
33                 throw invalid_argument("MsvcCompiler::MsvcCompiler");
34
35         set_command((ms_tools.get_vc_bin_dir()/"cl.exe").str(), false);
36         set_run_external(_run);
37 }
38
39 Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const
40 {
41         return new CSourceFile(builder, comp, path);
42 }
43
44 Target *MsvcCompiler::create_source(const FS::Path &path) const
45 {
46         return new CSourceFile(builder, path);
47 }
48
49 Target *MsvcCompiler::create_target(const vector<Target *> &sources, const string &)
50 {
51         if(sources.size()!=1)
52                 throw invalid_argument("MsvcCompiler::create_target");
53         SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
54         ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
55         obj->set_tool(*this);
56         return obj;
57 }
58
59 string MsvcCompiler::create_build_signature(const BuildInfo &binfo) const
60 {
61         string result = Tool::create_build_signature(binfo);
62         result += ',';
63         if(binfo.debug)
64                 result += 'g';
65         if(binfo.optimize)
66         {
67                 result += 'O';
68                 result += (binfo.optimize<0 ? '1' : binfo.optimize==1 ? 'x' : '2');
69         }
70         if(binfo.libmode<=BuildInfo::STATIC)
71                 result += 't';
72         return result;
73 }
74
75 void MsvcCompiler::do_prepare(ToolData &tool) const
76 {
77         const std::string &tool_tag = static_cast<Tool &>(tool).get_tag();
78
79         const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
80         tool.system_path.push_back(vc_base_dir/"include");
81
82         const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
83         const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
84         tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt");
85         tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared");
86         tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um");
87
88         string path;
89         for(const FS::Path &p: tool.system_path)
90         {
91                 append(path, ";", p.str());
92                 builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, p);
93         }
94
95         setenv("INCLUDE", path);
96 }
97
98 ExternalTask::Arguments MsvcCompiler::_run(const ObjectFile &object, FS::Path &work_dir)
99 {
100         const Tool &tool = *object.get_tool();
101
102         ExternalTask::Arguments argv;
103         argv.push_back(tool.get_executable()->get_path().str());
104         argv.push_back("/nologo");
105         argv.push_back("/c");
106
107         BuildInfo binfo;
108         object.collect_build_info(binfo);
109
110         if(binfo.standards.count(tool.get_tag()))
111         {
112                 const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tool.get_tag());
113                 if((tool.get_tag()=="CXX" && std.year>2011) || (tool.get_tag()=="CC" && std.year>1999))
114                         argv.push_back("/std:"+std.str());
115         }
116
117         if(binfo.warning_level>=1)
118         {
119                 argv.push_back(format("/W%d", binfo.warning_level));
120                 if(binfo.fatal_warnings)
121                         argv.push_back("/WX");
122                 if(binfo.warning_level>=3)
123                         argv.push_back("/permissive-");
124
125                 argv.push_back("/wd4068");  // Unknown pragma
126                 if(binfo.warning_level<4)
127                 {
128                         argv.push_back("/wd4244");  // Narrowing conversion on arg or return
129                         argv.push_back("/wd4267");  // Narrowing conversion
130                 }
131         }
132         else
133                 argv.push_back("/w");
134
135         for(const FS::Path &p: binfo.local_incpath)
136         {
137                 argv.push_back("/I");
138                 argv.push_back(p.str());
139         }
140         for(const FS::Path &p: binfo.incpath)
141         {
142                 argv.push_back("/I");
143                 argv.push_back(p.str());
144         }
145
146         for(const auto &kvp: binfo.defines)
147         {
148                 argv.push_back("/D");
149                 if(kvp.second.empty())
150                         argv.push_back(kvp.first);
151                 else
152                         argv.push_back(format("%s=%s", kvp.first, kvp.second));
153         }
154
155         if(binfo.debug)
156                 argv.push_back("/Z7");
157         if(binfo.optimize)
158         {
159                 if(binfo.optimize<0)
160                         argv.push_back("/O1");
161                 else if(binfo.optimize==1)
162                         argv.push_back("/Ox");
163                 else
164                         argv.push_back("/O2");
165         }
166
167         if(binfo.libmode<=BuildInfo::STATIC)
168                 argv.push_back(binfo.debug ? "/MTd" : "/MT");
169         else
170                 argv.push_back(binfo.debug ? "/MDd" : "/MD");
171
172         argv.push_back("/EHsc");
173
174         FS::Path obj_path = object.get_path();
175         FS::Path src_path = object.get_source().get_path();
176
177         argv.push_back("/Fo"+relative(obj_path, work_dir).str());
178         argv.push_back(relative(src_path, work_dir).str());
179
180         return argv;
181 }