ENH: Generate native Xcode 3.0 and 3.1 projects
CMake previously generated Xcode project files labeled as 2.4-compatible by recent versions of Xcode (3.0 and 3.1). It is better to generate native Xcode 3.0 and 3.1 projects. In particular, this can improve build times by using the "Build independent targets in parallel" feature. Patch from Doug Gregor. See issue #9216.
This commit is contained in:
parent
fb81cd93f0
commit
f33a27abd6
|
@ -38,6 +38,11 @@ cmGlobalXCode21Generator::WriteXCodePBXProj(std::ostream& fout,
|
||||||
cmXCode21Object::Indent(1, fout);
|
cmXCode21Object::Indent(1, fout);
|
||||||
fout << "};\n";
|
fout << "};\n";
|
||||||
cmXCode21Object::Indent(1, fout);
|
cmXCode21Object::Indent(1, fout);
|
||||||
|
if (this->XcodeVersion >= 31)
|
||||||
|
fout << "objectVersion = 45;\n";
|
||||||
|
else if (this->XcodeVersion >= 30)
|
||||||
|
fout << "objectVersion = 44;\n";
|
||||||
|
else
|
||||||
fout << "objectVersion = 42;\n";
|
fout << "objectVersion = 42;\n";
|
||||||
cmXCode21Object::PrintList(this->XCodeObjects, fout);
|
cmXCode21Object::PrintList(this->XCodeObjects, fout);
|
||||||
cmXCode21Object::Indent(1, fout);
|
cmXCode21Object::Indent(1, fout);
|
||||||
|
|
|
@ -451,6 +451,57 @@ cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Builds either an object list or a space-separated string from the
|
||||||
|
// given inputs.
|
||||||
|
class cmGlobalXCodeGenerator::BuildObjectListOrString
|
||||||
|
{
|
||||||
|
cmGlobalXCodeGenerator *Generator;
|
||||||
|
cmXCodeObject *Group;
|
||||||
|
bool Empty;
|
||||||
|
std::string String;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BuildObjectListOrString(cmGlobalXCodeGenerator *gen, bool buildObjectList)
|
||||||
|
: Generator(gen), Group(0), Empty(true)
|
||||||
|
{
|
||||||
|
if (buildObjectList)
|
||||||
|
{
|
||||||
|
this->Group = this->Generator->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const { return this->Empty; }
|
||||||
|
|
||||||
|
void Add(const char *newString)
|
||||||
|
{
|
||||||
|
this->Empty = false;
|
||||||
|
|
||||||
|
if (this->Group)
|
||||||
|
{
|
||||||
|
this->Group->AddObject(this->Generator->CreateString(newString));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->String += newString;
|
||||||
|
this->String += ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &GetString() const { return this->String; }
|
||||||
|
|
||||||
|
cmXCodeObject *CreateList()
|
||||||
|
{
|
||||||
|
if (this->Group)
|
||||||
|
{
|
||||||
|
return this->Group;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this->Generator->CreateString(this->String.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmXCodeObject*
|
cmXCodeObject*
|
||||||
cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
|
cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
|
||||||
|
@ -466,7 +517,17 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
|
||||||
lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
|
lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
|
||||||
|
|
||||||
// Add per-source definitions.
|
// Add per-source definitions.
|
||||||
this->AppendDefines(flags, sf->GetProperty("COMPILE_DEFINITIONS"), true);
|
BuildObjectListOrString flagsBuild(this, false);
|
||||||
|
this->AppendDefines(flagsBuild,
|
||||||
|
sf->GetProperty("COMPILE_DEFINITIONS"), true);
|
||||||
|
if (!flagsBuild.IsEmpty())
|
||||||
|
{
|
||||||
|
if (flags.size())
|
||||||
|
{
|
||||||
|
flags += ' ';
|
||||||
|
}
|
||||||
|
flags += flagsBuild.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
// Using a map and the full path guarantees that we will always get the same
|
// Using a map and the full path guarantees that we will always get the same
|
||||||
// fileRef object for any given full path.
|
// fileRef object for any given full path.
|
||||||
|
@ -1348,7 +1409,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
this->CurrentMakefile->GetDefineFlags());
|
this->CurrentMakefile->GetDefineFlags());
|
||||||
|
|
||||||
// Add preprocessor definitions for this target and configuration.
|
// Add preprocessor definitions for this target and configuration.
|
||||||
std::string ppDefs;
|
BuildObjectListOrString ppDefs(this, this->XcodeVersion >= 30);
|
||||||
if(this->XcodeVersion > 15)
|
if(this->XcodeVersion > 15)
|
||||||
{
|
{
|
||||||
this->AppendDefines(ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
|
this->AppendDefines(ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
|
||||||
|
@ -1370,7 +1431,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
this->AppendDefines(ppDefs, target.GetProperty(defVarName.c_str()));
|
this->AppendDefines(ppDefs, target.GetProperty(defVarName.c_str()));
|
||||||
}
|
}
|
||||||
buildSettings->AddAttribute
|
buildSettings->AddAttribute
|
||||||
("GCC_PREPROCESSOR_DEFINITIONS", this->CreateString(ppDefs.c_str()));
|
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
|
||||||
|
|
||||||
std::string extraLinkOptions;
|
std::string extraLinkOptions;
|
||||||
if(target.GetType() == cmTarget::EXECUTABLE)
|
if(target.GetType() == cmTarget::EXECUTABLE)
|
||||||
|
@ -1563,10 +1624,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
buildSettings->AddAttribute("PREBINDING",
|
buildSettings->AddAttribute("PREBINDING",
|
||||||
this->CreateString("NO"));
|
this->CreateString("NO"));
|
||||||
}
|
}
|
||||||
std::string dirs;
|
|
||||||
|
BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
|
||||||
|
BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
|
||||||
std::vector<std::string> includes;
|
std::vector<std::string> includes;
|
||||||
this->CurrentLocalGenerator->GetIncludeDirectories(includes);
|
this->CurrentLocalGenerator->GetIncludeDirectories(includes);
|
||||||
std::string fdirs;
|
|
||||||
std::set<cmStdString> emitted;
|
std::set<cmStdString> emitted;
|
||||||
emitted.insert("/System/Library/Frameworks");
|
emitted.insert("/System/Library/Frameworks");
|
||||||
for(std::vector<std::string>::iterator i = includes.begin();
|
for(std::vector<std::string>::iterator i = includes.begin();
|
||||||
|
@ -1579,15 +1641,14 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
|
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
|
||||||
if(emitted.insert(frameworkDir).second)
|
if(emitted.insert(frameworkDir).second)
|
||||||
{
|
{
|
||||||
fdirs += this->XCodeEscapePath(frameworkDir.c_str());
|
fdirs.Add(this->XCodeEscapePath(frameworkDir.c_str()).c_str());
|
||||||
fdirs += " ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string incpath =
|
std::string incpath =
|
||||||
this->XCodeEscapePath(i->c_str());
|
this->XCodeEscapePath(i->c_str());
|
||||||
dirs += incpath + " ";
|
dirs.Add(incpath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<std::string>& frameworks = target.GetFrameworks();
|
std::vector<std::string>& frameworks = target.GetFrameworks();
|
||||||
|
@ -1598,20 +1659,19 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
{
|
{
|
||||||
if(emitted.insert(*fmIt).second)
|
if(emitted.insert(*fmIt).second)
|
||||||
{
|
{
|
||||||
fdirs += this->XCodeEscapePath(fmIt->c_str());
|
fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str());
|
||||||
fdirs += " ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fdirs.size())
|
if(!fdirs.IsEmpty())
|
||||||
{
|
{
|
||||||
buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS",
|
buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS",
|
||||||
this->CreateString(fdirs.c_str()));
|
fdirs.CreateList());
|
||||||
}
|
}
|
||||||
if(dirs.size())
|
if(!dirs.IsEmpty())
|
||||||
{
|
{
|
||||||
buildSettings->AddAttribute("HEADER_SEARCH_PATHS",
|
buildSettings->AddAttribute("HEADER_SEARCH_PATHS",
|
||||||
this->CreateString(dirs.c_str()));
|
dirs.CreateList());
|
||||||
}
|
}
|
||||||
std::string oflagc = this->ExtractFlag("-O", cflags);
|
std::string oflagc = this->ExtractFlag("-O", cflags);
|
||||||
char optLevel[2];
|
char optLevel[2];
|
||||||
|
@ -1714,10 +1774,21 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
||||||
this->CreateString(""));
|
this->CreateString(""));
|
||||||
buildSettings->AddAttribute("USE_HEADERMAP",
|
buildSettings->AddAttribute("USE_HEADERMAP",
|
||||||
this->CreateString("NO"));
|
this->CreateString("NO"));
|
||||||
|
if (this->XcodeVersion >= 30)
|
||||||
|
{
|
||||||
|
cmXCodeObject *group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||||
|
group->AddObject(this->CreateString("-Wmost"));
|
||||||
|
group->AddObject(this->CreateString("-Wno-four-char-constants"));
|
||||||
|
group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
|
||||||
|
buildSettings->AddAttribute("WARNING_CFLAGS", group);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
buildSettings->AddAttribute("WARNING_CFLAGS",
|
buildSettings->AddAttribute("WARNING_CFLAGS",
|
||||||
this->CreateString(
|
this->CreateString(
|
||||||
"-Wmost -Wno-four-char-constants"
|
"-Wmost -Wno-four-char-constants"
|
||||||
" -Wno-unknown-pragmas"));
|
" -Wno-unknown-pragmas"));
|
||||||
|
}
|
||||||
|
|
||||||
// Runtime version information.
|
// Runtime version information.
|
||||||
if(target.GetType() == cmTarget::SHARED_LIBRARY)
|
if(target.GetType() == cmTarget::SHARED_LIBRARY)
|
||||||
|
@ -2432,6 +2503,20 @@ void cmGlobalXCodeGenerator
|
||||||
this->RootObject->AddAttribute("buildStyles", listObjs);
|
this->RootObject->AddAttribute("buildStyles", listObjs);
|
||||||
this->RootObject->AddAttribute("hasScannedForEncodings",
|
this->RootObject->AddAttribute("hasScannedForEncodings",
|
||||||
this->CreateString("0"));
|
this->CreateString("0"));
|
||||||
|
if (this->XcodeVersion >= 30)
|
||||||
|
{
|
||||||
|
group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
|
||||||
|
group->AddAttribute("BuildIndependentTargetsInParallel",
|
||||||
|
this->CreateString("YES"));
|
||||||
|
this->RootObject->AddAttribute("attributes", group);
|
||||||
|
if (this->XcodeVersion >= 31)
|
||||||
|
this->RootObject->AddAttribute("compatibilityVersion",
|
||||||
|
this->CreateString("Xcode 3.1"));
|
||||||
|
else
|
||||||
|
this->RootObject->AddAttribute("compatibilityVersion",
|
||||||
|
this->CreateString("Xcode 3.0"));
|
||||||
|
this->RootObject->AddAttribute("projectDirPath", this->CreateString(""));
|
||||||
|
}
|
||||||
// Point Xcode at the top of the source tree.
|
// Point Xcode at the top of the source tree.
|
||||||
{
|
{
|
||||||
std::string proot = root->GetMakefile()->GetCurrentDirectory();
|
std::string proot = root->GetMakefile()->GetCurrentDirectory();
|
||||||
|
@ -2946,7 +3031,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmGlobalXCodeGenerator::AppendDefines(std::string& defs,
|
void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
|
||||||
const char* defines_list,
|
const char* defines_list,
|
||||||
bool dflag)
|
bool dflag)
|
||||||
{
|
{
|
||||||
|
@ -2967,21 +3052,18 @@ void cmGlobalXCodeGenerator::AppendDefines(std::string& defs,
|
||||||
// - Escape a backslash as \\\\ since it itself is an escape
|
// - Escape a backslash as \\\\ since it itself is an escape
|
||||||
// Note that in the code below we need one more level of escapes for
|
// Note that in the code below we need one more level of escapes for
|
||||||
// C string syntax in this source file.
|
// C string syntax in this source file.
|
||||||
const char* sep = defs.empty()? "" : " ";
|
|
||||||
for(std::vector<std::string>::const_iterator di = defines.begin();
|
for(std::vector<std::string>::const_iterator di = defines.begin();
|
||||||
di != defines.end(); ++di)
|
di != defines.end(); ++di)
|
||||||
{
|
{
|
||||||
// Separate from previous definition.
|
std::string def;
|
||||||
defs += sep;
|
|
||||||
sep = " ";
|
|
||||||
|
|
||||||
// Open single quote.
|
// Open single quote.
|
||||||
defs += "'";
|
def += "'";
|
||||||
|
|
||||||
// Add -D flag if requested.
|
// Add -D flag if requested.
|
||||||
if(dflag)
|
if(dflag)
|
||||||
{
|
{
|
||||||
defs += "-D";
|
def += "-D";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escaped definition string.
|
// Escaped definition string.
|
||||||
|
@ -2989,20 +3071,22 @@ void cmGlobalXCodeGenerator::AppendDefines(std::string& defs,
|
||||||
{
|
{
|
||||||
if(*c == '\'')
|
if(*c == '\'')
|
||||||
{
|
{
|
||||||
defs += "\\\\'";
|
def += "\\\\'";
|
||||||
}
|
}
|
||||||
else if(*c == '\\')
|
else if(*c == '\\')
|
||||||
{
|
{
|
||||||
defs += "\\\\\\\\";
|
def += "\\\\\\\\";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
defs += *c;
|
def += *c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close single quote.
|
// Close single quote.
|
||||||
defs += "'";
|
def += "'";
|
||||||
|
|
||||||
|
defs.Add(def.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,10 @@ private:
|
||||||
const char* varNameSuffix,
|
const char* varNameSuffix,
|
||||||
const char* default_flags);
|
const char* default_flags);
|
||||||
|
|
||||||
void AppendDefines(std::string& defs, const char* defines_list,
|
class BuildObjectListOrString;
|
||||||
|
friend class BuildObjectListOrString;
|
||||||
|
|
||||||
|
void AppendDefines(BuildObjectListOrString& defs, const char* defines_list,
|
||||||
bool dflag = false);
|
bool dflag = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue