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