예제 #1
0
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);
}
예제 #2
0
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;
    }
}
예제 #3
0
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);
}
예제 #4
0
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
    ));
}
예제 #5
0
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);
}
예제 #6
0
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));
}
예제 #7
0
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));
}
예제 #8
0
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));
}
예제 #9
0
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>()
    ));
}
예제 #10
0
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);
}
예제 #11
0
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;
}