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