Skip to content

Commit 26e67d9

Browse files
committed
Added: Experimental support to clang
1 parent 2db1cf1 commit 26e67d9

File tree

9 files changed

+301
-187
lines changed

9 files changed

+301
-187
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
module redub.archiver_identification;
2+
import hip.data.json;
3+
import redub.compiler_identification;
4+
public import std.system : OS;
5+
import redub.command_generators.commons;
6+
7+
8+
enum AcceptedArchiver : string
9+
{
10+
ar = "ar",
11+
llvmLib = "llvm-lib",
12+
llvmAr = "llvm-ar",
13+
libtool = "libtool",
14+
/**
15+
* D compiler will be used for creating the library
16+
*/
17+
none = ""
18+
}
19+
20+
struct Archiver
21+
{
22+
AcceptedArchiver type;
23+
string bin;
24+
}
25+
26+
/**
27+
* For generating libraries, redub might use dmd/ldc2 by default since that simplifies the logic.
28+
* Although it is slightly slower, this is also a compromise one takes by using integration with C
29+
*/
30+
AcceptedArchiver defaultArchiverFromCompiler(AcceptedCompiler compiler, OS target)
31+
{
32+
if(compiler.isDCompiler || compiler == AcceptedCompiler.invalid)
33+
return AcceptedArchiver.none;
34+
if(target.isWindows)
35+
return AcceptedArchiver.llvmLib;
36+
if(compiler == AcceptedCompiler.clang)
37+
return AcceptedArchiver.llvmAr;
38+
return AcceptedArchiver.ar;
39+
}
40+
41+
42+
Archiver getArchiver(AcceptedArchiver archiver)
43+
{
44+
import std.array:staticArray;
45+
import redub.misc.find_executable;
46+
import std.process;
47+
import redub.meta;
48+
if(archiver == AcceptedArchiver.none)
49+
return Archiver(AcceptedArchiver.none);
50+
51+
JSONValue compilersInfo = getRedubMeta();
52+
JSONValue* archiversCache = "archivers" in compilersInfo;
53+
if(archiversCache)
54+
{
55+
JSONValue* binPath = archiver in *archiversCache;
56+
if(binPath)
57+
return Archiver(archiver, binPath.str);
58+
}
59+
string help = " --help";
60+
if(archiver == AcceptedArchiver.llvmLib) help = " /help";
61+
auto res = executeShell(archiver~help);
62+
if(res.status == 0)
63+
{
64+
Archiver arch = Archiver(archiver, findExecutable(archiver));
65+
saveArchiver(compilersInfo, arch);
66+
return arch;
67+
}
68+
return Archiver(AcceptedArchiver.none);
69+
}
70+
71+
void saveArchiver(ref JSONValue v, Archiver arch)
72+
{
73+
import redub.meta;
74+
if(arch.type != AcceptedArchiver.none)
75+
{
76+
JSONValue* archivers = "archivers" in v;
77+
if(!archivers)
78+
{
79+
v["archivers"] = JSONValue.emptyObject;
80+
archivers = "archivers" in v;
81+
}
82+
(*archivers)[cast(string)arch.type] = arch.bin;
83+
saveRedubMeta(v);
84+
}
85+
}
86+
87+
private AcceptedArchiver acceptedArchiverFromString(string str)
88+
{
89+
switch(str)
90+
{
91+
static foreach(mem; __traits(allMembers, AcceptedArchiver))
92+
{
93+
case mem:
94+
return __traits(getMember, AcceptedArchiver, mem);
95+
}
96+
default:
97+
return AcceptedArchiver.none;
98+
}
99+
}

source/redub/buildapi.d

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
module redub.buildapi;
2-
32
public import std.system:OS, ISA, instructionSetArchitecture;
4-
public import redub.compiler_identification: Compiler, CompilerBinary;
3+
public import redub.compiler_identification: Compiler, CompilerBinary, Archiver, AcceptedArchiver;
54
public import redub.plugin.api;
65
import redub.logging;
76
import redub.package_searching.api;
87

98

109
///vX.X.X
11-
enum RedubVersionOnly = "v1.25.14";
10+
enum RedubVersionOnly = "v1.26.0";
1211
///Redub vX.X.X
1312
enum RedubVersionShort = "Redub "~RedubVersionOnly;
1413
///Redub vX.X.X - Description
@@ -52,6 +51,12 @@ struct CompilingSession
5251
this.os = osFromArch(arch);
5352
this.isa = isaFromArch(arch);
5453
}
54+
55+
AcceptedArchiver getArchiverType(const ref BuildConfiguration cfg) const
56+
{
57+
import redub.archiver_identification;
58+
return defaultArchiverFromCompiler(cfg.getCompiler(compiler).compiler, os);
59+
}
5560
}
5661

5762
enum TargetType : ubyte
@@ -731,11 +736,13 @@ struct BuildRequirements
731736
return output;
732737
}
733738

734-
immutable(ThreadBuildData) buildData(bool isLeaf) inout
739+
immutable(ThreadBuildData) buildData(bool isLeaf, CompilingSession s) inout
735740
{
741+
import redub.archiver_identification;
736742
return immutable ThreadBuildData(
737743
cfg.idup,
738744
extra.idup,
745+
getArchiver(s.getArchiverType(cfg)),
739746
false,
740747
isLeaf
741748
);
@@ -792,6 +799,7 @@ struct ThreadBuildData
792799
{
793800
BuildConfiguration cfg;
794801
ExtraInformation extra;
802+
Archiver archiver;
795803

796804
bool isRoot;
797805
///Used for letting it get high priority so redub may exit fast.

source/redub/building/cache.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ DirectoryFilterType filterTypeFromCompiler(const ref BuildRequirements cfg, cons
266266
case dmd, ldc2: return DirectoryFilterType.d;
267267
case gcc: return DirectoryFilterType.c;
268268
case gxx: return DirectoryFilterType.cpp;
269+
case clang: return DirectoryFilterType.cpp;
269270
case invalid: return DirectoryFilterType.none;
270271
}
271272
}

source/redub/building/compile.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ bool buildProjectParallelSimple(ProjectNode root, CompilingSession s, const(AdvC
273273
{
274274
spawned[dep] = true;
275275
spawn(&execCompilationThread,
276-
dep.requirements.buildData(false), cast(shared)dep,
276+
dep.requirements.buildData(false, s), cast(shared)dep,
277277
s, HashPair(mainPackHash, hashFrom(dep.requirements, s)),
278278
getEnvForProject(dep, env),
279279
execID
@@ -367,7 +367,7 @@ bool buildProjectFullyParallelized(ProjectNode root, CompilingSession s, const(A
367367
{
368368
sentPackages++;
369369
spawn(&execCompilationThread,
370-
pack.requirements.buildData(pack is priority),
370+
pack.requirements.buildData(pack is priority, s),
371371
cast(shared)pack,
372372
s,
373373
HashPair(mainPackHash, hashFrom(pack.requirements, s)),
@@ -476,7 +476,7 @@ bool buildProjectSingleThread(ProjectNode root, CompilingSession s, const(AdvCac
476476
{
477477
if(dep.shouldEnterCompilationThread)
478478
{
479-
CompilationResult res = execCompilation(dep.requirements.buildData(true), cast(shared)dep,
479+
CompilationResult res = execCompilation(dep.requirements.buildData(true, s), cast(shared)dep,
480480
s,
481481
HashPair(mainPackHash, hashFrom(dep.requirements, s)), getEnvForProject(dep, env), Tid.init, 0
482482
);
@@ -656,7 +656,7 @@ private bool doLink(ProjectNode root, CompilingSession info, string mainPackHash
656656
{
657657
CompilationResult linkRes;
658658
auto result = timed(() {
659-
linkRes = link(root, mainPackHash, root.requirements.buildData(true), info, getEnvForProject(root, env ? env : cast(const)getCurrentEnv()));
659+
linkRes = link(root, mainPackHash, root.requirements.buildData(true, info), info, getEnvForProject(root, env ? env : cast(const)getCurrentEnv()));
660660
return true;
661661
});
662662
if(linkRes.status)

source/redub/building/utils.d

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,19 @@ auto executeArchiver(const ThreadBuildData data, CompilingSession s, string main
9595
import redub.compiler_identification;
9696
import std.path;
9797
import redub.building.cache;
98-
Archiver a = s.compiler.archiver;
9998

100-
string[] cmd = [a.bin];
101-
final switch(a.type) with(AcceptedArchiver)
99+
string[] cmd = [data.archiver.bin];
100+
final switch(data.archiver.type) with(AcceptedArchiver)
102101
{
103102
case ar, llvmAr: cmd~= ["rcs"]; break;
103+
case llvmLib: break;
104104
case libtool: cmd~= ["-static", "-o"]; break;
105-
case none: break;
105+
case none: throw new Exception("No archiver registered."); break;
106106
}
107-
108-
cmd~= buildNormalizedPath(data.cfg.outputDirectory, getOutputName(data.cfg, s.os, s.isa));
107+
if(data.archiver.type == AcceptedArchiver.llvmLib)
108+
cmd~= "/out:"~buildNormalizedPath(data.cfg.outputDirectory, getOutputName(data.cfg, s.os, s.isa));
109+
else
110+
cmd~= buildNormalizedPath(data.cfg.outputDirectory, getOutputName(data.cfg, s.os, s.isa));
109111

110112
string cacheDir = getCacheOutputDir(mainPackHash, data.cfg, s, data.extra.isRoot);
111113

source/redub/command_generators/automatic.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public import redub.buildapi;
44
public import redub.compiler_identification;
55

66
static import redub.command_generators.gnu_based;
7+
static import redub.command_generators.clang;
78
static import redub.command_generators.dmd;
89
static import redub.command_generators.ldc;
910

@@ -28,6 +29,8 @@ string[] getCompilationFlags(const BuildConfiguration cfg, CompilingSession s, s
2829
{
2930
case gxx:
3031
return redub.command_generators.gnu_based.parseBuildConfiguration(cfg, s, mainPackHash, isRoot, cppExt);
32+
case clang:
33+
return redub.command_generators.clang.parseBuildConfiguration(cfg, s, mainPackHash, isRoot, cppExt);
3134
case gcc:
3235
return redub.command_generators.gnu_based.parseBuildConfiguration(cfg, s, mainPackHash, isRoot, cExt);
3336
case dmd:
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module redub.command_generators.clang;
2+
public import redub.buildapi;
3+
public import std.system;
4+
import redub.command_generators.commons;
5+
import redub.logging;
6+
import redub.building.cache;
7+
8+
/// Parse G++ configuration
9+
string[] parseBuildConfiguration(const BuildConfiguration b, CompilingSession s, string mainPackhash, bool isRoot, const string[] extensions...)
10+
{
11+
import std.algorithm.iteration:map;
12+
import std.file;
13+
import redub.misc.path;
14+
15+
string[] cmds;
16+
17+
with(b)
18+
{
19+
if(isDebug) cmds~= "-g";
20+
if(targetType.isLinkedSeparately || targetType.isStaticLibrary)
21+
cmds~= "-c";
22+
23+
cmds = mapAppendPrefix(cmds, versions, "-D", false);
24+
cmds~= dFlags;
25+
cmds = mapAppendPrefix(cmds, importDirectories, "-I", true);
26+
putSourceFiles(cmds, workingDir, sourcePaths, sourceFiles, excludeSourceFiles, extensions);
27+
28+
29+
string outFlag = getTargetTypeFlag(targetType);
30+
string cacheDir = getCacheOutputDir(mainPackhash, b, s, isRoot);
31+
32+
mkdirRecurse(cacheDir);
33+
if(outFlag)
34+
cmds~= outFlag;
35+
cmds~= "-o";
36+
if(outFlag)
37+
cmds ~= buildNormalizedPath(cacheDir, getConfigurationOutputName(b, s.os)).escapePath;
38+
else
39+
cmds ~= buildNormalizedPath(cacheDir, getObjectOutputName(b, os)).escapePath;
40+
}
41+
42+
return cmds;
43+
}
44+
45+
string getTargetTypeFlag(TargetType o)
46+
{
47+
final switch(o) with(TargetType)
48+
{
49+
case invalid, none: throw new Exception("Invalid targetType");
50+
case autodetect, executable, sourceLibrary, staticLibrary, library: return null;
51+
case dynamicLibrary: return "-shared";
52+
}
53+
}

0 commit comments

Comments
 (0)