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);
39 Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const
41 return new CSourceFile(builder, comp, path);
44 Target *MsvcCompiler::create_source(const FS::Path &path) const
46 return new CSourceFile(builder, path);
49 Target *MsvcCompiler::create_target(const list<Target *> &sources, const string &)
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);
59 string MsvcCompiler::create_build_signature(const BuildInfo &binfo) const
61 string result = FS::basename(executable->get_path());
68 result += (binfo.optimize<0 ? '1' : binfo.optimize==1 ? 'x' : '2');
70 if(binfo.libmode<=BuildInfo::STATIC)
75 void MsvcCompiler::do_prepare()
77 const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
78 system_path.push_back(vc_base_dir/"include");
80 const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
81 const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
82 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt");
83 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared");
84 system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um");
87 for(SearchPath::const_iterator i=system_path.begin(); i!=system_path.end(); ++i)
89 append(path, ";", i->str());
90 builder.get_logger().log("tools", format("Got %s system path: %s", tag, *i));
93 setenv("INCLUDE", path);
96 Task *MsvcCompiler::run(const Target &target) const
98 const ObjectFile &object = dynamic_cast<const ObjectFile &>(target);
100 ExternalTask::Arguments argv;
101 argv.push_back(executable->get_path().str());
102 argv.push_back("/nologo");
103 argv.push_back("/c");
106 target.collect_build_info(binfo);
108 if(binfo.standards.count(tag))
110 string std = get_item(binfo.standards, tag);
111 if(std!="c++11" && std!="c99")
112 argv.push_back("/std:"+std);
115 if(binfo.warning_level>=1)
117 argv.push_back(format("/W%d", binfo.warning_level));
118 if(binfo.fatal_warnings)
119 argv.push_back("/WX");
120 if(binfo.warning_level>=3)
121 argv.push_back("/permissive-");
123 argv.push_back("/wd4068"); // Unknown pragma
124 if(binfo.warning_level<4)
126 argv.push_back("/wd4244"); // Narrowing conversion on arg or return
127 argv.push_back("/wd4267"); // Narrowing conversion
131 argv.push_back("/w");
133 for(BuildInfo::PathList::const_iterator i=binfo.local_incpath.begin(); i!=binfo.local_incpath.end(); ++i)
135 argv.push_back("/I");
136 argv.push_back(i->str());
138 for(BuildInfo::PathList::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
140 argv.push_back("/I");
141 argv.push_back(i->str());
144 for(BuildInfo::DefineMap::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
146 argv.push_back("/D");
147 if(i->second.empty())
148 argv.push_back(i->first);
150 argv.push_back(format("%s=%s", i->first, i->second));
154 argv.push_back("/Z7");
158 argv.push_back("/O1");
159 else if(binfo.optimize==1)
160 argv.push_back("/Ox");
162 argv.push_back("/O2");
165 if(binfo.libmode<=BuildInfo::STATIC)
166 argv.push_back(binfo.debug ? "/MTd" : "/MT");
168 argv.push_back(binfo.debug ? "/MDd" : "/MD");
170 argv.push_back("/EHsc");
172 FS::Path obj_path = object.get_path();
173 FS::Path src_path = object.get_source().get_path();
174 FS::Path work_dir = object.get_component()->get_package().get_source_directory();
176 argv.push_back("/Fo"+relative(obj_path, work_dir).str());
177 argv.push_back(relative(src_path, work_dir).str());
179 return new ExternalTask(argv, work_dir);