示例#1
0
VCProject* SBNativeTarget::constructVCProject(VSTemplateProject* projTemplate)
{
  VCProject* proj = SBTarget::constructVCProject(projTemplate);
  String vsProjDir = sb_dirname(proj->getPath());

  // Write variables file for App targets
  for (auto bs : m_buildSettings) {
    if (getProductType() == TargetApplication || getProductType() == TargetBundle) {
      String configName = bs.first;
      BuildSettings* configBS = bs.second;

      // Figure out where the file should go
      String varsFilePath = joinPaths(vsProjDir, getName() + "-" + configName + "-xcvars.txt");

      // Open a file stream to write to
      OFStream varsOut;
      openOutputFileStream(varsOut, varsFilePath);

      // Write the build settings out
      XCConfigPrinter varsPrinter(varsOut);
      configBS->print(varsPrinter);

      // Add the variables file to the project
      VCProjectItem* xcvarsFile = addRelativeFilePathToVS("Text", varsFilePath, "Xcode Variable Files", *proj, *configBS);

      // Mark the file as non-deployable
      xcvarsFile->setDefinition("DeploymentContent", "false");
    }
  }

  return proj;
}
void SBResourcesBuildPhase::writeVCProjectFiles(VCProject& proj) const
{
  TargetProductType productType = m_parentTarget.getProductType();
  if (productType != TargetApplication && productType != TargetBundle) {
    return;
  }

  // Process build files
  const BuildSettings& projBS = m_parentTarget.getProject().getBuildSettings();
  const BuildFileList& buildFiles = m_phase->getBuildFileList();
  sbAssert(buildFiles.size() == m_buildFileTargets.size());
  for (size_t i = 0; i < buildFiles.size(); i++) {
    // Construct a path for Bundle build products, relative to the SolutionDir,
    // instead of using the Xcode path
    String pathOverride;
    if (m_buildFileTargets[i]) {
      String productFileName = sb_basename(buildFiles[i]->getFile()->getFullPath());
      String productFileType = buildFiles[i]->getFile()->getFileType();
      if (productFileType == "wrapper.cfbundle") {
        pathOverride = "$(SolutionDir)$(Configuration)\\" + productFileName;
      } else {
        SBLog::warning() << "Unexpected build product in ResourceBuildPhase: " << productFileName << std::endl;
      }
    }

    VCItemHint itemHint = { "SBResourceCopy" , pathOverride };
    addBuildFileToVS(buildFiles[i], proj, projBS, &itemHint);
  }

  // Process all Info.plist files
  std::map<std::string, VCProjectItem*> infoPlistMap;
  for (auto bs : m_parentTarget.getBuildSettings()) {
    VCProjectConfiguration* config = proj.addConfiguration(bs.first);

    // Exclude all plist from building, by default
    config->setItemDefinition("SBInfoPlistCopy", "ExcludedFromBuild", "true");
    
    // Get absolute path to plist
    String plistPath = bs.second->getValue("INFOPLIST_FILE");
    plistPath = m_parentTarget.makeAbsolutePath(plistPath);

    // Add plist file to project (only once)
    if (infoPlistMap.find(plistPath) == infoPlistMap.end()) {
      infoPlistMap[plistPath] = addRelativeFilePathToVS("SBInfoPlistCopy", plistPath, "", proj, *bs.second);
    }

    // Un-exclude building plist for configuration
    String condition = "'$(Configuration)'=='" + bs.first + "'";
    infoPlistMap[plistPath]->setDefinition("ExcludedFromBuild", "false", condition);

    // Specify which variables files to use
    String varsFile = m_parentTarget.getName() + "-" + bs.first + "-xcvars.txt";
    infoPlistMap[plistPath]->setDefinition("VariableFile", varsFile, condition);
  }
}
示例#3
0
static VCProjectItem* addFileToVSInternal(const PBXFile* file, VCProject& proj, const BuildSettings& bs, bool isVariant, const VCItemHint* itemHint)
{
  // Add all children of any PBXVariantGroup
  const PBXVariantGroup* variantGroup = dynamic_cast<const PBXVariantGroup*>(file);
  if (variantGroup) {
    const ConstFileList& children = variantGroup->getChildren();
    for (auto child : children) {
      addFileToVSInternal(child, proj, bs, true, itemHint);
    }
    return NULL;
  }

  // Get the real and virtual paths for the file in Xcode
  String realPath = file->getFullPath();
  String virtualPath = file->getVirtualPath();

  // Fix up virtual path for variant files
  // Resources/MainStoryboard.storyboard/en => Resources/en/MainStoryboard.storyboard
  if (isVariant) {
    String variantLang = sb_basename(virtualPath);
    String filePath = sb_dirname(virtualPath);
    String fixedDir = joinPaths(sb_dirname(filePath), variantLang);
    virtualPath = joinPaths(fixedDir, sb_basename(filePath));
  }

  // Compute the VS ItemType for the file
  String fileType = file->getFileType();
  String vsType = getVSItemType(fileType);
  if (vsType == "Unknown") {
    if (itemHint && !itemHint->defaultType.empty()) {
      vsType = itemHint->defaultType;
    }
  }

  // Add the item to the project, taking into account path overrides
  VCProjectItem* item = NULL;
  if (itemHint && !itemHint->pathOverride.empty()) {
    sbAssert(!isVariant, "Unexpected path override for variant file: " + realPath);
    item = proj.addItem(vsType, itemHint->pathOverride, sb_dirname(virtualPath));
  } else {
    item = addRelativeFilePathToVS(vsType, realPath, sb_dirname(virtualPath), proj, bs);
  }

  // Handle Variant files
  if (isVariant) {
    String variantDir = sb_basename(sb_dirname(realPath));
    item->setDefinition("VariantDir", variantDir);
  }

  return item;
}
void SBSourcesBuildPhase::writeVCProjectFiles(VCProject& proj) const
{
  // We don't support source compilation when building bundles
  TargetProductType productType = m_parentTarget.getProductType();
  if (productType == TargetBundle)
  {
    if (!m_phase->getBuildFileList().empty()) {
      SBLog::warning() << "Ignoring all source files in \"" << m_parentTarget.getName() << "\" bundle target." << std::endl;
    }
    return;
  }

  SBBuildPhase::writeVSFileDescriptions(proj, "Text");

  String xcProjectDir = m_parentTarget.getProject().getProjectDir();
  String vsProjectDir = sb_dirname(proj.getPath());
  StringSet prefixHeaders;
  for (auto bs : m_parentTarget.getBuildSettings()) {
    VCProjectConfiguration* config = proj.addConfiguration(bs.first);

    // Prefix header (recalculate relative path)
    String prefixHeader = bs.second->getValue("GCC_PREFIX_HEADER");
    if (!prefixHeader.empty()) {
      String absHeaderPath = m_parentTarget.makeAbsolutePath(prefixHeader);
      String relHeaderPath = m_parentTarget.makeRelativePath(prefixHeader, vsProjectDir);;
      relHeaderPath = winPath(relHeaderPath);
      config->setItemDefinition("ClangCompile", "PrefixHeader", relHeaderPath);

      // Add plist file to project (only once)
      if (prefixHeaders.find(absHeaderPath) == prefixHeaders.end()) {
        addRelativeFilePathToVS("ClInclude", absHeaderPath, "", proj, *bs.second);
        prefixHeaders.insert(absHeaderPath);
      }
    }

    // Preprocessor definitions
    StringVec preprocessorTokens;
    bs.second->getValue("GCC_PREPROCESSOR_DEFINITIONS", preprocessorTokens);
    String preprocessorDefs = joinStrings(preprocessorTokens, ";");
    if (!preprocessorDefs.empty()) {
      config->setItemDefinition("ClangCompile", "PreprocessorDefinitions", preprocessorDefs);
    }

    // Optimization level
    String optimizationLevel = bs.second->getValue("GCC_OPTIMIZATION_LEVEL");
    if (!optimizationLevel.empty()) {
      String vsOptimizationLevel;
      if (optimizationLevel == "s") {
        vsOptimizationLevel = "MinSpace";
      } else if (optimizationLevel == "0") {
        vsOptimizationLevel = "Disabled";
      } else {
        vsOptimizationLevel = "MaxSpeed";
      }
      config->setItemDefinition("ClangCompile", "OptimizationLevel", vsOptimizationLevel);
    }

    // ARC
    String enableARC = bs.second->getValue("CLANG_ENABLE_OBJC_ARC");
    if (enableARC == "YES") {
      config->setItemDefinition("ClangCompile", "ObjectiveCARC", "true");
    }

    // Modules
    String enableModules = bs.second->getValue("CLANG_ENABLE_MODULES");
    if (enableModules == "YES") {
        config->setItemDefinition("ClangCompile", "ObjectiveCModules", "true");
    }

    // Header search paths (make them relative)
    StringVec includePaths;
    bs.second->getValue("HEADER_SEARCH_PATHS", includePaths);
    for (auto &cur : includePaths) {
      cur = m_parentTarget.makeRelativePath(cur, vsProjectDir);
      cur = winPath(cur);
    }
    includePaths.insert(includePaths.begin(), "$(SolutionPublicHeadersDir)");
    config->setItemDefinition("ClangCompile", "IncludePaths", joinStrings(includePaths, ";"));

    // User header search paths (make them relative)
    StringVec userIncludePaths;
    bs.second->getValue("USER_HEADER_SEARCH_PATHS", userIncludePaths);
    for (auto &cur : userIncludePaths) {
      cur = m_parentTarget.makeRelativePath(cur, vsProjectDir);
      cur = winPath(cur);
    }
    if (!userIncludePaths.empty()) {
      config->setItemDefinition("ClangCompile", "UserIncludePaths", joinStrings(userIncludePaths, ";"));
    }

    // Exclude search path subdirectories
    StringVec excludeSubDirectories;
    bs.second->getValue("EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES", excludeSubDirectories);
    if (!excludeSubDirectories.empty()) {
        config->setItemDefinition("ClangCompile", "ExcludedSearchPathSubdirectories", joinStrings(excludeSubDirectories, ";"));
    }

    // Header map
    if (bs.second->getValue("USE_HEADERMAP") == "YES") {
      if (bs.second->getValue("ALWAYS_SEARCH_USER_PATHS") == "YES") {
        config->setItemDefinition("ClangCompile", "HeaderMap", "Combined");
      } else if (bs.second->getValue("HEADERMAP_INCLUDES_PROJECT_HEADERS") == "YES") {
        config->setItemDefinition("ClangCompile", "HeaderMap", "Project");
      }
    }

    // Other C flags
    String otherCFlags = bs.second->getValue("OTHER_CFLAGS");
    processClangFlags(otherCFlags, xcProjectDir, vsProjectDir);
    if (!otherCFlags.empty()) {
      config->setItemDefinition("ClangCompile", "OtherCFlags", otherCFlags);
    }

    // Other C++ flags
    String otherCPlusPlusFlags = bs.second->getValue("OTHER_CPLUSPLUSFLAGS");
    processClangFlags(otherCPlusPlusFlags, xcProjectDir, vsProjectDir);
    if (!otherCPlusPlusFlags.empty()) {
      config->setItemDefinition("ClangCompile", "OtherCPlusPlusFlags", otherCPlusPlusFlags);
    }

    // CRT
    String configNameUpper = strToUpper(bs.first);
    if (configNameUpper.find("DEBUG") != String::npos) {
      config->setItemDefinition("ClangCompile", "RuntimeLibrary", "MultiThreadedDebugDLL");
    }
  }
}