diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/compiler-core/slang-artifact.cpp | 103 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact.h | 52 | ||||
| -rw-r--r-- | source/compiler-core/slang-dxc-compiler.cpp | 92 | ||||
| -rw-r--r-- | source/compiler-core/slang-gcc-compiler-util.cpp | 71 | ||||
| -rw-r--r-- | source/compiler-core/slang-visual-studio-compiler-util.cpp | 29 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 6 |
8 files changed, 225 insertions, 139 deletions
diff --git a/source/compiler-core/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp index 5d9f8692c..1f11c31df 100644 --- a/source/compiler-core/slang-artifact.cpp +++ b/source/compiler-core/slang-artifact.cpp @@ -364,11 +364,88 @@ ISlangUnknown* Artifact::findInterfaceInstance(const Guid& guid) return nullptr; } -SlangResult Artifact::requireFilePath(Keep keep, String& outFilePath) +/* static */String Artifact::getBaseNameFromPath(Desc& desc, const UnownedStringSlice& path) +{ + String name = Path::getFileName(path); + + const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; + if (isSharedLibraryPrefixPlatform) + { + // Strip lib prefix + if (desc.isCpuBinary() && + (desc.kind == ArtifactKind::Library || + desc.kind == ArtifactKind::SharedLibrary)) + { + // If it starts with lib strip it + if (name.startsWith("lib")) + { + const String stripLib = name.getUnownedSlice().tail(3); + name = stripLib; + } + } + } + + // Strip any extension + { + auto descExt = desc.getDefaultExtension(); + // Strip the extension if it's a match + if (descExt.getLength() && + Path::getPathExt(name) == descExt) + { + name = Path::getFileNameWithoutExt(name); + } + } + + return name; +} + +String Artifact::getBaseName() +{ + if (m_pathType != PathType::None) + { + return getBaseNameFromPath(m_desc, m_path.getUnownedSlice()); + } + return m_name; +} + +String Artifact::getParentPath() +{ + if (m_pathType != PathType::None && m_path.getLength()) + { + return Path::getParentDirectory(m_path); + } + return String(); +} + +SlangResult Artifact::requireFileLike(Keep keep) +{ + // If there is no path set and no blob we still need a name. + // If the artifact is a library we can assume it's a system level library, + // or it can be found by appropriate search paths. + if (m_pathType == PathType::None && + m_blob == nullptr && + (m_desc.kind == ArtifactKind::Library || + m_desc.kind == ArtifactKind::SharedLibrary)) + { + if (m_name.getLength() > 0) + { + return SLANG_OK; + } + + // TODO(JS): If we could serialize, we could turn some other representation into a file, and therefore + // a name, but currently that's not supported + return SLANG_E_NOT_FOUND; + } + + // Will turn into a file if necessary + SLANG_RETURN_ON_FAIL(requireFile(keep)); + return SLANG_OK; +} + +SlangResult Artifact::requireFile(Keep keep) { if (m_pathType != PathType::None) { - outFilePath = m_path; return SLANG_OK; } @@ -377,15 +454,28 @@ SlangResult Artifact::requireFilePath(Keep keep, String& outFilePath) // Get the contents as a blob. If we can't do that, then we can't write anything... SLANG_RETURN_ON_FAIL(loadBlob(getIntermediateKeep(keep), blob)); - const UnownedStringSlice ext = m_desc.getDefaultExtension(); + // If we have a name, make the generated name based on that name + // Else just use 'slang-generated' the basis + + UnownedStringSlice nameBase; + if (m_name.getLength() > 0) + { + nameBase = m_name.getUnownedSlice(); + } + else + { + nameBase = UnownedStringSlice::fromLiteral("slang-generated"); + } // TODO(JS): NOTE! This isn't strictly correct, as the generated filename is not guarenteed to be unique // if we change it with an extension (or prefix). // This doesn't change the previous behavior though. String path; - SLANG_RETURN_ON_FAIL(File::generateTemporary(UnownedStringSlice::fromLiteral("slang-generated"), path)); + SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, path)); - if (m_desc.isCpuBinary() && m_desc.kind == ArtifactKind::SharedLibrary) + if (m_desc.isCpuBinary() && + (m_desc.kind == ArtifactKind::SharedLibrary || + m_desc.kind == ArtifactKind::Library)) { const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; if (isSharedLibraryPrefixPlatform) @@ -409,6 +499,9 @@ SlangResult Artifact::requireFilePath(Keep keep, String& outFilePath) } // If there is an extension append it + + const UnownedStringSlice ext = m_desc.getDefaultExtension(); + if (ext.getLength()) { path.appendChar('.'); diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 232e9a8eb..651e0ad3b 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -157,7 +157,7 @@ public: static This makeFromCompileTarget(SlangCompileTarget target); /// Construct from the elements - static This make(Kind inKind, Payload inPayload, Style inStyle = Style::Kernel, Flags flags = 0) + static This make(Kind inKind, Payload inPayload, Style inStyle = Style::Unknown, Flags flags = 0) { return This{ inKind, inPayload, inStyle, flags }; } @@ -202,6 +202,7 @@ An abstraction is desirable here, because depending on the compiler the artifact * A blob * Multiple files * Some other (perhaps multiple) in memory representations +* A name The artifact uses the Blob as the standard representation of in memory data. @@ -223,14 +224,6 @@ A more long term goal would be to * Make Artifact an interface (such that it can work long term over binary boundaries) * Make Diagnostics into an interface (such it can be added to a Artifact result) * Use Artifact and related types for downstream compiler - -TODO(JS): There is an issue here around libraries in that downstream compilers can use -named libraries, but the name doesn't directly relate to a file. If it is a file it may -not be easily possible to determine it's location. So there is a desire to indicate the -`name` as opposed to the path. - -As a second related issue. Lets say we have a blob (and not a file). - */ class Artifact : public RefObject { @@ -296,9 +289,30 @@ public: /// Load as a blob SlangResult loadBlob(Keep keep, ComPtr<ISlangBlob>& outBlob); - /// Get as a file. May need to serialize and write as a temporary file. - SlangResult requireFilePath(Keep keep, String& outPath); - + /// Require artifact is available as a file. + /// NOTE! May need to serialize and write as a temporary file. + SlangResult requireFile(Keep keep); + + /// Require artifact is available in file-like scenarion. + /// + /// This is similar to requireFile, but for some special cases doesn't actually require a + /// *explicit* path/file. + /// + /// For example when system libraries are specified - the library paths may be known to + /// a downstream compiler (or the path is passed in explicitly), in that case only the + /// artifact name needs to be correct. + SlangResult requireFileLike(Keep keep); + + /// Get the base name of this artifact. + /// If there is a path set, will extract the name from that (stripping prefix, extension as necessary). + /// Else if there is an explicit name set, this is returned. + /// Else returns the empty string + String getBaseName(); + + /// Get the parent path (empty if there isn't one) + String getParentPath(); + + /// Get the Desc defining the contents of the artifact SLANG_FORCE_INLINE const Desc& getDesc() { return m_desc; } /// Returns the index of the entry @@ -306,6 +320,8 @@ public: /// Add items void setPath(PathType pathType, const String& filePath) { m_pathType = pathType; m_path = filePath; } + + /// Set the blob representing the contents of the asset void setBlob(ISlangBlob* blob) { m_blob = blob; } void add(Entry::Style style, RefObject* obj); @@ -314,15 +330,25 @@ public: PathType getPathType() const { return m_pathType; } const String& getPath() const { return m_path; } + /// Get the name of the artifact. This can be empty. + const String& getName() const { return m_name; } + const List<Entry>& getEntries() const { return m_entries; } + /// Given a desc and a path returns the base name from the path (stripped of prefix and extension) + static String getBaseNameFromPath(Desc& desc, const UnownedStringSlice& path); + /// Ctor - Artifact(const Desc& desc) :m_desc(desc) {} + Artifact(const Desc& desc, const String& name): + m_desc(desc), + m_name(name) + {} /// Dtor ~Artifact(); protected: Desc m_desc; + String m_name; PathType m_pathType = PathType::None; ///< What the path indicates String m_path; ///< The path diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index eb26dd3cc..0d05bf724 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -50,51 +50,39 @@ static UnownedStringSlice _getSlice(IDxcBlob* blob) { return StringUtil::getSlic // 7f61fc7d-950d-467f-b3e3-3c02fb49187c static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } }; -namespace { // anonymous - -class LibraryNameList +static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlicePool& pool) { -public: - void addName(Artifact* library) + UnownedStringSlice slice = inSlice; + if (slice.getLength() == 0) { - String name; - if (library->getPathType() == Artifact::Existing) - { - name = Path::getFileNameWithoutExt(library->getPath()); - } - addName(name); + slice = UnownedStringSlice::fromLiteral("unnamed"); } - void addName(const String& inName) + + StringBuilder buf; + const Index length = slice.getLength(); + buf << slice; + + for (Index i = 0; ; ++i) { - String name(inName); - if (name.getLength() == 0) + buf.reduceLength(length); + + if (i > 0) { - name = "unnamed"; + buf << "_" << i; } - if (m_names.indexOf(name) >= 0) + StringSlicePool::Handle handle; + if (!pool.findOrAdd(buf.getUnownedSlice(), handle)) { - StringBuilder buf; - for (Index i = 1; ; ++i) - { - buf.Clear(); - buf << name << "_" << i; - - if (m_names.indexOf(buf) < 0) - { - name = buf; - break; - } - } + return pool.getSlice(handle); } - - m_names.add(name); } +} - List<String> m_names; -}; - -} // anonymous +static UnownedStringSlice _addName(Artifact* artifact, StringSlicePool& pool) +{ + return _addName(artifact->getBaseName().getUnownedSlice(), pool); +} class DxcIncludeHandler : public IDxcIncludeHandler { @@ -469,9 +457,10 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr ComPtr<IDxcLinker> linker; SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef())); - List<ComPtr<ISlangBlob>> libraryBlobs; + StringSlicePool pool(StringSlicePool::Style::Default); - LibraryNameList libraryNames; + List<ComPtr<ISlangBlob>> libraryBlobs; + List<OSString> libraryNames; for (Artifact* library : libraries) { @@ -479,42 +468,37 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& options, RefPtr SLANG_RETURN_ON_FAIL(library->loadBlob(ArtifactKeep::Yes, blob)); libraryBlobs.add(blob); - libraryNames.addName(library); + libraryNames.add(String(_addName(library, pool)).toWString()); } // Add the compiled blob name - - { - auto blob = (ISlangBlob*)dxcResultBlob.get(); - libraryBlobs.add(ComPtr<ISlangBlob>(blob)); - } - + String name; if (options.modulePath.getLength()) { - libraryNames.addName(Path::getFileNameWithoutExt(options.modulePath)); + name = Path::getFileNameWithoutExt(options.modulePath); } else if (options.sourceContentsPath.getLength()) { - libraryNames.addName(Path::getFileNameWithoutExt(options.sourceContentsPath)); + name = Path::getFileNameWithoutExt(options.sourceContentsPath); } - else + + // Add the blob with name { - libraryNames.addName(""); + auto blob = (ISlangBlob*)dxcResultBlob.get(); + libraryBlobs.add(ComPtr<ISlangBlob>(blob)); + libraryNames.add(String(_addName(name.getUnownedSlice(), pool)).toWString()); } - const Index librariesCount = libraryNames.m_names.getCount(); + const Index librariesCount = libraryNames.getCount(); SLANG_ASSERT(libraryBlobs.getCount() == librariesCount); List<const wchar_t*> linkLibraryNames; - List<OSString> wideLibraryNames; - + linkLibraryNames.setCount(librariesCount); - wideLibraryNames.setCount(librariesCount); - + for (Index i = 0; i < librariesCount; ++i) { - wideLibraryNames[i] = libraryNames.m_names[i].toWString(); - linkLibraryNames[i] = wideLibraryNames[i].begin(); + linkLibraryNames[i] = libraryNames[i].begin(); // Register the library SLANG_RETURN_ON_FAIL(linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get())); diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 7d1b7b86a..2d1ad2555 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -8,6 +8,7 @@ #include "../core/slang-io.h" #include "../core/slang-shared-library.h" #include "../core/slang-char-util.h" +#include "../core/slang-string-slice-pool.h" namespace Slang { @@ -620,65 +621,28 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse } // Add the library paths - List<String> libraryPaths; - libraryPaths.addRange(options.libraryPaths.getBuffer(), options.libraryPaths.getCount()); + StringSlicePool libPathPool(StringSlicePool::Style::Default); + + for (const auto& libPath : options.libraryPaths) + { + libPathPool.add(libPath); + } // Artifacts might add library paths for (Artifact* artifact : options.libraries) { const auto desc = artifact->getDesc(); // If it's a library for CPU types, try and use it - if (desc.isCpuBinary()) - { - if (desc.kind == ArtifactKind::Library) - { - String path; - SLANG_RETURN_ON_FAIL(artifact->requireFilePath(ArtifactKeep::No, path)); - - String parentDir = Path::getParentDirectory(parentDir); - if (parentDir.getLength()) - { - // Check if we already have the library path, only add it if it's not found - if (libraryPaths.indexOf(parentDir) < 0) - { - libraryPaths.add(parentDir); - } - path = Path::getFileName(path); - } - - // If it starts with lib strip it - if (path.startsWith("lib")) - { - const String stripLib = path.getUnownedSlice().tail(3); - path = stripLib; - } - - // Strip the extension if it's a match - auto extension = Path::getPathExt(path); - if (extension.getLength()) - { - auto libExt = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU).getDefaultExtension(); - if (extension == libExt) - { - path = Path::getFileNameWithoutExt(path); - } - } + if (desc.isCpuBinary() && desc.kind == ArtifactKind::Library) + { + // Get the name and path (can be empty) to the library + SLANG_RETURN_ON_FAIL(artifact->requireFileLike(ArtifactKeep::No)); - cmdLine.addPrefixPathArg("-l", path); - } + libPathPool.add(artifact->getParentPath()); + cmdLine.addPrefixPathArg("-l", artifact->getBaseName()); } } - for (const auto& libPath : options.libraryPaths) - { - // Note that any escaping of the path is handled in the ProcessUtil:: - cmdLine.addArg("-L"); - cmdLine.addArg(libPath); - cmdLine.addArg("-F"); - cmdLine.addArg(libPath); - } - - if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind)) { // Make STD libs available @@ -687,6 +651,15 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse cmdLine.addArg("-lm"); } + for (const auto& libPath : libPathPool.getAdded()) + { + // Note that any escaping of the path is handled in the ProcessUtil:: + cmdLine.addArg("-L"); + cmdLine.addArg(libPath); + cmdLine.addArg("-F"); + cmdLine.addArg(libPath); + } + return SLANG_OK; } diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index df64ed821..0552657f8 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -4,6 +4,7 @@ #include "../core/slang-common.h" #include "../../slang-com-helper.h" #include "../core/slang-string-util.h" +#include "../core/slang-string-slice-pool.h" // if Visual Studio import the visual studio platform specific header #if SLANG_VC @@ -250,28 +251,36 @@ namespace Slang // Link options (parameters past /link go to linker) cmdLine.addArg("/link"); + StringSlicePool libPathPool(StringSlicePool::Style::Default); + for (const auto& libPath : options.libraryPaths) { - // Note that any escaping of the path is handled in the ProcessUtil:: - cmdLine.addPrefixPathArg("/LIBPATH:", libPath); + libPathPool.add(libPath); } // Link libraries. for (Artifact* artifact : options.libraries) { - if (artifact->getDesc().isCpuBinary()) + auto desc = artifact->getDesc(); + + if (desc.isCpuBinary() && desc.kind == ArtifactKind::Library) { - String path; - SLANG_RETURN_ON_FAIL(artifact->requireFilePath(ArtifactKeep::No, path)); + // Get the libray name and path + SLANG_RETURN_ON_FAIL(artifact->requireFileLike(ArtifactKeep::No)); - if (Path::getPathExt(path).getLength() == 0) - { - path.append(".lib"); - } - cmdLine.addArg(path); + libPathPool.add(artifact->getParentPath()); + // We need the extension for windows + cmdLine.addArg(artifact->getBaseName() + ".lib"); } } + // Add all the library paths + for (const auto& libPath : libPathPool.getAdded()) + { + // Note that any escaping of the path is handled in the ProcessUtil:: + cmdLine.addPrefixPathArg("/LIBPATH:", libPath); + } + return SLANG_OK; } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 789103ff8..edcb6e2d4 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1285,12 +1285,8 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) if (_isCPUHostTarget(target)) { options.libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath())); - // Set up the library artifact - const ArtifactDesc desc = ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU, ArtifactStyle::Unknown); - RefPtr<Artifact> artifact = new Artifact(desc); - artifact->setPath(Artifact::PathType::Existing, "slang-rt"); - + RefPtr<Artifact> artifact = new Artifact(ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU), "slang-rt"); options.libraries.add(artifact); } } diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 4c7234753..b02c25549 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -1422,8 +1422,11 @@ struct OptionsParser return SLANG_FAIL; } + const String name = Artifact::getBaseNameFromPath(desc, referenceModuleName.value.getUnownedSlice()); + // Create the artifact - RefPtr<Artifact> artifact = new Artifact(desc); + RefPtr<Artifact> artifact = new Artifact(desc, name); + // Set the path artifact->setPath(Artifact::PathType::Existing, referenceModuleName.value); diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 5b65cd15a..83c52c660 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -4361,8 +4361,10 @@ SlangResult EndToEndCompileRequest::addLibraryReference(const void* libData, siz RefPtr<ModuleLibrary> library; SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)libData, libDataSize, this, library)); - const auto desc = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR, ArtifactStyle::Unknown); - RefPtr<Artifact> artifact = new Artifact(desc); + const auto desc = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); + + // Create an artifact without any name (as one is not provided) + RefPtr<Artifact> artifact = new Artifact(desc, String()); artifact->add(Artifact::Entry::Style::Artifact, library); |
