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>
8 #include "csourcefile.h"
9 #include "externaltask.h"
10 #include "microsofttools.h"
11 #include "msvccompiler.h"
12 #include "objectfile.h"
13 #include "sourcepackage.h"
18 MsvcCompiler::MsvcCompiler(Builder &b, const Architecture &a, const string &t, const MicrosoftTools &m):
24 input_suffixes.push_back(".c");
25 aux_suffixes.push_back(".h");
29 input_suffixes.push_back(".cpp");
30 input_suffixes.push_back(".cc");
31 aux_suffixes.push_back(".hpp");
34 throw invalid_argument("MsvcCompiler::MsvcCompiler");
36 set_command((ms_tools.get_vc_bin_dir()/"cl.exe").str(), false);
40 Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const
42 return new CSourceFile(builder, comp, path);
45 Target *MsvcCompiler::create_source(const FS::Path &path) const
47 return new CSourceFile(builder, path);
50 Target *MsvcCompiler::create_target(const vector<Target *> &sources, const string &)
53 throw invalid_argument("MsvcCompiler::create_target");
54 SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
55 ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
60 string MsvcCompiler::create_build_signature(const BuildInfo &binfo) const
62 string result = Tool::create_build_signature(binfo);
69 result += (binfo.optimize<0 ? '1' : binfo.optimize==1 ? 'x' : '2');
71 if(binfo.libmode<=BuildInfo::STATIC)
76 void MsvcCompiler::do_prepare()
78 const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
79 system_path.push_back(vc_base_dir/"include");
81 const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
82 const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
83 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt");
84 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared");
85 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um");
88 for(const FS::Path &p: system_path)
90 append(path, ";", p.str());
91 builder.get_logger().log("tools", "Got %s system path: %s", tag, p);
94 setenv("INCLUDE", path);
97 Task *MsvcCompiler::_run(const ObjectFile &object)
99 const Tool &tool = *object.get_tool();
101 ExternalTask::Arguments argv;
102 argv.push_back(tool.get_executable()->get_path().str());
103 argv.push_back("/nologo");
104 argv.push_back("/c");
107 object.collect_build_info(binfo);
109 if(binfo.standards.count(tool.get_tag()))
111 const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tool.get_tag());
112 if((tool.get_tag()=="CXX" && std.year>2011) || (tool.get_tag()=="CC" && std.year>1999))
113 argv.push_back("/std:"+std.str());
116 if(binfo.warning_level>=1)
118 argv.push_back(format("/W%d", binfo.warning_level));
119 if(binfo.fatal_warnings)
120 argv.push_back("/WX");
121 if(binfo.warning_level>=3)
122 argv.push_back("/permissive-");
124 argv.push_back("/wd4068"); // Unknown pragma
125 if(binfo.warning_level<4)
127 argv.push_back("/wd4244"); // Narrowing conversion on arg or return
128 argv.push_back("/wd4267"); // Narrowing conversion
132 argv.push_back("/w");
134 for(const FS::Path &p: binfo.local_incpath)
136 argv.push_back("/I");
137 argv.push_back(p.str());
139 for(const FS::Path &p: binfo.incpath)
141 argv.push_back("/I");
142 argv.push_back(p.str());
145 for(const auto &kvp: binfo.defines)
147 argv.push_back("/D");
148 if(kvp.second.empty())
149 argv.push_back(kvp.first);
151 argv.push_back(format("%s=%s", kvp.first, kvp.second));
155 argv.push_back("/Z7");
159 argv.push_back("/O1");
160 else if(binfo.optimize==1)
161 argv.push_back("/Ox");
163 argv.push_back("/O2");
166 if(binfo.libmode<=BuildInfo::STATIC)
167 argv.push_back(binfo.debug ? "/MTd" : "/MT");
169 argv.push_back(binfo.debug ? "/MDd" : "/MD");
171 argv.push_back("/EHsc");
173 FS::Path obj_path = object.get_path();
174 FS::Path src_path = object.get_source().get_path();
175 FS::Path work_dir = object.get_component()->get_package().get_source_directory();
177 argv.push_back("/Fo"+relative(obj_path, work_dir).str());
178 argv.push_back(relative(src_path, work_dir).str());
180 return new ExternalTask(argv, work_dir);