1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gn/visual_studio_utils.h"
6 
7 #include <vector>
8 
9 #include "base/md5.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 
13 CompilerOptions::CompilerOptions() = default;
14 
15 CompilerOptions::~CompilerOptions() = default;
16 
17 LinkerOptions::LinkerOptions() = default;
18 
19 LinkerOptions::~LinkerOptions() = default;
20 
MakeGuid(const std::string & entry_path,const std::string & seed)21 std::string MakeGuid(const std::string& entry_path, const std::string& seed) {
22   std::string str = base::ToUpperASCII(base::MD5String(seed + entry_path));
23   return '{' + str.substr(0, 8) + '-' + str.substr(8, 4) + '-' +
24          str.substr(12, 4) + '-' + str.substr(16, 4) + '-' +
25          str.substr(20, 12) + '}';
26 }
27 
28 #define SetOption(condition, member, value) \
29   if (condition) {                          \
30     options->member = value;                \
31     return;                                 \
32   }
33 
34 #define AppendOption(condition, member, value, separator) \
35   if (condition) {                                        \
36     options->member += value + separator;                 \
37     return;                                               \
38   }
39 
ParseCompilerOption(const std::string & cflag,CompilerOptions * options)40 void ParseCompilerOption(const std::string& cflag, CompilerOptions* options) {
41   if (cflag.size() > 2 && cflag[0] == '/') {
42     switch (cflag[1]) {
43       case 'F':
44         AppendOption(cflag.size() > 3 && cflag[2] == 'I', forced_include_files,
45                      cflag.substr(3), ';') break;
46 
47       case 'G':
48         if (cflag[2] == 'S') {
49           SetOption(cflag.size() == 3, buffer_security_check, "true")
50               SetOption(cflag.size() == 4 && cflag[3] == '-',
51                         buffer_security_check, "false")
52         }
53         break;
54 
55       case 'M':
56         switch (cflag[2]) {
57           case 'D':
58             SetOption(cflag.size() == 3, runtime_library, "MultiThreadedDLL")
59                 SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library,
60                           "MultiThreadedDebugDLL") break;
61 
62           case 'T':
63             SetOption(cflag.size() == 3, runtime_library, "MultiThreaded")
64                 SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library,
65                           "MultiThreadedDebug") break;
66         }
67         break;
68 
69       case 'O':
70         switch (cflag[2]) {
71           case '1':
72             SetOption(cflag.size() == 3, optimization, "MinSpace") break;
73 
74           case '2':
75             SetOption(cflag.size() == 3, optimization, "MaxSpeed") break;
76 
77           case 'd':
78             SetOption(cflag.size() == 3, optimization, "Disabled") break;
79 
80           case 'x':
81             SetOption(cflag.size() == 3, optimization, "Full") break;
82         }
83         break;
84 
85       case 'T':
86         // Skip flags that cause treating all source files as C and C++ files.
87         if (cflag.size() == 3 && (cflag[2] == 'C' || cflag[2] == 'P'))
88           return;
89         break;
90 
91       case 'W':
92         switch (cflag[2]) {
93           case '0':
94           case '1':
95           case '2':
96           case '3':
97           case '4':
98             SetOption(cflag.size() == 3, warning_level,
99                       std::string("Level") + cflag[2]) break;
100 
101           case 'X':
102             SetOption(cflag.size() == 3, treat_warning_as_error, "true") break;
103         }
104         break;
105 
106       case 'w':
107         AppendOption(cflag.size() > 3 && cflag[2] == 'd',
108                      disable_specific_warnings, cflag.substr(3), ';') break;
109     }
110   }
111 
112   // Put everything else into additional_options.
113   options->additional_options += cflag + ' ';
114 }
115 
116 // Parses |ldflags| value and stores it in |options|.
ParseLinkerOption(const std::string & ldflag,LinkerOptions * options)117 void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options) {
118   const char kSubsytemPrefix[] = "/SUBSYSTEM:";
119   if (base::StartsWith(ldflag, kSubsytemPrefix, base::CompareCase::SENSITIVE)) {
120     const std::string subsystem(
121         ldflag.begin() + std::string(kSubsytemPrefix).length(), ldflag.end());
122     const std::vector<std::string> tokens = base::SplitString(
123         subsystem, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
124     if (!tokens.empty())
125       options->subsystem = tokens[0];
126   }
127 }
128