File: CompilerLocatorMSVC.cpp

package info (click to toggle)
codelite 17.0.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 136,204 kB
  • sloc: cpp: 491,547; ansic: 280,393; php: 10,259; sh: 8,930; lisp: 7,664; vhdl: 6,518; python: 6,020; lex: 4,920; yacc: 3,123; perl: 2,385; javascript: 1,715; cs: 1,193; xml: 1,110; makefile: 804; cobol: 741; sql: 709; ruby: 620; f90: 566; ada: 534; asm: 464; fortran: 350; objc: 289; tcl: 258; java: 157; erlang: 61; pascal: 51; ml: 49; awk: 44; haskell: 36
file content (333 lines) | stat: -rw-r--r-- 15,469 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// copyright            : (C) 2014 Eran Ifrah
// file name            : CompilerLocatorMSVC.cpp
//
// -------------------------------------------------------------------------
// A
//              _____           _      _     _ _
//             /  __ \         | |    | |   (_) |
//             | /  \/ ___   __| | ___| |    _| |_ ___
//             | |    / _ \ / _  |/ _ \ |   | | __/ _ )
//             | \__/\ (_) | (_| |  __/ |___| | ||  __/
//              \____/\___/ \__,_|\___\_____/_|\__\___|
//
//                                                  F i l e
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

#include "CompilerLocatorMSVC.h"

#include "compiler.h"

#include <globals.h>
#include <wx/regex.h>

CompilerLocatorMSVC::CompilerLocatorMSVC()
{
    // We only deal with x86/x64 Native Tools here for simplicity
    // Other platforms (such as ARM64 Cross Tools) can be added manually by cloning the compiler
    m_vcPlatforms.Add("x86");
    m_vcPlatforms.Add("x64");
}

CompilerLocatorMSVC::~CompilerLocatorMSVC() {}

bool CompilerLocatorMSVC::Locate()
{
    m_compilers.clear();

    wxEnvVariableHashMap envvars;
    ::wxGetEnvMap(&envvars);

    for(wxEnvVariableHashMap::const_iterator it = envvars.begin(); it != envvars.end(); ++it) {
        wxString const& envvarName = it->first;
        wxString const& envvarPath = it->second;

        if(!envvarName.Matches("VS??*COMNTOOLS") || envvarPath.IsEmpty() || (envvarName.Find('C') < 3)) {
            continue;
        }

        wxString vcVersion = envvarName.Mid(2, envvarName.Find('C') - 3);
        for(size_t j = 0; j < m_vcPlatforms.GetCount(); ++j) {
            wxString compilerName = "Visual C++ " + vcVersion + " (" + m_vcPlatforms[j] + ")";
            AddToolsVC2005(envvarPath, compilerName, m_vcPlatforms[j]);
        }
    }

    // Visual Studio 2017+ no longer sets the above environment variable on system-wide
    ScanUninstRegKeys();

    return !m_compilers.empty();
}

void CompilerLocatorMSVC::CheckUninstRegKey(const wxString& displayName, const wxString& installFolder,
                                            const wxString& displayVersion)
{
    static const wxRegEx reName("^Visual Studio (Community|Professional|Enterprise) ([0-9]{4})( (Current|Preview))?$"),
        reVersion("^([0-9]+).*$");
    if(reName.Matches(displayName) && reVersion.Matches(displayVersion)) {
        wxString vcEdition = reName.GetMatch(displayName, 1);
        wxString vcChannel = reName.GetMatch(displayName, 4);
        wxString vcVersion = reVersion.GetMatch(displayVersion, 1);
        long lvcVersion;
        if(!vcVersion.ToLong(&lvcVersion) || lvcVersion < 15) {
            // This detection is valid for Visual Studio 2017 (version 15)+ only
            return;
        }
        for(size_t i = 0; i < m_vcPlatforms.GetCount(); ++i) {
            wxString compilerName = "Visual C++ ";
            compilerName << vcVersion << " " << vcEdition << " ";
            if(!vcChannel.IsEmpty() && vcChannel != "Current") {
                compilerName << vcChannel << " ";
            }
            compilerName << "(" << m_vcPlatforms[i] << ")";
            AddToolsVC2017(installFolder, compilerName, m_vcPlatforms[i]);
        }
    }
}

void CompilerLocatorMSVC::AddTools(const wxString& name, const wxString& platform, const wxFileName& installPath,
                                   const wxFileName& fnVCvars, const wxFileName& fnIdeFolder)
{
    CompilerPtr compiler(new Compiler(NULL, Compiler::kRegexVC));
    compiler->SetCompilerFamily(COMPILER_FAMILY_VC);
    compiler->SetName(name);
    compiler->SetInstallationPath(installPath.GetPath());

    // CXX
    AddTool("cl.exe", "/nologo /TP /FC", "CXX", compiler);

    // CC
    AddTool("cl.exe", "/nologo /TC /FC", "CC", compiler);

    // AR
    AddTool("lib.exe", "/nologo", "AR", compiler);

    // SharedObjectLinkerName
    AddTool("link.exe", "/nologo /DLL", "SharedObjectLinkerName", compiler);

    // LinkerName
    AddTool("link.exe", "/nologo", "LinkerName", compiler);

    // AS
    AddTool("ml.exe", "/nologo", "AS", compiler);

    // Resource
    AddTool("rc.exe", "/nologo", "ResourceCompiler", compiler);
    compiler->AddCmpFileType("rc", Compiler::CmpFileKindResource,
                             "$(RcCompilerName) $(RcCmpOptions) "
                             "$(ObjectSwitch)$(IntermediateDirectory)/"
                             "$(ObjectName)$(ObjectSuffix) $(RcIncludePath) \"$(FileFullPath)\"");

    // Make
    wxString vcVarsArgs = platform + " > nul";
    AddTool(fnVCvars.GetFullPath(), vcVarsArgs + " && nmake.exe /nologo", "MAKE", compiler);

    compiler->SetSwitch("ArchiveOutput", "/OUT:");
    compiler->SetSwitch("Debug", "/Zi ");
    compiler->SetSwitch("Include", "/I");
    compiler->SetSwitch("Library", " ");
    compiler->SetSwitch("LibraryPath", "/LIBPATH:");
    compiler->SetSwitch("Object", "/Fo");
    compiler->SetSwitch("Output", "/OUT:");
    compiler->SetSwitch("PreprocessOnly", "/P /Fi:");
    compiler->SetSwitch("Preprocessor", "/D");
    compiler->SetSwitch("Source", "");
    compiler->SetObjectSuffix(".obj");

    // IDE path
    compiler->SetPathVariable(fnIdeFolder.GetPath() + ";$PATH");

    // include and lib path, check if cl.exe exists
    wxString vcVarsCmd = fnVCvars.GetFullPath();
    WrapWithQuotes(vcVarsCmd);
    wxString command = "CMD.EXE /V:ON /C ";
    command << vcVarsCmd << " " << vcVarsArgs << " & echo !INCLUDE! & echo !LIB! & where cl.exe";

    wxArrayString output;
    wxArrayString errors;
    wxExecute(command, output, errors);

    if(output.size() >= 2) {
        wxString includePath = output[0];
        if(includePath.Trim().Trim(false) != "!INCLUDE!") {
            compiler->SetGlobalIncludePath(includePath);
        }

        wxString libPath = output[1];
        if(libPath.Trim().Trim(false) != "!LIB!") {
            compiler->SetGlobalLibPath(libPath);
        }
    }

    AddCompilerOptions(compiler);
    AddLinkerOptions(compiler);

    // cl.exe exists
    if(errors.IsEmpty()) {
        m_compilers.push_back(compiler);
    }
}

// For Visual Studio 2005 and up to 2015
void CompilerLocatorMSVC::AddToolsVC2005(const wxString& masterFolder, const wxString& name, const wxString& platform)
{
    wxFileName installPath(masterFolder, "");
    installPath.RemoveLastDir();
    installPath.RemoveLastDir();

    wxFileName fnVCvars(installPath);
    fnVCvars.AppendDir("VC");
    fnVCvars.SetFullName("vcvarsall.bat");

    wxFileName fnIdeFolder(masterFolder, "");
    fnIdeFolder.RemoveLastDir();
    fnIdeFolder.AppendDir("IDE");

    AddTools(name, platform, installPath, fnVCvars, fnIdeFolder);
}

// For Visual Studio 2017 or above
void CompilerLocatorMSVC::AddToolsVC2017(const wxString& masterFolder, const wxString& name, const wxString& platform)
{
    wxFileName installPath(masterFolder, "");

    wxFileName fnVCvars(installPath);
    fnVCvars.AppendDir("VC");
    fnVCvars.AppendDir("Auxiliary");
    fnVCvars.AppendDir("Build");
    fnVCvars.SetFullName("vcvarsall.bat");

    wxFileName fnIdeFolder(masterFolder, "");
    fnIdeFolder.AppendDir("Common7");
    fnIdeFolder.AppendDir("IDE");

    AddTools(name, platform, installPath, fnVCvars, fnIdeFolder);
}

void CompilerLocatorMSVC::AddTool(const wxString& toolpath, const wxString& extraArgs, const wxString& toolname,
                                  CompilerPtr compiler)
{
    wxString tool = toolpath;
    ::WrapWithQuotes(tool);

    if(!extraArgs.IsEmpty()) {
        tool << " " << extraArgs;
    }
    compiler->SetTool(toolname, tool);
}

void CompilerLocatorMSVC::AddCompilerOptions(CompilerPtr compiler)
{
    compiler->AddCompilerOption("/c", "Compiles without linking");
    compiler->AddCompilerOption(
        "/MD",
        "Causes the application to use the multithread-specific and DLL-specific version of the run-time library");
    compiler->AddCompilerOption("/MDd", "Causes the application to use the debug multithread-specific and DLL-specific "
                                        "version of the run-time library");
    compiler->AddCompilerOption(
        "/MT", "Causes the application to use the multithread, static version of the run-time library");
    compiler->AddCompilerOption(
        "/MTd", "Causes the application to use the debug multithread, static version of the run-time library");

    compiler->AddCompilerOption("/O1", "Creates small code");
    compiler->AddCompilerOption("/O2", "Creates fast code");
    compiler->AddCompilerOption("/Od", "Disables optimization");
    compiler->AddCompilerOption("/Ox", "Uses maximum optimization");
    compiler->AddCompilerOption("/Oi", "Generates intrinsic functions");

    compiler->AddCompilerOption("/MP", "Compiles multiple source files by using multiple processes");
    compiler->AddCompilerOption("/sdl", "Enables additional security features and warnings");
    compiler->AddCompilerOption("/errorReport:none",
                                "Reports about internal compiler errors will not be collected or sent to Microsoft");
    compiler->AddCompilerOption("/errorReport:prompt",
                                "Prompts you to send a report when you receive an internal compiler error");
    compiler->AddCompilerOption(
        "/FS", "Forces writes to the program database (PDB) file to be serialized through MSPDBSRV.EXE");
    compiler->AddCompilerOption("/Zs", "Checks syntax only");
    compiler->AddCompilerOption("/GA", "Optimizes code for Windows application");
    compiler->AddCompilerOption("/GL", "Enables whole program optimization");
    compiler->AddCompilerOption("/Gm", "Enables minimal rebuild");
    compiler->AddCompilerOption("/Gy", "Enables function-level linking");
    compiler->AddCompilerOption("/EHa", "Enable C++ Exceptions with SEH exception");
    compiler->AddCompilerOption("/EHs", "Enable C++ Exceptions with Extern C functions");
    compiler->AddCompilerOption("/EHsc", "Enable C++ Exceptions with SEH and Extern C functions");

    compiler->AddCompilerOption(
        "/Z7", "Produces an .obj file containing full symbolic debugging information for use with the debugger");
    compiler->AddCompilerOption("/Zi", "Produces a program database (PDB) that contains type information and symbolic "
                                       "debugging information for use with the debugger");
    compiler->AddCompilerOption(
        "/ZI",
        "Produces a program database, as described above, in a format that supports the Edit and Continue feature");

    compiler->AddCompilerOption("/w", "Disables all compiler warnings");
    compiler->AddCompilerOption("/W0", "Disables all warnings");
    compiler->AddCompilerOption("/W1", "Displays level 1 (severe) warnings");
    compiler->AddCompilerOption("/W2", "Displays level 1 and level 2 (significant) warnings");
    compiler->AddCompilerOption("/W3", "Displays level 1, level 2 and level 3 (production quality) warnings");
    compiler->AddCompilerOption("/W4", "Displays level 1, level 2, and level 3 warnings, and all level 4 "
                                       "(informational) warnings that are not turned off by default");
    compiler->AddCompilerOption(
        "/Wall", "Displays all warnings displayed by /W4 and all other warnings that /W4 does not include");
    compiler->AddCompilerOption("/WX", "Treats all compiler warnings as errors");

    compiler->AddCompilerOption("/std:c11", "Enable C11 features");
    compiler->AddCompilerOption("/std:c++14", "Enable C++14 features");
    compiler->AddCompilerOption("/std:c++17", "Enable C++17 features");
    compiler->AddCompilerOption("/std:c++20", "Enable C++20 features");
    compiler->AddCompilerOption("/std:c++latest", "Enable latest C++ features");
}

void CompilerLocatorMSVC::AddLinkerOptions(CompilerPtr compiler)
{
    compiler->AddLinkerOption("/DEBUG", "Creates debugging information");
    compiler->AddLinkerOption("/DYNAMICBASE", "Use address space layout randomization");
    compiler->AddLinkerOption("/DYNAMICBASE:NO", "Don't use address space layout randomizatio");
    compiler->AddLinkerOption("/ERRORREPORT:NONE",
                              "Reports about internal compiler errors will not be collected or sent to Microsoft");
    compiler->AddLinkerOption("/ERRORREPORT:PROMPT",
                              "Prompts you to send a report when you receive an internal compiler error");
    compiler->AddLinkerOption("/INCREMENTAL", "Enables incremental linking");
    compiler->AddLinkerOption("/INCREMENTAL:NO", "Disables incremental linking");
    compiler->AddLinkerOption("/LARGEADDRESSAWARE",
                              "Tells the compiler that the application supports addresses larger than two gigabytes");
    compiler->AddLinkerOption(
        "/LARGEADDRESSAWARE:NO",
        "Tells the compiler that the application does not support addresses larger than two gigabytes");

    compiler->AddLinkerOption("/LTCG:INCREMENTAL", "Specifies link-time code generation");
    compiler->AddLinkerOption("/LTCG:STATUS", "Specifies link-time code generation");
    compiler->AddLinkerOption("/LTCG:NOSTATUS", "Specifies link-time code generation");
    compiler->AddLinkerOption("/LTCG:OFF", "Specifies link-time code generation");
    compiler->AddLinkerOption("/MACHINE:X64", "Specifies the target platform");
    compiler->AddLinkerOption("/MACHINE:X86", "Specifies the target platform");
    compiler->AddLinkerOption("/NOENTRY", "Creates a resource-only DLL");
    compiler->AddLinkerOption("/NXCOMPAT", "Specify Compatibility with Data Execution Prevention");
    compiler->AddLinkerOption("/NXCOMPAT:NO", "Specify Compatibility with Data Execution Prevention");

    compiler->AddLinkerOption("/OPT:REF", "Controls LINK optimizations");
    compiler->AddLinkerOption("/OPT:NOREF", "Controls LINK optimizations");
    compiler->AddLinkerOption("/OPT:ICF", "Controls LINK optimizations");
    compiler->AddLinkerOption("/OPT:NOICF", "Controls LINK optimizations");
    compiler->AddLinkerOption("/OPT:LBR", "Controls LINK optimizations");
    compiler->AddLinkerOption("/OPT:NOLBR", "Controls LINK optimizations");

    compiler->AddLinkerOption("/PROFILE",
                              "Produces an output file that can be used with the Performance Tools profiler");
    compiler->AddLinkerOption("/SAFESEH", "Image has Safe Exception Handlers");
    compiler->AddLinkerOption("/SAFESEH:NO", "Image does not have Safe Exception Handler");
    compiler->AddLinkerOption("/SUBSYSTEM:CONSOLE", "Tells the operating system how to run the .exe file");
    compiler->AddLinkerOption("/SUBSYSTEM:WINDOWS", "Tells the operating system how to run the .exe file");
    compiler->AddLinkerOption("/VERBOSE", "Prints linker progress messages");
    compiler->AddLinkerOption("/WX", "Treats linker warnings as errors");
    compiler->AddLinkerOption("/WX:NO", "Do not treats linker warnings as errors");
}