Target::BuildRules Target::BuildRules:: Create(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::PBX::Target::shared_ptr const &target) { Target::BuildRules::BuildRule::vector buildRules; if (target->type() == pbxproj::PBX::Target::kTypeNative) { pbxproj::PBX::NativeTarget::shared_ptr nativeTarget = std::static_pointer_cast <pbxproj::PBX::NativeTarget> (target); for (pbxproj::PBX::BuildRule::shared_ptr const &projBuildRule : nativeTarget->buildRules()) { if (Target::BuildRules::BuildRule::shared_ptr buildRule = ProjectBuildRule(specManager, domains, projBuildRule)) { buildRules.push_back(buildRule); } } } for (pbxspec::PBX::BuildRule::shared_ptr const &specBuildRule : specManager->buildRules()) { if (Target::BuildRules::BuildRule::shared_ptr buildRule = SpecificationBuildRule(specManager, domains, specBuildRule)) { buildRules.push_back(buildRule); } } for (pbxspec::PBX::BuildRule::shared_ptr const &specBuildRule : specManager->synthesizedBuildRules(domains)) { if (BuildRule::shared_ptr buildRule = SpecificationBuildRule(specManager, domains, specBuildRule)) { buildRules.push_back(buildRule); } } return Target::BuildRules(buildRules); }
static pbxspec::PBX::BuildSystem::shared_ptr TargetBuildSystem(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &specDomains, pbxproj::PBX::Target::shared_ptr const &target) { if (target->type() == pbxproj::PBX::Target::Type::Native) { return specManager->buildSystem("com.apple.build-system.native", specDomains); } else if (target->type() == pbxproj::PBX::Target::Type::Legacy) { return specManager->buildSystem("com.apple.build-system.external", specDomains); } else if (target->type() == pbxproj::PBX::Target::Type::Aggregate) { return specManager->buildSystem("com.apple.build-system.external", specDomains); } else { fprintf(stderr, "error: unknown target type\n"); return nullptr; } }
pbxspec::PBX::FileType::shared_ptr FileTypeResolver:: Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::PBX::FileReference::shared_ptr const &fileReference, std::string const &filePath) { if (!fileReference->explicitFileType().empty()) { if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(fileReference->explicitFileType(), domains)) { return fileType; } } if (!fileReference->lastKnownFileType().empty()) { if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(fileReference->lastKnownFileType(), domains)) { return fileType; } } return Resolve(specManager, domains, filePath); }
static Target::BuildRules::BuildRule::shared_ptr ProjectBuildRule(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::PBX::BuildRule::shared_ptr const &projBuildRule) { pbxspec::PBX::Tool::shared_ptr tool = nullptr; std::string TS = projBuildRule->compilerSpec(); if (TS != "com.apple.compilers.proxy.script") { tool = specManager->tool(TS, domains); if (tool == nullptr) { tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->compiler(TS, domains)); } if (tool == nullptr) { tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->linker(TS, domains)); } if (tool == nullptr) { fprintf(stderr, "warning: couldn't find tool %s specified in build rule\n", TS.c_str()); return nullptr; } } pbxspec::PBX::FileType::vector fileTypes; std::string FT = projBuildRule->fileType(); if (FT != "pattern.proxy") { pbxspec::PBX::FileType::shared_ptr fileType = specManager->fileType(FT, domains); if (fileType == nullptr) { fprintf(stderr, "warning: couldn't find input file type %s specified in build rule\n", FT.c_str()); return nullptr; } fileTypes.push_back(fileType); } std::vector<pbxsetting::Value> outputFiles; for (std::string const &outputFile : projBuildRule->outputFiles()) { outputFiles.push_back(pbxsetting::Value::Parse(outputFile)); } return std::make_shared <Target::BuildRules::BuildRule> (Target::BuildRules::BuildRule( projBuildRule->filePatterns(), fileTypes, tool, projBuildRule->script(), outputFiles )); }
pbxspec::PBX::FileType::shared_ptr FileTypeResolver:: Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::XC::VersionGroup::shared_ptr const &versionGroup, std::string const &filePath) { if (!versionGroup->versionGroupType().empty()) { if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(versionGroup->versionGroupType(), domains)) { return fileType; } } return Resolve(specManager, domains, filePath); }
std::unique_ptr<Tool::SymlinkResolver> Tool::SymlinkResolver:: Create(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &specDomains) { pbxspec::PBX::Tool::shared_ptr symlinkTool = specManager->tool(Tool::SymlinkResolver::ToolIdentifier(), specDomains); if (symlinkTool == nullptr) { fprintf(stderr, "warning: could not find symlink tool\n"); return nullptr; } return std::unique_ptr<Tool::SymlinkResolver>(new Tool::SymlinkResolver(symlinkTool)); }
std::unique_ptr<Tool::HeadermapResolver> Tool::HeadermapResolver:: Create(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &specDomains, pbxspec::PBX::Compiler::shared_ptr const &compiler) { pbxspec::PBX::Tool::shared_ptr headermapTool = specManager->tool(Tool::HeadermapResolver::ToolIdentifier(), specDomains); if (headermapTool == nullptr) { fprintf(stderr, "warning: could not find headermap tool\n"); return nullptr; } return std::unique_ptr<Tool::HeadermapResolver>(new Tool::HeadermapResolver(headermapTool, compiler, specManager)); }
std::unique_ptr<Tool::AssetCatalogResolver> Tool::AssetCatalogResolver:: Create(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &specDomains) { pbxspec::PBX::Compiler::shared_ptr assetCatalogTool = specManager->compiler(Tool::AssetCatalogResolver::ToolIdentifier(), specDomains); if (assetCatalogTool == nullptr) { fprintf(stderr, "warning: could not find asset catalog compiler\n"); return nullptr; } return std::unique_ptr<Tool::AssetCatalogResolver>(new Tool::AssetCatalogResolver(assetCatalogTool)); }
static Target::BuildRules::BuildRule::shared_ptr SpecificationBuildRule(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxspec::PBX::BuildRule::shared_ptr const &specBuildRule) { if (!specBuildRule->compilerSpec()) { return nullptr; } std::string const &TS = *specBuildRule->compilerSpec(); pbxspec::PBX::Tool::shared_ptr tool = specManager->tool(TS, domains); if (tool == nullptr) { tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->compiler(TS, domains)); } if (tool == nullptr) { tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->linker(TS, domains)); } if (tool == nullptr) { return nullptr; } pbxspec::PBX::FileType::vector fileTypes; if (specBuildRule->fileTypes()) { for (std::string const &FT : *specBuildRule->fileTypes()) { pbxspec::PBX::FileType::shared_ptr fileType = specManager->fileType(FT, domains); if (fileType == nullptr) { return nullptr; } fileTypes.push_back(fileType); } } return std::make_shared <Target::BuildRules::BuildRule> (Target::BuildRules::BuildRule( std::string(), fileTypes, tool, std::string(), std::vector<pbxsetting::Value>() )); }
static pbxsetting::Level PlatformArchitecturesLevel(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &specDomains) { std::vector<pbxsetting::Setting> architectureSettings; std::vector<std::string> platformArchitectures; pbxspec::PBX::Architecture::vector architectures = specManager->architectures(specDomains); for (pbxspec::PBX::Architecture::shared_ptr const &architecture : architectures) { ext::optional<pbxsetting::Setting> architectureSetting = architecture->defaultSetting(); if (architectureSetting) { architectureSettings.push_back(*architectureSetting); } if (!architecture->realArchitectures()) { if (std::find(platformArchitectures.begin(), platformArchitectures.end(), architecture->identifier()) == platformArchitectures.end()) { platformArchitectures.push_back(architecture->identifier()); } } } architectureSettings.push_back(pbxsetting::Setting::Create("VALID_ARCHS", pbxsetting::Type::FormatList(platformArchitectures))); return pbxsetting::Level(architectureSettings); }
pbxspec::PBX::FileType::shared_ptr FileTypeResolver:: Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, std::string const &filePath) { bool isReadable = FSUtil::TestForRead(filePath); bool isFolder = isReadable && FSUtil::TestForDirectory(filePath); std::string fileExtension = FSUtil::GetFileExtension(filePath); std::string fileName = FSUtil::GetBaseName(filePath); std::ifstream fileHandle; std::vector<uint8_t> fileContents; // Reverse first so more specific file types are processed first. std::vector<pbxspec::PBX::FileType::shared_ptr> const &fileTypes = specManager->fileTypes(domains); ext::optional<std::vector<pbxspec::PBX::FileType::shared_ptr>> result = SortedFileTypes(fileTypes); if (!result) { fprintf(stderr, "error: cycle creating file type graph\n"); return nullptr; } std::vector<pbxspec::PBX::FileType::shared_ptr> const &sortedFileTypes = *result; for (pbxspec::PBX::FileType::shared_ptr const &fileType : sortedFileTypes) { if (isReadable && fileType->isFolder() != isFolder) { continue; } bool empty = true; if (fileType->extensions()) { empty = false; bool matched = false; for (std::string const &extension : *fileType->extensions()) { // TODO(grp): Is this correct? Needed for handling ".S" as ".s", but might be over-broad. if (strcasecmp(extension.c_str(), fileExtension.c_str()) == 0) { matched = true; } } if (!matched) { continue; } } if (fileType->prefix()) { empty = false; bool matched = false; for (std::string const &prefix : *fileType->prefix()) { if (fileName.find(prefix) == 0) { matched = true; } } if (!matched) { continue; } } if (fileType->filenamePatterns()) { empty = false; bool matched = false; for (std::string const &pattern : *fileType->filenamePatterns()) { if (Wildcard::Match(pattern, fileName)) { matched = true; } } if (!matched) { continue; } } if (isReadable && fileType->permissions()) { empty = false; bool matched = false; std::string const &permissions = *fileType->permissions(); if (permissions == "read") { matched = isReadable; } else if (permissions == "write") { matched = FSUtil::TestForWrite(filePath); } else if (permissions == "executable") { matched = FSUtil::TestForExecute(filePath); } else { fprintf(stderr, "warning: unhandled permission %s\n", permissions.c_str()); } if (!matched) { continue; } } // TODO(grp): Support TypeCodes. Not very important. if (isReadable && fileType->magicWords()) { empty = false; bool matched = false; for (std::vector<uint8_t> const &magicWord : *fileType->magicWords()) { if (fileContents.size() < magicWord.size()) { if (!fileHandle.is_open()) { fileHandle.open(fileName, std::ios::in | std::ios::binary); if (!fileHandle.good()) { continue; } } size_t offset = fileContents.size(); fileContents.resize(magicWord.size()); fileHandle.read((char *)&fileContents[offset], magicWord.size() - offset); if (!fileHandle.good()) { fileContents.resize(offset); continue; } } if (std::equal(magicWord.begin(), magicWord.end(), fileContents.begin())) { matched = true; } } if (!matched) { continue; } } // // Matched no checks. // if (empty) { continue; } // // Matched all checks. // return fileType; } pbxspec::PBX::FileType::shared_ptr fileType = (isFolder ? specManager->fileType("folder", domains) : specManager->fileType("file", domains)); return fileType; }