/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "config.h"
#include "xcode.h"
#include
#include
#include
#include
#ifdef MACOSX
#include
#include
#include
#endif
namespace CreateProjectTool {
#define LAST_XCODE_VERSION "0830"
#define DEBUG_XCODE_HASH 0
#define IOS_TARGET 0
#define OSX_TARGET 1
#define TVOS_TARGET 2
#define ADD_DEFINE(defines, name) \
defines.push_back(name);
#define REMOVE_DEFINE(defines, name) \
{ ValueList::iterator i = std::find(defines.begin(), defines.end(), name); if (i != defines.end()) defines.erase(i); }
#define CONTAINS_DEFINE(defines, name) \
(std::find(defines.begin(), defines.end(), name) != defines.end())
#define ADD_SETTING(config, key, value) \
config._settings[key] = Setting(value, "", kSettingsNoQuote);
#define ADD_SETTING_ORDER(config, key, value, order) \
config._settings[key] = Setting(value, "", kSettingsNoQuote, 0, order);
#define ADD_SETTING_ORDER_NOVALUE(config, key, comment, order) \
config._settings[key] = Setting("", comment, kSettingsNoValue, 0, order);
#define ADD_SETTING_QUOTE(config, key, value) \
config._settings[key] = Setting(value);
#define ADD_SETTING_QUOTE_VAR(config, key, value) \
config._settings[key] = Setting(value, "", kSettingsQuoteVariable);
#define ADD_SETTING_LIST(config, key, values, flags, indent) \
config._settings[key] = Setting(values, flags, indent);
#define REMOVE_SETTING(config, key) \
config._settings.erase(key);
#define ADD_BUILD_FILE(id, name, fileRefId, comment) { \
Object *buildFile = new Object(this, id, name, "PBXBuildFile", "PBXBuildFile", comment); \
buildFile->addProperty("fileRef", fileRefId, name, kSettingsNoValue); \
_buildFile.add(buildFile); \
_buildFile._flags = kSettingsSingleItem; \
}
#define ADD_FILE_REFERENCE(id, name, properties) { \
Object *fileRef = new Object(this, id, name, "PBXFileReference", "PBXFileReference", name); \
if (!properties._fileEncoding.empty()) fileRef->addProperty("fileEncoding", properties._fileEncoding, "", kSettingsNoValue); \
if (!properties._lastKnownFileType.empty()) fileRef->addProperty("lastKnownFileType", properties._lastKnownFileType, "", kSettingsNoValue|kSettingsQuoteVariable); \
if (!properties._fileName.empty()) fileRef->addProperty("name", properties._fileName, "", kSettingsNoValue|kSettingsQuoteVariable); \
if (!properties._filePath.empty()) fileRef->addProperty("path", properties._filePath, "", kSettingsNoValue|kSettingsQuoteVariable); \
if (!properties._sourceTree.empty()) fileRef->addProperty("sourceTree", properties._sourceTree, "", kSettingsNoValue); \
_fileReference.add(fileRef); \
_fileReference._flags = kSettingsSingleItem; \
}
bool producesObjectFileOnOSX(const std::string &fileName) {
std::string n, ext;
splitFilename(fileName, n, ext);
// Note that the difference between this and the general producesObjectFile is that
// this one adds Objective-C(++), and removes asm-support.
if (ext == "cpp" || ext == "c" || ext == "m" || ext == "mm")
return true;
else
return false;
}
bool targetIsIOS(const std::string &targetName) {
return targetName.length() > 4 && targetName.substr(targetName.length() - 4) == "-iOS";
}
bool targetIsTVOS(const std::string &targetName) {
return targetName.length() > 5 && targetName.substr(targetName.length() - 5) == "-tvOS";
}
bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targetName, const std::string &fileName) {
// Rules:
// - if the parent directory is "backends/platform/ios7", the file belongs to the iOS target.
// - if the parent directory is "/sdl", the file belongs to the macOS target.
// - if the file has a suffix, like "_osx", or "_ios", the file belongs to one of the target.
// - if the file is a macOS icon file (icns), it belongs to the macOS target.
std::string name, ext;
splitFilename(fileName, name, ext);
if (targetIsIOS(targetName) || targetIsTVOS(targetName)) {
// iOS & tvOS target: we skip all files with the "_osx" suffix
if (name.length() > 4 && name.substr(name.length() - 4) == "_osx") {
return true;
}
if (targetIsIOS(targetName)) {
// skip tvos dist files
if (fileID.find("dists/tvos/") != std::string::npos)
return true;
} else {
// skip ios dist files
if (fileID.find("dists/ios7/") != std::string::npos)
return true;
}
// We don't need SDL for the iOS target
static const std::string sdl_directory = "/sdl/";
static const std::string surfacesdl_directory = "/surfacesdl/";
static const std::string openglsdl_directory = "/openglsdl/";
static const std::string doublebufferdl_directory = "/doublebuffersdl/";
if (fileID.find(sdl_directory) != std::string::npos
|| fileID.find(surfacesdl_directory) != std::string::npos
|| fileID.find(openglsdl_directory) != std::string::npos
|| fileID.find(doublebufferdl_directory) != std::string::npos) {
return true;
}
if (ext == "icns") {
return true;
}
}
else {
// macOS target: we skip all files with the "_ios" suffix
if (name.length() > 4 && name.substr(name.length() - 4) == "_ios") {
return true;
}
// macOS target: we skip all files with the "_tvos" suffix
if (name.length() > 5 && name.substr(name.length() - 5) == "_tvos") {
return true;
}
// macOS target: we skip all files with the "ios7_" prefix
if (name.length() > 5 && name.substr(0, 5) == "ios7_") {
return true;
}
// parent directory
const std::string directory = fileID.substr(0, fileID.length() - fileName.length());
static const std::string iphone_directory = "backends/platform/ios7";
if (directory.length() > iphone_directory.length() && directory.substr(directory.length() - iphone_directory.length()) == iphone_directory) {
return true;
}
}
return false;
}
XcodeProvider::Group::Group(XcodeProvider *objectParent, const std::string &groupName, const std::string &uniqueName, const std::string &path) : Object(objectParent, uniqueName, groupName, "PBXGroup", "", groupName) {
bool path_is_absolute = (path.length() > 0 && path.at(0) == '/');
addProperty("name", _name, "", kSettingsNoValue | kSettingsQuoteVariable);
addProperty("sourceTree", path_is_absolute ? "" : "", "", kSettingsNoValue | kSettingsQuoteVariable);
if (path != "") {
addProperty("path", path, "", kSettingsNoValue | kSettingsQuoteVariable);
}
_childOrder = 0;
_treeName = uniqueName;
}
void XcodeProvider::Group::ensureChildExists(const std::string &name) {
std::map::iterator it = _childGroups.find(name);
if (it == _childGroups.end()) {
Group *child = new Group(_parent, name, this->_treeName + '/' + name, name);
_childGroups[name] = child;
addChildGroup(child);
_parent->_groups.add(child);
}
}
void XcodeProvider::Group::addChildInternal(const std::string &id, const std::string &comment) {
if (_properties.find("children") == _properties.end()) {
Property children;
children._hasOrder = true;
children._flags = kSettingsAsList;
_properties["children"] = children;
}
_properties["children"]._settings[id] = Setting("", comment + " in Sources", kSettingsNoValue, 0, _childOrder++);
if (_childOrder == 1) {
// Force children to use () even when there is only 1 child.
// Also this enforces the use of "," after the single item, instead of ; (see writeProperty)
_properties["children"]._flags |= kSettingsSingleItem;
} else {
_properties["children"]._flags ^= kSettingsSingleItem;
}
}
void XcodeProvider::Group::addChildGroup(const Group *group) {
addChildInternal(_parent->getHash(group->_treeName), group->_treeName);
}
void XcodeProvider::Group::addChildFile(const std::string &name) {
std::string id = "FileReference_" + _treeName + "/" + name;
addChildInternal(_parent->getHash(id), name);
FileProperty property = FileProperty(name, name, name, "\"\"");
_parent->addFileReference(id, name, property);
if (producesObjectFileOnOSX(name)) {
_parent->addBuildFile(_treeName + "/" + name, name, _parent->getHash(id), name + " in Sources");
}
}
void XcodeProvider::Group::addChildByHash(const std::string &hash, const std::string &name) {
addChildInternal(hash, name);
}
XcodeProvider::Group *XcodeProvider::Group::getChildGroup(const std::string &name) {
std::map::iterator it = _childGroups.find(name);
assert(it != _childGroups.end());
return it->second;
}
XcodeProvider::Group *XcodeProvider::touchGroupsForPath(const std::string &path) {
if (_rootSourceGroup == nullptr) {
assert(path == _projectRoot);
_rootSourceGroup = new Group(this, "Sources", path, path);
_groups.add(_rootSourceGroup);
return _rootSourceGroup;
} else {
assert(path.find(_projectRoot) == 0);
std::string subPath = path.substr(_projectRoot.size() + 1);
Group *currentGroup = _rootSourceGroup;
size_t firstPathComponent = subPath.find_first_of('/');
// We assume here that all paths have trailing '/', otherwise this breaks.
while (firstPathComponent != std::string::npos) {
currentGroup->ensureChildExists(subPath.substr(0, firstPathComponent));
currentGroup = currentGroup->getChildGroup(subPath.substr(0, firstPathComponent));
subPath = subPath.substr(firstPathComponent + 1);
firstPathComponent = subPath.find_first_of('/');
}
return currentGroup;
}
}
void XcodeProvider::addFileReference(const std::string &id, const std::string &name, FileProperty properties) {
Object *fileRef = new Object(this, id, name, "PBXFileReference", "PBXFileReference", name);
if (!properties._fileEncoding.empty()) fileRef->addProperty("fileEncoding", properties._fileEncoding, "", kSettingsNoValue);
if (!properties._lastKnownFileType.empty()) fileRef->addProperty("lastKnownFileType", properties._lastKnownFileType, "", kSettingsNoValue | kSettingsQuoteVariable);
if (!properties._fileName.empty()) fileRef->addProperty("name", properties._fileName, "", kSettingsNoValue | kSettingsQuoteVariable);
if (!properties._filePath.empty()) fileRef->addProperty("path", properties._filePath, "", kSettingsNoValue | kSettingsQuoteVariable);
if (!properties._sourceTree.empty()) fileRef->addProperty("sourceTree", properties._sourceTree, "", kSettingsNoValue);
_fileReference.add(fileRef);
_fileReference._flags = kSettingsSingleItem;
}
void XcodeProvider::addProductFileReference(const std::string &id, const std::string &name) {
Object *fileRef = new Object(this, id, name, "PBXFileReference", "PBXFileReference", name);
fileRef->addProperty("explicitFileType", "wrapper.application", "", kSettingsNoValue | kSettingsQuoteVariable);
fileRef->addProperty("includeInIndex", "0", "", kSettingsNoValue);
fileRef->addProperty("path", name, "", kSettingsNoValue | kSettingsQuoteVariable);
fileRef->addProperty("sourceTree", "BUILT_PRODUCTS_DIR", "", kSettingsNoValue);
_fileReference.add(fileRef);
_fileReference._flags = kSettingsSingleItem;
}
void XcodeProvider::addBuildFile(const std::string &id, const std::string &name, const std::string &fileRefId, const std::string &comment) {
Object *buildFile = new Object(this, id, name, "PBXBuildFile", "PBXBuildFile", comment);
buildFile->addProperty("fileRef", fileRefId, name, kSettingsNoValue);
_buildFile.add(buildFile);
_buildFile._flags = kSettingsSingleItem;
}
XcodeProvider::XcodeProvider(StringList &global_warnings, std::map &project_warnings, StringList &global_errors, const int version)
: ProjectProvider(global_warnings, project_warnings, global_errors, version) {
_rootSourceGroup = nullptr;
}
void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
includeList.push_back(setup.srcDir + "/dists/ios7/Info.plist");
includeList.push_back(setup.srcDir + "/dists/tvos/Info.plist");
ValueList &resources = getResourceFiles(setup);
for (ValueList::iterator it = resources.begin(); it != resources.end(); ++it) {
includeList.push_back(setup.srcDir + "/" + *it);
}
StringList td;
createModuleList(setup.srcDir + "/backends/platform/ios7", setup.defines, td, includeList, excludeList);
}
void XcodeProvider::createWorkspace(const BuildSetup &setup) {
// Create project folder
std::string workspace = setup.outputDir + '/' + PROJECT_NAME ".xcodeproj";
createDirectory(workspace);
_projectRoot = setup.srcDir;
touchGroupsForPath(_projectRoot);
// Setup global objects
setupDefines(setup);
_targets.push_back(PROJECT_DESCRIPTION "-iOS");
_targets.push_back(PROJECT_DESCRIPTION "-macOS");
_targets.push_back(PROJECT_DESCRIPTION "-tvOS");
setupCopyFilesBuildPhase();
setupFrameworksBuildPhase(setup);
setupNativeTarget();
setupProject();
setupResourcesBuildPhase(setup);
setupBuildConfiguration(setup);
setupImageAssetCatalog(setup);
}
// We are done with constructing all the object graph and we got through every project, output the main project file
// (this is kind of a hack since other providers use separate project files)
void XcodeProvider::createOtherBuildFiles(const BuildSetup &setup) {
// This needs to be done at the end when all build files have been accounted for
setupSourcesBuildPhase();
outputMainProjectFile(setup);
}
// Store information about a project here, for use at the end
void XcodeProvider::createProjectFile(const std::string &, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
const StringList &includeList, const StringList &excludeList) {
std::string modulePath;
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
modulePath = moduleDir.substr(setup.srcDir.size());
if (!modulePath.empty() && modulePath.at(0) == '/')
modulePath.erase(0, 1);
}
std::ofstream project;
if (!modulePath.empty())
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
else
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
}
//////////////////////////////////////////////////////////////////////////
// Main Project file
//////////////////////////////////////////////////////////////////////////
void XcodeProvider::outputMainProjectFile(const BuildSetup &setup) {
std::ofstream project((setup.outputDir + '/' + PROJECT_NAME ".xcodeproj" + '/' + "project.pbxproj").c_str());
if (!project)
error("Could not open \"" + setup.outputDir + '/' + PROJECT_NAME ".xcodeproj" + '/' + "project.pbxproj\" for writing");
//////////////////////////////////////////////////////////////////////////
// Header
project << "// !$*UTF8*$!\n"
"{\n"
"\t" << writeSetting("archiveVersion", "1", "", kSettingsNoQuote) << ";\n"
"\tclasses = {\n"
"\t};\n"
"\t" << writeSetting("objectVersion", "46", "", kSettingsNoQuote) << ";\n"
"\tobjects = {\n";
//////////////////////////////////////////////////////////////////////////
// List of objects
project << _buildFile.toString();
project << _copyFilesBuildPhase.toString();
project << _fileReference.toString();
project << _frameworksBuildPhase.toString();
project << _groups.toString();
project << _nativeTarget.toString();
project << _project.toString();
project << _resourcesBuildPhase.toString();
project << _sourcesBuildPhase.toString();
project << _buildConfiguration.toString();
project << _configurationList.toString();
//////////////////////////////////////////////////////////////////////////
// Footer
project << "\t};\n"
"\t" << writeSetting("rootObject", getHash("PBXProject"), "Project object", kSettingsNoQuote) << ";\n"
"}\n";
}
//////////////////////////////////////////////////////////////////////////
// Files
//////////////////////////////////////////////////////////////////////////
void XcodeProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
const std::string &objPrefix, const std::string &filePrefix) {
// Ensure that top-level groups are generated for i.e. engines/
Group *group = touchGroupsForPath(filePrefix);
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
const FileNode *node = *i;
// Iff it is a file, then add (build) file references. Since we're using Groups and not File References
// for folders, we shouldn't add folders as file references, obviously.
if (node->children.empty()) {
group->addChildFile(node->name);
}
// Process child nodes
if (!node->children.empty())
writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/');
}
}
//////////////////////////////////////////////////////////////////////////
// Setup functions
//////////////////////////////////////////////////////////////////////////
void XcodeProvider::setupCopyFilesBuildPhase() {
// Nothing to do here
}
#define DEF_SYSFRAMEWORK(framework) { properties[framework".framework"] = FileProperty("wrapper.framework", framework".framework", "System/Library/Frameworks/" framework ".framework", "SDKROOT"); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(framework".framework"), framework".framework", fwOrder++); }
#define DEF_SYSTBD(lib) { properties[lib".tbd"] = FileProperty("sourcecode.text-based-dylib-definition", lib".tbd", "usr/lib/" lib ".tbd", "SDKROOT"); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(lib".tbd"), lib".tbd", fwOrder++); }
#define DEF_LOCALLIB_STATIC_PATH(path,lib,absolute) { properties[lib".a"] = FileProperty("archive.ar", lib ".a", path, (absolute ? "\"\"" : "\"\"")); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(lib".a"), lib".a", fwOrder++); }
#define DEF_LOCALLIB_STATIC(lib) DEF_LOCALLIB_STATIC_PATH(lib ".a", lib, false)
#define DEF_LOCALXCFRAMEWORK(xcframework,path) { properties[xcframework".xcframework"] = FileProperty("wrapper.xcframework", xcframework".xcframework", path + "/frameworks/" + xcframework ".xcframework", "\"\""); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(xcframework".xcframework"), xcframework".xcframework", fwOrder++); }
/**
* Sets up the frameworks build phase.
*
* (each native target has different build rules)
*/
void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
_frameworksBuildPhase._comment = "PBXFrameworksBuildPhase";
// Just use a hardcoded id for the Frameworks-group
Group *frameworksGroup = new Group(this, "Frameworks", "PBXGroup_CustomTemplate_Frameworks_", "");
Property children;
children._hasOrder = true;
children._flags = kSettingsAsList;
std::string projectOutputDirectory;
#ifdef POSIX
char tmpbuf[PATH_MAX];
char *rp = realpath(setup.outputDir.c_str(), tmpbuf);
projectOutputDirectory = rp;
#endif
// Setup framework file properties
std::map properties;
int fwOrder = 0;
// Frameworks
DEF_SYSFRAMEWORK("Accelerate");
DEF_SYSFRAMEWORK("ApplicationServices");
DEF_SYSFRAMEWORK("AudioToolbox");
DEF_SYSFRAMEWORK("AudioUnit");
DEF_SYSFRAMEWORK("Carbon");
DEF_SYSFRAMEWORK("Cocoa");
DEF_SYSFRAMEWORK("CoreAudio");
DEF_SYSFRAMEWORK("CoreMIDI");
DEF_SYSFRAMEWORK("CoreGraphics");
DEF_SYSFRAMEWORK("CoreFoundation");
DEF_SYSFRAMEWORK("Foundation");
DEF_SYSFRAMEWORK("GameController");
DEF_SYSFRAMEWORK("IOKit");
DEF_SYSFRAMEWORK("OpenGL");
DEF_SYSFRAMEWORK("OpenGLES");
DEF_SYSFRAMEWORK("QuartzCore");
DEF_SYSFRAMEWORK("UIKit");
DEF_SYSFRAMEWORK("Security");
DEF_SYSFRAMEWORK("SystemConfiguration");
DEF_SYSTBD("libiconv");
// Local libraries
if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
DEF_LOCALLIB_STATIC("libfaad");
DEF_LOCALXCFRAMEWORK("faad", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
DEF_LOCALLIB_STATIC("libFLAC");
DEF_LOCALXCFRAMEWORK("FLAC", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
DEF_LOCALLIB_STATIC("libfluidlite");
} else if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH")) {
DEF_LOCALLIB_STATIC("libfluidsynth");
DEF_LOCALLIB_STATIC("libffi");
DEF_LOCALLIB_STATIC("libglib-2.0");
DEF_SYSTBD("libffi");
DEF_LOCALXCFRAMEWORK("fluidsynth", projectOutputDirectory);
DEF_LOCALXCFRAMEWORK("ffi", projectOutputDirectory);
DEF_LOCALXCFRAMEWORK("intl", projectOutputDirectory);
DEF_LOCALXCFRAMEWORK("bz2", projectOutputDirectory);
DEF_LOCALXCFRAMEWORK("glib-2.0", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
DEF_LOCALLIB_STATIC("libfreetype");
DEF_LOCALXCFRAMEWORK("freetype", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
DEF_LOCALLIB_STATIC("libjpeg");
DEF_LOCALXCFRAMEWORK("jpeg", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
DEF_LOCALLIB_STATIC("libcurl");
DEF_LOCALXCFRAMEWORK("curl", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
DEF_LOCALLIB_STATIC("libmad");
DEF_LOCALXCFRAMEWORK("mad", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_MIKMOD")) {
DEF_LOCALLIB_STATIC("libmikmod");
DEF_LOCALXCFRAMEWORK("mikmod", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
DEF_LOCALLIB_STATIC("libmpeg2");
DEF_LOCALXCFRAMEWORK("mpeg2", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
DEF_LOCALLIB_STATIC("libfribidi");
DEF_LOCALXCFRAMEWORK("fribidi", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
DEF_LOCALLIB_STATIC("libpng");
DEF_LOCALXCFRAMEWORK("png", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
DEF_LOCALLIB_STATIC("libgif");
DEF_LOCALXCFRAMEWORK("gif", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
DEF_LOCALLIB_STATIC("libogg");
DEF_LOCALXCFRAMEWORK("ogg", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
DEF_LOCALLIB_STATIC("libvorbis");
DEF_LOCALLIB_STATIC("libvorbisfile");
DEF_LOCALXCFRAMEWORK("vorbis", projectOutputDirectory);
DEF_LOCALXCFRAMEWORK("vorbisfile", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
DEF_LOCALLIB_STATIC("libvorbisidec");
}
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
DEF_LOCALLIB_STATIC("libtheoradec");
DEF_LOCALXCFRAMEWORK("theoradec", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
DEF_LOCALLIB_STATIC("libretrowave");
}
if (CONTAINS_DEFINE(setup.defines, "USE_VPX")) {
DEF_LOCALLIB_STATIC("libvpx");
DEF_LOCALXCFRAMEWORK("vpx", projectOutputDirectory);
}
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
DEF_SYSTBD("libz");
}
if (CONTAINS_DEFINE(setup.defines, "USE_DISCORD")) {
DEF_LOCALLIB_STATIC("libdiscord-rpc");
}
if (setup.useSDL2) {
DEF_LOCALLIB_STATIC("libSDL2main");
DEF_LOCALLIB_STATIC("libSDL2");
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
DEF_LOCALLIB_STATIC("libSDL2_net");
DEF_LOCALXCFRAMEWORK("SDL2_net", projectOutputDirectory);
}
} else {
DEF_LOCALLIB_STATIC("libSDLmain");
DEF_LOCALLIB_STATIC("libSDL");
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
DEF_LOCALLIB_STATIC("libSDL_net");
}
}
frameworksGroup->_properties["children"] = children;
_groups.add(frameworksGroup);
// Force this to be added as a sub-group in the root.
_rootSourceGroup->addChildGroup(frameworksGroup);
// Declare this here, as it's used across all the targets
int order = 0;
//////////////////////////////////////////////////////////////////////////
// ScummVM-iOS
Object *framework_iPhone = new Object(this, "PBXFrameworksBuildPhase_" + _targets[IOS_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
framework_iPhone->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
framework_iPhone->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
// List of frameworks
Property iOS_files;
iOS_files._hasOrder = true;
iOS_files._flags = kSettingsAsList;
ValueList frameworks_iOS;
frameworks_iOS.push_back("CoreAudio.framework");
frameworks_iOS.push_back("CoreGraphics.framework");
frameworks_iOS.push_back("CoreFoundation.framework");
frameworks_iOS.push_back("Foundation.framework");
frameworks_iOS.push_back("GameController.framework");
frameworks_iOS.push_back("UIKit.framework");
frameworks_iOS.push_back("SystemConfiguration.framework");
frameworks_iOS.push_back("AudioToolbox.framework");
frameworks_iOS.push_back("QuartzCore.framework");
frameworks_iOS.push_back("OpenGLES.framework");
frameworks_iOS.push_back("Accelerate.framework");
if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
frameworks_iOS.push_back(getLibString("faad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
frameworks_iOS.push_back(getLibString("FLAC", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
frameworks_iOS.push_back(getLibString("freetype", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
frameworks_iOS.push_back(getLibString("jpeg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
frameworks_iOS.push_back(getLibString("png", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
frameworks_iOS.push_back(getLibString("gif", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
frameworks_iOS.push_back(getLibString("ogg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
frameworks_iOS.push_back(getLibString("vorbis", setup.useXCFramework));
frameworks_iOS.push_back(getLibString("vorbisfile", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
frameworks_iOS.push_back(getLibString("vorbisidec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
frameworks_iOS.push_back(getLibString("theoradec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VPX")) {
frameworks_iOS.push_back(getLibString("vpx", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
frameworks_iOS.push_back(getLibString("mad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MIKMOD")) {
frameworks_iOS.push_back(getLibString("mikmod", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
frameworks_iOS.push_back(getLibString("mpeg2", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
frameworks_iOS.push_back(getLibString("fribidi", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
frameworks_iOS.push_back(getLibString("fluidsynth", setup.useXCFramework));
frameworks_iOS.push_back(getLibString("ffi", setup.useXCFramework));
frameworks_iOS.push_back(getLibString("glib-2.0", setup.useXCFramework));
if (setup.useXCFramework) {
// The libintl and libbz2 libs are not combined into glib-2.0 in the xcframework libs
frameworks_iOS.push_back(getLibString("intl", setup.useXCFramework));
frameworks_iOS.push_back(getLibString("bz2", setup.useXCFramework));
}
frameworks_iOS.push_back("CoreMIDI.framework");
frameworks_iOS.push_back("libiconv.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
frameworks_iOS.push_back("libz.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
frameworks_iOS.push_back(getLibString("curl", setup.useXCFramework));
frameworks_iOS.push_back("Security.framework");
}
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
if (setup.useSDL2) {
frameworks_iOS.push_back(getLibString("SDL2_net", setup.useXCFramework));
} else {
frameworks_iOS.push_back(getLibString("SDL_net", setup.useXCFramework));
}
}
for (ValueList::iterator framework = frameworks_iOS.begin(); framework != frameworks_iOS.end(); framework++) {
std::string id = "Frameworks_" + *framework + "_iphone";
std::string comment = *framework + " in Frameworks";
ADD_SETTING_ORDER_NOVALUE(iOS_files, getHash(id), comment, order++);
ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
}
framework_iPhone->_properties["files"] = iOS_files;
_frameworksBuildPhase.add(framework_iPhone);
//////////////////////////////////////////////////////////////////////////
// ScummVM-macOS
Object *framework_OSX = new Object(this, "PBXFrameworksBuildPhase_" + _targets[OSX_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
framework_OSX->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
framework_OSX->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
// List of frameworks
Property osx_files;
osx_files._hasOrder = true;
osx_files._flags = kSettingsAsList;
ValueList frameworks_osx;
frameworks_osx.push_back("CoreFoundation.framework");
frameworks_osx.push_back("Foundation.framework");
frameworks_osx.push_back("AudioToolbox.framework");
frameworks_osx.push_back("CoreMIDI.framework");
frameworks_osx.push_back("CoreAudio.framework");
frameworks_osx.push_back("QuartzCore.framework");
frameworks_osx.push_back("Carbon.framework");
frameworks_osx.push_back("ApplicationServices.framework");
frameworks_osx.push_back("IOKit.framework");
frameworks_osx.push_back("Cocoa.framework");
frameworks_osx.push_back("OpenGL.framework");
frameworks_osx.push_back("AudioUnit.framework");
if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
frameworks_osx.push_back(getLibString("faad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
frameworks_osx.push_back(getLibString("FLAC", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
frameworks_osx.push_back(getLibString("fluidsynth", setup.useXCFramework));
frameworks_osx.push_back(getLibString("glib-2.0", setup.useXCFramework));
frameworks_osx.push_back("libffi.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
frameworks_osx.push_back(getLibString("freetype", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
frameworks_osx.push_back(getLibString("jpeg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
frameworks_osx.push_back(getLibString("curl", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
frameworks_osx.push_back(getLibString("mad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MIKMOD")) {
frameworks_osx.push_back("libmikmod.a");
}
if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
frameworks_osx.push_back(getLibString("mpeg2", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
frameworks_osx.push_back(getLibString("fribidi", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
frameworks_osx.push_back(getLibString("png", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
frameworks_osx.push_back(getLibString("gif", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
frameworks_osx.push_back(getLibString("ogg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
frameworks_osx.push_back(getLibString("vorbis", setup.useXCFramework));
frameworks_osx.push_back(getLibString("vorbisfile", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
frameworks_osx.push_back(getLibString("vorbisidec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
frameworks_osx.push_back(getLibString("theoradec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
frameworks_osx.push_back(getLibString("retrowave", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VPX")) {
frameworks_osx.push_back(getLibString("vpx", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
frameworks_osx.push_back("libz.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_DISCORD")) {
frameworks_osx.push_back(getLibString("discord-rpc", setup.useXCFramework));
}
if (setup.useSDL2) {
frameworks_osx.push_back(getLibString("SDL2main", setup.useXCFramework));
frameworks_osx.push_back(getLibString("SDL2", setup.useXCFramework));
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
frameworks_osx.push_back(getLibString("SDL2_net", setup.useXCFramework));
} else {
frameworks_osx.push_back(getLibString("SDLmain", setup.useXCFramework));
frameworks_osx.push_back(getLibString("SDL", setup.useXCFramework));
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
frameworks_osx.push_back(getLibString("SDL_net", setup.useXCFramework));
}
order = 0;
for (ValueList::iterator framework = frameworks_osx.begin(); framework != frameworks_osx.end(); framework++) {
std::string id = "Frameworks_" + *framework + "_osx";
std::string comment = *framework + " in Frameworks";
ADD_SETTING_ORDER_NOVALUE(osx_files, getHash(id), comment, order++);
ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
}
framework_OSX->_properties["files"] = osx_files;
_frameworksBuildPhase.add(framework_OSX);
//////////////////////////////////////////////////////////////////////////
// ScummVM-tvOS
Object *framework_tvOS = new Object(this, "PBXFrameworksBuildPhase_" + _targets[TVOS_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
framework_tvOS->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
framework_tvOS->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
// List of frameworks
Property tvOS_files;
tvOS_files._hasOrder = true;
tvOS_files._flags = kSettingsAsList;
ValueList frameworks_tvOS;
frameworks_tvOS.push_back("CoreAudio.framework");
frameworks_tvOS.push_back("CoreGraphics.framework");
frameworks_tvOS.push_back("CoreFoundation.framework");
frameworks_tvOS.push_back("Foundation.framework");
frameworks_tvOS.push_back("GameController.framework");
frameworks_tvOS.push_back("UIKit.framework");
frameworks_tvOS.push_back("SystemConfiguration.framework");
frameworks_tvOS.push_back("AudioToolbox.framework");
frameworks_tvOS.push_back("QuartzCore.framework");
frameworks_tvOS.push_back("OpenGLES.framework");
frameworks_tvOS.push_back("Accelerate.framework");
if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
frameworks_tvOS.push_back(getLibString("faad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
frameworks_tvOS.push_back(getLibString("FLAC", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
frameworks_tvOS.push_back(getLibString("freetype", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
frameworks_tvOS.push_back(getLibString("jpeg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
frameworks_tvOS.push_back(getLibString("png", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
frameworks_tvOS.push_back(getLibString("gif", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
frameworks_tvOS.push_back(getLibString("ogg", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
frameworks_tvOS.push_back(getLibString("vorbis", setup.useXCFramework));
frameworks_tvOS.push_back(getLibString("vorbisfile", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
frameworks_tvOS.push_back(getLibString("vorbisidec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
frameworks_tvOS.push_back(getLibString("theoradec", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_VPX")) {
frameworks_tvOS.push_back(getLibString("vpx", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
frameworks_tvOS.push_back(getLibString("mad", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MIKMOD")) {
frameworks_tvOS.push_back(getLibString("mikmod", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
frameworks_tvOS.push_back(getLibString("mpeg2", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
frameworks_tvOS.push_back(getLibString("fribidi", setup.useXCFramework));
}
if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
frameworks_tvOS.push_back(getLibString("fluidsynth", setup.useXCFramework));
frameworks_tvOS.push_back(getLibString("ffi", setup.useXCFramework));
frameworks_tvOS.push_back(getLibString("glib-2.0", setup.useXCFramework));
frameworks_tvOS.push_back(getLibString("intl", setup.useXCFramework));
frameworks_tvOS.push_back(getLibString("bz2", setup.useXCFramework));
frameworks_tvOS.push_back("CoreMIDI.framework");
frameworks_tvOS.push_back("libiconv.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
frameworks_tvOS.push_back("libz.tbd");
}
if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
frameworks_tvOS.push_back(getLibString("curl", setup.useXCFramework));
frameworks_tvOS.push_back("Security.framework");
}
if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
if (setup.useSDL2) {
frameworks_tvOS.push_back(getLibString("SDL2_net", setup.useXCFramework));
} else {
frameworks_tvOS.push_back(getLibString("SDL_net", setup.useXCFramework));
}
}
for (ValueList::iterator framework = frameworks_tvOS.begin(); framework != frameworks_tvOS.end(); framework++) {
std::string id = "Frameworks_" + *framework + "_appletv";
std::string comment = *framework + " in Frameworks";
ADD_SETTING_ORDER_NOVALUE(tvOS_files, getHash(id), comment, order++);
ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
}
framework_tvOS->_properties["files"] = tvOS_files;
_frameworksBuildPhase.add(framework_tvOS);
}
void XcodeProvider::setupNativeTarget() {
_nativeTarget._comment = "PBXNativeTarget";
// Just use a hardcoded id for the Products-group
Group *productsGroup = new Group(this, "Products", "PBXGroup_CustomTemplate_Products_" , "");
// Output native target section
for (unsigned int i = 0; i < _targets.size(); i++) {
Object *target = new Object(this, "PBXNativeTarget_" + _targets[i], "PBXNativeTarget", "PBXNativeTarget", "", _targets[i]);
target->addProperty("buildConfigurationList", getHash("XCConfigurationList_" + _targets[i]), "Build configuration list for PBXNativeTarget \"" + _targets[i] + "\"", kSettingsNoValue);
Property buildPhases;
buildPhases._hasOrder = true;
buildPhases._flags = kSettingsAsList;
buildPhases._settings[getHash("PBXResourcesBuildPhase_" + _targets[i])] = Setting("", "Resources", kSettingsNoValue, 0, 0);
buildPhases._settings[getHash("PBXSourcesBuildPhase_" + _targets[i])] = Setting("", "Sources", kSettingsNoValue, 0, 1);
buildPhases._settings[getHash("PBXFrameworksBuildPhase_" + _targets[i])] = Setting("", "Frameworks", kSettingsNoValue, 0, 2);
target->_properties["buildPhases"] = buildPhases;
target->addProperty("buildRules", "", "", kSettingsNoValue | kSettingsAsList);
target->addProperty("dependencies", "", "", kSettingsNoValue | kSettingsAsList);
target->addProperty("name", _targets[i], "", kSettingsNoValue | kSettingsQuoteVariable);
target->addProperty("productName", PROJECT_NAME, "", kSettingsNoValue);
addProductFileReference("PBXFileReference_" PROJECT_DESCRIPTION ".app_" + _targets[i], PROJECT_DESCRIPTION ".app");
productsGroup->addChildByHash(getHash("PBXFileReference_" PROJECT_DESCRIPTION ".app_" + _targets[i]), PROJECT_DESCRIPTION ".app");
target->addProperty("productReference", getHash("PBXFileReference_" PROJECT_DESCRIPTION ".app_" + _targets[i]), PROJECT_DESCRIPTION ".app", kSettingsNoValue);
target->addProperty("productType", "com.apple.product-type.application", "", kSettingsNoValue | kSettingsQuoteVariable);
_nativeTarget.add(target);
}
_rootSourceGroup->addChildGroup(productsGroup);
_groups.add(productsGroup);
}
void XcodeProvider::setupProject() {
_project._comment = "PBXProject";
Object *project = new Object(this, "PBXProject", "PBXProject", "PBXProject", "", "Project object");
project->addProperty("buildConfigurationList", getHash("XCConfigurationList_" PROJECT_NAME), "Build configuration list for PBXProject \"" PROJECT_NAME "\"", kSettingsNoValue);
project->addProperty("compatibilityVersion", "Xcode 3.2", "", kSettingsNoValue | kSettingsQuoteVariable);
project->addProperty("developmentRegion", "English", "", kSettingsNoValue);
project->addProperty("hasScannedForEncodings", "1", "", kSettingsNoValue);
project->addProperty("attributes", "{ LastUpgradeCheck = " LAST_XCODE_VERSION "; }", "", kSettingsNoQuote | kSettingsNoValue);
// List of known regions
Property regions;
regions._flags = kSettingsAsList;
ADD_SETTING_ORDER_NOVALUE(regions, "English", "", 0);
ADD_SETTING_ORDER_NOVALUE(regions, "Japanese", "", 1);
ADD_SETTING_ORDER_NOVALUE(regions, "French", "", 2);
ADD_SETTING_ORDER_NOVALUE(regions, "German", "", 3);
project->_properties["knownRegions"] = regions;
project->addProperty("mainGroup", _rootSourceGroup->getHashRef(), "CustomTemplate", kSettingsNoValue);
project->addProperty("productRefGroup", getHash("PBXGroup_CustomTemplate_Products_"), "" , kSettingsNoValue);
project->addProperty("projectDirPath", _projectRoot, "", kSettingsNoValue | kSettingsQuoteVariable);
project->addProperty("projectRoot", "", "", kSettingsNoValue | kSettingsQuoteVariable);
// List of targets
Property targets;
targets._flags = kSettingsAsList;
targets._settings[getHash("PBXNativeTarget_" + _targets[IOS_TARGET])] = Setting("", _targets[IOS_TARGET], kSettingsNoValue, 0, 0);
targets._settings[getHash("PBXNativeTarget_" + _targets[OSX_TARGET])] = Setting("", _targets[OSX_TARGET], kSettingsNoValue, 0, 1);
targets._settings[getHash("PBXNativeTarget_" + _targets[TVOS_TARGET])] = Setting("", _targets[TVOS_TARGET], kSettingsNoValue, 0, 2);
project->_properties["targets"] = targets;
// Force list even when there is only a single target
project->_properties["targets"]._flags |= kSettingsSingleItem;
_project.add(project);
}
XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setup) const {
static ValueList files;
if (files.empty()) {
files.push_back("gui/themes/scummclassic.zip");
files.push_back("gui/themes/scummmodern.zip");
files.push_back("gui/themes/scummremastered.zip");
files.push_back("gui/themes/residualvm.zip");
files.push_back("gui/themes/gui-icons.dat");
files.push_back("gui/themes/shaders.dat");
files.push_back("gui/themes/translations.dat");
files.push_back("dists/engine-data/access.dat");
files.push_back("dists/engine-data/achievements.dat");
files.push_back("dists/engine-data/cryo.dat");
files.push_back("dists/engine-data/cryomni3d.dat");
files.push_back("dists/engine-data/drascula.dat");
files.push_back("dists/engine-data/encoding.dat");
files.push_back("dists/engine-data/fonts.dat");
files.push_back("dists/engine-data/freescape.dat");
files.push_back("dists/engine-data/hadesch_translations.dat");
files.push_back("dists/engine-data/hugo.dat");
files.push_back("dists/engine-data/kyra.dat");
files.push_back("dists/engine-data/lure.dat");
files.push_back("dists/engine-data/macgui.dat");
files.push_back("dists/engine-data/myst3.dat");
files.push_back("dists/engine-data/monkey4-patch.m4b");
files.push_back("dists/engine-data/grim-patch.lab");
files.push_back("dists/engine-data/macventure.dat");
files.push_back("dists/engine-data/mm.dat");
files.push_back("dists/engine-data/mort.dat");
files.push_back("dists/engine-data/nancy.dat");
files.push_back("dists/engine-data/neverhood.dat");
files.push_back("dists/engine-data/prince_translation.dat");
files.push_back("dists/engine-data/queen.tbl");
files.push_back("dists/engine-data/sky.cpt");
files.push_back("dists/engine-data/supernova.dat");
files.push_back("dists/engine-data/teenagent.dat");
files.push_back("dists/engine-data/titanic.dat");
files.push_back("dists/engine-data/tony.dat");
files.push_back("dists/engine-data/toon.dat");
files.push_back("dists/engine-data/ultima.dat");
files.push_back("dists/engine-data/wintermute.zip");
files.push_back("dists/ios7/LaunchScreen_ios.storyboard");
files.push_back("dists/tvos/LaunchScreen_tvos.storyboard");
files.push_back("dists/pred.dic");
files.push_back("dists/networking/wwwroot.zip");
if (CONTAINS_DEFINE(setup.defines, "ENABLE_GRIME")) {
files.push_back("engines/grim/shaders/grim_dim.fragment");
files.push_back("engines/grim/shaders/grim_dim.vertex");
files.push_back("engines/grim/shaders/grim_emerg.fragment");
files.push_back("engines/grim/shaders/grim_emerg.vertex");
files.push_back("engines/grim/shaders/emi_actor.fragment");
files.push_back("engines/grim/shaders/emi_actor.vertex");
files.push_back("engines/grim/shaders/emi_actorlights.fragment");
files.push_back("engines/grim/shaders/emi_actorlights.vertex");
files.push_back("engines/grim/shaders/emi_background.fragment");
files.push_back("engines/grim/shaders/emi_background.vertex");
files.push_back("engines/grim/shaders/emi_dimplane.fragment");
files.push_back("engines/grim/shaders/emi_dimplane.vertex");
files.push_back("engines/grim/shaders/emi_sprite.fragment");
files.push_back("engines/grim/shaders/emi_sprite.vertex");
files.push_back("engines/grim/shaders/grim_actor.fragment");
files.push_back("engines/grim/shaders/grim_actor.vertex");
files.push_back("engines/grim/shaders/grim_actorlights.fragment");
files.push_back("engines/grim/shaders/grim_actorlights.vertex");
files.push_back("engines/grim/shaders/grim_background.fragment");
files.push_back("engines/grim/shaders/grim_background.vertex");
files.push_back("engines/grim/shaders/grim_primitive.fragment");
files.push_back("engines/grim/shaders/grim_primitive.vertex");
files.push_back("engines/grim/shaders/grim_shadowplane.fragment");
files.push_back("engines/grim/shaders/grim_shadowplane.vertex");
files.push_back("engines/grim/shaders/grim_smush.fragment");
files.push_back("engines/grim/shaders/grim_smush.vertex");
files.push_back("engines/grim/shaders/grim_text.fragment");
files.push_back("engines/grim/shaders/grim_text.vertex");
}
if (CONTAINS_DEFINE(setup.defines, "ENABLE_MYST3")) {
files.push_back("engines/myst3/shaders/myst3_box.fragment");
files.push_back("engines/myst3/shaders/myst3_box.vertex");
files.push_back("engines/myst3/shaders/myst3_cube.fragment");
files.push_back("engines/myst3/shaders/myst3_cube.vertex");
files.push_back("engines/myst3/shaders/myst3_text.fragment");
files.push_back("engines/myst3/shaders/myst3_text.vertex");
}
if (CONTAINS_DEFINE(setup.defines, "ENABLE_PLAYGROUND3D")) {
files.push_back("engines/playground3d/shaders/playground3d_bitmap.fragment");
files.push_back("engines/playground3d/shaders/playground3d_bitmap.vertex");
files.push_back("engines/playground3d/shaders/playground3d_cube.fragment");
files.push_back("engines/playground3d/shaders/playground3d_cube.vertex");
files.push_back("engines/playground3d/shaders/playground3d_fade.fragment");
files.push_back("engines/playground3d/shaders/playground3d_fade.vertex");
}
if (CONTAINS_DEFINE(setup.defines, "ENABLE_STARK")) {
files.push_back("engines/stark/shaders/stark_actor.fragment");
files.push_back("engines/stark/shaders/stark_actor.vertex");
files.push_back("engines/stark/shaders/stark_prop.fragment");
files.push_back("engines/stark/shaders/stark_prop.vertex");
files.push_back("engines/stark/shaders/stark_surface.fragment");
files.push_back("engines/stark/shaders/stark_surface.vertex");
files.push_back("engines/stark/shaders/stark_surface_fill.fragment");
files.push_back("engines/stark/shaders/stark_surface_fill.vertex");
files.push_back("engines/stark/shaders/stark_fade.fragment");
files.push_back("engines/stark/shaders/stark_fade.vertex");
files.push_back("engines/stark/shaders/stark_shadow.fragment");
files.push_back("engines/stark/shaders/stark_shadow.vertex");
}
if (CONTAINS_DEFINE(setup.defines, "ENABLE_WINTERMUTE")) {
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_fade.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_fade.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_mask.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_flat_shadow_modelx.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_geometry.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_geometry.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_line.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_line.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_modelx.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_modelx.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_shadow_mask.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_shadow_mask.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_shadow_volume.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_shadow_volume.vertex");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_sprite.vertex");
}
if (CONTAINS_DEFINE(setup.defines, "ENABLE_FREESCAPE")) {
files.push_back("engines/freescape/shaders/freescape_bitmap.fragment");
files.push_back("engines/freescape/shaders/freescape_bitmap.vertex");
files.push_back("engines/freescape/shaders/freescape_triangle.fragment");
files.push_back("engines/freescape/shaders/freescape_triange.vertex");
}
files.push_back("icons/scummvm.icns");
files.push_back("AUTHORS");
files.push_back("COPYING");
files.push_back("LICENSES/COPYING.BSD");
files.push_back("LICENSES/COPYING.LGPL");
files.push_back("LICENSES/COPYING.FREEFONT");
files.push_back("LICENSES/COPYING.OFL");
files.push_back("LICENSES/COPYING.ISC");
files.push_back("LICENSES/COPYING.LUA");
files.push_back("LICENSES/COPYING.MIT");
files.push_back("LICENSES/COPYING.MKV");
files.push_back("LICENSES/COPYING.TINYGL");
files.push_back("LICENSES/COPYING.GLAD");
files.push_back("NEWS.md");
files.push_back("README.md");
}
return files;
}
std::string XcodeProvider::getLibString(std::string libName, bool xcframework) const {
std::string libString;
if (xcframework) {
libString = libName + std::string(".xcframework");
} else {
libString = std::string("lib") + libName + std::string(".a");
}
return libString;
}
void XcodeProvider::setupResourcesBuildPhase(const BuildSetup &setup) {
_resourcesBuildPhase._comment = "PBXResourcesBuildPhase";
ValueList &files_list = getResourceFiles(setup);
// Same as for containers: a rule for each native target
for (unsigned int i = 0; i < _targets.size(); i++) {
Object *resource = new Object(this, "PBXResourcesBuildPhase_" + _targets[i], "PBXResourcesBuildPhase", "PBXResourcesBuildPhase", "", "Resources");
resource->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
// Add default files
Property files;
files._hasOrder = true;
files._flags = kSettingsAsList;
int order = 0;
for (ValueList::iterator file = files_list.begin(); file != files_list.end(); file++) {
if (shouldSkipFileForTarget(*file, _targets[i], *file)) {
continue;
}
std::string resourceAbsolutePath = _projectRoot + "/" + *file;
std::string file_id = "FileReference_" + resourceAbsolutePath;
std::string base = basename(*file);
std::string comment = base + " in Resources";
addBuildFile(resourceAbsolutePath, base, getHash(file_id), comment);
ADD_SETTING_ORDER_NOVALUE(files, getHash(resourceAbsolutePath), comment, order++);
}
resource->_properties["files"] = files;
resource->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
_resourcesBuildPhase.add(resource);
}
}
void XcodeProvider::setupSourcesBuildPhase() {
_sourcesBuildPhase._comment = "PBXSourcesBuildPhase";
// Same as for containers: a rule for each native target
for (unsigned int i = 0; i < _targets.size(); i++) {
const std::string &targetName = _targets[i];
Object *source = new Object(this, "PBXSourcesBuildPhase_" + _targets[i], "PBXSourcesBuildPhase", "PBXSourcesBuildPhase", "", "Sources");
source->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
Property files;
files._hasOrder = true;
files._flags = kSettingsAsList;
int order = 0;
for (std::vector