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 }