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(ToolData &tool) const
78 const std::string &tool_tag = static_cast<Tool &>(tool).get_tag();
80 const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
81 tool.system_path.push_back(vc_base_dir/"include");
83 const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
84 const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
85 tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt");
86 tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared");
87 tool.system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um");
90 for(const FS::Path &p: tool.system_path)
92 append(path, ";", p.str());
93 builder.get_logger().log("tools", "Got %s system path: %s", tool_tag, p);
96 setenv("INCLUDE", path);
99 Task *MsvcCompiler::_run(const ObjectFile &object)
101 const Tool &tool = *object.get_tool();
103 ExternalTask::Arguments argv;
104 argv.push_back(tool.get_executable()->get_path().str());
105 argv.push_back("/nologo");
106 argv.push_back("/c");
109 object.collect_build_info(binfo);
111 if(binfo.standards.count(tool.get_tag()))
113 const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tool.get_tag());
114 if((tool.get_tag()=="CXX" && std.year>2011) || (tool.get_tag()=="CC" && std.year>1999))
115 argv.push_back("/std:"+std.str());
118 if(binfo.warning_level>=1)
120 argv.push_back(format("/W%d", binfo.warning_level));
121 if(binfo.fatal_warnings)
122 argv.push_back("/WX");
123 if(binfo.warning_level>=3)
124 argv.push_back("/permissive-");
126 argv.push_back("/wd4068"); // Unknown pragma
127 if(binfo.warning_level<4)
129 argv.push_back("/wd4244"); // Narrowing conversion on arg or return
130 argv.push_back("/wd4267"); // Narrowing conversion
134 argv.push_back("/w");
136 for(const FS::Path &p: binfo.local_incpath)
138 argv.push_back("/I");
139 argv.push_back(p.str());
141 for(const FS::Path &p: binfo.incpath)
143 argv.push_back("/I");
144 argv.push_back(p.str());
147 for(const auto &kvp: binfo.defines)
149 argv.push_back("/D");
150 if(kvp.second.empty())
151 argv.push_back(kvp.first);
153 argv.push_back(format("%s=%s", kvp.first, kvp.second));
157 argv.push_back("/Z7");
161 argv.push_back("/O1");
162 else if(binfo.optimize==1)
163 argv.push_back("/Ox");
165 argv.push_back("/O2");
168 if(binfo.libmode<=BuildInfo::STATIC)
169 argv.push_back(binfo.debug ? "/MTd" : "/MT");
171 argv.push_back(binfo.debug ? "/MDd" : "/MD");
173 argv.push_back("/EHsc");
175 FS::Path obj_path = object.get_path();
176 FS::Path src_path = object.get_source().get_path();
177 FS::Path work_dir = object.get_component()->get_package().get_source_directory();
179 argv.push_back("/Fo"+relative(obj_path, work_dir).str());
180 argv.push_back(relative(src_path, work_dir).str());
182 return new ExternalTask(argv, work_dir);