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); }
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); }
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 )); }
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>() )); }
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; }