Loading...
cache_builder/mrm_shared_cache_builder.cpp dyld-1241.17 /dev/null
--- dyld/dyld-1241.17/cache_builder/mrm_shared_cache_builder.cpp
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
- *
- * Copyright (c) 2017 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include "mrm_shared_cache_builder.h"
-#include "Defines.h"
-#include "BuilderFileSystem.h"
-#include "NewSharedCacheBuilder.h"
-#include "Error.h"
-#include "ClosureFileSystem.h"
-#include "ClosureFileSystemNull.h"
-#include "FileUtils.h"
-#include "JSONReader.h"
-#include "JSONWriter.h"
-#include "Misc.h"
-#include "SymbolsCache.h"
-#include "Universal.h"
-#include <pthread.h>
-#include <memory>
-#include <unordered_set>
-#include <vector>
-#include <map>
-#include <sys/stat.h>
-
-
-using cache_builder::CacheBuffer;
-using cache_builder::SharedCacheBuilder;
-
-using error::Error;
-
-static const uint64_t kMinBuildVersion = 1; //The minimum version BuildOptions struct we can support
-static const uint64_t kMaxBuildVersion = 3; //The maximum version BuildOptions struct we can support
-
-static const uint32_t MajorVersion = 1;
-static const uint32_t MinorVersion = 6;
-
-struct BuildInstance {
-    std::unique_ptr<cache_builder::BuilderOptions>  options;
-    std::vector<cache_builder::FileAlias>           aliases;
-    std::vector<cache_builder::FileAlias>           intermediateAliases;
-    std::string                                     mainCacheFilePath;
-    std::vector<const char*>                        errors;
-    std::vector<const char*>                        warnings;
-    std::vector<std::string>                        errorStrings;   // Owns the data for the errors
-    std::vector<std::string>                        warningStrings; // Owns the data for the warnings
-    std::vector<CacheBuffer>                        cacheBuffers;
-    std::vector<std::string>                        cachePaths;     // Owns the data for the cache paths
-    std::string                                     loggingPrefix;
-    std::string                                     jsonMap;
-    std::string                                     mainCacheUUID;
-    std::string                                     customerLoggingPrefix;
-    std::string                                     customerJsonMap;
-    std::string                                     customerMainCacheUUID;
-    std::string                                     macOSMap;       // For compatibility with update_dyld_shared_cache's .map file
-    std::string                                     macOSMapPath;   // Owns the string for the path
-    std::string                                     cdHashType;     // Owns the data for the cdHashType
-};
-
-struct BuildFileResult {
-    std::string                                 path;
-    const uint8_t*                              data;
-    uint64_t                                    size;
-};
-
-struct TranslationResult {
-    const uint8_t*   data;
-    size_t           size;
-    std::string      cdHash;
-    std::string      path;
-    bool             bufferWasMalloced;
-};
-
-struct FileBuffer
-{
-    void*   buffer;
-    size_t  size;
-};
-
-struct MappedBuffer
-{
-    void*       buffer;
-    size_t      size;
-    int         fd;
-    std::string tempPath;
-};
-
-struct MRMSharedCacheBuilder {
-    MRMSharedCacheBuilder(const BuildOptions_v1* options);
-    const BuildOptions_v1*          options;
-    cache_builder::FileSystemMRM    fileSystem;
-
-    std::string dylibOrderFileData;
-    std::string dirtyDataOrderFileData;
-    std::string swiftGenericMetadataFileData;
-    void* objcOptimizationsFileData;
-    size_t objcOptimizationsFileLength;
-
-    // An array of builders and their options as we may have more than one builder for a given device variant.
-    std::vector<BuildInstance> builders;
-
-    // The paths in all of the caches
-    // We keep this here to own the std::string path data
-    std::map<std::string, std::unordered_set<const BuildInstance*>> dylibsInCaches;
-
-    // The results from all of the builders
-    // We keep this in a vector to own the data.
-    std::vector<FileResult*>                     fileResults;
-
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-    // The builder dylib passes back buffers
-    std::vector<FileResult_v1>                   fileResultStorage_v1;
-#else
-    // The builder executable gets file descriptors
-    std::vector<FileResult_v2>                   fileResultStorage_v2;
-#endif
-
-    // Buffers which were malloc()ed and need free()d
-    std::vector<FileBuffer> buffersToFree;
-
-    // Buffers which were vm_allocate()d, and need vm_deallocate()d
-    std::vector<FileBuffer> buffersToDeallocate;
-
-#if !SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-    // Buffers which were open()ed and mmap()ed
-    std::vector<MappedBuffer> buffersToUnmap;
-#endif
-
-    // The results from all of the builders
-    // We keep this in a vector to own the data.
-    std::vector<CacheResult*>    cacheResults;
-    std::vector<CacheResult>     cacheResultStorage;
-
-
-    // The files to remove.  These are in every copy of the caches we built
-    std::vector<const char*> filesToRemove;
-
-    std::vector<const char*> errors;
-    std::vector<std::string> errorStorage;
-    std::vector<std::string> warningsStorage;
-    pthread_mutex_t lock;
-
-    enum State {
-        AcceptingFiles,
-        Building,
-        FinishedBuilding
-    };
-
-    State state = AcceptingFiles;
-
-    void runSync(void (^block)()) {
-        pthread_mutex_lock(&lock);
-        block();
-        pthread_mutex_unlock(&lock);
-    }
-
-    __attribute__((format(printf, 2, 3)))
-    void error(const char* format, ...) {
-        va_list list;
-        va_start(list, format);
-        Diagnostics diag;
-        diag.error(format, list);
-        va_end(list);
-
-        errorStorage.push_back(diag.errorMessage());
-        errors.push_back(errorStorage.back().data());
-    }
-
-    __attribute__((format(printf, 2, 3)))
-    void warning(const char* format, ...) {
-        va_list list;
-        va_start(list, format);
-        Diagnostics diag;
-        diag.error(format, list);
-        va_end(list);
-
-        warningsStorage.push_back(diag.errorMessage());
-    }
-};
-
-MRMSharedCacheBuilder::MRMSharedCacheBuilder(const BuildOptions_v1* options)
-: options(options)
-, objcOptimizationsFileData(nullptr)
-, objcOptimizationsFileLength(0)
-, lock(PTHREAD_MUTEX_INITIALIZER)
-{
-
-}
-
-static void validateBuildOptions(const BuildOptions_v1* options, MRMSharedCacheBuilder& builder) {
-    if (options->version < kMinBuildVersion) {
-        builder.error("Builder version %llu is less than minimum supported version of %llu", options->version, kMinBuildVersion);
-    }
-    if (options->version > kMaxBuildVersion) {
-        builder.error("Builder version %llu is greater than maximum supported version of %llu", options->version, kMaxBuildVersion);
-    }
-    if (!options->updateName) {
-        builder.error("updateName must not be null");
-    }
-    if (!options->deviceName) {
-        builder.error("deviceName must not be null");
-    }
-    switch (options->disposition) {
-        case Disposition::Unknown:
-        case Disposition::InternalDevelopment:
-        case Disposition::Customer:
-        case Disposition::InternalMinDevelopment:
-        case Disposition::SymbolsCache:
-            break;
-        default:
-            builder.error("unknown disposition value");
-            break;
-    }
-    if ( options->platform == Platform::unknown ) {
-        builder.error("platform must not be unknown");
-    }
-    if (!options->archs) {
-        builder.error("archs must not be null");
-    }
-    if (!options->numArchs) {
-        builder.error("numArchs must not be 0");
-    }
-}
-
-void getVersion(uint32_t *major, uint32_t *minor) {
-    *major = MajorVersion;
-    *minor = MinorVersion;
-}
-
-struct MRMSharedCacheBuilder* createSharedCacheBuilder(const BuildOptions_v1* options) {
-    MRMSharedCacheBuilder* builder = new MRMSharedCacheBuilder(options);
-
-    // Check the option struct values are valid
-    validateBuildOptions(options, *builder);
-
-    return builder;
-}
-
-static bool addFileImpl(struct MRMSharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags,
-                        uint64_t inode, uint64_t modTime, const char* projectName) {
-    __block bool success = false;
-    builder->runSync(^() {
-        if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
-            builder->error("Cannot add file: '%s' as we have already started building", path);
-            return;
-        }
-        size_t pathLength = strlen(path);
-        if (pathLength == 0) {
-            builder->error("Empty path");
-            return;
-        }
-        if (pathLength >= MAXPATHLEN) {
-            builder->error("Path is too long: '%s'", path);
-            return;
-        }
-        if (data == nullptr) {
-            builder->error("Data cannot be null for file: '%s'", path);
-            return;
-        }
-        switch (fileFlags) {
-            case NoFlags:
-            case MustBeInCache:
-            case ShouldBeExcludedFromCacheIfUnusedLeaf:
-            case RequiredClosure:
-                break;
-            case DylibOrderFile:
-                builder->dylibOrderFileData = std::string((char*)data, size);
-                success = true;
-                return;
-            case DirtyDataOrderFile:
-                builder->dirtyDataOrderFileData = std::string((char*)data, size);
-                success = true;
-                return;
-            case ObjCOptimizationsFile:
-                builder->objcOptimizationsFileData = data;
-                builder->objcOptimizationsFileLength = size;
-                success = true;
-                return;
-            case SwiftGenericMetadataFile:
-                builder->swiftGenericMetadataFileData = std::string((char*)data, size);
-                success = true;
-                return;
-            default:
-                builder->error("unknown file flags value");
-                break;
-        }
-        Diagnostics diag;
-        if (!builder->fileSystem.addFile(path, data, size, diag, fileFlags, inode, modTime, projectName)) {
-            builder->errorStorage.push_back(diag.errorMessage());
-            builder->errors.push_back(builder->errorStorage.back().data());
-            return;
-        }
-        success = true;
-    });
-    return success;
-}
-
-bool addFile(struct MRMSharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags) {
-    return addFileImpl(builder, path, data, size, fileFlags, 0, 0, "");
-}
-
-bool addFile_v2(struct MRMSharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags, const char* projectName) {
-    return addFileImpl(builder, path, data, size, fileFlags, 0, 0, projectName);
-}
-
-bool addOnDiskFile(struct MRMSharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags,
-                   uint64_t inode, uint64_t modTime) {
-    return addFileImpl(builder, path, data, size, fileFlags, inode, modTime, "");
-}
-
-bool addSymlink(struct MRMSharedCacheBuilder* builder, const char* fromPath, const char* toPath) {
-    __block bool success = false;
-    builder->runSync(^() {
-        if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
-            builder->error("Cannot add file: '%s' as we have already started building", fromPath);
-            return;
-        }
-        size_t pathLength = strlen(fromPath);
-        if (pathLength == 0) {
-            builder->error("Empty path");
-            return;
-        }
-        if (pathLength >= MAXPATHLEN) {
-            builder->error("Path is too long: '%s'", fromPath);
-            return;
-        }
-        Diagnostics diag;
-        if (!builder->fileSystem.addSymlink(fromPath, toPath, diag)) {
-            builder->errorStorage.push_back(diag.errorMessage());
-            builder->errors.push_back(builder->errorStorage.back().data());
-            return;
-        }
-        success = true;
-    });
-    return success;
-}
-
-static cache_builder::LocalSymbolsMode platformExcludeLocalSymbols(Platform platform) {
-    if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)platform) )
-        return cache_builder::LocalSymbolsMode::keep;
-    if ( (platform == Platform::macOS) || (platform == Platform::iOSMac) )
-        return cache_builder::LocalSymbolsMode::keep;
-    // Everything else is based on iOS so just use that value
-    return cache_builder::LocalSymbolsMode::unmap;
-}
-
-static cache_builder::LocalSymbolsMode excludeLocalSymbols(const BuildOptions_v1* options) {
-    if ( options->version >= 2 ) {
-        const BuildOptions_v2* v2 = (const BuildOptions_v2*)options;
-        if ( v2->optimizeForSize )
-            return cache_builder::LocalSymbolsMode::strip;
-    }
-
-    // Old build options always use the platform default
-    return platformExcludeLocalSymbols(options->platform);
-}
-
-static DyldSharedCache::CodeSigningDigestMode platformCodeSigningDigestMode(Platform platform) {
-    if ( platform == Platform::watchOS )
-        return DyldSharedCache::Agile;
-    return DyldSharedCache::SHA256only;
-}
-
-static const char* dispositionName(Disposition disposition) {
-    switch (disposition) {
-        case Disposition::Unknown:
-            return "";
-        case Disposition::InternalDevelopment:
-            return "Internal";
-        case Disposition::Customer:
-            return "Customer";
-        case Disposition::InternalMinDevelopment:
-            return "InternalMinDevelopment";
-        case Disposition::SymbolsCache:
-            return "SymbolsCache";
-    }
-}
-
-static bool filesRemovedFromDisk(const BuildOptions_v1* options) {
-    // Old builds are platforms which always remove files from disk
-    if ( options->version < 3 ) {
-        return true;
-    }
-
-    const BuildOptions_v3* v3 = (const BuildOptions_v3*)options;
-    return v3->filesRemovedFromDisk;
-}
-
-static bool timePasses(const BuildOptions_v1* options) {
-    // Old builds just use the verbose flags
-    if ( options->version < 3 ) {
-        return options->verboseDiagnostics;
-    }
-
-    const BuildOptions_v3* v3 = (const BuildOptions_v3*)options;
-    return v3->timePasses;
-}
-
-static bool printStats(const BuildOptions_v1* options) {
-    // Old builds just use the verbose flags
-    if ( options->version < 3 ) {
-        return options->verboseDiagnostics;
-    }
-
-    const BuildOptions_v3* v3 = (const BuildOptions_v3*)options;
-    return v3->printStats;
-}
-
-// This is a JSON file containing the list of classes for which
-// we should try to build IMP caches.
-static dyld3::json::Node parseObjcOptimizationsFile(Diagnostics& diags, const void* data, size_t length) {
-    if ( data == nullptr )
-        return dyld3::json::Node();
-    return dyld3::json::readJSON(diags, data, length);
-}
-
-static cache_builder::CacheKind getCacheKind(const BuildOptions_v1* options)
-{
-    // Work out what kind of cache we are building.  macOS/driverKit/exclaveKit are always development
-    if (   (options->platform == macOS)
-        || (options->platform == driverKit)
-        || dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)options->platform) )
-        return cache_builder::CacheKind::development;
-
-    // Sims are always development
-    if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)options->platform) )
-        return cache_builder::CacheKind::development;
-
-    // iOS is always universal. If building for InternalMinDevelopment, we'll build universal
-    // anyway, then throw away the development pieces
-    return cache_builder::CacheKind::universal;
-}
-
-static bool shouldEmitDevelopmentCache(const BuildOptions_v1* options)
-{
-    // Filter dev/customer based on the cache kind and disposition
-    switch ( getCacheKind(options) ) {
-        case cache_builder::CacheKind::development:
-            return true;
-        case cache_builder::CacheKind::universal:
-            break;
-    }
-
-    switch ( options->disposition ) {
-        case Disposition::Unknown:
-        case Disposition::InternalDevelopment:
-            return true;
-        case Disposition::Customer:
-            return false;
-        case Disposition::InternalMinDevelopment:
-            return true;
-        case Disposition::SymbolsCache:
-            return false;
-    }
-
-    return true;
-}
-
-static bool shouldEmitCustomerCache(const BuildOptions_v1* options)
-{
-    // Filter dev/customer based on the cache kind and disposition
-    switch ( getCacheKind(options) ) {
-        case cache_builder::CacheKind::development:
-            return false;
-        case cache_builder::CacheKind::universal:
-            break;
-    }
-
-    switch ( options->disposition ) {
-        case Disposition::Unknown:
-        case Disposition::InternalDevelopment:
-            return true;
-        case Disposition::Customer:
-            return true;
-        case Disposition::InternalMinDevelopment:
-            return false;
-        case Disposition::SymbolsCache:
-            return false;
-    }
-
-    return true;
-}
-
-static bool createBuilders(struct MRMSharedCacheBuilder* builder)
-{
-    if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
-        builder->error("Builder has already been run");
-        return false;
-    }
-    builder->state = MRMSharedCacheBuilder::Building;
-    if (builder->fileSystem.fileCount() == 0) {
-        builder->error("Cannot run builder with no files");
-    }
-
-    auto symlinkResolverError = ^(const std::string& error) {
-        builder->warning("%s", error.c_str());
-    };
-    std::vector<cache_builder::FileAlias> aliases = builder->fileSystem.getResolvedSymlinks(symlinkResolverError);
-    std::vector<cache_builder::FileAlias> intermediateAliases = builder->fileSystem.getIntermediateSymlinks();
-
-    if (!builder->errors.empty()) {
-        builder->error("Skipping running shared cache builder due to previous errors");
-        return false;
-    }
-
-    // Enqueue a cache for each configuration
-    Diagnostics diag;
-    for (uint64_t i = 0; i != builder->options->numArchs; ++i) {
-        // HACK: Skip i386 for macOS
-        if ( strcmp(builder->options->archs[i], "i386") == 0 )
-            continue;
-
-        // Add a driverKit/exclaveKit suffix.  Note we don't need to add .development suffixes any
-        // more as the universal caches don't build customer and development seperately
-        const char *loggingSuffix = "";
-        if ( builder->options->platform == Platform::driverKit )
-            loggingSuffix = ".driverKit";
-        if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
-            loggingSuffix = ".exclaveKit";
-
-        std::string loggingPrefix = "";
-        loggingPrefix += std::string(builder->options->deviceName);
-        loggingPrefix += dispositionName(builder->options->disposition);
-        loggingPrefix += std::string(".") + builder->options->archs[i];
-        loggingPrefix += loggingSuffix;
-
-        std::string runtimePath;
-        if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)builder->options->platform) ) {
-            // Sim caches are written exactly where instructed, without adding any directory structure
-            runtimePath = runtimePath + "dyld_sim_shared_cache_" + builder->options->archs[i];
-        } else {
-            if ( builder->options->platform == Platform::macOS )
-                runtimePath = MACOSX_MRM_DYLD_SHARED_CACHE_DIR;
-            else if ( builder->options->platform == Platform::driverKit )
-                runtimePath = DRIVERKIT_DYLD_SHARED_CACHE_DIR;
-            else if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
-                runtimePath = EXCLAVEKIT_DYLD_SHARED_CACHE_DIR;
-            else
-                runtimePath = IPHONE_DYLD_SHARED_CACHE_DIR;
-            runtimePath = runtimePath + "dyld_shared_cache_" + builder->options->archs[i];
-        }
-
-        bool dylibsRemovedFromDisk  = filesRemovedFromDisk(builder->options);
-        bool isLocallyBuiltCache    = builder->options->isLocallyBuiltCache;
-
-        cache_builder::CacheKind cacheKind = getCacheKind(builder->options);
-
-        // If we have a universal cache, but min development disposition, then we want dev
-        // caches only, and should change the names to match.
-        // This also lets us install a dev cache on top of a universal one, without breaking
-        // the customer bits in the universal cache
-        bool forceDevelopmentSubCacheSuffix = false;
-        if ( (cacheKind == cache_builder::CacheKind::universal)
-            && (builder->options->disposition == InternalMinDevelopment) )
-            forceDevelopmentSubCacheSuffix = true;
-
-        auto options = std::make_unique<cache_builder::BuilderOptions>(builder->options->archs[i],
-                                                                       (dyld3::Platform)builder->options->platform,
-                                                                       dylibsRemovedFromDisk, isLocallyBuiltCache,
-                                                                       cacheKind, forceDevelopmentSubCacheSuffix);
-
-        options->logPrefix                   = loggingPrefix;
-        options->debug                       = builder->options->verboseDiagnostics;
-        options->timePasses                  = options->debug ? true : timePasses(builder->options);
-        options->stats                       = options->debug ? true : printStats(builder->options);
-        options->dylibOrdering               = parseOrderFile(builder->dylibOrderFileData);
-        options->dirtyDataSegmentOrdering    = parseOrderFile(builder->dirtyDataOrderFileData);
-        options->objcOptimizations           = parseObjcOptimizationsFile(diag, builder->objcOptimizationsFileData,
-                                                                          builder->objcOptimizationsFileLength);
-        options->localSymbolsMode            = excludeLocalSymbols(builder->options);
-        options->swiftGenericMetadataFile    = builder->swiftGenericMetadataFileData;
-
-        BuildInstance buildInstance;
-        buildInstance.options               = std::move(options);
-        buildInstance.aliases               = aliases;
-        buildInstance.intermediateAliases   = intermediateAliases;
-        buildInstance.mainCacheFilePath     = runtimePath;
-
-        builder->builders.push_back(std::move(buildInstance));
-    }
-
-    return true;
-}
-
-static void runBuilders(struct MRMSharedCacheBuilder* builder)
-{
-    for (auto& buildInstance : builder->builders) {
-        // The build might overflow, so loop until we don't error from overflow
-        std::string              swiftPrespecializedDylibBuildError;
-        std::vector<std::string> evictedDylibs;
-        std::unordered_set<std::string> evictedDylibsSet;
-        __block std::unique_ptr<SharedCacheBuilder> cacheBuilder;
-        Error error;
-        while ( true ) {
-            cacheBuilder = std::make_unique<SharedCacheBuilder>(*buildInstance.options.get(), builder->fileSystem);
-
-            // Add all the input files
-            __block std::vector<cache_builder::InputFile> inputFiles;
-            builder->fileSystem.forEachFileInfo(^(const char* path, const void* buffer, size_t bufferSize,
-                                                  FileFlags fileFlags, uint64_t inode, uint64_t modTime,
-                                                  const char* projectName) {
-                switch (fileFlags) {
-                    case FileFlags::NoFlags:
-                    case FileFlags::MustBeInCache:
-                    case FileFlags::ShouldBeExcludedFromCacheIfUnusedLeaf:
-                    case FileFlags::RequiredClosure:
-                        break;
-                    case FileFlags::DylibOrderFile:
-                    case FileFlags::DirtyDataOrderFile:
-                    case FileFlags::ObjCOptimizationsFile:
-                    case FileFlags::SwiftGenericMetadataFile:
-                        builder->error("Order files should not be in the file system");
-                        return;
-                }
-
-                cacheBuilder->addFile(buffer, bufferSize, path, inode, modTime, evictedDylibsSet.count(path));
-            });
-
-            // Add resolved aliases (symlinks)
-            cacheBuilder->setAliases(buildInstance.aliases, buildInstance.intermediateAliases);
-
-            error = cacheBuilder->build();
-
-            // Get result buffers, even if there's an error.  That way we'll free them
-            cacheBuilder->getResults(buildInstance.cacheBuffers);
-
-            if ( !error.hasError() )
-                break;
-
-            // try without Swift metadata dylib if building it failed
-            bool retryWithoutSwiftMetadata = false;
-            if ( !cacheBuilder->getSwiftPrespecializedDylibBuildError().empty() ) {
-                assert(!buildInstance.options->swiftGenericMetadataFile.empty()
-                        && "Swift prespecialization build error even with an empty metadata file");
-                swiftPrespecializedDylibBuildError = std::string(cacheBuilder->getSwiftPrespecializedDylibBuildError());
-                buildInstance.options->swiftGenericMetadataFile.clear();
-                retryWithoutSwiftMetadata = true;
-            }
-
-            // We have an error. If its cache overflow, then we can try again, with some evicted dylibs
-            bool retryEvictedDylibs = false;
-            std::span<const std::string_view> newEvictedDylibs = cacheBuilder->getEvictedDylibs();
-            if ( !newEvictedDylibs.empty() ) {
-                evictedDylibs.insert(evictedDylibs.end(), newEvictedDylibs.begin(), newEvictedDylibs.end());
-                evictedDylibsSet.insert(newEvictedDylibs.begin(), newEvictedDylibs.end());
-                retryEvictedDylibs = true;
-            }
-
-            bool retry = retryEvictedDylibs || retryWithoutSwiftMetadata;
-            if ( !retry ) {
-                // Error wasn't eviction, nor Swift metadata build. Break out an handle it as a fatal error
-                break;
-            }
-
-            // Cache eviction happened. Note down the bad dylibs, and try again
-            // Note we should never have buffer data to free at this point as eviction should be
-            // determined before buffers are allocated
-            for ( const CacheBuffer& buffer : buildInstance.cacheBuffers ) {
-                assert(buffer.bufferData == nullptr);
-            }
-            buildInstance.cacheBuffers.clear();
-        }
-
-        buildInstance.loggingPrefix = cacheBuilder->developmentLoggingPrefix();
-        buildInstance.customerLoggingPrefix = cacheBuilder->customerLoggingPrefix();
-
-        // Track all buffers to be freed/unmapped (see allocateSubCacheBuffers() for allocation)
-        for ( const CacheBuffer& buffer : buildInstance.cacheBuffers ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-            // In MRM, we vm_allocated
-            builder->buffersToDeallocate.emplace_back((FileBuffer){ buffer.bufferData, buffer.bufferSize });
-#else
-            // In the local builder, we mmap()ed
-            builder->buffersToUnmap.emplace_back((MappedBuffer) {
-                buffer.bufferData,
-                buffer.bufferSize,
-                buffer.fd,
-                buffer.tempPath
-            });
-#endif
-        }
-
-        if ( error.hasError() ) {
-            // First put the error in to a vector to own it
-            buildInstance.errorStrings.push_back(error.message());
-
-            cacheBuilder->forEachError(^(const std::string_view &str) {
-                buildInstance.errorStrings.push_back(std::string(str));
-            });
-
-            // Then copy to a vector to reference the owner
-            buildInstance.errors.reserve(buildInstance.errorStrings.size());
-            for (const std::string& err : buildInstance.errorStrings)
-                buildInstance.errors.push_back(err.c_str());
-
-            // First put the warnings in to a vector to own them.
-            if ( builder->options->verboseDiagnostics ) {
-                // Add cache eviction warnings, if any
-                for ( std::string path : evictedDylibs ) {
-                    std::string reason = "Dylib located at '" + path + "' not placed in shared cache because: cache overflow";
-                    buildInstance.warningStrings.push_back(reason);
-                }
-                if ( !swiftPrespecializedDylibBuildError.empty() )
-                    buildInstance.warningStrings.push_back("Couldn't build Swift prespecialized metadata dylib: " + swiftPrespecializedDylibBuildError);
-
-                cacheBuilder->forEachWarning(^(const std::string_view &str) {
-                    buildInstance.warningStrings.push_back(std::string(str));
-                });
-
-                // Then copy to a vector to reference the owner
-                buildInstance.warnings.reserve(buildInstance.warningStrings.size());
-                for ( const std::string& warning : buildInstance.warningStrings )
-                    buildInstance.warnings.push_back(warning.c_str());
-            }
-        } else {
-            // Successfully built a cache
-
-            // Remove buffers we don't need
-            bool needDevelopmentCaches = shouldEmitDevelopmentCache(builder->options);
-            bool needCustomerCaches = shouldEmitCustomerCache(builder->options);
-            std::erase_if(buildInstance.cacheBuffers, [&](const CacheBuffer& buffer) {
-                if ( needDevelopmentCaches && buffer.usedByDevelopmentConfig )
-                    return false;
-
-                if ( needCustomerCaches && buffer.usedByCustomerConfig )
-                    return false;
-
-                return true;
-            });
-
-            if ( (buildInstance.options->platform == dyld3::Platform::macOS)
-                || dyld3::MachOFile::isSimulatorPlatform(buildInstance.options->platform) ) {
-                // For compatibility with update_dyld_shared_cache/update_dyld_sim_shared_cache, put a .map file next to the shared cache
-                buildInstance.macOSMap = cacheBuilder->getMapFileBuffer();
-                buildInstance.macOSMapPath = buildInstance.mainCacheFilePath + ".map";
-            }
-
-            buildInstance.jsonMap = cacheBuilder->developmentJSONMap(builder->options->deviceName);
-            buildInstance.mainCacheUUID = cacheBuilder->developmentCacheUUID();
-
-            // If building for universal, we'll have customer JSON maps and UUID
-            buildInstance.customerJsonMap = cacheBuilder->customerJSONMap(builder->options->deviceName);
-            buildInstance.customerMainCacheUUID = cacheBuilder->customerCacheUUID();
-
-            // Only add warnings if the build was good
-            // First put the warnings in to a vector to own them.
-
-            // Add cache eviction warnings, if any
-            for ( std::string path : evictedDylibs ) {
-                std::string reason = "Dylib located at '" + path + "' not placed in shared cache because: cache overflow";
-                buildInstance.warningStrings.push_back(reason);
-            }
-            if ( !swiftPrespecializedDylibBuildError.empty() )
-                buildInstance.warningStrings.push_back("Couldn't build Swift prespecialized metadata dylib: " + swiftPrespecializedDylibBuildError);
-
-            cacheBuilder->forEachWarning(^(const std::string_view &str) {
-                buildInstance.warningStrings.push_back(std::string(str));
-            });
-
-            // Then copy to a vector to reference the owner
-            buildInstance.warnings.reserve(buildInstance.warningStrings.size());
-            for ( const std::string& warning : buildInstance.warningStrings )
-                buildInstance.warnings.push_back(warning.c_str());
-
-            switch ( platformCodeSigningDigestMode(builder->options->platform) ) {
-                case DyldSharedCache::SHA256only:
-                    buildInstance.cdHashType = "sha256";
-                    break;
-                case DyldSharedCache::SHA1only:
-                    buildInstance.cdHashType = "sha1";
-                    break;
-                case DyldSharedCache::Agile:
-                    buildInstance.cdHashType = "sha1";
-                    break;
-            }
-
-            // Track the dylibs which were included in this cache
-            cacheBuilder->forEachCacheDylib(^(const std::string_view &path) {
-                builder->dylibsInCaches[std::string(path)].insert(&buildInstance);
-            });
-            cacheBuilder->forEachCacheSymlink(^(const std::string_view &path) {
-                builder->dylibsInCaches[std::string(path)].insert(&buildInstance);
-            });
-        }
-    }
-}
-
-
-static void createBuildResults(struct MRMSharedCacheBuilder* builder)
-{
-    // Now that we have run all of the builds, collect the results
-    // First push file results for each of the shared caches we built
-    for (auto& buildInstance : builder->builders) {
-        bool emittedWarningsAndErrors = false;
-        if ( shouldEmitDevelopmentCache(builder->options) ) {
-            CacheResult cacheBuildResult;
-            cacheBuildResult.version                = 1;
-            cacheBuildResult.loggingPrefix          = buildInstance.loggingPrefix.c_str();
-            cacheBuildResult.deviceConfiguration    = buildInstance.loggingPrefix.c_str();
-            cacheBuildResult.warnings               = buildInstance.warnings.empty() ? nullptr : buildInstance.warnings.data();
-            cacheBuildResult.numWarnings            = buildInstance.warnings.size();
-            cacheBuildResult.errors                 = buildInstance.errors.empty() ? nullptr : buildInstance.errors.data();
-            cacheBuildResult.numErrors              = buildInstance.errors.size();
-            cacheBuildResult.uuidString             = buildInstance.mainCacheUUID.empty() ? "" : buildInstance.mainCacheUUID.c_str();
-            cacheBuildResult.mapJSON                = buildInstance.jsonMap.empty() ? "" : buildInstance.jsonMap.c_str();
-
-            builder->cacheResultStorage.emplace_back(cacheBuildResult);
-
-            emittedWarningsAndErrors = true;
-        }
-
-        if ( shouldEmitCustomerCache(builder->options) ) {
-            CacheResult cacheBuildResult;
-            cacheBuildResult.version              = 1;
-            cacheBuildResult.loggingPrefix        = buildInstance.customerLoggingPrefix.c_str();
-            cacheBuildResult.deviceConfiguration  = buildInstance.customerLoggingPrefix.c_str();
-            cacheBuildResult.warnings             = nullptr;
-            cacheBuildResult.numWarnings          = 0;
-            cacheBuildResult.errors               = nullptr;
-            cacheBuildResult.numErrors            = 0;
-            cacheBuildResult.uuidString           = buildInstance.customerMainCacheUUID.empty() ? "" : buildInstance.customerMainCacheUUID.c_str();
-            cacheBuildResult.mapJSON              = buildInstance.customerJsonMap.empty() ? "" : buildInstance.customerJsonMap.c_str();
-
-            if ( !emittedWarningsAndErrors ) {
-                cacheBuildResult.warnings         = buildInstance.warnings.empty() ? nullptr : buildInstance.warnings.data();
-                cacheBuildResult.numWarnings      = buildInstance.warnings.size();
-                cacheBuildResult.errors           = buildInstance.errors.empty() ? nullptr : buildInstance.errors.data();
-                cacheBuildResult.numErrors        = buildInstance.errors.size();
-            }
-
-            builder->cacheResultStorage.emplace_back(cacheBuildResult);
-        }
-
-        if (!buildInstance.errors.empty())
-            continue;
-
-        for ( const CacheBuffer& buffer : buildInstance.cacheBuffers )
-            buildInstance.cachePaths.push_back(buildInstance.mainCacheFilePath + buffer.cacheFileSuffix);
-
-        uint32_t cacheIndex = 0;
-        for ( const CacheBuffer& cacheBuffer : buildInstance.cacheBuffers ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-            FileResult_v1 cacheFileResult;
-            cacheFileResult.version          = 1;
-            cacheFileResult.path             = buildInstance.cachePaths[cacheIndex].c_str();
-            cacheFileResult.behavior         = AddFile;
-            cacheFileResult.data             = cacheBuffer.bufferData;
-            cacheFileResult.size             = cacheBuffer.bufferSize;
-            cacheFileResult.hashArch         = buildInstance.options->archs.name();
-            cacheFileResult.hashType         = buildInstance.cdHashType.c_str();
-            cacheFileResult.hash             = cacheBuffer.cdHash.c_str();
-
-            builder->fileResultStorage_v1.emplace_back(cacheFileResult);
-#else
-            FileResult_v2 cacheFileResult;
-            cacheFileResult.version          = 2;
-            cacheFileResult.path             = buildInstance.cachePaths[cacheIndex].c_str();
-            cacheFileResult.behavior         = AddFile;
-            cacheFileResult.data             = cacheBuffer.bufferData;
-            cacheFileResult.size             = cacheBuffer.bufferSize;
-            cacheFileResult.hashArch         = buildInstance.options->archs.name();
-            cacheFileResult.hashType         = buildInstance.cdHashType.c_str();
-            cacheFileResult.hash             = cacheBuffer.cdHash.c_str();
-            cacheFileResult.fd               = cacheBuffer.fd;
-            cacheFileResult.tempFilePath     = cacheBuffer.tempPath.c_str();
-
-            builder->fileResultStorage_v2.emplace_back(cacheFileResult);
-#endif
-            ++cacheIndex;
-        }
-
-        // Add a file result for the .map file
-        // FIXME: We only emit a single map file right now.
-        if ( !buildInstance.macOSMap.empty() ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-            FileResult_v1 cacheFileResult;
-            cacheFileResult.version     = 1;
-            cacheFileResult.path        = buildInstance.macOSMapPath.c_str();
-            cacheFileResult.behavior    = AddFile;
-            cacheFileResult.data        = (const uint8_t*)buildInstance.macOSMap.data();
-            cacheFileResult.size        = buildInstance.macOSMap.size();
-            cacheFileResult.hashArch    = buildInstance.options->archs.name();
-            cacheFileResult.hashType    = buildInstance.cdHashType.c_str();
-            cacheFileResult.hash        = buildInstance.cacheBuffers.front().cdHash.c_str();;
-
-            builder->fileResultStorage_v1.emplace_back(cacheFileResult);
-#else
-            FileResult_v2 cacheFileResult;
-            cacheFileResult.version          = 2;
-            cacheFileResult.path             = buildInstance.macOSMapPath.c_str();
-            cacheFileResult.behavior         = AddFile;
-            cacheFileResult.data             = (const uint8_t*)buildInstance.macOSMap.data();
-            cacheFileResult.size             = buildInstance.macOSMap.size();
-            cacheFileResult.hashArch         = buildInstance.options->archs.name();
-            cacheFileResult.hashType         = buildInstance.cdHashType.c_str();
-            cacheFileResult.hash             = buildInstance.cacheBuffers.front().cdHash.c_str();
-            cacheFileResult.fd               = 0;
-            cacheFileResult.tempFilePath     = nullptr;
-
-            builder->fileResultStorage_v2.emplace_back(cacheFileResult);
-#endif
-        }
-    }
-}
-
-static void calculateDylibsToDelete(struct MRMSharedCacheBuilder* builder)
-{
-    // Keep ExclaveKit binaries on disk, remove that exception later (rdar://112851136)
-    if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
-        return;
-
-    // Add entries to tell us to remove all of the dylibs from disk which are in every cache.
-    const size_t numCaches = builder->builders.size();
-    for (const auto& dylibAndCount : builder->dylibsInCaches) {
-        const char* pathToRemove = dylibAndCount.first.c_str();
-        // Mastering should not remove dyld from disk
-        if ( strcmp(pathToRemove, "/usr/lib/dyld") == 0 )
-            continue;
-
-        if ( builder->options->platform == Platform::macOS ) {
-            // macOS has to leave the simulator support binaries on disk
-            if ( strcmp(pathToRemove, "/usr/lib/system/libsystem_kernel.dylib") == 0 )
-                continue;
-            if ( strcmp(pathToRemove, "/usr/lib/system/libsystem_platform.dylib") == 0 )
-                continue;
-            if ( strcmp(pathToRemove, "/usr/lib/system/libsystem_pthread.dylib") == 0 )
-                continue;
-        }
-
-        if (dylibAndCount.second.size() == numCaches) {
-            builder->filesToRemove.push_back(pathToRemove);
-        } else {
-            // File is not in every cache, so likely has perhaps only x86_64h slice
-            // but we built both x86_64 and x86_64h caches.
-            // We may still delete it if its in all caches it's eligible for, ie, we
-            // assume the cache builder knows about all possible arch's on the system and
-            // can delete anything it knows can't run
-            bool canDeletePath = true;
-            for (auto& buildInstance : builder->builders) {
-                if ( dylibAndCount.second.count(&buildInstance) != 0 )
-                    continue;
-
-                dyld3::closure::LoadedFileInfo fileInfo;
-                char realerPath[MAXPATHLEN];
-                auto errorHandler = ^(const char*, ...) { };
-                if ( !builder->fileSystem.loadFile(pathToRemove, fileInfo, realerPath, errorHandler) ) {
-                    // Somehow the file isn't loadable any more
-                    continue;
-                }
-
-                if ( fileInfo.fileContent == nullptr )
-                    continue;
-
-                const void* buffer = fileInfo.fileContent;
-                size_t bufferSize = fileInfo.fileContentLen;
-
-                // This builder didn't get this image.  See if the image was ineligible
-                // based on slice, ie, that dyld at runtime couldn't load this anyway, so
-                // so removing it from disk won't hurt
-                Diagnostics loaderDiag;
-                const bool  isOSBinary = false;
-                const dyld3::GradedArchs& archs = buildInstance.options->archs;
-                dyld3::Platform platform = buildInstance.options->platform;
-                uint64_t sliceSize = 0;
-                if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceSize, buffer, bufferSize,
-                                                                        pathToRemove, platform,
-                                                                        isOSBinary, archs) ) {
-                    // This arch was compatible, so the dylib was rejected from this cache for some other reason, eg,
-                    // cache overflow.  We need to keep it on-disk
-                    if ( !loaderDiag.hasError() ) {
-                        canDeletePath = false;
-                        break;
-                    }
-                }
-
-                // Check iOSMac, just in case we couldn't load the slice on macOS
-                if ( (platform == dyld3::Platform::macOS) && loaderDiag.hasError() ) {
-                    loaderDiag.clearError();
-
-                    if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceSize, buffer, bufferSize,
-                                                                            pathToRemove, dyld3::Platform::iOSMac,
-                                                                            isOSBinary, archs) ) {
-                        // This arch was compatible, so the dylib was rejected from this cache for some other reason, eg,
-                        // cache overflow.  We need to keep it on-disk
-                        if ( !loaderDiag.hasError() ) {
-                            canDeletePath = false;
-                            break;
-                        }
-                    }
-                }
-            }
-            if ( canDeletePath )
-                builder->filesToRemove.push_back(pathToRemove);
-        }
-    }
-}
-
-static bool runSymbolsCacheBuilder(struct MRMSharedCacheBuilder* builder) {
-    __block bool success = false;
-    builder->runSync(^() {
-        __block SymbolsCache::ArchPlatforms archPlatforms;
-        if ( builder->options->platform == driverKit ) {
-            // Note Image Assembly might not know which archs/platforms to build as a single DylibCache could
-            // have different archs for different platforms, like userland vs driverKit vs exclaves.
-            builder->fileSystem.forEachFileInfo(^(const char* path, const void* buffer, size_t bufferSize,
-                                                  FileFlags fileFlags, uint64_t inode, uint64_t modTime,
-                                                  const char* projectName) {
-                if ( !strcmp(path, "/System/DriverKit/usr/lib/libSystem.dylib")
-                    || !strcmp(path, "/System/DriverKit/usr/lib/libSystem.B.dylib") ) {
-                    const std::span<uint8_t> bufferSpan = { (uint8_t*)buffer, bufferSize };
-                    mach_o::Error parseErr = mach_o::forEachHeader(bufferSpan, path,
-                                                                   ^(const mach_o::Header* mh, size_t sliceHeader, bool &stop) {
-                        mach_o::PlatformAndVersions pvs = mh->platformAndVersions();
-                        if ( pvs.platform.empty() )
-                            return;
-
-                        // HACK: Pretend zippered are macOS, so that the database doesn't have to care about zippering
-                        mach_o::Platform platform;
-                        if ( (pvs.platform == mach_o::Platform::zippered) || (pvs.platform == mach_o::Platform::macCatalyst) )
-                            platform = mach_o::Platform::macOS;
-                        else
-                            platform = pvs.platform;
-
-                        archPlatforms[mh->archName()].push_back(platform);
-                    });
-                    if ( parseErr ) {
-                        builder->error("Cannot build symbols cache because: %s", parseErr.message());
-                    }
-                }
-            });
-        } else {
-            // Note Image Assembly might not know which archs/platforms to build as a single DylibCache could
-            // have different archs for different platforms, like userland vs driverKit vs exclaves.
-            builder->fileSystem.forEachFileInfo(^(const char* path, const void* buffer, size_t bufferSize,
-                                                  FileFlags fileFlags, uint64_t inode, uint64_t modTime,
-                                                  const char* projectName) {
-                if ( !strcmp(path, "/usr/lib/libSystem.dylib")
-                    || !strcmp(path, "/usr/lib/libSystem.B.dylib")
-                    || !strcmp(path, "/System/DriverKit/usr/lib/libSystem.dylib")
-                    || !strcmp(path, "/System/DriverKit/usr/lib/libSystem.B.dylib") ) {
-                    const std::span<uint8_t> bufferSpan = { (uint8_t*)buffer, bufferSize };
-                    mach_o::Error parseErr = mach_o::forEachHeader(bufferSpan, path,
-                                                                   ^(const mach_o::Header* mh, size_t sliceHeader, bool &stop) {
-                        mach_o::PlatformAndVersions pvs = mh->platformAndVersions();
-                        if ( pvs.platform.empty() )
-                            return;
-
-                        // HACK: Pretend zippered are macOS, so that the database doesn't have to care about zippering
-                        mach_o::Platform platform;
-                        if ( (pvs.platform == mach_o::Platform::zippered) || (pvs.platform == mach_o::Platform::macCatalyst) )
-                            platform = mach_o::Platform::macOS;
-                        else
-                            platform = pvs.platform;
-
-                        archPlatforms[mh->archName()].push_back(platform);
-                    });
-                    if ( parseErr ) {
-                        builder->error("Cannot build symbols cache because: %s", parseErr.message());
-                    }
-                }
-            });
-        }
-
-        __block class SymbolsCache cache;
-
-        if ( mach_o::Error err = cache.create() ) {
-            builder->error("Cannot create symbols cache because: %s", err.message());
-            return;
-        }
-
-        __block bool gotFileErr = false;
-        __block std::vector<SymbolsCacheBinary> binaries;
-        builder->fileSystem.forEachFileInfo(^(const char* path, const void* buffer, size_t bufferSize,
-                                              FileFlags fileFlags, uint64_t inode, uint64_t modTime,
-                                              const char* projectName) {
-            if ( gotFileErr )
-                return;
-            switch (fileFlags) {
-                case FileFlags::NoFlags:
-                case FileFlags::MustBeInCache:
-                case FileFlags::ShouldBeExcludedFromCacheIfUnusedLeaf:
-                case FileFlags::RequiredClosure:
-                    break;
-                case FileFlags::DylibOrderFile:
-                case FileFlags::DirtyDataOrderFile:
-                case FileFlags::ObjCOptimizationsFile:
-                case FileFlags::SwiftGenericMetadataFile:
-                    builder->error("Order files should not be in the file system");
-                    return;
-            }
-
-            if ( mach_o::Error err = cache.makeBinaries(archPlatforms, builder->fileSystem, 
-                                                        buffer, bufferSize, path, projectName,
-                                                        binaries) ) {
-                builder->error("Cannot build symbols cache because: %s", err.message());
-                gotFileErr = true;
-                return;
-            }
-        });
-
-        if ( gotFileErr )
-            return;
-
-        if ( mach_o::Error err = cache.addBinaries(binaries) ) {
-            builder->error("Cannot build symbols cache because: %s", err.message());
-            return;
-        }
-
-        const uint8_t* buffer = nullptr;
-        uint64_t bufferSize = 0;
-        if ( mach_o::Error err = cache.serialize(buffer, bufferSize) ) {
-            builder->error("Cannot serialize symbols cache because: %s", err.message());
-            return;
-        }
-
-        CacheResult cacheBuildResult;
-        cacheBuildResult.version              = 1;
-        cacheBuildResult.loggingPrefix        = "symbols-cache";
-        cacheBuildResult.deviceConfiguration  = "symbols-cache";
-        cacheBuildResult.warnings             = nullptr;
-        cacheBuildResult.numWarnings          = 0;
-        cacheBuildResult.errors               = nullptr;
-        cacheBuildResult.numErrors            = 0;
-        cacheBuildResult.uuidString           = "";
-        cacheBuildResult.mapJSON              = "";
-        cacheBuildResult.warnings             = nullptr;
-        cacheBuildResult.numWarnings          = 0;
-        cacheBuildResult.errors               = builder->errors.empty() ? nullptr : builder->errors.data();
-        cacheBuildResult.numErrors            = builder->errors.size();
-
-        builder->cacheResultStorage.push_back(cacheBuildResult);
-        builder->cacheResults.push_back(&builder->cacheResultStorage.back());
-
-        const char* resultPath = MACOSX_MRM_DYLD_SHARED_CACHE_DIR "dyld_symbols.db";;
-        if ( builder->options->platform == driverKit )
-            resultPath = DRIVERKIT_DYLD_SHARED_CACHE_DIR "dyld_symbols.db";
-
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-        FileResult_v1 cacheFileResult;
-        cacheFileResult.version          = 2;
-        cacheFileResult.path             = resultPath;
-        cacheFileResult.behavior         = AddFile;
-        cacheFileResult.data             = buffer;
-        cacheFileResult.size             = bufferSize;
-        cacheFileResult.hashArch         = "x86_64";
-        cacheFileResult.hashType         = "sha256";
-        cacheFileResult.hash             = "";
-
-        builder->fileResultStorage_v1.emplace_back(cacheFileResult);
-        builder->fileResults.push_back((FileResult*)&builder->fileResultStorage_v1.back());
-#else
-        FileResult_v2 cacheFileResult;
-        cacheFileResult.version          = 2;
-        cacheFileResult.path             = resultPath;
-        cacheFileResult.behavior         = AddFile;
-        cacheFileResult.data             = buffer;
-        cacheFileResult.size             = bufferSize;
-        cacheFileResult.hashArch         = "x86_64";
-        cacheFileResult.hashType         = "sha256";
-        cacheFileResult.hash             = "";
-        cacheFileResult.fd               = 0;
-        cacheFileResult.tempFilePath     = nullptr;
-
-        builder->fileResultStorage_v2.emplace_back(cacheFileResult);
-        builder->fileResults.push_back((FileResult*)&builder->fileResultStorage_v2.back());
-#endif
-
-        builder->buffersToFree.emplace_back((FileBuffer) { (void*)buffer, bufferSize });
-
-        success = true;
-    });
-    return success;
-}
-
-
-bool runSharedCacheBuilder(struct MRMSharedCacheBuilder* builder) {
-    if ( builder->options->disposition == SymbolsCache )
-        return runSymbolsCacheBuilder(builder);
-
-    __block bool success = false;
-    builder->runSync(^() {
-        if ( !createBuilders(builder) )
-            return;
-        
-        runBuilders(builder);
-
-
-        createBuildResults(builder);
-        calculateDylibsToDelete(builder);
-
-        // Copy from the storage to the vector we can return to the API.
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-        for (auto &fileResult : builder->fileResultStorage_v1)
-            builder->fileResults.push_back((FileResult*)&fileResult);
-#else
-        for (auto &fileResult : builder->fileResultStorage_v2)
-            builder->fileResults.push_back((FileResult*)&fileResult);
-#endif
-        for (auto &cacheResult : builder->cacheResultStorage)
-            builder->cacheResults.push_back(&cacheResult);
-
-        // Quit if we had any errors.
-        for (auto& buildInstance : builder->builders) {
-            if (!buildInstance.errors.empty())
-                return;
-        }
-
-        builder->state = MRMSharedCacheBuilder::FinishedBuilding;
-        success = true;
-    });
-    return success;
-}
-
-const char* const* getErrors(const struct MRMSharedCacheBuilder* builder, uint64_t* errorCount) {
-    if (builder->errors.empty())
-        return nullptr;
-    *errorCount = builder->errors.size();
-    return builder->errors.data();
-}
-
-const struct FileResult* const* getFileResults(struct MRMSharedCacheBuilder* builder, uint64_t* resultCount) {
-    if (builder->fileResults.empty())
-        return nullptr;
-    *resultCount = builder->fileResults.size();
-    return builder->fileResults.data();
-}
-
-const struct CacheResult* const* getCacheResults(struct MRMSharedCacheBuilder* builder, uint64_t* resultCount) {
-    if (builder->cacheResults.empty())
-        return nullptr;
-    *resultCount = builder->cacheResults.size();
-    return builder->cacheResults.data();
-}
-
-const char* const* getFilesToRemove(const struct MRMSharedCacheBuilder* builder, uint64_t* fileCount) {
-    if (builder->filesToRemove.empty())
-        return nullptr;
-    *fileCount = builder->filesToRemove.size();
-    return builder->filesToRemove.data();
-}
-
-void destroySharedCacheBuilder(struct MRMSharedCacheBuilder* builder) {
-
-    for ( FileBuffer& buffer : builder->buffersToFree ) {
-        free((void*)buffer.buffer);
-    }
-
-    for ( FileBuffer& buffer : builder->buffersToDeallocate ) {
-        vm_deallocate(mach_task_self(), (vm_address_t)buffer.buffer, buffer.size);
-    }
-
-#if !SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
-    for ( MappedBuffer& buffer : builder->buffersToUnmap ) {
-        ::munmap(buffer.buffer, buffer.size);
-        ::close(buffer.fd);
-
-        // The builder tool will link this temp path to the new location, if needed.  We then
-        // remove the old path with this unlink().
-        ::unlink(buffer.tempPath.c_str());
-    }
-#endif
-
-    delete builder;
-}