1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
// slang-downstream-compiler.cpp
#include "slang-downstream-compiler.h"
#include "../core/slang-blob.h"
#include "../core/slang-castable.h"
#include "../core/slang-char-util.h"
#include "../core/slang-common.h"
#include "../core/slang-io.h"
#include "../core/slang-shared-library.h"
#include "../core/slang-string-util.h"
#include "../core/slang-type-text-util.h"
#include "slang-artifact-associated-impl.h"
#include "slang-artifact-desc-util.h"
#include "slang-artifact-helper.h"
#include "slang-artifact-impl.h"
#include "slang-artifact-representation-impl.h"
#include "slang-artifact-util.h"
#include "slang-com-helper.h"
namespace Slang
{
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
SlangResult DownstreamCompilerBase::convert(
IArtifact* from,
const ArtifactDesc& to,
IArtifact** outArtifact)
{
SLANG_UNUSED(from);
SLANG_UNUSED(to);
SLANG_UNUSED(outArtifact);
return SLANG_E_NOT_AVAILABLE;
}
void* DownstreamCompilerBase::castAs(const Guid& guid)
{
if (auto ptr = getInterface(guid))
{
return ptr;
}
return getObject(guid);
}
void* DownstreamCompilerBase::getInterface(const Guid& guid)
{
if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() ||
guid == IDownstreamCompiler::getTypeGuid())
{
return static_cast<IDownstreamCompiler*>(this);
}
return nullptr;
}
void* DownstreamCompilerBase::getObject(const Guid& guid)
{
SLANG_UNUSED(guid);
return nullptr;
}
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/
SlangResult CommandLineDownstreamCompiler::compile(
const CompileOptions& inOptions,
IArtifact** outArtifact)
{
if (!isVersionCompatible(inOptions))
{
// Not possible to compile with this version of the interface.
return SLANG_E_NOT_IMPLEMENTED;
}
CompileOptions options = getCompatibleVersion(&inOptions);
// Copy the command line options
CommandLine cmdLine(m_cmdLine);
// Work out the ArtifactDesc
const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType);
auto helper = DefaultArtifactHelper::getSingleton();
List<ComPtr<IArtifact>> artifactList;
// It may be necessary to produce a temporary file 'lock file'.
ComPtr<IOSFileArtifactRepresentation> lockFile;
// The allocator can be used for items that are not kept in scope by the options
String modulePath;
// If no module path is set we will need to generate one
if (options.modulePath.count == 0)
{
// We could use the path to the source, or use the source name/paths as defined on the
// artifact For now we just go with a lock file based on "slang-generated".
SLANG_RETURN_ON_FAIL(
helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef()));
auto lockArtifact = Artifact::create(
ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None));
lockArtifact->addRepresentation(lockFile);
artifactList.add(lockArtifact);
// Add the source files such that they can exist
modulePath = lockFile->getPath();
options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath);
}
// Append command line args to the end of cmdLine using the target specific function for the
// specified options
SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine));
// The 'productArtifact' is the main product produced from the compilation - the
// executable/sharedlibrary/object etc
ComPtr<IArtifact> productArtifact;
{
List<ComPtr<IArtifact>> artifacts;
SLANG_RETURN_ON_FAIL(
calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts));
for (IArtifact* artifact : artifacts)
{
// The main artifact must be in the list, so add it if we find it
if (artifact->getDesc() == targetDesc)
{
SLANG_ASSERT(productArtifact == nullptr);
productArtifact = artifact;
}
artifactList.add(ComPtr<IArtifact>(artifact));
}
}
SLANG_ASSERT(productArtifact);
// Somethings gone wrong if we don't find the main artifact
if (!productArtifact)
{
return SLANG_FAIL;
}
ExecuteResult exeRes;
#if 0
// Test
{
String line = ProcessUtil::getCommandLineString(cmdLine);
printf("%s", line.getBuffer());
}
#endif
SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes));
#if 0
{
printf("stdout=\"%s\"\nstderr=\"%s\"\nret=%d\n", exeRes.standardOutput.getBuffer(), exeRes.standardError.getBuffer(), int(exeRes.resultCode));
}
#endif
// Go through the list of artifacts in the artifactList and check if they exist.
//
// This is useful because `calcCompileProducts` is conservative and may produce artifacts for
// products that aren't actually produced, by the compilation.
{
Count count = artifactList.getCount();
for (Index i = 0; i < count; ++i)
{
IArtifact* artifact = artifactList[i];
if (!artifact->exists())
{
// We should find a file rep and if we do we can disown it. Disowning will mean
// when scope is lost the rep won't try and delete the (apparently non existing)
// backing file.
if (auto fileRep = findRepresentation<IOSFileArtifactRepresentation>(artifact))
{
fileRep->disown();
}
// If the main artifact doesn't exist, we don't have a main artifact
if (artifact == productArtifact)
{
productArtifact.setNull();
}
// Remove from the list
artifactList.removeAt(i);
--count;
--i;
}
}
}
// Add all of the source artifacts, that are temporary on the file system, such that they can
// stay in scope for debugging
for (auto sourceArtifact : options.sourceArtifacts)
{
if (auto fileRep = findRepresentation<IOSFileArtifactRepresentation>(sourceArtifact))
{
// If it has a lock file we can assume it's a temporary
if (fileRep->getLockFile())
{
artifactList.add(ComPtr<IArtifact>(sourceArtifact));
}
}
}
// Create the result artifact
auto artifact = ArtifactUtil::createArtifact(targetDesc);
// Createa the diagnostics
auto diagnostics = ArtifactDiagnostics::create();
SLANG_RETURN_ON_FAIL(parseOutput(exeRes, diagnostics));
ArtifactUtil::addAssociated(artifact, diagnostics);
// Find the rep from the 'main' artifact, we'll just use the same representation on the output
// artifact. Sharing is desirable, because the rep owns the file.
if (auto fileRep = productArtifact
? findRepresentation<IOSFileArtifactRepresentation>(productArtifact)
: nullptr)
{
artifact->addRepresentation(fileRep);
}
// Add the artifact list if there is anything in it
if (artifactList.getCount())
{
// Holds all of the artifacts that are relatated to the final artifact - such as debug
// files, ancillary file and lock files
auto artifactContainer = ArtifactUtil::createArtifact(ArtifactDesc::make(
ArtifactKind::Container,
ArtifactPayload::Unknown,
ArtifactStyle::Unknown));
auto slice = SliceUtil::asSlice(artifactList);
artifactContainer->setChildren(slice.data, slice.count);
artifact->addAssociated(artifactContainer);
}
*outArtifact = artifact.detach();
return SLANG_OK;
}
} // namespace Slang
|