1// Copyright (c) 2013 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 "testing/gtest/include/gtest/gtest.h" 6#include "tools/gn/build_settings.h" 7#include "tools/gn/config.h" 8#include "tools/gn/settings.h" 9#include "tools/gn/target.h" 10#include "tools/gn/test_with_scope.h" 11#include "tools/gn/toolchain.h" 12 13// Tests that lib[_dir]s are inherited across deps boundaries for static 14// libraries but not executables. 15TEST(Target, LibInheritance) { 16 TestWithScope setup; 17 Err err; 18 19 const std::string lib("foo"); 20 const SourceDir libdir("/foo_dir/"); 21 22 // Leaf target with ldflags set. 23 Target z(setup.settings(), Label(SourceDir("//foo/"), "z")); 24 z.set_output_type(Target::STATIC_LIBRARY); 25 z.config_values().libs().push_back(lib); 26 z.config_values().lib_dirs().push_back(libdir); 27 z.visibility().SetPublic(); 28 z.SetToolchain(setup.toolchain()); 29 ASSERT_TRUE(z.OnResolved(&err)); 30 31 // All lib[_dir]s should be set when target is resolved. 32 ASSERT_EQ(1u, z.all_libs().size()); 33 EXPECT_EQ(lib, z.all_libs()[0]); 34 ASSERT_EQ(1u, z.all_lib_dirs().size()); 35 EXPECT_EQ(libdir, z.all_lib_dirs()[0]); 36 37 // Shared library target should inherit the libs from the static library 38 // and its own. Its own flag should be before the inherited one. 39 const std::string second_lib("bar"); 40 const SourceDir second_libdir("/bar_dir/"); 41 Target shared(setup.settings(), Label(SourceDir("//foo/"), "shared")); 42 shared.set_output_type(Target::SHARED_LIBRARY); 43 shared.config_values().libs().push_back(second_lib); 44 shared.config_values().lib_dirs().push_back(second_libdir); 45 shared.private_deps().push_back(LabelTargetPair(&z)); 46 shared.visibility().SetPublic(); 47 shared.SetToolchain(setup.toolchain()); 48 ASSERT_TRUE(shared.OnResolved(&err)); 49 50 ASSERT_EQ(2u, shared.all_libs().size()); 51 EXPECT_EQ(second_lib, shared.all_libs()[0]); 52 EXPECT_EQ(lib, shared.all_libs()[1]); 53 ASSERT_EQ(2u, shared.all_lib_dirs().size()); 54 EXPECT_EQ(second_libdir, shared.all_lib_dirs()[0]); 55 EXPECT_EQ(libdir, shared.all_lib_dirs()[1]); 56 57 // Executable target shouldn't get either by depending on shared. 58 Target exec(setup.settings(), Label(SourceDir("//foo/"), "exec")); 59 exec.set_output_type(Target::EXECUTABLE); 60 exec.private_deps().push_back(LabelTargetPair(&shared)); 61 exec.SetToolchain(setup.toolchain()); 62 ASSERT_TRUE(exec.OnResolved(&err)); 63 EXPECT_EQ(0u, exec.all_libs().size()); 64 EXPECT_EQ(0u, exec.all_lib_dirs().size()); 65} 66 67// Test all_dependent_configs, public_config inheritance, and 68// forward_dependent_configs_from 69TEST(Target, DependentConfigs) { 70 TestWithScope setup; 71 Err err; 72 73 // Set up a dependency chain of a -> b -> c 74 Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); 75 a.set_output_type(Target::EXECUTABLE); 76 a.visibility().SetPublic(); 77 a.SetToolchain(setup.toolchain()); 78 Target b(setup.settings(), Label(SourceDir("//foo/"), "b")); 79 b.set_output_type(Target::STATIC_LIBRARY); 80 b.visibility().SetPublic(); 81 b.SetToolchain(setup.toolchain()); 82 Target c(setup.settings(), Label(SourceDir("//foo/"), "c")); 83 c.set_output_type(Target::STATIC_LIBRARY); 84 c.visibility().SetPublic(); 85 c.SetToolchain(setup.toolchain()); 86 a.private_deps().push_back(LabelTargetPair(&b)); 87 b.private_deps().push_back(LabelTargetPair(&c)); 88 89 // Normal non-inherited config. 90 Config config(setup.settings(), Label(SourceDir("//foo/"), "config")); 91 c.configs().push_back(LabelConfigPair(&config)); 92 93 // All dependent config. 94 Config all(setup.settings(), Label(SourceDir("//foo/"), "all")); 95 c.all_dependent_configs().push_back(LabelConfigPair(&all)); 96 97 // Direct dependent config. 98 Config direct(setup.settings(), Label(SourceDir("//foo/"), "direct")); 99 c.public_configs().push_back(LabelConfigPair(&direct)); 100 101 ASSERT_TRUE(c.OnResolved(&err)); 102 ASSERT_TRUE(b.OnResolved(&err)); 103 ASSERT_TRUE(a.OnResolved(&err)); 104 105 // B should have gotten both dependent configs from C. 106 ASSERT_EQ(2u, b.configs().size()); 107 EXPECT_EQ(&all, b.configs()[0].ptr); 108 EXPECT_EQ(&direct, b.configs()[1].ptr); 109 ASSERT_EQ(1u, b.all_dependent_configs().size()); 110 EXPECT_EQ(&all, b.all_dependent_configs()[0].ptr); 111 112 // A should have just gotten the "all" dependent config from C. 113 ASSERT_EQ(1u, a.configs().size()); 114 EXPECT_EQ(&all, a.configs()[0].ptr); 115 EXPECT_EQ(&all, a.all_dependent_configs()[0].ptr); 116 117 // Making an an alternate A and B with B forwarding the direct dependents. 118 Target a_fwd(setup.settings(), Label(SourceDir("//foo/"), "a_fwd")); 119 a_fwd.set_output_type(Target::EXECUTABLE); 120 a_fwd.visibility().SetPublic(); 121 a_fwd.SetToolchain(setup.toolchain()); 122 Target b_fwd(setup.settings(), Label(SourceDir("//foo/"), "b_fwd")); 123 b_fwd.set_output_type(Target::STATIC_LIBRARY); 124 b_fwd.SetToolchain(setup.toolchain()); 125 b_fwd.visibility().SetPublic(); 126 a_fwd.private_deps().push_back(LabelTargetPair(&b_fwd)); 127 b_fwd.private_deps().push_back(LabelTargetPair(&c)); 128 b_fwd.forward_dependent_configs().push_back(LabelTargetPair(&c)); 129 130 ASSERT_TRUE(b_fwd.OnResolved(&err)); 131 ASSERT_TRUE(a_fwd.OnResolved(&err)); 132 133 // A_fwd should now have both configs. 134 ASSERT_EQ(2u, a_fwd.configs().size()); 135 EXPECT_EQ(&all, a_fwd.configs()[0].ptr); 136 EXPECT_EQ(&direct, a_fwd.configs()[1].ptr); 137 ASSERT_EQ(1u, a_fwd.all_dependent_configs().size()); 138 EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr); 139} 140 141TEST(Target, InheritLibs) { 142 TestWithScope setup; 143 Err err; 144 145 // Create a dependency chain: 146 // A (executable) -> B (shared lib) -> C (static lib) -> D (source set) 147 Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); 148 a.set_output_type(Target::EXECUTABLE); 149 a.visibility().SetPublic(); 150 a.SetToolchain(setup.toolchain()); 151 Target b(setup.settings(), Label(SourceDir("//foo/"), "b")); 152 b.set_output_type(Target::SHARED_LIBRARY); 153 b.visibility().SetPublic(); 154 b.SetToolchain(setup.toolchain()); 155 Target c(setup.settings(), Label(SourceDir("//foo/"), "c")); 156 c.set_output_type(Target::STATIC_LIBRARY); 157 c.visibility().SetPublic(); 158 c.SetToolchain(setup.toolchain()); 159 Target d(setup.settings(), Label(SourceDir("//foo/"), "d")); 160 d.set_output_type(Target::SOURCE_SET); 161 d.visibility().SetPublic(); 162 d.SetToolchain(setup.toolchain()); 163 a.private_deps().push_back(LabelTargetPair(&b)); 164 b.private_deps().push_back(LabelTargetPair(&c)); 165 c.private_deps().push_back(LabelTargetPair(&d)); 166 167 ASSERT_TRUE(d.OnResolved(&err)); 168 ASSERT_TRUE(c.OnResolved(&err)); 169 ASSERT_TRUE(b.OnResolved(&err)); 170 ASSERT_TRUE(a.OnResolved(&err)); 171 172 // C should have D in its inherited libs. 173 const UniqueVector<const Target*>& c_inherited = c.inherited_libraries(); 174 EXPECT_EQ(1u, c_inherited.size()); 175 EXPECT_TRUE(c_inherited.IndexOf(&d) != static_cast<size_t>(-1)); 176 177 // B should have C and D in its inherited libs. 178 const UniqueVector<const Target*>& b_inherited = b.inherited_libraries(); 179 EXPECT_EQ(2u, b_inherited.size()); 180 EXPECT_TRUE(b_inherited.IndexOf(&c) != static_cast<size_t>(-1)); 181 EXPECT_TRUE(b_inherited.IndexOf(&d) != static_cast<size_t>(-1)); 182 183 // A should have B in its inherited libs, but not any others (the shared 184 // library will include the static library and source set). 185 const UniqueVector<const Target*>& a_inherited = a.inherited_libraries(); 186 EXPECT_EQ(1u, a_inherited.size()); 187 EXPECT_TRUE(a_inherited.IndexOf(&b) != static_cast<size_t>(-1)); 188} 189 190TEST(Target, InheritCompleteStaticLib) { 191 TestWithScope setup; 192 Err err; 193 194 // Create a dependency chain: 195 // A (executable) -> B (complete static lib) -> C (source set) 196 Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); 197 a.set_output_type(Target::EXECUTABLE); 198 a.visibility().SetPublic(); 199 a.SetToolchain(setup.toolchain()); 200 Target b(setup.settings(), Label(SourceDir("//foo/"), "b")); 201 b.set_output_type(Target::STATIC_LIBRARY); 202 b.visibility().SetPublic(); 203 b.set_complete_static_lib(true); 204 b.SetToolchain(setup.toolchain()); 205 Target c(setup.settings(), Label(SourceDir("//foo/"), "c")); 206 c.set_output_type(Target::SOURCE_SET); 207 c.visibility().SetPublic(); 208 c.SetToolchain(setup.toolchain()); 209 a.public_deps().push_back(LabelTargetPair(&b)); 210 b.public_deps().push_back(LabelTargetPair(&c)); 211 212 ASSERT_TRUE(c.OnResolved(&err)); 213 ASSERT_TRUE(b.OnResolved(&err)); 214 ASSERT_TRUE(a.OnResolved(&err)); 215 216 // B should have C in its inherited libs. 217 const UniqueVector<const Target*>& b_inherited = b.inherited_libraries(); 218 EXPECT_EQ(1u, b_inherited.size()); 219 EXPECT_TRUE(b_inherited.IndexOf(&c) != static_cast<size_t>(-1)); 220 221 // A should have B in its inherited libs, but not any others (the complete 222 // static library will include the source set). 223 const UniqueVector<const Target*>& a_inherited = a.inherited_libraries(); 224 EXPECT_EQ(1u, a_inherited.size()); 225 EXPECT_TRUE(a_inherited.IndexOf(&b) != static_cast<size_t>(-1)); 226} 227 228TEST(Target, InheritCompleteStaticLibNoDirectStaticLibDeps) { 229 TestWithScope setup; 230 Err err; 231 232 // Create a dependency chain: 233 // A (complete static lib) -> B (static lib) 234 Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); 235 a.set_output_type(Target::STATIC_LIBRARY); 236 a.visibility().SetPublic(); 237 a.set_complete_static_lib(true); 238 a.SetToolchain(setup.toolchain()); 239 Target b(setup.settings(), Label(SourceDir("//foo/"), "b")); 240 b.set_output_type(Target::STATIC_LIBRARY); 241 b.visibility().SetPublic(); 242 b.SetToolchain(setup.toolchain()); 243 244 a.public_deps().push_back(LabelTargetPair(&b)); 245 ASSERT_TRUE(b.OnResolved(&err)); 246 ASSERT_FALSE(a.OnResolved(&err)); 247} 248 249TEST(Target, InheritCompleteStaticLibNoIheritedStaticLibDeps) { 250 TestWithScope setup; 251 Err err; 252 253 // Create a dependency chain: 254 // A (complete static lib) -> B (source set) -> C (static lib) 255 Target a(setup.settings(), Label(SourceDir("//foo/"), "a")); 256 a.set_output_type(Target::STATIC_LIBRARY); 257 a.visibility().SetPublic(); 258 a.set_complete_static_lib(true); 259 a.SetToolchain(setup.toolchain()); 260 Target b(setup.settings(), Label(SourceDir("//foo/"), "b")); 261 b.set_output_type(Target::SOURCE_SET); 262 b.visibility().SetPublic(); 263 b.SetToolchain(setup.toolchain()); 264 Target c(setup.settings(), Label(SourceDir("//foo/"), "c")); 265 c.set_output_type(Target::STATIC_LIBRARY); 266 c.visibility().SetPublic(); 267 c.SetToolchain(setup.toolchain()); 268 269 a.public_deps().push_back(LabelTargetPair(&b)); 270 b.public_deps().push_back(LabelTargetPair(&c)); 271 272 ASSERT_TRUE(c.OnResolved(&err)); 273 ASSERT_TRUE(b.OnResolved(&err)); 274 ASSERT_FALSE(a.OnResolved(&err)); 275} 276 277TEST(Target, GetComputedOutputName) { 278 TestWithScope setup; 279 Err err; 280 281 // Basic target with no prefix (executable type tool in the TestWithScope has 282 // no prefix) or output name. 283 Target basic(setup.settings(), Label(SourceDir("//foo/"), "bar")); 284 basic.set_output_type(Target::EXECUTABLE); 285 basic.SetToolchain(setup.toolchain()); 286 ASSERT_TRUE(basic.OnResolved(&err)); 287 EXPECT_EQ("bar", basic.GetComputedOutputName(false)); 288 EXPECT_EQ("bar", basic.GetComputedOutputName(true)); 289 290 // Target with no prefix but an output name. 291 Target with_name(setup.settings(), Label(SourceDir("//foo/"), "bar")); 292 with_name.set_output_type(Target::EXECUTABLE); 293 with_name.set_output_name("myoutput"); 294 with_name.SetToolchain(setup.toolchain()); 295 ASSERT_TRUE(with_name.OnResolved(&err)); 296 EXPECT_EQ("myoutput", with_name.GetComputedOutputName(false)); 297 EXPECT_EQ("myoutput", with_name.GetComputedOutputName(true)); 298 299 // Target with a "lib" prefix (the static library tool in the TestWithScope 300 // should specify a "lib" output prefix). 301 Target with_prefix(setup.settings(), Label(SourceDir("//foo/"), "bar")); 302 with_prefix.set_output_type(Target::STATIC_LIBRARY); 303 with_prefix.SetToolchain(setup.toolchain()); 304 ASSERT_TRUE(with_prefix.OnResolved(&err)); 305 EXPECT_EQ("bar", with_prefix.GetComputedOutputName(false)); 306 EXPECT_EQ("libbar", with_prefix.GetComputedOutputName(true)); 307 308 // Target with a "lib" prefix that already has it applied. The prefix should 309 // not duplicate something already in the target name. 310 Target dup_prefix(setup.settings(), Label(SourceDir("//foo/"), "bar")); 311 dup_prefix.set_output_type(Target::STATIC_LIBRARY); 312 dup_prefix.set_output_name("libbar"); 313 dup_prefix.SetToolchain(setup.toolchain()); 314 ASSERT_TRUE(dup_prefix.OnResolved(&err)); 315 EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName(false)); 316 EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName(true)); 317} 318 319// Test visibility failure case. 320TEST(Target, VisibilityFails) { 321 TestWithScope setup; 322 Err err; 323 324 Target b(setup.settings(), Label(SourceDir("//private/"), "b")); 325 b.set_output_type(Target::STATIC_LIBRARY); 326 b.SetToolchain(setup.toolchain()); 327 b.visibility().SetPrivate(b.label().dir()); 328 ASSERT_TRUE(b.OnResolved(&err)); 329 330 // Make a target depending on "b". The dependency must have an origin to mark 331 // it as user-set so we check visibility. This check should fail. 332 Target a(setup.settings(), Label(SourceDir("//app/"), "a")); 333 a.set_output_type(Target::EXECUTABLE); 334 a.private_deps().push_back(LabelTargetPair(&b)); 335 IdentifierNode origin; // Dummy origin. 336 a.private_deps()[0].origin = &origin; 337 a.SetToolchain(setup.toolchain()); 338 ASSERT_FALSE(a.OnResolved(&err)); 339} 340 341// Test visibility with a single data_dep. 342TEST(Target, VisibilityDatadeps) { 343 TestWithScope setup; 344 Err err; 345 346 Target b(setup.settings(), Label(SourceDir("//public/"), "b")); 347 b.set_output_type(Target::STATIC_LIBRARY); 348 b.SetToolchain(setup.toolchain()); 349 b.visibility().SetPublic(); 350 ASSERT_TRUE(b.OnResolved(&err)); 351 352 // Make a target depending on "b". The dependency must have an origin to mark 353 // it as user-set so we check visibility. This check should fail. 354 Target a(setup.settings(), Label(SourceDir("//app/"), "a")); 355 a.set_output_type(Target::EXECUTABLE); 356 a.data_deps().push_back(LabelTargetPair(&b)); 357 IdentifierNode origin; // Dummy origin. 358 a.data_deps()[0].origin = &origin; 359 a.SetToolchain(setup.toolchain()); 360 ASSERT_TRUE(a.OnResolved(&err)) << err.help_text(); 361} 362 363// Tests that A -> Group -> B where the group is visible from A but B isn't, 364// passes visibility even though the group's deps get expanded into A. 365TEST(Target, VisibilityGroup) { 366 TestWithScope setup; 367 Err err; 368 369 IdentifierNode origin; // Dummy origin. 370 371 // B has private visibility. This lets the group see it since the group is in 372 // the same directory. 373 Target b(setup.settings(), Label(SourceDir("//private/"), "b")); 374 b.set_output_type(Target::STATIC_LIBRARY); 375 b.SetToolchain(setup.toolchain()); 376 b.visibility().SetPrivate(b.label().dir()); 377 ASSERT_TRUE(b.OnResolved(&err)); 378 379 // The group has public visibility and depends on b. 380 Target g(setup.settings(), Label(SourceDir("//private/"), "g")); 381 g.set_output_type(Target::GROUP); 382 g.SetToolchain(setup.toolchain()); 383 g.private_deps().push_back(LabelTargetPair(&b)); 384 g.private_deps()[0].origin = &origin; 385 g.visibility().SetPublic(); 386 ASSERT_TRUE(b.OnResolved(&err)); 387 388 // Make a target depending on "g". This should succeed. 389 Target a(setup.settings(), Label(SourceDir("//app/"), "a")); 390 a.set_output_type(Target::EXECUTABLE); 391 a.private_deps().push_back(LabelTargetPair(&g)); 392 a.private_deps()[0].origin = &origin; 393 a.SetToolchain(setup.toolchain()); 394 ASSERT_TRUE(a.OnResolved(&err)); 395} 396 397// Verifies that only testonly targets can depend on other testonly targets. 398// Many of the above dependency checking cases covered the non-testonly 399// case. 400TEST(Target, Testonly) { 401 TestWithScope setup; 402 Err err; 403 404 // "testlib" is a test-only library. 405 Target testlib(setup.settings(), Label(SourceDir("//test/"), "testlib")); 406 testlib.set_testonly(true); 407 testlib.set_output_type(Target::STATIC_LIBRARY); 408 testlib.visibility().SetPublic(); 409 testlib.SetToolchain(setup.toolchain()); 410 ASSERT_TRUE(testlib.OnResolved(&err)); 411 412 // "test" is a test-only executable depending on testlib, this is OK. 413 Target test(setup.settings(), Label(SourceDir("//test/"), "test")); 414 test.set_testonly(true); 415 test.set_output_type(Target::EXECUTABLE); 416 test.private_deps().push_back(LabelTargetPair(&testlib)); 417 test.SetToolchain(setup.toolchain()); 418 ASSERT_TRUE(test.OnResolved(&err)); 419 420 // "product" is a non-test depending on testlib. This should fail. 421 Target product(setup.settings(), Label(SourceDir("//app/"), "product")); 422 product.set_testonly(false); 423 product.set_output_type(Target::EXECUTABLE); 424 product.private_deps().push_back(LabelTargetPair(&testlib)); 425 product.SetToolchain(setup.toolchain()); 426 ASSERT_FALSE(product.OnResolved(&err)); 427} 428 429TEST(Target, PublicConfigs) { 430 TestWithScope setup; 431 Err err; 432 433 Label pub_config_label(SourceDir("//a/"), "pubconfig"); 434 Config pub_config(setup.settings(), pub_config_label); 435 436 // This is the destination target that has a public config. 437 Target dest(setup.settings(), Label(SourceDir("//a/"), "a")); 438 dest.set_output_type(Target::SOURCE_SET); 439 dest.visibility().SetPublic(); 440 dest.SetToolchain(setup.toolchain()); 441 dest.public_configs().push_back(LabelConfigPair(&pub_config)); 442 ASSERT_TRUE(dest.OnResolved(&err)); 443 444 // This target has a public dependency on dest. 445 Target pub(setup.settings(), Label(SourceDir("//a/"), "pub")); 446 pub.set_output_type(Target::SOURCE_SET); 447 pub.visibility().SetPublic(); 448 pub.SetToolchain(setup.toolchain()); 449 pub.public_deps().push_back(LabelTargetPair(&dest)); 450 ASSERT_TRUE(pub.OnResolved(&err)); 451 452 // Depending on the target with the public dependency should forward dest's 453 // to the current target. 454 Target dep_on_pub(setup.settings(), Label(SourceDir("//a/"), "dop")); 455 dep_on_pub.set_output_type(Target::SOURCE_SET); 456 dep_on_pub.visibility().SetPublic(); 457 dep_on_pub.SetToolchain(setup.toolchain()); 458 dep_on_pub.private_deps().push_back(LabelTargetPair(&pub)); 459 ASSERT_TRUE(dep_on_pub.OnResolved(&err)); 460 ASSERT_EQ(1u, dep_on_pub.configs().size()); 461 EXPECT_EQ(&pub_config, dep_on_pub.configs()[0].ptr); 462 463 // This target has a private dependency on dest for forwards configs. 464 Target forward(setup.settings(), Label(SourceDir("//a/"), "f")); 465 forward.set_output_type(Target::SOURCE_SET); 466 forward.visibility().SetPublic(); 467 forward.SetToolchain(setup.toolchain()); 468 forward.private_deps().push_back(LabelTargetPair(&dest)); 469 forward.forward_dependent_configs().push_back(LabelTargetPair(&dest)); 470 ASSERT_TRUE(forward.OnResolved(&err)); 471 472 // Depending on the forward target should apply the config. 473 Target dep_on_forward(setup.settings(), Label(SourceDir("//a/"), "dof")); 474 dep_on_forward.set_output_type(Target::SOURCE_SET); 475 dep_on_forward.visibility().SetPublic(); 476 dep_on_forward.SetToolchain(setup.toolchain()); 477 dep_on_forward.private_deps().push_back(LabelTargetPair(&forward)); 478 ASSERT_TRUE(dep_on_forward.OnResolved(&err)); 479 ASSERT_EQ(1u, dep_on_forward.configs().size()); 480 EXPECT_EQ(&pub_config, dep_on_forward.configs()[0].ptr); 481} 482 483// Tests that different link/depend outputs work for solink tools. 484TEST(Target, LinkAndDepOutputs) { 485 TestWithScope setup; 486 Err err; 487 488 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc")); 489 490 scoped_ptr<Tool> solink_tool(new Tool()); 491 solink_tool->set_output_prefix("lib"); 492 solink_tool->set_default_output_extension(".so"); 493 494 const char kLinkPattern[] = 495 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"; 496 SubstitutionPattern link_output = SubstitutionPattern::MakeForTest( 497 kLinkPattern); 498 solink_tool->set_link_output(link_output); 499 500 const char kDependPattern[] = 501 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC"; 502 SubstitutionPattern depend_output = SubstitutionPattern::MakeForTest( 503 kDependPattern); 504 solink_tool->set_depend_output(depend_output); 505 506 solink_tool->set_outputs(SubstitutionList::MakeForTest( 507 kLinkPattern, kDependPattern)); 508 509 toolchain.SetTool(Toolchain::TYPE_SOLINK, solink_tool.Pass()); 510 511 Target target(setup.settings(), Label(SourceDir("//a/"), "a")); 512 target.set_output_type(Target::SHARED_LIBRARY); 513 target.SetToolchain(&toolchain); 514 ASSERT_TRUE(target.OnResolved(&err)); 515 516 EXPECT_EQ("./liba.so", target.link_output_file().value()); 517 EXPECT_EQ("./liba.so.TOC", target.dependency_output_file().value()); 518} 519