Index: tools/gn/ninja_binary_target_writer_unittest.cc |
diff --git a/tools/gn/ninja_binary_target_writer_unittest.cc b/tools/gn/ninja_binary_target_writer_unittest.cc |
index 16f75893c03e776196767f7a148062dfe2219d24..4bb055337d31ff260d459c7c5a6492a0d5a393a2 100644 |
--- a/tools/gn/ninja_binary_target_writer_unittest.cc |
+++ b/tools/gn/ninja_binary_target_writer_unittest.cc |
@@ -388,6 +388,17 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
cxx_tool->set_precompiled_header_type(Tool::PCH_MSVC); |
pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass()); |
+ |
+ // Add a C compiler as well. |
+ scoped_ptr<Tool> cc_tool(new Tool); |
+ TestWithScope::SetCommandForTool( |
+ "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " |
+ "-o {{output}}", |
+ cc_tool.get()); |
+ cc_tool->set_outputs(SubstitutionList::MakeForTest( |
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
+ cc_tool->set_precompiled_header_type(Tool::PCH_MSVC); |
+ pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass()); |
pch_toolchain.ToolchainSetupComplete(); |
// This target doesn't specify precompiled headers. |
@@ -397,6 +408,7 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
no_pch_target.set_output_type(Target::SOURCE_SET); |
no_pch_target.visibility().SetPublic(); |
no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
+ no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
no_pch_target.SetToolchain(&pch_toolchain); |
ASSERT_TRUE(no_pch_target.OnResolved(&err)); |
@@ -408,14 +420,18 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
"defines =\n" |
"include_dirs =\n" |
"cflags =\n" |
+ "cflags_c =\n" |
"cflags_cc =\n" |
"target_output_name = no_pch_target\n" |
"\n" |
"build withpch/obj/foo/no_pch_target.input1.o: " |
"withpch_cxx ../../foo/input1.cc\n" |
+ "build withpch/obj/foo/no_pch_target.input2.o: " |
+ "withpch_cc ../../foo/input2.c\n" |
"\n" |
"build withpch/obj/foo/no_pch_target.stamp: " |
- "withpch_stamp withpch/obj/foo/no_pch_target.input1.o\n"; |
+ "withpch_stamp withpch/obj/foo/no_pch_target.input1.o " |
+ "withpch/obj/foo/no_pch_target.input2.o\n"; |
EXPECT_EQ(no_pch_expected, out.str()); |
} |
@@ -429,6 +445,7 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
pch_target.set_output_type(Target::SOURCE_SET); |
pch_target.visibility().SetPublic(); |
pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
+ pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
pch_target.SetToolchain(&pch_toolchain); |
ASSERT_TRUE(pch_target.OnResolved(&err)); |
@@ -440,12 +457,18 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
"defines =\n" |
"include_dirs =\n" |
"cflags =\n" |
- // There should only be one .pch file created, for C++ files. |
+ // It should output language-specific pch files. |
+ "cflags_c = /Fpwithpch/obj/foo/pch_target_c.pch " |
+ "/Yubuild/precompile.h\n" |
"cflags_cc = /Fpwithpch/obj/foo/pch_target_cc.pch " |
"/Yubuild/precompile.h\n" |
"target_output_name = pch_target\n" |
"\n" |
- // Compile the precompiled source file with /Yc. |
+ // Compile the precompiled source files with /Yc. |
+ "build withpch/obj/build/pch_target.precompile.c.o: " |
+ "withpch_cc ../../build/precompile.cc\n" |
+ " cflags_c = ${cflags_c} /Ycbuild/precompile.h\n" |
+ "\n" |
"build withpch/obj/build/pch_target.precompile.cc.o: " |
"withpch_cxx ../../build/precompile.cc\n" |
" cflags_cc = ${cflags_cc} /Ycbuild/precompile.h\n" |
@@ -454,15 +477,145 @@ TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) { |
"withpch_cxx ../../foo/input1.cc | " |
// Explicit dependency on the PCH build step. |
"withpch/obj/build/pch_target.precompile.cc.o\n" |
+ "build withpch/obj/foo/pch_target.input2.o: " |
+ "withpch_cc ../../foo/input2.c | " |
+ // Explicit dependency on the PCH build step. |
+ "withpch/obj/build/pch_target.precompile.c.o\n" |
"\n" |
- "build withpch/obj/foo/pch_target.stamp: " |
- "withpch_stamp withpch/obj/foo/pch_target.input1.o " |
- // The precompiled object file was added to the outputs. |
+ "build withpch/obj/foo/pch_target.stamp: withpch_stamp " |
+ "withpch/obj/foo/pch_target.input1.o " |
+ "withpch/obj/foo/pch_target.input2.o " |
+ // The precompiled object files were added to the outputs. |
+ "withpch/obj/build/pch_target.precompile.c.o " |
"withpch/obj/build/pch_target.precompile.cc.o\n"; |
EXPECT_EQ(pch_win_expected, out.str()); |
} |
} |
+TEST(NinjaBinaryTargetWriter, GCCPrecompiledHeaders) { |
+ Err err; |
+ |
+ // This setup's toolchain does not have precompiled headers defined. |
+ TestWithScope setup; |
+ |
+ // A precompiled header toolchain. |
+ Settings pch_settings(setup.build_settings(), "withpch/"); |
+ Toolchain pch_toolchain(&pch_settings, |
+ Label(SourceDir("//toolchain/"), "withpch")); |
+ pch_settings.set_toolchain_label(pch_toolchain.label()); |
+ pch_settings.set_default_toolchain_label(setup.toolchain()->label()); |
+ |
+ // Declare a C++ compiler that supports PCH. |
+ scoped_ptr<Tool> cxx_tool(new Tool); |
+ TestWithScope::SetCommandForTool( |
+ "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " |
+ "-o {{output}}", |
+ cxx_tool.get()); |
+ cxx_tool->set_outputs(SubstitutionList::MakeForTest( |
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
+ cxx_tool->set_precompiled_header_type(Tool::PCH_GCC); |
+ pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass()); |
+ pch_toolchain.ToolchainSetupComplete(); |
+ |
+ // Add a C compiler as well. |
+ scoped_ptr<Tool> cc_tool(new Tool); |
+ TestWithScope::SetCommandForTool( |
+ "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " |
+ "-o {{output}}", |
+ cc_tool.get()); |
+ cc_tool->set_outputs(SubstitutionList::MakeForTest( |
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); |
+ cc_tool->set_precompiled_header_type(Tool::PCH_GCC); |
+ pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass()); |
+ pch_toolchain.ToolchainSetupComplete(); |
+ |
+ // This target doesn't specify precompiled headers. |
+ { |
+ Target no_pch_target(&pch_settings, |
+ Label(SourceDir("//foo/"), "no_pch_target")); |
+ no_pch_target.set_output_type(Target::SOURCE_SET); |
+ no_pch_target.visibility().SetPublic(); |
+ no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
+ no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
+ no_pch_target.SetToolchain(&pch_toolchain); |
+ ASSERT_TRUE(no_pch_target.OnResolved(&err)); |
+ |
+ std::ostringstream out; |
+ NinjaBinaryTargetWriter writer(&no_pch_target, out); |
+ writer.Run(); |
+ |
+ const char no_pch_expected[] = |
+ "defines =\n" |
+ "include_dirs =\n" |
+ "cflags =\n" |
+ "cflags_c =\n" |
+ "cflags_cc =\n" |
+ "target_output_name = no_pch_target\n" |
+ "\n" |
+ "build withpch/obj/foo/no_pch_target.input1.o: " |
+ "withpch_cxx ../../foo/input1.cc\n" |
+ "build withpch/obj/foo/no_pch_target.input2.o: " |
+ "withpch_cc ../../foo/input2.c\n" |
+ "\n" |
+ "build withpch/obj/foo/no_pch_target.stamp: " |
+ "withpch_stamp withpch/obj/foo/no_pch_target.input1.o " |
+ "withpch/obj/foo/no_pch_target.input2.o\n"; |
+ EXPECT_EQ(no_pch_expected, out.str()); |
+ } |
+ |
+ // This target specifies PCH. |
+ { |
+ Target pch_target(&pch_settings, |
+ Label(SourceDir("//foo/"), "pch_target")); |
+ pch_target.config_values().set_precompiled_header("build/precompile.h"); |
+ pch_target.config_values().set_precompiled_source( |
+ SourceFile("//build/precompile.h")); |
+ pch_target.config_values().cflags_c().push_back("-std=c99"); |
+ pch_target.set_output_type(Target::SOURCE_SET); |
+ pch_target.visibility().SetPublic(); |
+ pch_target.sources().push_back(SourceFile("//foo/input1.cc")); |
+ pch_target.sources().push_back(SourceFile("//foo/input2.c")); |
+ pch_target.SetToolchain(&pch_toolchain); |
+ ASSERT_TRUE(pch_target.OnResolved(&err)); |
+ |
+ std::ostringstream out; |
+ NinjaBinaryTargetWriter writer(&pch_target, out); |
+ writer.Run(); |
+ |
+ const char pch_gcc_expected[] = |
+ "defines =\n" |
+ "include_dirs =\n" |
+ "cflags =\n" |
+ "cflags_c = -std=c99 " |
+ "-include withpch/obj/build/pch_target.precompile.h-c\n" |
+ "cflags_cc = -include withpch/obj/build/pch_target.precompile.h-cc\n" |
+ "target_output_name = pch_target\n" |
+ "\n" |
+ // Compile the precompiled sources with -x <lang>. |
+ "build withpch/obj/build/pch_target.precompile.h-c.gch: " |
+ "withpch_cc ../../build/precompile.h\n" |
+ " cflags_c = -std=c99 -x c-header\n" |
+ "\n" |
+ "build withpch/obj/build/pch_target.precompile.h-cc.gch: " |
+ "withpch_cxx ../../build/precompile.h\n" |
+ " cflags_cc = -x c++-header\n" |
+ "\n" |
+ "build withpch/obj/foo/pch_target.input1.o: " |
+ "withpch_cxx ../../foo/input1.cc | " |
+ // Explicit dependency on the PCH build step. |
+ "withpch/obj/build/pch_target.precompile.h-cc.gch\n" |
+ "build withpch/obj/foo/pch_target.input2.o: " |
+ "withpch_cc ../../foo/input2.c | " |
+ // Explicit dependency on the PCH build step. |
+ "withpch/obj/build/pch_target.precompile.h-c.gch\n" |
+ "\n" |
+ "build withpch/obj/foo/pch_target.stamp: " |
+ "withpch_stamp withpch/obj/foo/pch_target.input1.o " |
+ "withpch/obj/foo/pch_target.input2.o\n"; |
+ EXPECT_EQ(pch_gcc_expected, out.str()); |
+ } |
+} |
+ |
// Should throw an error with the scheduler if a duplicate object file exists. |
// This is dependent on the toolchain's object file mapping. |
TEST(NinjaBinaryTargetWriter, DupeObjFileError) { |