Commit 2f8e5b9b authored by drbasic's avatar drbasic Committed by Commit bot

Setting "SubSystem" option on "Link" page for Visual Studio project.

When the debugger session in Visual Studio finished, the console window closed
by default. For console applications, such as unit tests, it is possible not to
close the console window immediately. This is controlled by the property
"SubSystem" on "Link" page in project settings. This patch set property
"SubSystem" in generated *.vcxproj file based on the "ldflags" field.

R=brettw@chromium.org
BUG=

Review-Url: https://chromiumcodereview.appspot.com/2428013002
Cr-Commit-Position: refs/heads/master@{#426977}
parent 9add242a
...@@ -4,13 +4,20 @@ ...@@ -4,13 +4,20 @@
#include "tools/gn/visual_studio_utils.h" #include "tools/gn/visual_studio_utils.h"
#include <vector>
#include "base/md5.h" #include "base/md5.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
CompilerOptions::CompilerOptions() = default; CompilerOptions::CompilerOptions() = default;
CompilerOptions::~CompilerOptions() = default; CompilerOptions::~CompilerOptions() = default;
LinkerOptions::LinkerOptions() = default;
LinkerOptions::~LinkerOptions() = default;
std::string MakeGuid(const std::string& entry_path, const std::string& seed) { std::string MakeGuid(const std::string& entry_path, const std::string& seed) {
std::string str = base::ToUpperASCII(base::MD5String(seed + entry_path)); std::string str = base::ToUpperASCII(base::MD5String(seed + entry_path));
return '{' + str.substr(0, 8) + '-' + str.substr(8, 4) + '-' + return '{' + str.substr(0, 8) + '-' + str.substr(8, 4) + '-' +
...@@ -115,3 +122,18 @@ void ParseCompilerOption(const std::string& cflag, CompilerOptions* options) { ...@@ -115,3 +122,18 @@ void ParseCompilerOption(const std::string& cflag, CompilerOptions* options) {
// Put everything else into additional_options. // Put everything else into additional_options.
options->additional_options += cflag + ' '; options->additional_options += cflag + ' ';
} }
// Parses |ldflags| value and stores it in |options|.
void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options) {
const char kSubsytemPrefix[] ="/SUBSYSTEM:";
if (base::StartsWith(ldflag, kSubsytemPrefix,
base::CompareCase::SENSITIVE)) {
const std::string subsystem(
ldflag.begin() + std::string(kSubsytemPrefix).length(),
ldflag.end());
const std::vector<std::string> tokens = base::SplitString(
subsystem, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (!tokens.empty())
options->subsystem = tokens[0];
}
}
...@@ -24,6 +24,16 @@ struct CompilerOptions { ...@@ -24,6 +24,16 @@ struct CompilerOptions {
std::string warning_level; std::string warning_level;
}; };
// Some linker options which will be written to project file. We don't need to
// specify all options because generated project file is going to be used only
// for compilation of single file. For real build ninja files are used.
struct LinkerOptions {
LinkerOptions();
~LinkerOptions();
std::string subsystem;
};
// Generates something which looks like a GUID, but depends only on the name and // Generates something which looks like a GUID, but depends only on the name and
// seed. This means the same name / seed will always generate the same GUID, so // seed. This means the same name / seed will always generate the same GUID, so
// that projects and solutions which refer to each other can explicitly // that projects and solutions which refer to each other can explicitly
...@@ -34,4 +44,7 @@ std::string MakeGuid(const std::string& entry_path, const std::string& seed); ...@@ -34,4 +44,7 @@ std::string MakeGuid(const std::string& entry_path, const std::string& seed);
// Parses |cflag| value and stores it in |options|. // Parses |cflag| value and stores it in |options|.
void ParseCompilerOption(const std::string& cflag, CompilerOptions* options); void ParseCompilerOption(const std::string& cflag, CompilerOptions* options);
// Parses |ldflags| value and stores it in |options|.
void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options);
#endif // TOOLS_GN_VISUAL_STUDIO_UTILS_H_ #endif // TOOLS_GN_VISUAL_STUDIO_UTILS_H_
...@@ -92,3 +92,12 @@ TEST(VisualStudioUtils, ParseCompilerOption) { ...@@ -92,3 +92,12 @@ TEST(VisualStudioUtils, ParseCompilerOption) {
ParseCompilerOption("/Zc:sizedDealloc", &options); ParseCompilerOption("/Zc:sizedDealloc", &options);
ASSERT_EQ("/MP /bigobj /Zc:sizedDealloc ", options.additional_options); ASSERT_EQ("/MP /bigobj /Zc:sizedDealloc ", options.additional_options);
} }
TEST(VisualStudioUtils, ParseLinkerOption) {
LinkerOptions options;
ParseLinkerOption("/SUBSYSTEM:CONSOLE,5.02h", &options);
ASSERT_EQ("CONSOLE", options.subsystem);
ParseLinkerOption("/SUBSYSTEM:WINDOWS", &options);
ASSERT_EQ("WINDOWS", options.subsystem);
}
...@@ -153,6 +153,18 @@ void ParseCompilerOptions(const Target* target, CompilerOptions* options) { ...@@ -153,6 +153,18 @@ void ParseCompilerOptions(const Target* target, CompilerOptions* options) {
} }
} }
void ParseLinkerOptions(const std::vector<std::string>& ldflags,
LinkerOptions* options) {
for (const std::string& flag : ldflags)
ParseLinkerOption(flag, options);
}
void ParseLinkerOptions(const Target* target, LinkerOptions* options) {
for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
ParseLinkerOptions(iter.cur().ldflags(), options);
}
}
// Returns a string piece pointing into the input string identifying the parent // Returns a string piece pointing into the input string identifying the parent
// directory path, excluding the last slash. Note that the input pointer must // directory path, excluding the last slash. Note that the input pointer must
// outlive the output. // outlive the output.
...@@ -539,8 +551,17 @@ bool VisualStudioWriter::WriteProjectFileContents( ...@@ -539,8 +551,17 @@ bool VisualStudioWriter::WriteProjectFileContents(
cl_compile->SubElement("WarningLevel")->Text(options.warning_level); cl_compile->SubElement("WarningLevel")->Text(options.warning_level);
} }
// We don't include resource compilation and link options as ninja files std::unique_ptr<XmlElementWriter> link =
// are used to generate real build. item_definitions->SubElement("Link");
{
LinkerOptions options;
ParseLinkerOptions(target, &options);
if (!options.subsystem.empty())
link->SubElement("SubSystem")->Text(options.subsystem);
}
// We don't include resource compilation and other link options as ninja
// files are used to generate real build.
} }
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment