]> git.tdb.fi Git - builder.git/blob - plugins/msvc/msvccompiler.cpp
Disable some warnings related to dllexport on MSVC
[builder.git] / plugins / msvc / msvccompiler.cpp
1 #include <msp/builder/builder.h>
2 #include <msp/builder/component.h>
3 #include <msp/builder/csourcefile.h>
4 #include <msp/builder/objectfile.h>
5 #include <msp/builder/sourcepackage.h>
6 #include <msp/core/environ.h>
7 #include <msp/core/maputils.h>
8 #include <msp/fs/utils.h>
9 #include <msp/strings/format.h>
10 #include <msp/strings/utils.h>
11 #include "microsofttools.h"
12 #include "msvccompiler.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                 argv.push_back("/wd4251");  // Dll-interface required on type of member variable
127                 argv.push_back("/wd4275");  // Dll-interface class derives from non-dll-interface class
128                 if(binfo.warning_level<4)
129                 {
130                         argv.push_back("/wd4244");  // Narrowing conversion on arg or return
131                         argv.push_back("/wd4267");  // Narrowing conversion
132                 }
133         }
134         else
135                 argv.push_back("/w");
136
137         for(const FS::Path &p: binfo.local_incpath)
138         {
139                 argv.push_back("/I");
140                 argv.push_back(p.str());
141         }
142         for(const FS::Path &p: binfo.incpath)
143         {
144                 argv.push_back("/I");
145                 argv.push_back(p.str());
146         }
147
148         for(const auto &kvp: binfo.defines)
149         {
150                 argv.push_back("/D");
151                 if(kvp.second.empty())
152                         argv.push_back(kvp.first);
153                 else
154                         argv.push_back(format("%s=%s", kvp.first, kvp.second));
155         }
156
157         if(binfo.debug)
158                 argv.push_back("/Z7");
159         if(binfo.optimize)
160         {
161                 if(binfo.optimize<0)
162                         argv.push_back("/O1");
163                 else if(binfo.optimize==1)
164                         argv.push_back("/Ox");
165                 else
166                         argv.push_back("/O2");
167         }
168
169         if(binfo.libmode<=BuildInfo::STATIC)
170                 argv.push_back(binfo.debug ? "/MTd" : "/MT");
171         else
172                 argv.push_back(binfo.debug ? "/MDd" : "/MD");
173
174         argv.push_back("/EHsc");
175
176         FS::Path obj_path = object.get_path();
177         FS::Path src_path = object.get_source().get_path();
178
179         argv.push_back("/Fo"+relative(obj_path, work_dir).str());
180         argv.push_back(relative(src_path, work_dir).str());
181
182         return argv;
183 }