| // Copyright 2017 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "src/main/cpp/option_processor.h" |
| |
| #include "src/main/cpp/blaze_util.h" |
| #include "src/main/cpp/blaze_util_platform.h" |
| #include "src/main/cpp/option_processor-internal.h" |
| #include "src/main/cpp/util/file.h" |
| #include "src/main/cpp/util/file_platform.h" |
| #include "src/main/cpp/workspace_layout.h" |
| #include "gtest/gtest.h" |
| #include "re2/re2.h" |
| |
| namespace blaze { |
| |
| class OptionProcessorTest : public ::testing::Test { |
| protected: |
| OptionProcessorTest() : |
| workspace_( |
| blaze_util::JoinPath(blaze::GetEnv("TEST_TMPDIR"), "testdir")), |
| cwd_("cwd"), |
| workspace_layout_(new WorkspaceLayout()) {} |
| |
| ~OptionProcessorTest() override {} |
| |
| void SetUp() override { |
| ASSERT_TRUE(blaze_util::MakeDirectories(workspace_, 0755)); |
| option_processor_.reset(new OptionProcessor( |
| workspace_layout_.get(), |
| std::unique_ptr<StartupOptions>( |
| new StartupOptions(workspace_layout_.get())))); |
| } |
| |
| void TearDown() override { |
| // TODO(bazel-team): The code below deletes all the files in the workspace |
| // but it intentionally skips directories. As a consequence, there may be |
| // empty directories from test to test. Remove this once |
| // blaze_util::DeleteDirectories(path) exists. |
| std::vector<std::string> files_in_workspace; |
| blaze_util::GetAllFilesUnder(workspace_, &files_in_workspace); |
| for (const std::string& file : files_in_workspace) { |
| blaze_util::UnlinkPath(file); |
| } |
| } |
| |
| void FailedSplitStartupOptionsTest(const std::vector<std::string>& args, |
| const std::string& expected_error) const { |
| std::string error; |
| const std::unique_ptr<CommandLine> result = |
| option_processor_->SplitCommandLine(args, &error); |
| ASSERT_EQ(expected_error, error); |
| ASSERT_EQ(nullptr, result); |
| } |
| |
| void SuccessfulSplitStartupOptionsTest(const std::vector<std::string>& args, |
| const CommandLine& expected) const { |
| std::string error; |
| const std::unique_ptr<CommandLine> result = |
| option_processor_->SplitCommandLine(args, &error); |
| |
| ASSERT_EQ("", error); |
| EXPECT_EQ(expected.path_to_binary, result->path_to_binary); |
| EXPECT_EQ(expected.startup_args, result->startup_args); |
| EXPECT_EQ(expected.command, result->command); |
| EXPECT_EQ(expected.command_args, result->command_args); |
| } |
| |
| const std::string workspace_; |
| const std::string cwd_; |
| const std::unique_ptr<WorkspaceLayout> workspace_layout_; |
| std::unique_ptr<OptionProcessor> option_processor_; |
| }; |
| |
| TEST_F(OptionProcessorTest, CanParseOptions) { |
| const std::vector<std::string> args = |
| {"bazel", |
| "--host_jvm_args=MyParam", "--nobatch", |
| "command", |
| "--flag", "//my:target", "--flag2=42"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| ASSERT_EQ("", error); |
| ASSERT_EQ(1, |
| option_processor_->GetParsedStartupOptions()->host_jvm_args.size()); |
| EXPECT_EQ("MyParam", |
| option_processor_->GetParsedStartupOptions()->host_jvm_args[0]); |
| EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch); |
| |
| EXPECT_EQ("command", option_processor_->GetCommand()); |
| |
| EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}), |
| option_processor_->GetExplicitCommandArguments()); |
| } |
| |
| TEST_F(OptionProcessorTest, CanParseHelpArgs) { |
| const std::vector<std::string> args = |
| {"bazel", |
| "--host_jvm_args=MyParam", "--nobatch", |
| "help", |
| "--flag", "//my:target", "--flag2=42"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| ASSERT_EQ("", error); |
| ASSERT_EQ(1, |
| option_processor_->GetParsedStartupOptions()->host_jvm_args.size()); |
| EXPECT_EQ("MyParam", |
| option_processor_->GetParsedStartupOptions()->host_jvm_args[0]); |
| EXPECT_FALSE(option_processor_->GetParsedStartupOptions()->batch); |
| |
| EXPECT_EQ("help", option_processor_->GetCommand()); |
| |
| EXPECT_EQ(std::vector<std::string>({"--flag", "//my:target", "--flag2=42"}), |
| option_processor_->GetExplicitCommandArguments()); |
| } |
| |
| TEST_F(OptionProcessorTest, CanParseEmptyArgs) { |
| const std::vector<std::string> args = {"bazel"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| ASSERT_EQ("", error); |
| |
| EXPECT_EQ("", option_processor_->GetCommand()); |
| |
| EXPECT_EQ(std::vector<std::string>({}), |
| option_processor_->GetExplicitCommandArguments()); |
| } |
| |
| TEST_F(OptionProcessorTest, CanParseDifferentStartupArgs) { |
| const std::vector<std::string> args = |
| {"bazel", |
| "--nobatch", "--host_jvm_args=MyParam", "--host_jvm_args", "42"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| ASSERT_EQ("", error); |
| |
| ASSERT_EQ(2, |
| option_processor_->GetParsedStartupOptions()->host_jvm_args.size()); |
| EXPECT_EQ("MyParam", |
| option_processor_->GetParsedStartupOptions()->host_jvm_args[0]); |
| EXPECT_EQ("42", |
| option_processor_->GetParsedStartupOptions()->host_jvm_args[1]); |
| |
| EXPECT_EQ("", option_processor_->GetCommand()); |
| |
| EXPECT_EQ(std::vector<std::string>({}), |
| option_processor_->GetExplicitCommandArguments()); |
| } |
| |
| TEST_F(OptionProcessorTest, CommandLineBazelrcTest) { |
| const std::string cmdline_rc_path = |
| blaze_util::JoinPath(workspace_, "mybazelrc"); |
| ASSERT_TRUE(blaze_util::MakeDirectories( |
| blaze_util::Dirname(cmdline_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("startup --foo", cmdline_rc_path, 0755)); |
| |
| const std::vector<std::string> args = |
| {"bazel", "--bazelrc=" + cmdline_rc_path, "build"}; |
| const std::string expected_error = |
| "Unknown startup option: '--foo'.\n" |
| " For more info, run 'bazel help startup_options'."; |
| std::string error; |
| ASSERT_NE(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| ASSERT_EQ(expected_error, error); |
| |
| // Check that the startup option option provenance message prints the correct |
| // information for the incorrect flag, and does not print the command-line |
| // provided startup flags. |
| testing::internal::CaptureStderr(); |
| option_processor_->PrintStartupOptionsProvenanceMessage(); |
| const std::string& output = testing::internal::GetCapturedStderr(); |
| |
| EXPECT_PRED1( |
| [](std::string actualOutput) { |
| return RE2::FullMatch( |
| actualOutput, |
| "INFO: Reading 'startup' options from .*mybazelrc: " |
| "--foo\n"); |
| }, |
| output); |
| } |
| |
| TEST_F(OptionProcessorTest, NoMasterBazelrcAndBazelrcWorkTogetherCorrectly) { |
| const std::string cmdline_rc_path = |
| blaze_util::JoinPath(workspace_, "mybazelrc"); |
| ASSERT_TRUE(blaze_util::MakeDirectories( |
| blaze_util::Dirname(cmdline_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("startup --max_idle_secs=123", |
| cmdline_rc_path, 0755)); |
| |
| const std::string master_rc_path = |
| blaze_util::JoinPath(workspace_, "tools/bazel.rc"); |
| ASSERT_TRUE(blaze_util::MakeDirectories( |
| blaze_util::Dirname(master_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("startup --foo", master_rc_path, 0755)); |
| |
| const std::vector<std::string> args = |
| {"bazel", |
| "--bazelrc=" + cmdline_rc_path, "--nomaster_bazelrc", |
| "build"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| EXPECT_EQ(123, option_processor_->GetParsedStartupOptions()->max_idle_secs); |
| |
| // Check that the startup option option provenance message prints the correct |
| // information for the provided rc, and prints nothing for the master bazelrc. |
| testing::internal::CaptureStderr(); |
| option_processor_->PrintStartupOptionsProvenanceMessage(); |
| const std::string& output = testing::internal::GetCapturedStderr(); |
| |
| EXPECT_PRED1( |
| [](std::string actualOutput) { |
| return RE2::FullMatch( |
| actualOutput, |
| "INFO: Reading 'startup' options from .*mybazelrc: " |
| "--max_idle_secs=123\n"); |
| }, |
| output); |
| } |
| |
| TEST_F(OptionProcessorTest, MultipleStartupArgsInMasterBazelrcWorksCorrectly) { |
| // Add startup flags to the master bazelrc. |
| const std::string master_rc_path = |
| blaze_util::JoinPath(workspace_, "tools/bazel.rc"); |
| ASSERT_TRUE( |
| blaze_util::MakeDirectories(blaze_util::Dirname(master_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile( |
| "startup --max_idle_secs=42\nstartup --io_nice_level=6", master_rc_path, |
| 0755)); |
| |
| const std::vector<std::string> args = {"bazel", "build"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| EXPECT_EQ(42, option_processor_->GetParsedStartupOptions()->max_idle_secs); |
| EXPECT_EQ(6, option_processor_->GetParsedStartupOptions()->io_nice_level); |
| |
| // Check that the startup options get grouped together properly in the output |
| // message. |
| testing::internal::CaptureStderr(); |
| option_processor_->PrintStartupOptionsProvenanceMessage(); |
| const std::string& output = testing::internal::GetCapturedStderr(); |
| |
| EXPECT_PRED1( |
| [](std::string actualOutput) { |
| return RE2::FullMatch( |
| actualOutput, |
| "INFO: Reading 'startup' options from .*tools.*bazel.rc: " |
| "--max_idle_secs=42 --io_nice_level=6\n"); |
| }, |
| output); |
| } |
| |
| TEST_F(OptionProcessorTest, CustomBazelrcOverridesMasterBazelrc) { |
| // Add startup flags to the master bazelrc. |
| const std::string master_rc_path = |
| blaze_util::JoinPath(workspace_, "tools/bazel.rc"); |
| ASSERT_TRUE( |
| blaze_util::MakeDirectories(blaze_util::Dirname(master_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile( |
| "startup --max_idle_secs=42\nstartup --io_nice_level=6", master_rc_path, |
| 0755)); |
| |
| // Override one of the master bazelrc's flags in the custom bazelrc. |
| const std::string cmdline_rc_path = |
| blaze_util::JoinPath(workspace_, "mybazelrc"); |
| ASSERT_TRUE( |
| blaze_util::MakeDirectories(blaze_util::Dirname(cmdline_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("startup --max_idle_secs=123", |
| cmdline_rc_path, 0755)); |
| const std::vector<std::string> args = { |
| "bazel", "--bazelrc=" + cmdline_rc_path, "build"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| EXPECT_EQ(123, option_processor_->GetParsedStartupOptions()->max_idle_secs); |
| EXPECT_EQ(6, option_processor_->GetParsedStartupOptions()->io_nice_level); |
| |
| // Check that the options are reported in the correct order in the provenance |
| // message. |
| testing::internal::CaptureStderr(); |
| option_processor_->PrintStartupOptionsProvenanceMessage(); |
| const std::string& output = testing::internal::GetCapturedStderr(); |
| |
| EXPECT_PRED1( |
| [](std::string actualOutput) { |
| return RE2::FullMatch( |
| actualOutput, |
| "INFO: Reading 'startup' options from .*tools.*bazel.rc: " |
| "--max_idle_secs=42 --io_nice_level=6\n" |
| "INFO: Reading 'startup' options from .*mybazelrc: " |
| "--max_idle_secs=123\n"); |
| }, |
| output); |
| } |
| |
| TEST_F(OptionProcessorTest, BazelRcImportsMaintainsFlagOrdering) { |
| // Override one of the master bazelrc's flags in the custom bazelrc. |
| const std::string imported_rc_path = |
| blaze_util::JoinPath(workspace_, "myimportedbazelrc"); |
| ASSERT_TRUE( |
| blaze_util::MakeDirectories(blaze_util::Dirname(imported_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile( |
| "startup --max_idle_secs=123\nstartup --io_nice_level=4", |
| imported_rc_path, 0755)); |
| |
| // Add startup flags the imported bazelrc. |
| const std::string master_rc_path = |
| blaze_util::JoinPath(workspace_, "tools/bazel.rc"); |
| ASSERT_TRUE( |
| blaze_util::MakeDirectories(blaze_util::Dirname(master_rc_path), 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("startup --max_idle_secs=42\nimport " + |
| imported_rc_path + |
| "\nstartup --io_nice_level=6", |
| master_rc_path, 0755)); |
| |
| const std::vector<std::string> args = {"bazel", "build"}; |
| std::string error; |
| ASSERT_EQ(blaze_exit_code::SUCCESS, |
| option_processor_->ParseOptions(args, workspace_, cwd_, &error)) |
| << error; |
| |
| EXPECT_EQ(123, option_processor_->GetParsedStartupOptions()->max_idle_secs); |
| EXPECT_EQ(6, option_processor_->GetParsedStartupOptions()->io_nice_level); |
| |
| // Check that the options are reported in the correct order in the provenance |
| // message, the imported file between the two master flags |
| testing::internal::CaptureStderr(); |
| option_processor_->PrintStartupOptionsProvenanceMessage(); |
| const std::string& output = testing::internal::GetCapturedStderr(); |
| |
| EXPECT_PRED1( |
| [](std::string actualOutput) { |
| return RE2::FullMatch( |
| actualOutput, |
| "INFO: Reading 'startup' options from .*tools.*bazel.rc: " |
| "--max_idle_secs=42\n" |
| "INFO: Reading 'startup' options from .*myimportedbazelrc: " |
| "--max_idle_secs=123 --io_nice_level=4\n" |
| "INFO: Reading 'startup' options from .*tools.*bazel.rc: " |
| "--io_nice_level=6\n"); |
| }, |
| output); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithEmptyArgs) { |
| FailedSplitStartupOptionsTest( |
| {}, |
| "Unable to split command line, args is empty"); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithAllParams) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--nomaster_bazelrc", "build", "--bar", ":mytarget"}, |
| CommandLine("bazel", |
| {"--nomaster_bazelrc"}, |
| "build", |
| {"--bar", ":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithAbsolutePathToBinary) { |
| SuccessfulSplitStartupOptionsTest( |
| {"mybazel", "build", ":mytarget"}, |
| CommandLine("mybazel", {}, "build", {":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithUnaryStartupWithEquals) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--bazelrc=foo", "build", ":mytarget"}, |
| CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, |
| SplitCommandLineWithUnaryStartupWithoutEquals) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--bazelrc", "foo", "build", ":mytarget"}, |
| CommandLine("bazel", {"--bazelrc=foo"}, "build", {":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithIncompleteUnaryOption) { |
| FailedSplitStartupOptionsTest( |
| {"bazel", "--bazelrc"}, |
| "Startup option '--bazelrc' expects a value.\n" |
| "Usage: '--bazelrc=somevalue' or '--bazelrc somevalue'.\n" |
| " For more info, run 'bazel help startup_options'."); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleStartup) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--bazelrc", "foo", "--nomaster_bazelrc", "build", ":mytarget"}, |
| CommandLine("bazel", |
| {"--bazelrc=foo", "--nomaster_bazelrc"}, |
| "build", |
| {":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithNoStartupArgs) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "build", ":mytarget"}, |
| CommandLine("bazel", {}, "build", {":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithNoCommandArgs) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "build"}, |
| CommandLine("bazel", {}, "build", {})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeHelp) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "help"}, |
| CommandLine("bazel", {}, "help", {})); |
| |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "-h"}, |
| CommandLine("bazel", {}, "-h", {})); |
| |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "-help"}, |
| CommandLine("bazel", {}, "-help", {})); |
| |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--help"}, |
| CommandLine("bazel", {}, "--help", {})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithBlazeVersion) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "version"}, |
| CommandLine("bazel", {}, "version", {})); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithMultipleCommandArgs) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "build", "--foo", "-s", ":mytarget"}, |
| CommandLine("bazel", {}, "build", {"--foo", "-s", ":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, |
| SplitCommandLineFailsWithDashDashInStartupArgs) { |
| FailedSplitStartupOptionsTest( |
| {"bazel", "--"}, |
| "Unknown startup option: '--'.\n" |
| " For more info, run 'bazel help startup_options'."); |
| } |
| |
| TEST_F(OptionProcessorTest, SplitCommandLineWithDashDash) { |
| SuccessfulSplitStartupOptionsTest( |
| {"bazel", "--nomaster_bazelrc", "build", "--b", "--", ":mytarget"}, |
| CommandLine("bazel", |
| {"--nomaster_bazelrc"}, |
| "build", |
| {"--b", "--", ":mytarget"})); |
| } |
| |
| TEST_F(OptionProcessorTest, TestDedupePathsOmitsInvalidPath) { |
| std::vector<std::string> input = {"foo"}; |
| std::vector<std::string> expected = {}; |
| ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); |
| } |
| |
| TEST_F(OptionProcessorTest, TestDedupePathsWithDifferentFiles) { |
| std::string foo_path = blaze_util::JoinPath(workspace_, "foo"); |
| std::string bar_path = blaze_util::JoinPath(workspace_, "bar"); |
| |
| ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path)); |
| ASSERT_TRUE(blaze_util::WriteFile("bar", bar_path)); |
| |
| std::vector<std::string> input = {foo_path, bar_path}; |
| ASSERT_EQ(input, internal::DedupeBlazercPaths(input)); |
| } |
| |
| TEST_F(OptionProcessorTest, TestDedupePathsWithSameFile) { |
| std::string foo_path = blaze_util::JoinPath(workspace_, "foo"); |
| |
| ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path)); |
| |
| std::vector<std::string> input = {foo_path, foo_path}; |
| std::vector<std::string> expected = {foo_path}; |
| ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); |
| } |
| |
| TEST_F(OptionProcessorTest, TestDedupePathsWithRelativePath) { |
| std::string dir(blaze_util::JoinPath(workspace_, "dir")); |
| std::string foo_path(blaze_util::JoinPath(dir, "foo")); |
| std::string relative_foo_path(blaze_util::JoinPath(dir, "../dir/foo")); |
| |
| ASSERT_TRUE(blaze_util::MakeDirectories(dir, 0755)); |
| ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path)); |
| |
| std::vector<std::string> input = {foo_path, relative_foo_path}; |
| std::vector<std::string> expected = {foo_path}; |
| ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); |
| } |
| |
| #if !defined(COMPILER_MSVC) && !defined(__CYGWIN__) |
| static bool Symlink(const std::string& old_path, const std::string& new_path) { |
| return symlink(old_path.c_str(), new_path.c_str()) == 0; |
| } |
| |
| TEST_F(OptionProcessorTest, TestDedupePathsWithSymbolicLink) { |
| std::string foo_path = blaze_util::JoinPath(workspace_, "foo"); |
| std::string sym_foo_path = blaze_util::JoinPath(workspace_, "sym_foo"); |
| |
| ASSERT_TRUE(blaze_util::WriteFile("foo", foo_path)); |
| ASSERT_TRUE(Symlink(foo_path, sym_foo_path)); |
| std::vector<std::string> input = {foo_path, sym_foo_path}; |
| std::vector<std::string> expected = {foo_path}; |
| ASSERT_EQ(expected, internal::DedupeBlazercPaths(input)); |
| } |
| #endif // !defined(COMPILER_MSVC) && !defined(__CYGWIN__) |
| |
| } // namespace blaze |