OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "testing/gtest/include/gtest/gtest.h" | 7 #include "testing/gtest/include/gtest/gtest.h" |
8 #include "tools/gn/ninja_binary_target_writer.h" | 8 #include "tools/gn/ninja_binary_target_writer.h" |
9 #include "tools/gn/scheduler.h" | 9 #include "tools/gn/scheduler.h" |
10 #include "tools/gn/target.h" | 10 #include "tools/gn/target.h" |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 // Declare a C++ compiler that supports PCH. | 381 // Declare a C++ compiler that supports PCH. |
382 scoped_ptr<Tool> cxx_tool(new Tool); | 382 scoped_ptr<Tool> cxx_tool(new Tool); |
383 TestWithScope::SetCommandForTool( | 383 TestWithScope::SetCommandForTool( |
384 "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " | 384 "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " |
385 "-o {{output}}", | 385 "-o {{output}}", |
386 cxx_tool.get()); | 386 cxx_tool.get()); |
387 cxx_tool->set_outputs(SubstitutionList::MakeForTest( | 387 cxx_tool->set_outputs(SubstitutionList::MakeForTest( |
388 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); | 388 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
389 cxx_tool->set_precompiled_header_type(Tool::PCH_MSVC); | 389 cxx_tool->set_precompiled_header_type(Tool::PCH_MSVC); |
390 pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass()); | 390 pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass()); |
| 391 |
| 392 // Add a C compiler as well. |
| 393 scoped_ptr<Tool> cc_tool(new Tool); |
| 394 TestWithScope::SetCommandForTool( |
| 395 "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " |
| 396 "-o {{output}}", |
| 397 cc_tool.get()); |
| 398 cc_tool->set_outputs(SubstitutionList::MakeForTest( |
| 399 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
| 400 cc_tool->set_precompiled_header_type(Tool::PCH_MSVC); |
| 401 pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass()); |
391 pch_toolchain.ToolchainSetupComplete(); | 402 pch_toolchain.ToolchainSetupComplete(); |
392 | 403 |
393 // This target doesn't specify precompiled headers. | 404 // This target doesn't specify precompiled headers. |
394 { | 405 { |
395 Target no_pch_target(&pch_settings, | 406 Target no_pch_target(&pch_settings, |
396 Label(SourceDir("//foo/"), "no_pch_target")); | 407 Label(SourceDir("//foo/"), "no_pch_target")); |
397 no_pch_target.set_output_type(Target::SOURCE_SET); | 408 no_pch_target.set_output_type(Target::SOURCE_SET); |
398 no_pch_target.visibility().SetPublic(); | 409 no_pch_target.visibility().SetPublic(); |
399 no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); | 410 no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
| 411 no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
400 no_pch_target.SetToolchain(&pch_toolchain); | 412 no_pch_target.SetToolchain(&pch_toolchain); |
401 ASSERT_TRUE(no_pch_target.OnResolved(&err)); | 413 ASSERT_TRUE(no_pch_target.OnResolved(&err)); |
402 | 414 |
403 std::ostringstream out; | 415 std::ostringstream out; |
404 NinjaBinaryTargetWriter writer(&no_pch_target, out); | 416 NinjaBinaryTargetWriter writer(&no_pch_target, out); |
405 writer.Run(); | 417 writer.Run(); |
406 | 418 |
407 const char no_pch_expected[] = | 419 const char no_pch_expected[] = |
408 "defines =\n" | 420 "defines =\n" |
409 "include_dirs =\n" | 421 "include_dirs =\n" |
410 "cflags =\n" | 422 "cflags =\n" |
| 423 "cflags_c =\n" |
411 "cflags_cc =\n" | 424 "cflags_cc =\n" |
412 "target_output_name = no_pch_target\n" | 425 "target_output_name = no_pch_target\n" |
413 "\n" | 426 "\n" |
414 "build withpch/obj/foo/no_pch_target.input1.o: " | 427 "build withpch/obj/foo/no_pch_target.input1.o: " |
415 "withpch_cxx ../../foo/input1.cc\n" | 428 "withpch_cxx ../../foo/input1.cc\n" |
| 429 "build withpch/obj/foo/no_pch_target.input2.o: " |
| 430 "withpch_cc ../../foo/input2.c\n" |
416 "\n" | 431 "\n" |
417 "build withpch/obj/foo/no_pch_target.stamp: " | 432 "build withpch/obj/foo/no_pch_target.stamp: " |
418 "withpch_stamp withpch/obj/foo/no_pch_target.input1.o\n"; | 433 "withpch_stamp withpch/obj/foo/no_pch_target.input1.o " |
| 434 "withpch/obj/foo/no_pch_target.input2.o\n"; |
419 EXPECT_EQ(no_pch_expected, out.str()); | 435 EXPECT_EQ(no_pch_expected, out.str()); |
420 } | 436 } |
421 | 437 |
422 // This target specifies PCH. | 438 // This target specifies PCH. |
423 { | 439 { |
424 Target pch_target(&pch_settings, | 440 Target pch_target(&pch_settings, |
425 Label(SourceDir("//foo/"), "pch_target")); | 441 Label(SourceDir("//foo/"), "pch_target")); |
426 pch_target.config_values().set_precompiled_header("build/precompile.h"); | 442 pch_target.config_values().set_precompiled_header("build/precompile.h"); |
427 pch_target.config_values().set_precompiled_source( | 443 pch_target.config_values().set_precompiled_source( |
428 SourceFile("//build/precompile.cc")); | 444 SourceFile("//build/precompile.cc")); |
429 pch_target.set_output_type(Target::SOURCE_SET); | 445 pch_target.set_output_type(Target::SOURCE_SET); |
430 pch_target.visibility().SetPublic(); | 446 pch_target.visibility().SetPublic(); |
431 pch_target.sources().push_back(SourceFile("//foo/input1.cc")); | 447 pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
| 448 pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
432 pch_target.SetToolchain(&pch_toolchain); | 449 pch_target.SetToolchain(&pch_toolchain); |
433 ASSERT_TRUE(pch_target.OnResolved(&err)); | 450 ASSERT_TRUE(pch_target.OnResolved(&err)); |
434 | 451 |
435 std::ostringstream out; | 452 std::ostringstream out; |
436 NinjaBinaryTargetWriter writer(&pch_target, out); | 453 NinjaBinaryTargetWriter writer(&pch_target, out); |
437 writer.Run(); | 454 writer.Run(); |
438 | 455 |
439 const char pch_win_expected[] = | 456 const char pch_win_expected[] = |
440 "defines =\n" | 457 "defines =\n" |
441 "include_dirs =\n" | 458 "include_dirs =\n" |
442 "cflags =\n" | 459 "cflags =\n" |
443 // There should only be one .pch file created, for C++ files. | 460 // It should output language-specific pch files. |
| 461 "cflags_c = /Fpwithpch/obj/foo/pch_target_c.pch " |
| 462 "/Yubuild/precompile.h\n" |
444 "cflags_cc = /Fpwithpch/obj/foo/pch_target_cc.pch " | 463 "cflags_cc = /Fpwithpch/obj/foo/pch_target_cc.pch " |
445 "/Yubuild/precompile.h\n" | 464 "/Yubuild/precompile.h\n" |
446 "target_output_name = pch_target\n" | 465 "target_output_name = pch_target\n" |
447 "\n" | 466 "\n" |
448 // Compile the precompiled source file with /Yc. | 467 // Compile the precompiled source files with /Yc. |
| 468 "build withpch/obj/build/pch_target.precompile.c.o: " |
| 469 "withpch_cc ../../build/precompile.cc\n" |
| 470 " cflags_c = ${cflags_c} /Ycbuild/precompile.h\n" |
| 471 "\n" |
449 "build withpch/obj/build/pch_target.precompile.cc.o: " | 472 "build withpch/obj/build/pch_target.precompile.cc.o: " |
450 "withpch_cxx ../../build/precompile.cc\n" | 473 "withpch_cxx ../../build/precompile.cc\n" |
451 " cflags_cc = ${cflags_cc} /Ycbuild/precompile.h\n" | 474 " cflags_cc = ${cflags_cc} /Ycbuild/precompile.h\n" |
452 "\n" | 475 "\n" |
453 "build withpch/obj/foo/pch_target.input1.o: " | 476 "build withpch/obj/foo/pch_target.input1.o: " |
454 "withpch_cxx ../../foo/input1.cc | " | 477 "withpch_cxx ../../foo/input1.cc | " |
455 // Explicit dependency on the PCH build step. | 478 // Explicit dependency on the PCH build step. |
456 "withpch/obj/build/pch_target.precompile.cc.o\n" | 479 "withpch/obj/build/pch_target.precompile.cc.o\n" |
| 480 "build withpch/obj/foo/pch_target.input2.o: " |
| 481 "withpch_cc ../../foo/input2.c | " |
| 482 // Explicit dependency on the PCH build step. |
| 483 "withpch/obj/build/pch_target.precompile.c.o\n" |
| 484 "\n" |
| 485 "build withpch/obj/foo/pch_target.stamp: withpch_stamp " |
| 486 "withpch/obj/foo/pch_target.input1.o " |
| 487 "withpch/obj/foo/pch_target.input2.o " |
| 488 // The precompiled object files were added to the outputs. |
| 489 "withpch/obj/build/pch_target.precompile.c.o " |
| 490 "withpch/obj/build/pch_target.precompile.cc.o\n"; |
| 491 EXPECT_EQ(pch_win_expected, out.str()); |
| 492 } |
| 493 } |
| 494 |
| 495 TEST(NinjaBinaryTargetWriter, GCCPrecompiledHeaders) { |
| 496 Err err; |
| 497 |
| 498 // This setup's toolchain does not have precompiled headers defined. |
| 499 TestWithScope setup; |
| 500 |
| 501 // A precompiled header toolchain. |
| 502 Settings pch_settings(setup.build_settings(), "withpch/"); |
| 503 Toolchain pch_toolchain(&pch_settings, |
| 504 Label(SourceDir("//toolchain/"), "withpch")); |
| 505 pch_settings.set_toolchain_label(pch_toolchain.label()); |
| 506 pch_settings.set_default_toolchain_label(setup.toolchain()->label()); |
| 507 |
| 508 // Declare a C++ compiler that supports PCH. |
| 509 scoped_ptr<Tool> cxx_tool(new Tool); |
| 510 TestWithScope::SetCommandForTool( |
| 511 "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " |
| 512 "-o {{output}}", |
| 513 cxx_tool.get()); |
| 514 cxx_tool->set_outputs(SubstitutionList::MakeForTest( |
| 515 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
| 516 cxx_tool->set_precompiled_header_type(Tool::PCH_GCC); |
| 517 pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass()); |
| 518 pch_toolchain.ToolchainSetupComplete(); |
| 519 |
| 520 // Add a C compiler as well. |
| 521 scoped_ptr<Tool> cc_tool(new Tool); |
| 522 TestWithScope::SetCommandForTool( |
| 523 "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " |
| 524 "-o {{output}}", |
| 525 cc_tool.get()); |
| 526 cc_tool->set_outputs(SubstitutionList::MakeForTest( |
| 527 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
| 528 cc_tool->set_precompiled_header_type(Tool::PCH_GCC); |
| 529 pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass()); |
| 530 pch_toolchain.ToolchainSetupComplete(); |
| 531 |
| 532 // This target doesn't specify precompiled headers. |
| 533 { |
| 534 Target no_pch_target(&pch_settings, |
| 535 Label(SourceDir("//foo/"), "no_pch_target")); |
| 536 no_pch_target.set_output_type(Target::SOURCE_SET); |
| 537 no_pch_target.visibility().SetPublic(); |
| 538 no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
| 539 no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
| 540 no_pch_target.SetToolchain(&pch_toolchain); |
| 541 ASSERT_TRUE(no_pch_target.OnResolved(&err)); |
| 542 |
| 543 std::ostringstream out; |
| 544 NinjaBinaryTargetWriter writer(&no_pch_target, out); |
| 545 writer.Run(); |
| 546 |
| 547 const char no_pch_expected[] = |
| 548 "defines =\n" |
| 549 "include_dirs =\n" |
| 550 "cflags =\n" |
| 551 "cflags_c =\n" |
| 552 "cflags_cc =\n" |
| 553 "target_output_name = no_pch_target\n" |
| 554 "\n" |
| 555 "build withpch/obj/foo/no_pch_target.input1.o: " |
| 556 "withpch_cxx ../../foo/input1.cc\n" |
| 557 "build withpch/obj/foo/no_pch_target.input2.o: " |
| 558 "withpch_cc ../../foo/input2.c\n" |
| 559 "\n" |
| 560 "build withpch/obj/foo/no_pch_target.stamp: " |
| 561 "withpch_stamp withpch/obj/foo/no_pch_target.input1.o " |
| 562 "withpch/obj/foo/no_pch_target.input2.o\n"; |
| 563 EXPECT_EQ(no_pch_expected, out.str()); |
| 564 } |
| 565 |
| 566 // This target specifies PCH. |
| 567 { |
| 568 Target pch_target(&pch_settings, |
| 569 Label(SourceDir("//foo/"), "pch_target")); |
| 570 pch_target.config_values().set_precompiled_header("build/precompile.h"); |
| 571 pch_target.config_values().set_precompiled_source( |
| 572 SourceFile("//build/precompile.h")); |
| 573 pch_target.config_values().cflags_c().push_back("-std=c99"); |
| 574 pch_target.set_output_type(Target::SOURCE_SET); |
| 575 pch_target.visibility().SetPublic(); |
| 576 pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
| 577 pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
| 578 pch_target.SetToolchain(&pch_toolchain); |
| 579 ASSERT_TRUE(pch_target.OnResolved(&err)); |
| 580 |
| 581 std::ostringstream out; |
| 582 NinjaBinaryTargetWriter writer(&pch_target, out); |
| 583 writer.Run(); |
| 584 |
| 585 const char pch_gcc_expected[] = |
| 586 "defines =\n" |
| 587 "include_dirs =\n" |
| 588 "cflags =\n" |
| 589 "cflags_c = -std=c99 " |
| 590 "-include withpch/obj/build/pch_target.precompile.h-c\n" |
| 591 "cflags_cc = -include withpch/obj/build/pch_target.precompile.h-cc\n" |
| 592 "target_output_name = pch_target\n" |
| 593 "\n" |
| 594 // Compile the precompiled sources with -x <lang>. |
| 595 "build withpch/obj/build/pch_target.precompile.h-c.gch: " |
| 596 "withpch_cc ../../build/precompile.h\n" |
| 597 " cflags_c = -std=c99 -x c-header\n" |
| 598 "\n" |
| 599 "build withpch/obj/build/pch_target.precompile.h-cc.gch: " |
| 600 "withpch_cxx ../../build/precompile.h\n" |
| 601 " cflags_cc = -x c++-header\n" |
| 602 "\n" |
| 603 "build withpch/obj/foo/pch_target.input1.o: " |
| 604 "withpch_cxx ../../foo/input1.cc | " |
| 605 // Explicit dependency on the PCH build step. |
| 606 "withpch/obj/build/pch_target.precompile.h-cc.gch\n" |
| 607 "build withpch/obj/foo/pch_target.input2.o: " |
| 608 "withpch_cc ../../foo/input2.c | " |
| 609 // Explicit dependency on the PCH build step. |
| 610 "withpch/obj/build/pch_target.precompile.h-c.gch\n" |
457 "\n" | 611 "\n" |
458 "build withpch/obj/foo/pch_target.stamp: " | 612 "build withpch/obj/foo/pch_target.stamp: " |
459 "withpch_stamp withpch/obj/foo/pch_target.input1.o " | 613 "withpch_stamp withpch/obj/foo/pch_target.input1.o " |
460 // The precompiled object file was added to the outputs. | 614 "withpch/obj/foo/pch_target.input2.o\n"; |
461 "withpch/obj/build/pch_target.precompile.cc.o\n"; | 615 EXPECT_EQ(pch_gcc_expected, out.str()); |
462 EXPECT_EQ(pch_win_expected, out.str()); | |
463 } | 616 } |
464 } | 617 } |
465 | 618 |
466 // Should throw an error with the scheduler if a duplicate object file exists. | 619 // Should throw an error with the scheduler if a duplicate object file exists. |
467 // This is dependent on the toolchain's object file mapping. | 620 // This is dependent on the toolchain's object file mapping. |
468 TEST(NinjaBinaryTargetWriter, DupeObjFileError) { | 621 TEST(NinjaBinaryTargetWriter, DupeObjFileError) { |
469 Scheduler scheduler; | 622 Scheduler scheduler; |
470 | 623 |
471 TestWithScope setup; | 624 TestWithScope setup; |
472 TestTarget target(setup, "//foo:bar", Target::EXECUTABLE); | 625 TestTarget target(setup, "//foo:bar", Target::EXECUTABLE); |
473 target.sources().push_back(SourceFile("//a.cc")); | 626 target.sources().push_back(SourceFile("//a.cc")); |
474 target.sources().push_back(SourceFile("//a.cc")); | 627 target.sources().push_back(SourceFile("//a.cc")); |
475 | 628 |
476 EXPECT_FALSE(scheduler.is_failed()); | 629 EXPECT_FALSE(scheduler.is_failed()); |
477 | 630 |
478 std::ostringstream out; | 631 std::ostringstream out; |
479 NinjaBinaryTargetWriter writer(&target, out); | 632 NinjaBinaryTargetWriter writer(&target, out); |
480 writer.Run(); | 633 writer.Run(); |
481 | 634 |
482 // Should have issued an error. | 635 // Should have issued an error. |
483 EXPECT_TRUE(scheduler.is_failed()); | 636 EXPECT_TRUE(scheduler.is_failed()); |
484 } | 637 } |
OLD | NEW |