1 module reggae.rules.common; 2 3 4 import reggae.build; 5 import reggae.config: projectPath; 6 import std.algorithm; 7 import std.path: buildPath; 8 import std.array: array; 9 10 version(Windows) { 11 immutable objExt = ".obj"; 12 immutable exeExt = ".exe"; 13 } else { 14 immutable objExt = ".o"; 15 immutable exeExt = ""; 16 } 17 18 19 package string objFileName(in string srcFileName) @safe pure nothrow { 20 import std.path: stripExtension, defaultExtension, isRooted, stripDrive; 21 immutable localFileName = srcFileName.isRooted 22 ? srcFileName.stripDrive[1..$] 23 : srcFileName; 24 return localFileName.stripExtension.defaultExtension(objExt); 25 } 26 27 28 Target[] srcObjects(alias func)(in string extension, 29 string[] dirs, 30 string[] srcFiles, 31 in string[] excludeFiles) { 32 auto files = selectSrcFiles(srcFilesInDirs(extension, dirs), srcFiles, excludeFiles); 33 return func(files); 34 } 35 36 //The parameters would be "in" except that "remove" doesn't like that... 37 string[] selectSrcFiles(string[] dirFiles, 38 string[] srcFiles, 39 in string[] excludeFiles) @safe pure nothrow { 40 return (dirFiles ~ srcFiles).remove!(a => excludeFiles.canFind(a)).array; 41 } 42 43 private string[] srcFilesInDirs(in string extension, in string[] dirs) { 44 import std.exception: enforce; 45 import std.file; 46 import std.path: buildNormalizedPath, buildPath; 47 import std.array: array; 48 49 DirEntry[] modules; 50 foreach(dir; dirs.map!(a => buildPath(projectPath, a))) { 51 enforce(isDir(dir), dir ~ " is not a directory name"); 52 auto entries = dirEntries(dir, "*." ~ extension, SpanMode.depth); 53 auto normalised = entries.map!(a => DirEntry(buildNormalizedPath(a))); 54 modules ~= array(normalised); 55 } 56 57 return modules.map!(a => a.name.removeProjectPath).array; 58 } 59 60 string removeProjectPath(in string path) @safe pure { 61 import std.path: relativePath, absolutePath; 62 return path.absolutePath.relativePath(projectPath.absolutePath); 63 }