void addBuildFileToVS(const PBXBuildFile* buildFile, VCProject& proj, const BuildSettings& bs, const VCItemHint* itemHint) { const String& compilerFlags = buildFile->getCompilerFlags(); int attribs = buildFile->getAttributes(); const PBXFile* file = buildFile->getFile(); if (!file) return; VCProjectItem* item = addFileToVSInternal(file, proj, bs, false, itemHint); // If the filetype doesn't match the file extension, specify the actual type String filePath = file->getFullPath(); String fileType = file->getFileType(); String inferredType = PBXFile::getFileType(filePath); String compileAs = getVSCompileAsType(fileType); if (item && !compileAs.empty() && (fileType != inferredType || fileType == "sourcecode.c.c" || fileType == "sourcecode.cpp.cpp")) { item->setDefinition("CompileAs", compileAs); } // Record file compiler flags if (item && !compilerFlags.empty()) { String fixedFlags = "$(AdditionalOptions) " + compilerFlags; String xcProjectDir = bs.getValue("PROJECT_DIR"); String vsProjectDir = sb_dirname(proj.getPath()); processClangFlags(fixedFlags, xcProjectDir, vsProjectDir); item->setDefinition("AdditionalOptions", fixedFlags); } // Mark public headers if ((attribs & ATTR_PUBLIC) && (fileType == "sourcecode.c.h" || fileType == "sourcecode.cpp.h")) { item->setDefinition("PublicHeader", "true"); } }
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 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"); } } }