Loading...
--- dyld/dyld-832.7.1/dyld3/shared-cache/mrm_shared_cache_builder.cpp
+++ dyld/dyld-640.2/dyld3/shared-cache/mrm_shared_cache_builder.cpp
@@ -23,27 +23,16 @@
*/
#include "mrm_shared_cache_builder.h"
-#include "SharedCacheBuilder.h"
+#include "CacheBuilder.h"
#include "ClosureFileSystem.h"
#include "FileUtils.h"
-#include "JSONReader.h"
#include <pthread.h>
#include <memory>
#include <vector>
#include <map>
-#include <sys/stat.h>
-
-#if __has_include(<Cambria/SharedCache.h>)
-#include <Cambria/SharedCache.h>
-asm(".linker_option \"-lcambria_sharedcache\"");
-asm(".linker_option \"-lcodedirectory_static\"");
-#endif
static const uint64_t kMinBuildVersion = 1; //The minimum version BuildOptions struct we can support
-static const uint64_t kMaxBuildVersion = 2; //The maximum version BuildOptions struct we can support
-
-static const uint32_t MajorVersion = 1;
-static const uint32_t MinorVersion = 2;
+static const uint64_t kMaxBuildVersion = 1; //The maximum version BuildOptions struct we can support
namespace dyld3 {
namespace closure {
@@ -104,7 +93,6 @@
info.fileContentLen = fileInfo.length;
info.sliceOffset = 0;
info.sliceLen = fileInfo.length;
- info.isOSBinary = true;
info.inode = fileInfo.inode;
info.mtime = fileInfo.mtime;
info.unload = nullptr;
@@ -123,8 +111,7 @@
info.fileContentLen = keepLength;
}
- bool fileExists(const char* path, uint64_t* inode=nullptr, uint64_t* mtime=nullptr,
- bool* issetuid=nullptr, bool* inodesMatchRuntime = nullptr) const override {
+ bool fileExists(const char* path, uint64_t* inode=nullptr, uint64_t* mtime=nullptr, bool* issetuid=nullptr) const override {
Diagnostics diag;
std::string resolvedPath = symlinkResolver.realPath(diag, path);
if (diag.hasError()) {
@@ -145,8 +132,6 @@
*mtime = fileInfo.mtime;
if (issetuid)
*issetuid = false;
- if (inodesMatchRuntime)
- *inodesMatchRuntime = false;
return true;
}
@@ -162,10 +147,11 @@
if (diag.hasError())
return false;
- // on iOS, inode is just a placeholder
- // Note its safe to just use the index here as we only compare it during closure building
- // and never record it in the closures
- uint64_t inode = files.size() + 1;
+ // on iOS, inode is used to hold hash of path
+ uint64_t hash = 0;
+ for (const char* s = path; *s != '\0'; ++s)
+ hash += hash*4 + *s;
+ uint64_t inode = hash;
uint64_t mtime = 0;
files.push_back((FileInfo){ path, data, size, fileFlags, mtime, inode });
@@ -201,7 +187,7 @@
struct BuildInstance {
std::unique_ptr<DyldSharedCache::CreateOptions> options;
- std::unique_ptr<SharedCacheBuilder> builder;
+ std::unique_ptr<CacheBuilder> builder;
std::vector<CacheBuilder::InputFile> inputFiles;
std::vector<const char*> errors;
std::vector<const char*> warnings;
@@ -209,12 +195,9 @@
std::vector<std::string> warningStrings; // Owns the data for the warnings
uint8_t* cacheData = nullptr;
uint64_t cacheSize = 0;
- std::string jsonMap;
- std::string macOSMap; // For compatibility with update_dyld_shared_cache's .map file
- std::string macOSMapPath; // Owns the string for the path
+ uint8_t* cacheMapData = nullptr;
+ uint64_t cacheMapSize = 0;
std::string cdHash; // Owns the data for the cdHash
- std::string cdHashType; // Owns the data for the cdHashType
- std::string uuid; // Owns the data for the uuid
};
struct BuildFileResult {
@@ -223,52 +206,22 @@
uint64_t size;
};
-struct TranslationResult {
- const uint8_t* data;
- size_t size;
- std::string cdHash;
- std::string path;
- bool bufferWasMalloced;
-};
-
-struct MRMSharedCacheBuilder {
- MRMSharedCacheBuilder(const BuildOptions_v1* options);
+struct SharedCacheBuilder {
+ SharedCacheBuilder(const BuildOptions_v1* options);
const BuildOptions_v1* options;
dyld3::closure::FileSystemMRM fileSystem;
std::string dylibOrderFileData;
std::string dirtyDataOrderFileData;
- 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;
- std::vector<FileResult> fileResultStorage;
- std::vector<std::pair<uint64_t, bool>> fileResultBuffers;
-
- // 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;
-
-#if __has_include(<Cambria/SharedCache.h>)
- // Storage for translated shared caches
- std::vector<TranslationResult> translationResults;
-#endif
-
- // 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<BuildFileResult> fileResults;
+
+ std::vector<std::string> errors;
pthread_mutex_t lock;
enum State {
@@ -293,21 +246,15 @@
diag.error(format, list);
va_end(list);
- errorStorage.push_back(diag.errorMessage());
- errors.push_back(errorStorage.back().data());
+ errors.push_back(diag.errorMessage());
}
};
-MRMSharedCacheBuilder::MRMSharedCacheBuilder(const BuildOptions_v1* options)
-: options(options)
-, lock(PTHREAD_MUTEX_INITIALIZER)
-, objcOptimizationsFileData(nullptr)
-, objcOptimizationsFileLength(0)
-{
-
-}
-
-void validiateBuildOptions(const BuildOptions_v1* options, MRMSharedCacheBuilder& builder) {
+SharedCacheBuilder::SharedCacheBuilder(const BuildOptions_v1* options) : options(options), lock(PTHREAD_MUTEX_INITIALIZER) {
+
+}
+
+void validiateBuildOptions(const BuildOptions_v1* options, SharedCacheBuilder& builder) {
if (options->version < kMinBuildVersion) {
builder.error("Builder version %llu is less than minimum supported version of %llu", options->version, kMinBuildVersion);
}
@@ -324,7 +271,6 @@
case Disposition::Unknown:
case Disposition::InternalDevelopment:
case Disposition::Customer:
- case Disposition::InternalMinDevelopment:
break;
default:
builder.error("unknown disposition value");
@@ -356,13 +302,8 @@
}
}
-void getVersion(uint32_t *major, uint32_t *minor) {
- *major = MajorVersion;
- *minor = MinorVersion;
-}
-
-struct MRMSharedCacheBuilder* createSharedCacheBuilder(const BuildOptions_v1* options) {
- MRMSharedCacheBuilder* builder = new MRMSharedCacheBuilder(options);
+struct SharedCacheBuilder* createSharedCacheBuilder(const BuildOptions_v1* options) {
+ SharedCacheBuilder* builder = new SharedCacheBuilder(options);
// Check the option struct values are valid
validiateBuildOptions(options, *builder);
@@ -370,10 +311,10 @@
return builder;
}
-bool addFile(struct MRMSharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags) {
+bool addFile(struct SharedCacheBuilder* builder, const char* path, uint8_t* data, uint64_t size, FileFlags fileFlags) {
__block bool success = false;
builder->runSync(^() {
- if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
+ if (builder->state != SharedCacheBuilder::AcceptingFiles) {
builder->error("Cannot add file: '%s' as we have already started building", path);
return;
}
@@ -404,19 +345,13 @@
builder->dirtyDataOrderFileData = std::string((char*)data, size);
success = true;
return;
- case ObjCOptimizationsFile:
- builder->objcOptimizationsFileData = data;
- builder->objcOptimizationsFileLength = size;
- success = true;
- return;
default:
builder->error("unknown file flags value");
break;
}
Diagnostics diag;
if (!builder->fileSystem.addFile(path, data, size, diag, fileFlags)) {
- builder->errorStorage.push_back(diag.errorMessage());
- builder->errors.push_back(builder->errorStorage.back().data());
+ builder->errors.push_back(diag.errorMessage());
return;
}
success = true;
@@ -424,10 +359,10 @@
return success;
}
-bool addSymlink(struct MRMSharedCacheBuilder* builder, const char* fromPath, const char* toPath) {
+bool addSymlink(struct SharedCacheBuilder* builder, const char* fromPath, const char* toPath) {
__block bool success = false;
builder->runSync(^() {
- if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
+ if (builder->state != SharedCacheBuilder::AcceptingFiles) {
builder->error("Cannot add file: '%s' as we have already started building", fromPath);
return;
}
@@ -442,8 +377,7 @@
}
Diagnostics diag;
if (!builder->fileSystem.addSymlink(fromPath, toPath, diag)) {
- builder->errorStorage.push_back(diag.errorMessage());
- builder->errors.push_back(builder->errorStorage.back().data());
+ builder->errors.push_back(diag.errorMessage());
return;
}
success = true;
@@ -451,44 +385,22 @@
return success;
}
-static DyldSharedCache::LocalSymbolsMode platformExcludeLocalSymbols(Platform platform) {
+static bool platformExcludeLocalSymbols(Platform platform) {
switch (platform) {
case Platform::unknown:
case Platform::macOS:
- return DyldSharedCache::LocalSymbolsMode::keep;
+ return false;
case Platform::iOS:
case Platform::tvOS:
case Platform::watchOS:
case Platform::bridgeOS:
- return DyldSharedCache::LocalSymbolsMode::unmap;
+ return true;
case Platform::iOSMac:
case Platform::iOS_simulator:
case Platform::tvOS_simulator:
case Platform::watchOS_simulator:
- return DyldSharedCache::LocalSymbolsMode::keep;
- }
-}
-
-static DyldSharedCache::LocalSymbolsMode excludeLocalSymbols(const BuildOptions_v1* options) {
- if ( options->version >= 2 ) {
- const BuildOptions_v2* v2 = (const BuildOptions_v2*)options;
- if ( v2->optimizeForSize )
- return DyldSharedCache::LocalSymbolsMode::strip;
- }
-
- // Old build options always use the platform default
- return platformExcludeLocalSymbols(options->platform);
-}
-
-static bool optimizeDyldDlopens(const BuildOptions_v1* options) {
- // Old builds always default to dyld3 optimisations
- if ( options->version < 2 ) {
- return true;
- }
-
- // If we want to optimize for size instead of speed, then disable dyld3 dlopen closures
- const BuildOptions_v2* v2 = (const BuildOptions_v2*)options;
- return !v2->optimizeForSize;
+ return false;
+ }
}
static DyldSharedCache::CodeSigningDigestMode platformCodeSigningDigestMode(Platform platform) {
@@ -539,25 +451,19 @@
}
}
-// This is a JSON file containing the list of classes for which
-// we should try to build IMP caches.
-dyld3::json::Node parseObjcOptimizationsFile(Diagnostics& diags, const void* data, size_t length) {
- return dyld3::json::readJSON(diags, data, length);
-}
-
-bool runSharedCacheBuilder(struct MRMSharedCacheBuilder* builder) {
+bool runSharedCacheBuilder(struct SharedCacheBuilder* builder) {
__block bool success = false;
builder->runSync(^() {
- if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
+ if (builder->state != SharedCacheBuilder::AcceptingFiles) {
builder->error("Builder has already been run");
return;
}
- builder->state = MRMSharedCacheBuilder::Building;
+ builder->state = SharedCacheBuilder::Building;
if (builder->fileSystem.fileCount() == 0) {
builder->error("Cannot run builder with no files");
}
- __block Diagnostics diag;
+ Diagnostics diag;
std::vector<DyldSharedCache::FileAlias> aliases = builder->fileSystem.getResolvedSymlinks(diag);
if (diag.hasError()) {
diag.verbose("Symlink resolver error: %s\n", diag.errorMessage().c_str());
@@ -568,49 +474,42 @@
return;
}
- __block std::vector<SharedCacheBuilder::InputFile> inputFiles;
+ __block std::vector<CacheBuilder::InputFile> inputFiles;
builder->fileSystem.forEachFileInfo(^(const char* path, FileFlags fileFlags) {
- SharedCacheBuilder::InputFile::State state = SharedCacheBuilder::InputFile::Unset;
+ CacheBuilder::InputFile::State state = CacheBuilder::InputFile::Unset;
switch (fileFlags) {
case FileFlags::NoFlags:
- state = SharedCacheBuilder::InputFile::Unset;
+ state = CacheBuilder::InputFile::Unset;
break;
case FileFlags::MustBeInCache:
- state = SharedCacheBuilder::InputFile::MustBeIncluded;
+ state = CacheBuilder::InputFile::MustBeIncluded;
break;
case FileFlags::ShouldBeExcludedFromCacheIfUnusedLeaf:
- state = SharedCacheBuilder::InputFile::MustBeExcludedIfUnused;
+ state = CacheBuilder::InputFile::MustBeExcludedIfUnused;
break;
case FileFlags::RequiredClosure:
- state = SharedCacheBuilder::InputFile::MustBeIncluded;
+ state = CacheBuilder::InputFile::MustBeIncluded;
break;
case FileFlags::DylibOrderFile:
case FileFlags::DirtyDataOrderFile:
- case FileFlags::ObjCOptimizationsFile:
builder->error("Order files should not be in the file system");
return;
}
- inputFiles.emplace_back((SharedCacheBuilder::InputFile){ path, state });
+ inputFiles.emplace_back((CacheBuilder::InputFile){ path, state });
});
auto addCacheConfiguration = ^(bool isOptimized) {
for (uint64_t i = 0; i != builder->options->numArchs; ++i) {
- // HACK: Skip i386 for macOS
- if ( (builder->options->platform == Platform::macOS) && (strcmp(builder->options->archs[i], "i386") == 0 ) )
- continue;
auto options = std::make_unique<DyldSharedCache::CreateOptions>((DyldSharedCache::CreateOptions){});
const char *cacheSuffix = (isOptimized ? "" : ".development");
- if ( builder->options->platform == Platform::macOS )
- cacheSuffix = "";
- std::string runtimePath = (builder->options->platform == Platform::macOS) ? MACOSX_MRM_DYLD_SHARED_CACHE_DIR : IPHONE_DYLD_SHARED_CACHE_DIR;
+ std::string runtimePath = (builder->options->platform == Platform::macOS) ? "/private/var/db/dyld/" : "/System/Library/Caches/com.apple.dyld/";
options->outputFilePath = runtimePath + "dyld_shared_cache_" + builder->options->archs[i] + cacheSuffix;
- options->outputMapFilePath = options->outputFilePath + ".json";
- options->archs = &dyld3::GradedArchs::forName(builder->options->archs[i]);
+ options->outputMapFilePath = options->outputFilePath + ".map";
+ options->archName = builder->options->archs[i];
options->platform = (dyld3::Platform)builder->options->platform;
- options->localSymbolMode = excludeLocalSymbols(builder->options);
+ options->excludeLocalSymbols = platformExcludeLocalSymbols(builder->options->platform);
options->optimizeStubs = isOptimized;
- options->optimizeDyldDlopens = optimizeDyldDlopens(builder->options);
- options->optimizeDyldLaunches = true;
+ options->optimizeObjC = true;
options->codeSigningDigestMode = platformCodeSigningDigestMode(builder->options->platform);
options->dylibsRemovedDuringMastering = true;
options->inodesAreSameAsRuntime = false;
@@ -620,11 +519,11 @@
options->verbose = builder->options->verboseDiagnostics;
options->evictLeafDylibsOnOverflow = true;
options->loggingPrefix = std::string(builder->options->deviceName) + dispositionName(builder->options->disposition) + "." + builder->options->archs[i] + cacheSuffix;
+ options->pathPrefixes = { "" };
options->dylibOrdering = parseOrderFile(builder->dylibOrderFileData);
options->dirtyDataSegmentOrdering = parseOrderFile(builder->dirtyDataOrderFileData);
- options->objcOptimizations = parseObjcOptimizationsFile(diag, builder->objcOptimizationsFileData, builder->objcOptimizationsFileLength);
-
- auto cacheBuilder = std::make_unique<SharedCacheBuilder>(*options.get(), builder->fileSystem);
+
+ auto cacheBuilder = std::make_unique<CacheBuilder>(*options.get(), builder->fileSystem);
builder->builders.emplace_back((BuildInstance) { std::move(options), std::move(cacheBuilder), inputFiles });
}
};
@@ -633,30 +532,23 @@
switch (builder->options->disposition) {
case Disposition::Unknown:
case Disposition::InternalDevelopment:
- // HACK: MRM for the mac should only get development, even if it requested both
- if (builder->options->platform == Platform::macOS) {
- addCacheConfiguration(false);
- } else {
- addCacheConfiguration(false);
- addCacheConfiguration(true);
- }
+ addCacheConfiguration(false);
+ addCacheConfiguration(true);
break;
case Disposition::Customer:
addCacheConfiguration(true);
- break;
case Disposition::InternalMinDevelopment:
addCacheConfiguration(false);
- break;
}
// FIXME: This step can run in parallel.
for (auto& buildInstance : builder->builders) {
- SharedCacheBuilder* cacheBuilder = buildInstance.builder.get();
- cacheBuilder->build(buildInstance.inputFiles, aliases);
+ CacheBuilder* builder = buildInstance.builder.get();
+ builder->build(buildInstance.inputFiles, aliases);
// First put the warnings in to a vector to own them.
- buildInstance.warningStrings.reserve(cacheBuilder->warnings().size());
- for (const std::string& warning : cacheBuilder->warnings())
+ buildInstance.warningStrings.reserve(builder->warnings().size());
+ for (const std::string& warning : builder->warnings())
buildInstance.warningStrings.push_back(warning);
// Then copy to a vector to reference the owner
@@ -664,9 +556,9 @@
for (const std::string& warning : buildInstance.warningStrings)
buildInstance.warnings.push_back(warning.c_str());
- if (!cacheBuilder->errorMessage().empty()) {
+ if (!builder->errorMessage().empty()) {
// First put the errors in to a vector to own them.
- buildInstance.errorStrings.push_back(cacheBuilder->errorMessage());
+ buildInstance.errorStrings.push_back(builder->errorMessage());
// Then copy to a vector to reference the owner
buildInstance.errors.reserve(buildInstance.errorStrings.size());
@@ -674,293 +566,82 @@
buildInstance.errors.push_back(error.c_str());
}
- if (cacheBuilder->errorMessage().empty()) {
- cacheBuilder->writeBuffer(buildInstance.cacheData, buildInstance.cacheSize);
- buildInstance.jsonMap = cacheBuilder->getMapFileJSONBuffer(builder->options->deviceName);
- if ( buildInstance.options->platform == dyld3::Platform::macOS ) {
- // For compatibility with update_dyld_shared_cache, put a .map file next to the shared cache
- buildInstance.macOSMap = cacheBuilder->getMapFileBuffer();
- buildInstance.macOSMapPath = buildInstance.options->outputFilePath + ".map";
- }
- buildInstance.cdHash = cacheBuilder->cdHashFirst();
- buildInstance.uuid = cacheBuilder->uuid();
- switch (buildInstance.options->codeSigningDigestMode) {
- 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 &path) {
- builder->dylibsInCaches[path.c_str()].insert(&buildInstance);
- });
- cacheBuilder->forEachCacheSymlink(^(const std::string &path) {
- builder->dylibsInCaches[path.c_str()].insert(&buildInstance);
- });
+ if (builder->errorMessage().empty()) {
+ builder->writeBuffer(buildInstance.cacheData, buildInstance.cacheSize);
+ builder->writeMapFileBuffer(buildInstance.cacheMapData, buildInstance.cacheMapSize);
+ buildInstance.cdHash = builder->cdHashFirst();
}
- // Free the cache builder now so that we don't keep too much memory resident
- cacheBuilder->deleteBuffer();
- buildInstance.builder.reset();
- }
-
-#if __has_include(<Cambria/SharedCache.h>)
- // Only build the cambria caches if we have x86_64(h) and at least one other arch
- bool gotX86Cache = false;
- bool gotOtherCache = false;
- for (uint64_t i = 0; i != builder->options->numArchs; ++i) {
- const char* arch = builder->options->archs[i];
- if ( !strcmp(arch, "x86_64") || !strcmp(arch, "x86_64h") ) {
- gotX86Cache = true;
- continue;
- }
- gotOtherCache = true;
- }
-
- if ( (builder->options->platform == Platform::macOS) && gotX86Cache && gotOtherCache ) {
- // Now create an Aot shared cache for any applicable caches
- for (const auto& buildInstance : builder->builders) {
- // Only convert the x86_64 cache
- if ( buildInstance.options->archs != &dyld3::GradedArchs::x86_64)
- continue;
-
- // Skip failed caches
- if (!buildInstance.errors.empty())
- continue;
-
- const uint8_t* aotCacheData;
- size_t aotCacheSize;
- std::string cdHashStr;
-
- // Translate this shared cache file.
- cambria::TranslationOptions options;
-
-#if !defined(RC_HIDE_J274) || !RC_HIDE_J274
- // <rdar://problem/63767839> Don't generate a Tonga shared cache translation in the seed trains
- cambria::translate_shared_cache(options, buildInstance.cacheData, buildInstance.cacheSize,
- &aotCacheData, &aotCacheSize, &cdHashStr);
-
- builder->translationResults.push_back({
- .data = aotCacheData,
- .size = aotCacheSize,
- .cdHash = cdHashStr,
- .path = std::string(cambria::kAotSharedCachePath),
- .bufferWasMalloced = false
- });
-#endif
-
- // Now translate again for aruba based systems
- options.is_aruba_shared_cache = true;
- cambria::translate_shared_cache(options, buildInstance.cacheData, buildInstance.cacheSize,
- &aotCacheData, &aotCacheSize, &cdHashStr);
-
- bool bufferWasMalloced = false;
-#if !defined(RC_HIDE_J274) || !RC_HIDE_J274
- // For GM we don't need to ship the Aruba AOT any more. It will be converted on the fly
- // for the DTK. We'll just put a 0-byte placeholder instead and record the cdHash
- vm_deallocate(mach_task_self(), (vm_address_t)aotCacheData, aotCacheSize);
- aotCacheData = (uint8_t*)calloc(1, 1);
- aotCacheSize = 0;
- bufferWasMalloced = true;
-#endif
-
- builder->translationResults.push_back({
- .data = aotCacheData,
- .size = aotCacheSize,
- .cdHash = cdHashStr,
- .path = std::string(cambria::kAotSharedCachePathAruba),
- .bufferWasMalloced = bufferWasMalloced
- });
- }
-
- // Convert translation results into File results
- for (auto& translationResult : builder->translationResults) {
- FileResult cacheFileResult;
- cacheFileResult.version = 1;
- cacheFileResult.behavior = AddFile;
- cacheFileResult.path = translationResult.path.c_str();
- cacheFileResult.data = translationResult.data;
- cacheFileResult.size = translationResult.size;
- cacheFileResult.hashArch = "x86_64";
- cacheFileResult.hashType = "sha256";
- cacheFileResult.hash = translationResult.cdHash.c_str();
-
- builder->fileResultBuffers.push_back({ builder->fileResultStorage.size(), translationResult.bufferWasMalloced });
- builder->fileResultStorage.emplace_back(cacheFileResult);
- }
- }
-#endif
+ }
// Now that we have run all of the builds, collect the results
// First push file results for each of the shared caches we built
+ __block std::map<std::string, uint32_t> dylibsInCaches;
for (auto& buildInstance : builder->builders) {
- CacheResult cacheBuildResult;
- cacheBuildResult.version = 1;
- cacheBuildResult.loggingPrefix = buildInstance.options->loggingPrefix.c_str();
- cacheBuildResult.deviceConfiguration = buildInstance.options->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.uuid.c_str();
- cacheBuildResult.mapJSON = buildInstance.jsonMap.c_str();
-
- builder->cacheResultStorage.emplace_back(cacheBuildResult);
-
- if (!buildInstance.errors.empty())
+ CacheBuilder* cacheBuilder = buildInstance.builder.get();
+ if (!cacheBuilder->errorMessage().empty())
continue;
-
- FileResult cacheFileResult;
- cacheFileResult.version = 1;
- cacheFileResult.path = buildInstance.options->outputFilePath.c_str();
- cacheFileResult.behavior = AddFile;
- cacheFileResult.data = buildInstance.cacheData;
- cacheFileResult.size = buildInstance.cacheSize;
- cacheFileResult.hashArch = buildInstance.options->archs->name();
- cacheFileResult.hashType = buildInstance.cdHashType.c_str();
- cacheFileResult.hash = buildInstance.cdHash.c_str();
-
- builder->fileResultBuffers.push_back({ builder->fileResultStorage.size(), true });
- builder->fileResultStorage.emplace_back(cacheFileResult);
-
- // Add a file result for the .map file
- if ( !buildInstance.macOSMap.empty() ) {
- FileResult 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.cdHash.c_str();
-
- builder->fileResultStorage.emplace_back(cacheFileResult);
- }
- }
-
- // Copy from the storage to the vector we can return to the API.
- for (auto &fileResult : builder->fileResultStorage)
- builder->fileResults.push_back(&fileResult);
- for (auto &cacheResult : builder->cacheResultStorage)
- builder->cacheResults.push_back(&cacheResult);
-
+ builder->fileResults.push_back((BuildFileResult) { buildInstance.options->outputFilePath, buildInstance.cacheData, buildInstance.cacheSize });
+ builder->fileResults.push_back((BuildFileResult) { buildInstance.options->outputMapFilePath, buildInstance.cacheMapData, buildInstance.cacheMapSize });
+
+ cacheBuilder->forEachCacheDylib(^(const std::string &path) {
+ ++dylibsInCaches[path];
+ });
+ }
// 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();
-
- 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;
- // This builder didn't get this image. See if the image was ineligible
- // based on slide, ie, that dyld at runtime couldn't load this anyway, so
- // so removing it from disk won't hurt
- Diagnostics loaderDiag;
- const dyld3::GradedArchs* archs = buildInstance.options->archs;
- dyld3::Platform platform = buildInstance.options->platform;
- char realerPath[MAXPATHLEN];
- dyld3::closure::LoadedFileInfo fileInfo = dyld3::MachOAnalyzer::load(loaderDiag, builder->fileSystem,
- pathToRemove, *archs, platform, realerPath);
- if ( (platform == dyld3::Platform::macOS) && loaderDiag.hasError() ) {
- // Try again with iOSMac
- loaderDiag.clearError();
- fileInfo = dyld3::MachOAnalyzer::load(loaderDiag, builder->fileSystem,
- pathToRemove, *archs, dyld3::Platform::iOSMac, realerPath);
- }
-
- // We don't need the file content now, as we only needed to know if this file could be loaded
- builder->fileSystem.unloadFile(fileInfo);
-
- if ( loaderDiag.hasError() || (fileInfo.fileContent == nullptr) ) {
- // This arch/platform combination couldn't load this path, so we can remove it
- continue;
- }
-
- // 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
- canDeletePath = false;
- break;
- }
- if ( canDeletePath )
- builder->filesToRemove.push_back(pathToRemove);
- }
- }
-
- // Quit if we had any errors.
- for (auto& buildInstance : builder->builders) {
- if (!buildInstance.errors.empty())
- return;
- }
-
- builder->state = MRMSharedCacheBuilder::FinishedBuilding;
+ for (const auto& dylibAndCount : dylibsInCaches) {
+ if (dylibAndCount.second == numCaches)
+ builder->fileResults.push_back((BuildFileResult) { dylibAndCount.first, nullptr, 0 });
+ }
+
+ builder->state = SharedCacheBuilder::FinishedBuilding;
success = true;
});
return success;
}
-const char* const* getErrors(const struct MRMSharedCacheBuilder* builder, uint64_t* errorCount) {
- if (builder->errors.empty())
+uint64_t getErrorCount(const struct SharedCacheBuilder* builder) {
+ return builder->errors.size();
+}
+
+const char* getError(const struct SharedCacheBuilder* builder, uint64_t errorIndex) {
+ if (errorIndex >= builder->errors.size())
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 (auto &indexAndIsDataMalloced : builder->fileResultBuffers) {
- FileResult& fileResult = builder->fileResultStorage[indexAndIsDataMalloced.first];
- if (indexAndIsDataMalloced.second) {
- free((void*)fileResult.data);
- } else {
- vm_deallocate(mach_task_self(), (vm_address_t)fileResult.data, fileResult.size);
- }
- fileResult.data = nullptr;
- }
+ return builder->errors[errorIndex].c_str();
+}
+
+uint64_t getCacheResultCount(const struct SharedCacheBuilder* builder) {
+ return builder->builders.size();
+}
+
+void getCacheResult(struct SharedCacheBuilder* builder, uint64_t cacheIndex, BuildResult* result) {
+ if (cacheIndex >= builder->builders.size())
+ return;
+
+ BuildInstance& buildInstance = builder->builders[cacheIndex];
+
+ result->version = 1;
+ result->loggingPrefix = buildInstance.options->loggingPrefix.c_str();
+ result->warnings = buildInstance.warnings.empty() ? nullptr : buildInstance.warnings.data();
+ result->numWarnings = buildInstance.warnings.size();
+ result->errors = buildInstance.errors.empty() ? nullptr : buildInstance.errors.data();
+ result->numErrors = buildInstance.errors.size();
+ result->sharedCachePath = buildInstance.options->outputFilePath.c_str();
+ result->cdHash = buildInstance.cdHash.c_str();
+}
+
+uint64_t getFileResultCount(const struct SharedCacheBuilder* builder) {
+ return builder->fileResults.size();
+}
+
+void getFileResult(struct SharedCacheBuilder* builder, uint64_t fileIndex, FileResult* result) {
+ if (fileIndex >= builder->fileResults.size())
+ return;
+ const BuildFileResult& buildFileResult = builder->fileResults[fileIndex];
+ *result = (FileResult) { buildFileResult.path.c_str(), buildFileResult.data, buildFileResult.size };
+}
+
+void destroySharedCacheBuilder(struct SharedCacheBuilder* builder) {
delete builder;
}