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