1 module tests.ut.cpprules; 2 3 4 import reggae; 5 import reggae.options; 6 import reggae.backend.ninja; 7 import unit_threaded; 8 9 10 void testNoIncludePaths() { 11 auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp"))); 12 auto ninja = Ninja(build, "/tmp/myproject"); 13 ninja.buildEntries.shouldEqual( 14 [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp", 15 ["DEPFILE = path/to/src/foo.o.dep"]), 16 ]); 17 } 18 19 20 void testIncludePaths() { 21 auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp"), Flags(""), 22 IncludePaths(["path/to/src", "other/path"]))); 23 auto ninja = Ninja(build, "/tmp/myproject"); 24 ninja.buildEntries.shouldEqual( 25 [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp", 26 ["includes = -I/tmp/myproject/path/to/src -I/tmp/myproject/other/path", 27 "DEPFILE = path/to/src/foo.o.dep"]), 28 ]); 29 } 30 31 32 void testFlagsCompileC() { 33 auto build = Build(objectFile(SourceFile("path/to/src/foo.c"), Flags("-m64 -fPIC -O3"))); 34 auto ninja = Ninja(build, "/tmp/myproject"); 35 ninja.buildEntries.shouldEqual( 36 [NinjaEntry("build path/to/src/foo.o: _ccompile /tmp/myproject/path/to/src/foo.c", 37 ["flags = -m64 -fPIC -O3", 38 "DEPFILE = path/to/src/foo.o.dep"]), 39 ]); 40 } 41 42 void testFlagsCompileCpp() { 43 auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp"), Flags("-m64 -fPIC -O3"))); 44 auto ninja = Ninja(build, "/tmp/myproject"); 45 ninja.buildEntries.shouldEqual( 46 [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp", 47 ["flags = -m64 -fPIC -O3", 48 "DEPFILE = path/to/src/foo.o.dep"]), 49 ]); 50 } 51 52 void testCppCompile() { 53 auto mathsObj = objectFile(SourceFile("src/cpp/maths.cpp"), 54 Flags("-m64 -fPIC -O3"), 55 IncludePaths(["headers"])); 56 57 import reggae.config: gDefaultOptions; 58 mathsObj.shellCommand(gDefaultOptions.withProjectPath("/path/to")).shouldEqual( 59 "g++ -m64 -fPIC -O3 -I/path/to/headers -MMD -MT src/cpp/maths.o -MF src/cpp/maths.o.dep " ~ 60 "-o src/cpp/maths.o -c /path/to/src/cpp/maths.cpp"); 61 } 62 63 void testCCompile() { 64 auto mathsObj = objectFile(SourceFile("src/c/maths.c"), 65 Flags("-m64 -fPIC -O3"), 66 IncludePaths(["headers"])); 67 68 mathsObj.shellCommand(gDefaultOptions.withProjectPath("/path/to")).shouldEqual( 69 "gcc -m64 -fPIC -O3 -I/path/to/headers -MMD -MT src/c/maths.o -MF src/c/maths.o.dep " ~ 70 "-o src/c/maths.o -c /path/to/src/c/maths.c"); 71 } 72 73 74 void testUnityNoFiles() { 75 string[] files; 76 immutable projectPath = ""; 77 unityFileContents(projectPath, files).shouldThrow; 78 } 79 80 81 private void shouldEqualLines(string actual, string[] expected, 82 in string file = __FILE__, in size_t line = __LINE__) { 83 import std.string; 84 actual.split("\n").shouldEqual(expected, file, line); 85 } 86 87 void testUnityCppFiles() { 88 auto files = ["src/foo.cpp", "src/bar.cpp"]; 89 unityFileContents("/path/to/proj/", files).shouldEqualLines( 90 [`#include "/path/to/proj/src/foo.cpp"`, 91 `#include "/path/to/proj/src/bar.cpp"`]); 92 } 93 94 95 void testUnityCFiles() { 96 auto files = ["src/foo.c", "src/bar.c"]; 97 unityFileContents("/foo/bar/", files).shouldEqualLines( 98 [`#include "/foo/bar/src/foo.c"`, 99 `#include "/foo/bar/src/bar.c"`]); 100 } 101 102 void testUnityMixedLanguages() { 103 auto files = ["src/foo.cpp", "src/bar.c"]; 104 unityFileContents("/project", files).shouldThrow; 105 } 106 107 void testUnityDFiles() { 108 auto files = ["src/foo.d", "src/bar.d"]; 109 unityFileContents("/project", files).shouldThrow; 110 } 111 112 113 void testUnityTargetCpp() @trusted { 114 import reggae.config: gDefaultOptions; 115 116 enum files = ["src/foo.cpp", "src/bar.cpp", "src/baz.cpp"]; 117 Target[] dependencies() @safe pure nothrow { 118 return [Target("$builddir/mylib.a")]; 119 } 120 121 immutable projectPath = "/path/to/proj"; 122 auto target = unityTarget!(ExeName("leapp"), 123 projectPath, 124 files, 125 Flags("-g -O0"), 126 IncludePaths(["headers"]), 127 dependencies); 128 target.rawOutputs.shouldEqual(["leapp"]); 129 target.shellCommand(gDefaultOptions.withProjectPath(projectPath)).shouldEqual( 130 "g++ -g -O0 -I/path/to/proj/headers -MMD -MT leapp -MF leapp.dep -o leapp " ~ 131 ".reggae/objs/leapp.objs/unity.cpp mylib.a"); 132 target.dependencyTargets.shouldEqual([Target.phony("$builddir/.reggae/objs/leapp.objs/unity.cpp", 133 "", 134 [], 135 [Target("src/foo.cpp"), 136 Target("src/bar.cpp"), 137 Target("src/baz.cpp")]), 138 Target("$builddir/mylib.a")]); 139 } 140 141 void testUnityTargetC() @trusted { 142 import reggae.config: gDefaultOptions; 143 144 enum files = ["src/foo.c", "src/bar.c", "src/baz.c"]; 145 Target[] dependencies() @safe pure nothrow { 146 return [Target("$builddir/mylib.a")]; 147 } 148 149 immutable projectPath = "/path/to/proj"; 150 auto target = unityTarget!(ExeName("leapp"), 151 projectPath, 152 files, 153 Flags("-g -O0"), 154 IncludePaths(["headers"]), 155 dependencies); 156 target.rawOutputs.shouldEqual(["leapp"]); 157 target.shellCommand(gDefaultOptions.withProjectPath(projectPath)).shouldEqual( 158 "gcc -g -O0 -I/path/to/proj/headers -MMD -MT leapp -MF leapp.dep -o leapp " ~ 159 ".reggae/objs/leapp.objs/unity.c mylib.a"); 160 target.dependencyTargets.shouldEqual([Target.phony("$builddir/.reggae/objs/leapp.objs/unity.c", 161 "", 162 [], 163 [Target("src/foo.c"), 164 Target("src/bar.c"), 165 Target("src/baz.c")]), 166 Target("$builddir/mylib.a")]); 167 }