16d528ed9Sopenharmony_ci// Copyright 2018 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#include "gn/compile_commands_writer.h" 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci#include <memory> 86d528ed9Sopenharmony_ci#include <sstream> 96d528ed9Sopenharmony_ci#include <utility> 106d528ed9Sopenharmony_ci 116d528ed9Sopenharmony_ci#include "gn/config.h" 126d528ed9Sopenharmony_ci#include "gn/ninja_target_command_util.h" 136d528ed9Sopenharmony_ci#include "gn/scheduler.h" 146d528ed9Sopenharmony_ci#include "gn/target.h" 156d528ed9Sopenharmony_ci#include "gn/test_with_scheduler.h" 166d528ed9Sopenharmony_ci#include "gn/test_with_scope.h" 176d528ed9Sopenharmony_ci#include "util/build_config.h" 186d528ed9Sopenharmony_ci#include "util/test/test.h" 196d528ed9Sopenharmony_ci 206d528ed9Sopenharmony_cinamespace { 216d528ed9Sopenharmony_ci 226d528ed9Sopenharmony_cibool CompareLabel(const Target* a, const Target* b) { 236d528ed9Sopenharmony_ci return a->label() < b->label(); 246d528ed9Sopenharmony_ci} 256d528ed9Sopenharmony_ci 266d528ed9Sopenharmony_ci// InputConversion needs a global scheduler object. 276d528ed9Sopenharmony_ciclass CompileCommandsTest : public TestWithScheduler { 286d528ed9Sopenharmony_ci public: 296d528ed9Sopenharmony_ci CompileCommandsTest() = default; 306d528ed9Sopenharmony_ci 316d528ed9Sopenharmony_ci const BuildSettings* build_settings() { return setup_.build_settings(); } 326d528ed9Sopenharmony_ci const Settings* settings() { return setup_.settings(); } 336d528ed9Sopenharmony_ci const TestWithScope& setup() { return setup_; } 346d528ed9Sopenharmony_ci const Toolchain* toolchain() { return setup_.toolchain(); } 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ci // Returns true if the two target vectors contain the same targets, order 376d528ed9Sopenharmony_ci // independent. 386d528ed9Sopenharmony_ci bool VectorsEqual(std::vector<const Target*> a, 396d528ed9Sopenharmony_ci std::vector<const Target*> b) const { 406d528ed9Sopenharmony_ci std::sort(a.begin(), a.end(), &CompareLabel); 416d528ed9Sopenharmony_ci std::sort(b.begin(), b.end(), &CompareLabel); 426d528ed9Sopenharmony_ci return a == b; 436d528ed9Sopenharmony_ci } 446d528ed9Sopenharmony_ci 456d528ed9Sopenharmony_ci private: 466d528ed9Sopenharmony_ci TestWithScope setup_; 476d528ed9Sopenharmony_ci}; 486d528ed9Sopenharmony_ci 496d528ed9Sopenharmony_ci} // namespace 506d528ed9Sopenharmony_ci 516d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, SourceSet) { 526d528ed9Sopenharmony_ci Err err; 536d528ed9Sopenharmony_ci 546d528ed9Sopenharmony_ci std::vector<const Target*> targets; 556d528ed9Sopenharmony_ci Target target(settings(), Label(SourceDir("//foo/"), "bar")); 566d528ed9Sopenharmony_ci target.set_output_type(Target::SOURCE_SET); 576d528ed9Sopenharmony_ci target.visibility().SetPublic(); 586d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input1.cc")); 596d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input2.cc")); 606d528ed9Sopenharmony_ci // Also test object files, which should be just passed through to the 616d528ed9Sopenharmony_ci // dependents to link. 626d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input3.o")); 636d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input4.obj")); 646d528ed9Sopenharmony_ci target.SetToolchain(toolchain()); 656d528ed9Sopenharmony_ci ASSERT_TRUE(target.OnResolved(&err)); 666d528ed9Sopenharmony_ci targets.push_back(&target); 676d528ed9Sopenharmony_ci 686d528ed9Sopenharmony_ci // Source set itself. 696d528ed9Sopenharmony_ci { 706d528ed9Sopenharmony_ci CompileCommandsWriter writer; 716d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 726d528ed9Sopenharmony_ci 736d528ed9Sopenharmony_ci#if defined(OS_WIN) 746d528ed9Sopenharmony_ci const char expected[] = 756d528ed9Sopenharmony_ci "[\r\n" 766d528ed9Sopenharmony_ci " {\r\n" 776d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 786d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 796d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 806d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\r\n" 816d528ed9Sopenharmony_ci " },\r\n" 826d528ed9Sopenharmony_ci " {\r\n" 836d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\r\n" 846d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 856d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 866d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\r\n" 876d528ed9Sopenharmony_ci " }\r\n" 886d528ed9Sopenharmony_ci "]\r\n"; 896d528ed9Sopenharmony_ci#else 906d528ed9Sopenharmony_ci const char expected[] = 916d528ed9Sopenharmony_ci "[\n" 926d528ed9Sopenharmony_ci " {\n" 936d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 946d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 956d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 966d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\n" 976d528ed9Sopenharmony_ci " },\n" 986d528ed9Sopenharmony_ci " {\n" 996d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\n" 1006d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 1016d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 1026d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\n" 1036d528ed9Sopenharmony_ci " }\n" 1046d528ed9Sopenharmony_ci "]\n"; 1056d528ed9Sopenharmony_ci#endif 1066d528ed9Sopenharmony_ci EXPECT_EQ(expected, out); 1076d528ed9Sopenharmony_ci } 1086d528ed9Sopenharmony_ci 1096d528ed9Sopenharmony_ci // A shared library that depends on the source set. 1106d528ed9Sopenharmony_ci Target shlib_target(settings(), Label(SourceDir("//foo/"), "shlib")); 1116d528ed9Sopenharmony_ci shlib_target.sources().push_back(SourceFile("//foo/input3.cc")); 1126d528ed9Sopenharmony_ci shlib_target.set_output_type(Target::SHARED_LIBRARY); 1136d528ed9Sopenharmony_ci shlib_target.public_deps().push_back(LabelTargetPair(&target)); 1146d528ed9Sopenharmony_ci shlib_target.SetToolchain(toolchain()); 1156d528ed9Sopenharmony_ci ASSERT_TRUE(shlib_target.OnResolved(&err)); 1166d528ed9Sopenharmony_ci targets.push_back(&shlib_target); 1176d528ed9Sopenharmony_ci 1186d528ed9Sopenharmony_ci { 1196d528ed9Sopenharmony_ci CompileCommandsWriter writer; 1206d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 1216d528ed9Sopenharmony_ci 1226d528ed9Sopenharmony_ci#if defined(OS_WIN) 1236d528ed9Sopenharmony_ci const char expected[] = 1246d528ed9Sopenharmony_ci "[\r\n" 1256d528ed9Sopenharmony_ci " {\r\n" 1266d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 1276d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 1286d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 1296d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\r\n" 1306d528ed9Sopenharmony_ci " },\r\n" 1316d528ed9Sopenharmony_ci " {\r\n" 1326d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\r\n" 1336d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 1346d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 1356d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\r\n" 1366d528ed9Sopenharmony_ci " },\r\n" 1376d528ed9Sopenharmony_ci " {\r\n" 1386d528ed9Sopenharmony_ci " \"file\": \"../../foo/input3.cc\",\r\n" 1396d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 1406d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input3.cc -o " 1416d528ed9Sopenharmony_ci "obj/foo/libshlib.input3.o\"\r\n" 1426d528ed9Sopenharmony_ci " }\r\n" 1436d528ed9Sopenharmony_ci "]\r\n"; 1446d528ed9Sopenharmony_ci#else 1456d528ed9Sopenharmony_ci const char expected[] = 1466d528ed9Sopenharmony_ci "[\n" 1476d528ed9Sopenharmony_ci " {\n" 1486d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 1496d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 1506d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 1516d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\n" 1526d528ed9Sopenharmony_ci " },\n" 1536d528ed9Sopenharmony_ci " {\n" 1546d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\n" 1556d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 1566d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 1576d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\n" 1586d528ed9Sopenharmony_ci " },\n" 1596d528ed9Sopenharmony_ci " {\n" 1606d528ed9Sopenharmony_ci " \"file\": \"../../foo/input3.cc\",\n" 1616d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 1626d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input3.cc -o " 1636d528ed9Sopenharmony_ci "obj/foo/libshlib.input3.o\"\n" 1646d528ed9Sopenharmony_ci " }\n" 1656d528ed9Sopenharmony_ci "]\n"; 1666d528ed9Sopenharmony_ci#endif 1676d528ed9Sopenharmony_ci EXPECT_EQ(expected, out); 1686d528ed9Sopenharmony_ci } 1696d528ed9Sopenharmony_ci 1706d528ed9Sopenharmony_ci // A static library that depends on the source set (should not link it). 1716d528ed9Sopenharmony_ci Target stlib_target(settings(), Label(SourceDir("//foo/"), "stlib")); 1726d528ed9Sopenharmony_ci stlib_target.sources().push_back(SourceFile("//foo/input4.cc")); 1736d528ed9Sopenharmony_ci stlib_target.set_output_type(Target::STATIC_LIBRARY); 1746d528ed9Sopenharmony_ci stlib_target.public_deps().push_back(LabelTargetPair(&target)); 1756d528ed9Sopenharmony_ci stlib_target.SetToolchain(toolchain()); 1766d528ed9Sopenharmony_ci ASSERT_TRUE(stlib_target.OnResolved(&err)); 1776d528ed9Sopenharmony_ci targets.push_back(&stlib_target); 1786d528ed9Sopenharmony_ci 1796d528ed9Sopenharmony_ci { 1806d528ed9Sopenharmony_ci CompileCommandsWriter writer; 1816d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 1826d528ed9Sopenharmony_ci 1836d528ed9Sopenharmony_ci#if defined(OS_WIN) 1846d528ed9Sopenharmony_ci const char expected[] = 1856d528ed9Sopenharmony_ci "[\r\n" 1866d528ed9Sopenharmony_ci " {\r\n" 1876d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 1886d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 1896d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 1906d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\r\n" 1916d528ed9Sopenharmony_ci " },\r\n" 1926d528ed9Sopenharmony_ci " {\r\n" 1936d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\r\n" 1946d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 1956d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 1966d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\r\n" 1976d528ed9Sopenharmony_ci " },\r\n" 1986d528ed9Sopenharmony_ci " {\r\n" 1996d528ed9Sopenharmony_ci " \"file\": \"../../foo/input3.cc\",\r\n" 2006d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 2016d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input3.cc -o " 2026d528ed9Sopenharmony_ci "obj/foo/libshlib.input3.o\"\r\n" 2036d528ed9Sopenharmony_ci " },\r\n" 2046d528ed9Sopenharmony_ci " {\r\n" 2056d528ed9Sopenharmony_ci " \"file\": \"../../foo/input4.cc\",\r\n" 2066d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 2076d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input4.cc -o " 2086d528ed9Sopenharmony_ci "obj/foo/libstlib.input4.o\"\r\n" 2096d528ed9Sopenharmony_ci " }\r\n" 2106d528ed9Sopenharmony_ci "]\r\n"; 2116d528ed9Sopenharmony_ci#else 2126d528ed9Sopenharmony_ci const char expected[] = 2136d528ed9Sopenharmony_ci "[\n" 2146d528ed9Sopenharmony_ci " {\n" 2156d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 2166d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 2176d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 2186d528ed9Sopenharmony_ci "obj/foo/bar.input1.o\"\n" 2196d528ed9Sopenharmony_ci " },\n" 2206d528ed9Sopenharmony_ci " {\n" 2216d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.cc\",\n" 2226d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 2236d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input2.cc -o " 2246d528ed9Sopenharmony_ci "obj/foo/bar.input2.o\"\n" 2256d528ed9Sopenharmony_ci " },\n" 2266d528ed9Sopenharmony_ci " {\n" 2276d528ed9Sopenharmony_ci " \"file\": \"../../foo/input3.cc\",\n" 2286d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 2296d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input3.cc -o " 2306d528ed9Sopenharmony_ci "obj/foo/libshlib.input3.o\"\n" 2316d528ed9Sopenharmony_ci " },\n" 2326d528ed9Sopenharmony_ci " {\n" 2336d528ed9Sopenharmony_ci " \"file\": \"../../foo/input4.cc\",\n" 2346d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 2356d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input4.cc -o " 2366d528ed9Sopenharmony_ci "obj/foo/libstlib.input4.o\"\n" 2376d528ed9Sopenharmony_ci " }\n" 2386d528ed9Sopenharmony_ci "]\n"; 2396d528ed9Sopenharmony_ci#endif 2406d528ed9Sopenharmony_ci EXPECT_EQ(expected, out); 2416d528ed9Sopenharmony_ci } 2426d528ed9Sopenharmony_ci} 2436d528ed9Sopenharmony_ci 2446d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, EscapeDefines) { 2456d528ed9Sopenharmony_ci Err err; 2466d528ed9Sopenharmony_ci 2476d528ed9Sopenharmony_ci std::vector<const Target*> targets; 2486d528ed9Sopenharmony_ci TestTarget target(setup(), "//foo:bar", Target::STATIC_LIBRARY); 2496d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input.cc")); 2506d528ed9Sopenharmony_ci target.config_values().defines().push_back("BOOL_DEF"); 2516d528ed9Sopenharmony_ci target.config_values().defines().push_back("INT_DEF=123"); 2526d528ed9Sopenharmony_ci target.config_values().defines().push_back("STR_DEF=\"ABCD 1\""); 2536d528ed9Sopenharmony_ci target.config_values().defines().push_back("INCLUDE=<header.h>"); 2546d528ed9Sopenharmony_ci ASSERT_TRUE(target.OnResolved(&err)); 2556d528ed9Sopenharmony_ci targets.push_back(&target); 2566d528ed9Sopenharmony_ci 2576d528ed9Sopenharmony_ci CompileCommandsWriter writer; 2586d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 2596d528ed9Sopenharmony_ci 2606d528ed9Sopenharmony_ci const char expected[] = 2616d528ed9Sopenharmony_ci "-DBOOL_DEF -DINT_DEF=123 \\\"-DSTR_DEF=\\\\\\\"ABCD 1\\\\\\\"\\\" " 2626d528ed9Sopenharmony_ci "\\\"-DINCLUDE=\\u003Cheader.h>\\\""; 2636d528ed9Sopenharmony_ci EXPECT_TRUE(out.find(expected) != std::string::npos); 2646d528ed9Sopenharmony_ci} 2656d528ed9Sopenharmony_ci 2666d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, WinPrecompiledHeaders) { 2676d528ed9Sopenharmony_ci Err err; 2686d528ed9Sopenharmony_ci 2696d528ed9Sopenharmony_ci // This setup's toolchain does not have precompiled headers defined. 2706d528ed9Sopenharmony_ci // A precompiled header toolchain. 2716d528ed9Sopenharmony_ci Settings pch_settings(build_settings(), "withpch/"); 2726d528ed9Sopenharmony_ci Toolchain pch_toolchain(&pch_settings, 2736d528ed9Sopenharmony_ci Label(SourceDir("//toolchain/"), "withpch")); 2746d528ed9Sopenharmony_ci pch_settings.set_toolchain_label(pch_toolchain.label()); 2756d528ed9Sopenharmony_ci pch_settings.set_default_toolchain_label(toolchain()->label()); 2766d528ed9Sopenharmony_ci 2776d528ed9Sopenharmony_ci // Declare a C++ compiler that supports PCH. 2786d528ed9Sopenharmony_ci std::unique_ptr<Tool> cxx = Tool::CreateTool(CTool::kCToolCxx); 2796d528ed9Sopenharmony_ci CTool* cxx_tool = cxx->AsC(); 2806d528ed9Sopenharmony_ci TestWithScope::SetCommandForTool( 2816d528ed9Sopenharmony_ci "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " 2826d528ed9Sopenharmony_ci "-o {{output}}", 2836d528ed9Sopenharmony_ci cxx_tool); 2846d528ed9Sopenharmony_ci cxx_tool->set_outputs(SubstitutionList::MakeForTest( 2856d528ed9Sopenharmony_ci "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); 2866d528ed9Sopenharmony_ci cxx_tool->set_precompiled_header_type(CTool::PCH_MSVC); 2876d528ed9Sopenharmony_ci pch_toolchain.SetTool(std::move(cxx)); 2886d528ed9Sopenharmony_ci 2896d528ed9Sopenharmony_ci // Add a C compiler as well. 2906d528ed9Sopenharmony_ci std::unique_ptr<Tool> cc = Tool::CreateTool(CTool::kCToolCc); 2916d528ed9Sopenharmony_ci CTool* cc_tool = cc->AsC(); 2926d528ed9Sopenharmony_ci TestWithScope::SetCommandForTool( 2936d528ed9Sopenharmony_ci "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " 2946d528ed9Sopenharmony_ci "-o {{output}}", 2956d528ed9Sopenharmony_ci cc_tool); 2966d528ed9Sopenharmony_ci cc_tool->set_outputs(SubstitutionList::MakeForTest( 2976d528ed9Sopenharmony_ci "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); 2986d528ed9Sopenharmony_ci cc_tool->set_precompiled_header_type(CTool::PCH_MSVC); 2996d528ed9Sopenharmony_ci pch_toolchain.SetTool(std::move(cc)); 3006d528ed9Sopenharmony_ci pch_toolchain.ToolchainSetupComplete(); 3016d528ed9Sopenharmony_ci 3026d528ed9Sopenharmony_ci // This target doesn't specify precompiled headers. 3036d528ed9Sopenharmony_ci { 3046d528ed9Sopenharmony_ci std::vector<const Target*> targets; 3056d528ed9Sopenharmony_ci Target no_pch_target(&pch_settings, 3066d528ed9Sopenharmony_ci Label(SourceDir("//foo/"), "no_pch_target")); 3076d528ed9Sopenharmony_ci no_pch_target.set_output_type(Target::SOURCE_SET); 3086d528ed9Sopenharmony_ci no_pch_target.visibility().SetPublic(); 3096d528ed9Sopenharmony_ci no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); 3106d528ed9Sopenharmony_ci no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); 3116d528ed9Sopenharmony_ci no_pch_target.config_values().cflags_c().push_back("-std=c99"); 3126d528ed9Sopenharmony_ci no_pch_target.SetToolchain(&pch_toolchain); 3136d528ed9Sopenharmony_ci ASSERT_TRUE(no_pch_target.OnResolved(&err)); 3146d528ed9Sopenharmony_ci targets.push_back(&no_pch_target); 3156d528ed9Sopenharmony_ci 3166d528ed9Sopenharmony_ci CompileCommandsWriter writer; 3176d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 3186d528ed9Sopenharmony_ci 3196d528ed9Sopenharmony_ci#if defined(OS_WIN) 3206d528ed9Sopenharmony_ci const char no_pch_expected[] = 3216d528ed9Sopenharmony_ci "[\r\n" 3226d528ed9Sopenharmony_ci " {\r\n" 3236d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 3246d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 3256d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 3266d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input1.o\"\r\n" 3276d528ed9Sopenharmony_ci " },\r\n" 3286d528ed9Sopenharmony_ci " {\r\n" 3296d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\r\n" 3306d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 3316d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -o " 3326d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input2.o\"\r\n" 3336d528ed9Sopenharmony_ci " }\r\n" 3346d528ed9Sopenharmony_ci "]\r\n"; 3356d528ed9Sopenharmony_ci#else 3366d528ed9Sopenharmony_ci const char no_pch_expected[] = 3376d528ed9Sopenharmony_ci "[\n" 3386d528ed9Sopenharmony_ci " {\n" 3396d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 3406d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 3416d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 3426d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input1.o\"\n" 3436d528ed9Sopenharmony_ci " },\n" 3446d528ed9Sopenharmony_ci " {\n" 3456d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\n" 3466d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 3476d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -o " 3486d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input2.o\"\n" 3496d528ed9Sopenharmony_ci " }\n" 3506d528ed9Sopenharmony_ci "]\n"; 3516d528ed9Sopenharmony_ci#endif 3526d528ed9Sopenharmony_ci EXPECT_EQ(no_pch_expected, out); 3536d528ed9Sopenharmony_ci } 3546d528ed9Sopenharmony_ci 3556d528ed9Sopenharmony_ci // This target specifies PCH. 3566d528ed9Sopenharmony_ci { 3576d528ed9Sopenharmony_ci std::vector<const Target*> targets; 3586d528ed9Sopenharmony_ci Target pch_target(&pch_settings, Label(SourceDir("//foo/"), "pch_target")); 3596d528ed9Sopenharmony_ci pch_target.config_values().set_precompiled_header("build/precompile.h"); 3606d528ed9Sopenharmony_ci pch_target.config_values().set_precompiled_source( 3616d528ed9Sopenharmony_ci SourceFile("//build/precompile.cc")); 3626d528ed9Sopenharmony_ci pch_target.set_output_type(Target::SOURCE_SET); 3636d528ed9Sopenharmony_ci pch_target.visibility().SetPublic(); 3646d528ed9Sopenharmony_ci pch_target.sources().push_back(SourceFile("//foo/input1.cc")); 3656d528ed9Sopenharmony_ci pch_target.sources().push_back(SourceFile("//foo/input2.c")); 3666d528ed9Sopenharmony_ci pch_target.SetToolchain(&pch_toolchain); 3676d528ed9Sopenharmony_ci ASSERT_TRUE(pch_target.OnResolved(&err)); 3686d528ed9Sopenharmony_ci targets.push_back(&pch_target); 3696d528ed9Sopenharmony_ci 3706d528ed9Sopenharmony_ci CompileCommandsWriter writer; 3716d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 3726d528ed9Sopenharmony_ci 3736d528ed9Sopenharmony_ci#if defined(OS_WIN) 3746d528ed9Sopenharmony_ci const char pch_win_expected[] = 3756d528ed9Sopenharmony_ci "[\r\n" 3766d528ed9Sopenharmony_ci " {\r\n" 3776d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 3786d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 3796d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc " 3806d528ed9Sopenharmony_ci "/Fpwithpch/obj/foo/pch_target_cc.pch /Yubuild/precompile.h -o " 3816d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input1.o\"\r\n" 3826d528ed9Sopenharmony_ci " },\r\n" 3836d528ed9Sopenharmony_ci " {\r\n" 3846d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\r\n" 3856d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 3866d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c " 3876d528ed9Sopenharmony_ci "/Fpwithpch/obj/foo/pch_target_c.pch /Yubuild/precompile.h -o " 3886d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input2.o\"\r\n" 3896d528ed9Sopenharmony_ci " }\r\n" 3906d528ed9Sopenharmony_ci "]\r\n"; 3916d528ed9Sopenharmony_ci#else 3926d528ed9Sopenharmony_ci const char pch_win_expected[] = 3936d528ed9Sopenharmony_ci "[\n" 3946d528ed9Sopenharmony_ci " {\n" 3956d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 3966d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 3976d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc " 3986d528ed9Sopenharmony_ci "/Fpwithpch/obj/foo/pch_target_cc.pch /Yubuild/precompile.h -o " 3996d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input1.o\"\n" 4006d528ed9Sopenharmony_ci " },\n" 4016d528ed9Sopenharmony_ci " {\n" 4026d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\n" 4036d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 4046d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c " 4056d528ed9Sopenharmony_ci "/Fpwithpch/obj/foo/pch_target_c.pch /Yubuild/precompile.h -o " 4066d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input2.o\"\n" 4076d528ed9Sopenharmony_ci " }\n" 4086d528ed9Sopenharmony_ci "]\n"; 4096d528ed9Sopenharmony_ci#endif 4106d528ed9Sopenharmony_ci EXPECT_EQ(pch_win_expected, out); 4116d528ed9Sopenharmony_ci } 4126d528ed9Sopenharmony_ci} 4136d528ed9Sopenharmony_ci 4146d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, GCCPrecompiledHeaders) { 4156d528ed9Sopenharmony_ci Err err; 4166d528ed9Sopenharmony_ci 4176d528ed9Sopenharmony_ci // This setup's toolchain does not have precompiled headers defined. 4186d528ed9Sopenharmony_ci // A precompiled header toolchain. 4196d528ed9Sopenharmony_ci Settings pch_settings(build_settings(), "withpch/"); 4206d528ed9Sopenharmony_ci Toolchain pch_toolchain(&pch_settings, 4216d528ed9Sopenharmony_ci Label(SourceDir("//toolchain/"), "withpch")); 4226d528ed9Sopenharmony_ci pch_settings.set_toolchain_label(pch_toolchain.label()); 4236d528ed9Sopenharmony_ci pch_settings.set_default_toolchain_label(toolchain()->label()); 4246d528ed9Sopenharmony_ci 4256d528ed9Sopenharmony_ci // Declare a C++ compiler that supports PCH. 4266d528ed9Sopenharmony_ci std::unique_ptr<Tool> cxx = Tool::CreateTool(CTool::kCToolCxx); 4276d528ed9Sopenharmony_ci CTool* cxx_tool = cxx->AsC(); 4286d528ed9Sopenharmony_ci TestWithScope::SetCommandForTool( 4296d528ed9Sopenharmony_ci "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} " 4306d528ed9Sopenharmony_ci "-o {{output}}", 4316d528ed9Sopenharmony_ci cxx_tool); 4326d528ed9Sopenharmony_ci cxx_tool->set_outputs(SubstitutionList::MakeForTest( 4336d528ed9Sopenharmony_ci "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); 4346d528ed9Sopenharmony_ci cxx_tool->set_precompiled_header_type(CTool::PCH_GCC); 4356d528ed9Sopenharmony_ci pch_toolchain.SetTool(std::move(cxx)); 4366d528ed9Sopenharmony_ci pch_toolchain.ToolchainSetupComplete(); 4376d528ed9Sopenharmony_ci 4386d528ed9Sopenharmony_ci // Add a C compiler as well. 4396d528ed9Sopenharmony_ci std::unique_ptr<Tool> cc = Tool::CreateTool(CTool::kCToolCc); 4406d528ed9Sopenharmony_ci CTool* cc_tool = cc->AsC(); 4416d528ed9Sopenharmony_ci TestWithScope::SetCommandForTool( 4426d528ed9Sopenharmony_ci "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} " 4436d528ed9Sopenharmony_ci "-o {{output}}", 4446d528ed9Sopenharmony_ci cc_tool); 4456d528ed9Sopenharmony_ci cc_tool->set_outputs(SubstitutionList::MakeForTest( 4466d528ed9Sopenharmony_ci "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o")); 4476d528ed9Sopenharmony_ci cc_tool->set_precompiled_header_type(CTool::PCH_GCC); 4486d528ed9Sopenharmony_ci pch_toolchain.SetTool(std::move(cc)); 4496d528ed9Sopenharmony_ci pch_toolchain.ToolchainSetupComplete(); 4506d528ed9Sopenharmony_ci 4516d528ed9Sopenharmony_ci // This target doesn't specify precompiled headers. 4526d528ed9Sopenharmony_ci { 4536d528ed9Sopenharmony_ci std::vector<const Target*> targets; 4546d528ed9Sopenharmony_ci Target no_pch_target(&pch_settings, 4556d528ed9Sopenharmony_ci Label(SourceDir("//foo/"), "no_pch_target")); 4566d528ed9Sopenharmony_ci no_pch_target.set_output_type(Target::SOURCE_SET); 4576d528ed9Sopenharmony_ci no_pch_target.visibility().SetPublic(); 4586d528ed9Sopenharmony_ci no_pch_target.sources().push_back(SourceFile("//foo/input1.cc")); 4596d528ed9Sopenharmony_ci no_pch_target.sources().push_back(SourceFile("//foo/input2.c")); 4606d528ed9Sopenharmony_ci no_pch_target.config_values().cflags_c().push_back("-std=c99"); 4616d528ed9Sopenharmony_ci no_pch_target.SetToolchain(&pch_toolchain); 4626d528ed9Sopenharmony_ci ASSERT_TRUE(no_pch_target.OnResolved(&err)); 4636d528ed9Sopenharmony_ci targets.push_back(&no_pch_target); 4646d528ed9Sopenharmony_ci 4656d528ed9Sopenharmony_ci CompileCommandsWriter writer; 4666d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 4676d528ed9Sopenharmony_ci 4686d528ed9Sopenharmony_ci#if defined(OS_WIN) 4696d528ed9Sopenharmony_ci const char no_pch_expected[] = 4706d528ed9Sopenharmony_ci "[\r\n" 4716d528ed9Sopenharmony_ci " {\r\n" 4726d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 4736d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 4746d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 4756d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input1.o\"\r\n" 4766d528ed9Sopenharmony_ci " },\r\n" 4776d528ed9Sopenharmony_ci " {\r\n" 4786d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\r\n" 4796d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 4806d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -o " 4816d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input2.o\"\r\n" 4826d528ed9Sopenharmony_ci " }\r\n" 4836d528ed9Sopenharmony_ci "]\r\n"; 4846d528ed9Sopenharmony_ci#else 4856d528ed9Sopenharmony_ci const char no_pch_expected[] = 4866d528ed9Sopenharmony_ci "[\n" 4876d528ed9Sopenharmony_ci " {\n" 4886d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 4896d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 4906d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -o " 4916d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input1.o\"\n" 4926d528ed9Sopenharmony_ci " },\n" 4936d528ed9Sopenharmony_ci " {\n" 4946d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\n" 4956d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 4966d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -o " 4976d528ed9Sopenharmony_ci "withpch/obj/foo/no_pch_target.input2.o\"\n" 4986d528ed9Sopenharmony_ci " }\n" 4996d528ed9Sopenharmony_ci "]\n"; 5006d528ed9Sopenharmony_ci#endif 5016d528ed9Sopenharmony_ci EXPECT_EQ(no_pch_expected, out); 5026d528ed9Sopenharmony_ci } 5036d528ed9Sopenharmony_ci 5046d528ed9Sopenharmony_ci // This target specifies PCH. 5056d528ed9Sopenharmony_ci { 5066d528ed9Sopenharmony_ci std::vector<const Target*> targets; 5076d528ed9Sopenharmony_ci Target pch_target(&pch_settings, Label(SourceDir("//foo/"), "pch_target")); 5086d528ed9Sopenharmony_ci pch_target.config_values().set_precompiled_source( 5096d528ed9Sopenharmony_ci SourceFile("//build/precompile.h")); 5106d528ed9Sopenharmony_ci pch_target.config_values().cflags_c().push_back("-std=c99"); 5116d528ed9Sopenharmony_ci pch_target.set_output_type(Target::SOURCE_SET); 5126d528ed9Sopenharmony_ci pch_target.visibility().SetPublic(); 5136d528ed9Sopenharmony_ci pch_target.sources().push_back(SourceFile("//foo/input1.cc")); 5146d528ed9Sopenharmony_ci pch_target.sources().push_back(SourceFile("//foo/input2.c")); 5156d528ed9Sopenharmony_ci pch_target.SetToolchain(&pch_toolchain); 5166d528ed9Sopenharmony_ci ASSERT_TRUE(pch_target.OnResolved(&err)); 5176d528ed9Sopenharmony_ci targets.push_back(&pch_target); 5186d528ed9Sopenharmony_ci 5196d528ed9Sopenharmony_ci CompileCommandsWriter writer; 5206d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 5216d528ed9Sopenharmony_ci 5226d528ed9Sopenharmony_ci#if defined(OS_WIN) 5236d528ed9Sopenharmony_ci const char pch_gcc_expected[] = 5246d528ed9Sopenharmony_ci "[\r\n" 5256d528ed9Sopenharmony_ci " {\r\n" 5266d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\r\n" 5276d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 5286d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -include " 5296d528ed9Sopenharmony_ci "withpch/obj/build/pch_target.precompile.h-cc -o " 5306d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input1.o\"\r\n" 5316d528ed9Sopenharmony_ci " },\r\n" 5326d528ed9Sopenharmony_ci " {\r\n" 5336d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\r\n" 5346d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 5356d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -include " 5366d528ed9Sopenharmony_ci "withpch/obj/build/pch_target.precompile.h-c -o " 5376d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input2.o\"\r\n" 5386d528ed9Sopenharmony_ci " }\r\n" 5396d528ed9Sopenharmony_ci "]\r\n"; 5406d528ed9Sopenharmony_ci#else 5416d528ed9Sopenharmony_ci const char pch_gcc_expected[] = 5426d528ed9Sopenharmony_ci "[\n" 5436d528ed9Sopenharmony_ci " {\n" 5446d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.cc\",\n" 5456d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 5466d528ed9Sopenharmony_ci " \"command\": \"c++ ../../foo/input1.cc -include " 5476d528ed9Sopenharmony_ci "withpch/obj/build/pch_target.precompile.h-cc -o " 5486d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input1.o\"\n" 5496d528ed9Sopenharmony_ci " },\n" 5506d528ed9Sopenharmony_ci " {\n" 5516d528ed9Sopenharmony_ci " \"file\": \"../../foo/input2.c\",\n" 5526d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 5536d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input2.c -std=c99 -include " 5546d528ed9Sopenharmony_ci "withpch/obj/build/pch_target.precompile.h-c -o " 5556d528ed9Sopenharmony_ci "withpch/obj/foo/pch_target.input2.o\"\n" 5566d528ed9Sopenharmony_ci " }\n" 5576d528ed9Sopenharmony_ci "]\n"; 5586d528ed9Sopenharmony_ci#endif 5596d528ed9Sopenharmony_ci EXPECT_EQ(pch_gcc_expected, out); 5606d528ed9Sopenharmony_ci } 5616d528ed9Sopenharmony_ci} 5626d528ed9Sopenharmony_ci 5636d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, EscapedFlags) { 5646d528ed9Sopenharmony_ci Err err; 5656d528ed9Sopenharmony_ci 5666d528ed9Sopenharmony_ci std::vector<const Target*> targets; 5676d528ed9Sopenharmony_ci Target target(settings(), Label(SourceDir("//foo/"), "bar")); 5686d528ed9Sopenharmony_ci target.set_output_type(Target::SOURCE_SET); 5696d528ed9Sopenharmony_ci target.sources().push_back(SourceFile("//foo/input1.c")); 5706d528ed9Sopenharmony_ci target.config_values().cflags_c().push_back("-DCONFIG=\"/config\""); 5716d528ed9Sopenharmony_ci target.SetToolchain(toolchain()); 5726d528ed9Sopenharmony_ci ASSERT_TRUE(target.OnResolved(&err)); 5736d528ed9Sopenharmony_ci targets.push_back(&target); 5746d528ed9Sopenharmony_ci 5756d528ed9Sopenharmony_ci CompileCommandsWriter writer; 5766d528ed9Sopenharmony_ci std::string out = writer.RenderJSON(build_settings(), targets); 5776d528ed9Sopenharmony_ci 5786d528ed9Sopenharmony_ci#if defined(OS_WIN) 5796d528ed9Sopenharmony_ci const char expected[] = 5806d528ed9Sopenharmony_ci "[\r\n" 5816d528ed9Sopenharmony_ci " {\r\n" 5826d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.c\",\r\n" 5836d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\r\n" 5846d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input1.c -DCONFIG=\\\"/config\\\" " 5856d528ed9Sopenharmony_ci "-o obj/foo/bar.input1.o\"\r\n" 5866d528ed9Sopenharmony_ci " }\r\n" 5876d528ed9Sopenharmony_ci "]\r\n"; 5886d528ed9Sopenharmony_ci#else 5896d528ed9Sopenharmony_ci const char expected[] = 5906d528ed9Sopenharmony_ci "[\n" 5916d528ed9Sopenharmony_ci " {\n" 5926d528ed9Sopenharmony_ci " \"file\": \"../../foo/input1.c\",\n" 5936d528ed9Sopenharmony_ci " \"directory\": \"out/Debug\",\n" 5946d528ed9Sopenharmony_ci " \"command\": \"cc ../../foo/input1.c -DCONFIG=\\\"/config\\\" " 5956d528ed9Sopenharmony_ci "-o obj/foo/bar.input1.o\"\n" 5966d528ed9Sopenharmony_ci " }\n" 5976d528ed9Sopenharmony_ci "]\n"; 5986d528ed9Sopenharmony_ci#endif 5996d528ed9Sopenharmony_ci EXPECT_EQ(expected, out); 6006d528ed9Sopenharmony_ci} 6016d528ed9Sopenharmony_ci 6026d528ed9Sopenharmony_ciTEST_F(CompileCommandsTest, CollectTargets) { 6036d528ed9Sopenharmony_ci // Contruct the dependency tree: 6046d528ed9Sopenharmony_ci // 6056d528ed9Sopenharmony_ci // //foo:bar1 6066d528ed9Sopenharmony_ci // //base:base 6076d528ed9Sopenharmony_ci // //foo:bar2 6086d528ed9Sopenharmony_ci // //base:i18n 6096d528ed9Sopenharmony_ci // //base:base 6106d528ed9Sopenharmony_ci // //third_party:icu 6116d528ed9Sopenharmony_ci // //random:random 6126d528ed9Sopenharmony_ci Err err; 6136d528ed9Sopenharmony_ci std::vector<const Target*> targets; 6146d528ed9Sopenharmony_ci 6156d528ed9Sopenharmony_ci Target icu_target(settings(), Label(SourceDir("//third_party/"), "icu")); 6166d528ed9Sopenharmony_ci icu_target.set_output_type(Target::SOURCE_SET); 6176d528ed9Sopenharmony_ci icu_target.visibility().SetPublic(); 6186d528ed9Sopenharmony_ci icu_target.SetToolchain(toolchain()); 6196d528ed9Sopenharmony_ci ASSERT_TRUE(icu_target.OnResolved(&err)); 6206d528ed9Sopenharmony_ci targets.push_back(&icu_target); 6216d528ed9Sopenharmony_ci 6226d528ed9Sopenharmony_ci Target base_target(settings(), Label(SourceDir("//base/"), "base")); 6236d528ed9Sopenharmony_ci base_target.set_output_type(Target::SOURCE_SET); 6246d528ed9Sopenharmony_ci base_target.visibility().SetPublic(); 6256d528ed9Sopenharmony_ci base_target.SetToolchain(toolchain()); 6266d528ed9Sopenharmony_ci ASSERT_TRUE(base_target.OnResolved(&err)); 6276d528ed9Sopenharmony_ci targets.push_back(&base_target); 6286d528ed9Sopenharmony_ci 6296d528ed9Sopenharmony_ci Target base_i18n(settings(), Label(SourceDir("//base/"), "i18n")); 6306d528ed9Sopenharmony_ci base_i18n.set_output_type(Target::SOURCE_SET); 6316d528ed9Sopenharmony_ci base_i18n.visibility().SetPublic(); 6326d528ed9Sopenharmony_ci base_i18n.private_deps().push_back(LabelTargetPair(&icu_target)); 6336d528ed9Sopenharmony_ci base_i18n.public_deps().push_back(LabelTargetPair(&base_target)); 6346d528ed9Sopenharmony_ci base_i18n.SetToolchain(toolchain()); 6356d528ed9Sopenharmony_ci ASSERT_TRUE(base_i18n.OnResolved(&err)) 6366d528ed9Sopenharmony_ci << err.message() << " " << err.help_text(); 6376d528ed9Sopenharmony_ci targets.push_back(&base_i18n); 6386d528ed9Sopenharmony_ci 6396d528ed9Sopenharmony_ci Target target1(settings(), Label(SourceDir("//foo/"), "bar1")); 6406d528ed9Sopenharmony_ci target1.set_output_type(Target::SOURCE_SET); 6416d528ed9Sopenharmony_ci target1.public_deps().push_back(LabelTargetPair(&base_target)); 6426d528ed9Sopenharmony_ci target1.SetToolchain(toolchain()); 6436d528ed9Sopenharmony_ci ASSERT_TRUE(target1.OnResolved(&err)); 6446d528ed9Sopenharmony_ci targets.push_back(&target1); 6456d528ed9Sopenharmony_ci 6466d528ed9Sopenharmony_ci Target target2(settings(), Label(SourceDir("//foo/"), "bar2")); 6476d528ed9Sopenharmony_ci target2.set_output_type(Target::SOURCE_SET); 6486d528ed9Sopenharmony_ci target2.public_deps().push_back(LabelTargetPair(&base_i18n)); 6496d528ed9Sopenharmony_ci target2.SetToolchain(toolchain()); 6506d528ed9Sopenharmony_ci ASSERT_TRUE(target2.OnResolved(&err)); 6516d528ed9Sopenharmony_ci targets.push_back(&target2); 6526d528ed9Sopenharmony_ci 6536d528ed9Sopenharmony_ci Target random_target(settings(), Label(SourceDir("//random/"), "random")); 6546d528ed9Sopenharmony_ci random_target.set_output_type(Target::SOURCE_SET); 6556d528ed9Sopenharmony_ci random_target.SetToolchain(toolchain()); 6566d528ed9Sopenharmony_ci ASSERT_TRUE(random_target.OnResolved(&err)); 6576d528ed9Sopenharmony_ci targets.push_back(&random_target); 6586d528ed9Sopenharmony_ci 6596d528ed9Sopenharmony_ci // Collect everything, the result should match the input. 6606d528ed9Sopenharmony_ci const std::string source_root("/home/me/build/"); 6616d528ed9Sopenharmony_ci LabelPattern wildcard_pattern = LabelPattern::GetPattern( 6626d528ed9Sopenharmony_ci SourceDir(), source_root, Value(nullptr, "//*"), &err); 6636d528ed9Sopenharmony_ci ASSERT_FALSE(err.has_error()); 6646d528ed9Sopenharmony_ci std::vector<const Target*> output = CompileCommandsWriter::CollectTargets( 6656d528ed9Sopenharmony_ci build_settings(), targets, std::vector<LabelPattern>{wildcard_pattern}, 6666d528ed9Sopenharmony_ci std::nullopt, &err); 6676d528ed9Sopenharmony_ci EXPECT_TRUE(VectorsEqual(output, targets)); 6686d528ed9Sopenharmony_ci 6696d528ed9Sopenharmony_ci // Collect nothing. 6706d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets(build_settings(), targets, 6716d528ed9Sopenharmony_ci std::vector<LabelPattern>(), 6726d528ed9Sopenharmony_ci std::nullopt, &err); 6736d528ed9Sopenharmony_ci EXPECT_TRUE(output.empty()); 6746d528ed9Sopenharmony_ci 6756d528ed9Sopenharmony_ci // Collect all deps of "//foo/*". 6766d528ed9Sopenharmony_ci LabelPattern foo_wildcard = LabelPattern::GetPattern( 6776d528ed9Sopenharmony_ci SourceDir(), source_root, Value(nullptr, "//foo/*"), &err); 6786d528ed9Sopenharmony_ci ASSERT_FALSE(err.has_error()); 6796d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets( 6806d528ed9Sopenharmony_ci build_settings(), targets, std::vector<LabelPattern>{foo_wildcard}, 6816d528ed9Sopenharmony_ci std::nullopt, &err); 6826d528ed9Sopenharmony_ci 6836d528ed9Sopenharmony_ci // The result should be everything except "random". 6846d528ed9Sopenharmony_ci std::sort(output.begin(), output.end(), &CompareLabel); 6856d528ed9Sopenharmony_ci ASSERT_EQ(5u, output.size()); 6866d528ed9Sopenharmony_ci EXPECT_EQ(&base_target, output[0]); 6876d528ed9Sopenharmony_ci EXPECT_EQ(&base_i18n, output[1]); 6886d528ed9Sopenharmony_ci EXPECT_EQ(&target1, output[2]); 6896d528ed9Sopenharmony_ci EXPECT_EQ(&target2, output[3]); 6906d528ed9Sopenharmony_ci EXPECT_EQ(&icu_target, output[4]); 6916d528ed9Sopenharmony_ci 6926d528ed9Sopenharmony_ci // Collect everything using the legacy filter (present string but empty). 6936d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets(build_settings(), targets, 6946d528ed9Sopenharmony_ci std::vector<LabelPattern>{}, 6956d528ed9Sopenharmony_ci std::string(), &err); 6966d528ed9Sopenharmony_ci EXPECT_TRUE(VectorsEqual(output, targets)); 6976d528ed9Sopenharmony_ci 6986d528ed9Sopenharmony_ci // Collect all deps of "bar2" using the legacy filter. 6996d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets(build_settings(), targets, 7006d528ed9Sopenharmony_ci std::vector<LabelPattern>{}, 7016d528ed9Sopenharmony_ci std::string("bar2"), &err); 7026d528ed9Sopenharmony_ci std::sort(output.begin(), output.end(), &CompareLabel); 7036d528ed9Sopenharmony_ci ASSERT_EQ(4u, output.size()); 7046d528ed9Sopenharmony_ci EXPECT_EQ(&base_target, output[0]); 7056d528ed9Sopenharmony_ci EXPECT_EQ(&base_i18n, output[1]); 7066d528ed9Sopenharmony_ci EXPECT_EQ(&target2, output[2]); 7076d528ed9Sopenharmony_ci EXPECT_EQ(&icu_target, output[3]); 7086d528ed9Sopenharmony_ci 7096d528ed9Sopenharmony_ci // Collect all deps of "bar1" and "bar2" using the legacy filter. 7106d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets( 7116d528ed9Sopenharmony_ci build_settings(), targets, std::vector<LabelPattern>{}, 7126d528ed9Sopenharmony_ci std::string("bar2,bar1"), &err); 7136d528ed9Sopenharmony_ci std::sort(output.begin(), output.end(), &CompareLabel); 7146d528ed9Sopenharmony_ci ASSERT_EQ(5u, output.size()); 7156d528ed9Sopenharmony_ci EXPECT_EQ(&base_target, output[0]); 7166d528ed9Sopenharmony_ci EXPECT_EQ(&base_i18n, output[1]); 7176d528ed9Sopenharmony_ci EXPECT_EQ(&target1, output[2]); 7186d528ed9Sopenharmony_ci EXPECT_EQ(&target2, output[3]); 7196d528ed9Sopenharmony_ci EXPECT_EQ(&icu_target, output[4]); 7206d528ed9Sopenharmony_ci 7216d528ed9Sopenharmony_ci // Combine the legacy (bar1) and pattern (bar2) filters, we should get the 7226d528ed9Sopenharmony_ci // union. 7236d528ed9Sopenharmony_ci LabelPattern foo_bar2 = LabelPattern::GetPattern( 7246d528ed9Sopenharmony_ci SourceDir(), source_root, Value(nullptr, "//foo:bar2"), &err); 7256d528ed9Sopenharmony_ci ASSERT_FALSE(err.has_error()); 7266d528ed9Sopenharmony_ci output = CompileCommandsWriter::CollectTargets( 7276d528ed9Sopenharmony_ci build_settings(), targets, std::vector<LabelPattern>{foo_bar2}, 7286d528ed9Sopenharmony_ci std::string("bar1"), &err); 7296d528ed9Sopenharmony_ci std::sort(output.begin(), output.end(), &CompareLabel); 7306d528ed9Sopenharmony_ci ASSERT_EQ(5u, output.size()); 7316d528ed9Sopenharmony_ci EXPECT_EQ(&base_target, output[0]); 7326d528ed9Sopenharmony_ci EXPECT_EQ(&base_i18n, output[1]); 7336d528ed9Sopenharmony_ci EXPECT_EQ(&target1, output[2]); 7346d528ed9Sopenharmony_ci EXPECT_EQ(&target2, output[3]); 7356d528ed9Sopenharmony_ci EXPECT_EQ(&icu_target, output[4]); 7366d528ed9Sopenharmony_ci} 737