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 <sstream> 6 7 #include "testing/gtest/include/gtest/gtest.h" 8 #include "tools/gn/ninja_binary_target_writer.h" 9 #include "tools/gn/test_with_scope.h" 10 11 TEST(NinjaBinaryTargetWriter, SourceSet) { 12 TestWithScope setup; 13 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/")); 14 setup.settings()->set_target_os(Settings::WIN); 15 16 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); 17 target.set_output_type(Target::SOURCE_SET); 18 target.sources().push_back(SourceFile("//foo/input1.cc")); 19 target.sources().push_back(SourceFile("//foo/input2.cc")); 20 // Also test object files, which should be just passed through to the 21 // dependents to link. 22 target.sources().push_back(SourceFile("//foo/input3.o")); 23 target.sources().push_back(SourceFile("//foo/input4.obj")); 24 target.OnResolved(); 25 26 // Source set itself. 27 { 28 std::ostringstream out; 29 NinjaBinaryTargetWriter writer(&target, setup.toolchain(), out); 30 writer.Run(); 31 32 // TODO(brettw) I think we'll need to worry about backslashes here 33 // depending if we're on actual Windows or Linux pretending to be Windows. 34 const char expected_win[] = 35 "defines =\n" 36 "includes =\n" 37 "cflags =\n" 38 "cflags_c =\n" 39 "cflags_cc =\n" 40 "cflags_objc =\n" 41 "cflags_objcc =\n" 42 "\n" 43 "build obj/foo/bar.input1.obj: cxx ../../foo/input1.cc\n" 44 "build obj/foo/bar.input2.obj: cxx ../../foo/input2.cc\n" 45 "\n" 46 "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.obj " 47 "obj/foo/bar.input2.obj ../../foo/input3.o ../../foo/input4.obj\n"; 48 std::string out_str = out.str(); 49 #if defined(OS_WIN) 50 std::replace(out_str.begin(), out_str.end(), '\\', '/'); 51 #endif 52 EXPECT_EQ(expected_win, out_str); 53 } 54 55 // A shared library that depends on the source set. 56 Target shlib_target(setup.settings(), Label(SourceDir("//foo/"), "shlib")); 57 shlib_target.set_output_type(Target::SHARED_LIBRARY); 58 shlib_target.deps().push_back(LabelTargetPair(&target)); 59 shlib_target.OnResolved(); 60 61 { 62 std::ostringstream out; 63 NinjaBinaryTargetWriter writer(&shlib_target, setup.toolchain(), out); 64 writer.Run(); 65 66 // TODO(brettw) I think we'll need to worry about backslashes here 67 // depending if we're on actual Windows or Linux pretending to be Windows. 68 const char expected_win[] = 69 "defines =\n" 70 "includes =\n" 71 "cflags =\n" 72 "cflags_c =\n" 73 "cflags_cc =\n" 74 "cflags_objc =\n" 75 "cflags_objcc =\n" 76 "\n" 77 "\n" 78 "manifests = obj/foo/shlib.intermediate.manifest\n" 79 "ldflags = /MANIFEST /ManifestFile:obj/foo/shlib.intermediate." 80 "manifest\n" 81 "libs =\n" 82 // Ordering of the obj files here is arbitrary. Currently they're put 83 // in a set and come out sorted. 84 "build shlib.dll shlib.dll.lib: solink ../../foo/input3.o " 85 "../../foo/input4.obj obj/foo/bar.input1.obj " 86 "obj/foo/bar.input2.obj\n" 87 " soname = shlib.dll\n" 88 " lib = shlib.dll\n" 89 " dll = shlib.dll\n" 90 " implibflag = /IMPLIB:shlib.dll.lib\n\n"; 91 std::string out_str = out.str(); 92 #if defined(OS_WIN) 93 std::replace(out_str.begin(), out_str.end(), '\\', '/'); 94 #endif 95 EXPECT_EQ(expected_win, out_str); 96 } 97 98 // A static library that depends on the source set (should not link it). 99 Target stlib_target(setup.settings(), Label(SourceDir("//foo/"), "stlib")); 100 stlib_target.set_output_type(Target::STATIC_LIBRARY); 101 stlib_target.deps().push_back(LabelTargetPair(&target)); 102 stlib_target.OnResolved(); 103 104 { 105 std::ostringstream out; 106 NinjaBinaryTargetWriter writer(&stlib_target, setup.toolchain(), out); 107 writer.Run(); 108 109 // TODO(brettw) I think we'll need to worry about backslashes here 110 // depending if we're on actual Windows or Linux pretending to be Windows. 111 const char expected_win[] = 112 "defines =\n" 113 "includes =\n" 114 "cflags =\n" 115 "cflags_c =\n" 116 "cflags_cc =\n" 117 "cflags_objc =\n" 118 "cflags_objcc =\n" 119 "\n" 120 "\n" 121 "manifests = obj/foo/stlib.intermediate.manifest\n" 122 "ldflags = /MANIFEST /ManifestFile:obj/foo/stlib.intermediate.manifest\n" 123 "libs =\n" 124 // There are no sources so there are no params to alink. 125 "build obj/foo/stlib.lib: alink\n\n"; 126 std::string out_str = out.str(); 127 #if defined(OS_WIN) 128 std::replace(out_str.begin(), out_str.end(), '\\', '/'); 129 #endif 130 EXPECT_EQ(expected_win, out_str); 131 } 132 133 } 134 135 TEST(NinjaBinaryTargetWriter, ProductExtension) { 136 TestWithScope setup; 137 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/")); 138 setup.settings()->set_target_os(Settings::LINUX); 139 140 // A shared library w/ the product_extension set to a custom value. 141 Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib")); 142 target.set_output_type(Target::SHARED_LIBRARY); 143 target.set_output_extension(std::string("so.6")); 144 target.sources().push_back(SourceFile("//foo/input1.cc")); 145 target.sources().push_back(SourceFile("//foo/input2.cc")); 146 target.OnResolved(); 147 148 std::ostringstream out; 149 NinjaBinaryTargetWriter writer(&target, setup.toolchain(), out); 150 writer.Run(); 151 152 // TODO(brettw) I think we'll need to worry about backslashes here 153 // depending if we're on actual Windows or Linux pretending to be Windows. 154 const char expected[] = 155 "defines =\n" 156 "includes =\n" 157 "cflags =\n" 158 "cflags_c =\n" 159 "cflags_cc =\n" 160 "cflags_objc =\n" 161 "cflags_objcc =\n" 162 "\n" 163 "build obj/foo/shlib.input1.o: cxx ../../foo/input1.cc\n" 164 "build obj/foo/shlib.input2.o: cxx ../../foo/input2.cc\n" 165 "\n" 166 "ldflags =\n" 167 "libs =\n" 168 "build lib/libshlib.so.6: solink obj/foo/shlib.input1.o " 169 "obj/foo/shlib.input2.o\n" 170 " soname = libshlib.so.6\n" 171 " lib = lib/libshlib.so.6\n" 172 "\n"; 173 174 std::string out_str = out.str(); 175 #if defined(OS_WIN) 176 std::replace(out_str.begin(), out_str.end(), '\\', '/'); 177 #endif 178 EXPECT_EQ(expected, out_str); 179 } 180 181 TEST(NinjaBinaryTargetWriter, EmptyProductExtension) { 182 TestWithScope setup; 183 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/")); 184 setup.settings()->set_target_os(Settings::LINUX); 185 186 // This test is the same as ProductExtension, except that 187 // we call set_output_extension("") and ensure that we still get the default. 188 Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib")); 189 target.set_output_type(Target::SHARED_LIBRARY); 190 target.set_output_extension(std::string()); 191 target.sources().push_back(SourceFile("//foo/input1.cc")); 192 target.sources().push_back(SourceFile("//foo/input2.cc")); 193 194 std::ostringstream out; 195 NinjaBinaryTargetWriter writer(&target, setup.toolchain(), out); 196 writer.Run(); 197 198 // TODO(brettw) I think we'll need to worry about backslashes here 199 // depending if we're on actual Windows or Linux pretending to be Windows. 200 const char expected[] = 201 "defines =\n" 202 "includes =\n" 203 "cflags =\n" 204 "cflags_c =\n" 205 "cflags_cc =\n" 206 "cflags_objc =\n" 207 "cflags_objcc =\n" 208 "\n" 209 "build obj/foo/shlib.input1.o: cxx ../../foo/input1.cc\n" 210 "build obj/foo/shlib.input2.o: cxx ../../foo/input2.cc\n" 211 "\n" 212 "ldflags =\n" 213 "libs =\n" 214 "build lib/libshlib.so: solink obj/foo/shlib.input1.o " 215 "obj/foo/shlib.input2.o\n" 216 " soname = libshlib.so\n" 217 " lib = lib/libshlib.so\n" 218 "\n"; 219 220 std::string out_str = out.str(); 221 #if defined(OS_WIN) 222 std::replace(out_str.begin(), out_str.end(), '\\', '/'); 223 #endif 224 EXPECT_EQ(expected, out_str); 225 } 226