You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
11 KiB
367 lines
11 KiB
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "vpc.h"
|
|
#include "projectgenerator_xcode.h"
|
|
|
|
#ifdef WIN32
|
|
#include <direct.h>
|
|
#define mkdir(dir, mode) _mkdir(dir)
|
|
#define getcwd _getcwd
|
|
#endif
|
|
|
|
static const char *k_pchSource = "Source Files";
|
|
static const char *k_pchHeaders = "Header Files";
|
|
static const char *k_pchResources = "Resources";
|
|
static const char *k_pchVPCFiles = "VPC Files";
|
|
static const char *k_pchFrameworksAndLibs = "VPC Files";
|
|
|
|
void CProjectGenerator_XCode::GenerateXCodeProject( CBaseProjectDataCollector *pCollector, const char *pOutFilename, const char *pMakefileFilename )
|
|
{
|
|
char sPbxProjFile[MAX_PATH];
|
|
sprintf( sPbxProjFile, "%s.xcodeproj", pOutFilename );
|
|
mkdir( sPbxProjFile, 0777 );
|
|
|
|
g_pVPC->VPCStatus( true, "Saving XCode project for: '%s' File: '%s'", pCollector->GetProjectName().String(), sPbxProjFile );
|
|
|
|
sprintf( sPbxProjFile, "%s.xcodeproj/project.pbxproj", pOutFilename );
|
|
m_fp = fopen( sPbxProjFile, "wt" );
|
|
|
|
m_nIndent = 0;
|
|
m_pCollector = pCollector;
|
|
m_pMakefileFilename = pMakefileFilename;
|
|
|
|
WriteHeader();
|
|
WriteFileReferences();
|
|
WriteFiles();
|
|
WriteProject( pMakefileFilename );
|
|
//WriteBuildFiles();
|
|
WriteBuildConfigurations();
|
|
// Write the files list.
|
|
|
|
WriteTrailer();
|
|
|
|
fclose( m_fp );
|
|
m_fp = NULL;
|
|
}
|
|
|
|
|
|
void CProjectGenerator_XCode::Write( const char *pMsg, ... )
|
|
{
|
|
char sOut[8192];
|
|
|
|
va_list marker;
|
|
va_start( marker, pMsg );
|
|
V_vsnprintf( sOut, sizeof( sOut ), pMsg, marker );
|
|
va_end( marker );
|
|
|
|
for ( int i=0; i < m_nIndent; i++ )
|
|
fprintf( m_fp, "\t" );
|
|
|
|
fprintf( m_fp, "%s", sOut );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteHeader()
|
|
{
|
|
// preamble
|
|
Write( "// !$*UTF8*$!\n{\n" );
|
|
++m_nIndent;
|
|
Write( "archiveVersion = 1;\n" );
|
|
Write( "classes = {\n" );
|
|
Write( "};\n" );
|
|
Write( "objectVersion = 42;\n" );
|
|
Write( "objects = {\n" );
|
|
}
|
|
|
|
|
|
void CProjectGenerator_XCode::WriteProject( const char *pMakefileFilename )
|
|
{
|
|
++m_nIndent;
|
|
Write( "%024X = {\n", m_pCollector );
|
|
++m_nIndent;
|
|
Write( "isa = PBXGroup;\n" );
|
|
Write( "children = (\n" );
|
|
++m_nIndent;
|
|
Write( "%024X /* %s */,\n", k_pchSource, k_pchSource );
|
|
Write( "%024X /* %s */,\n", k_pchHeaders, k_pchHeaders );
|
|
Write( "%024X /* %s */,\n", k_pchResources, k_pchResources );
|
|
Write( "%024X /* %s */,\n", k_pchVPCFiles, k_pchVPCFiles );
|
|
--m_nIndent;
|
|
Write( ");\n" );
|
|
Write( "sourceTree = \"<group>\";\n" );
|
|
--m_nIndent;
|
|
Write( "};" );
|
|
--m_nIndent;
|
|
Write( "\n/* End PBXGroup section */\n" );
|
|
|
|
WriteLegacyTargets( pMakefileFilename );
|
|
|
|
Write( "\n/* Begin PBXProject section */\n" );
|
|
Write( "%024X /* Project object */ = {\n", this );
|
|
++m_nIndent;
|
|
Write( "isa = PBXProject;\n" );
|
|
Write( "buildConfigurationList = %024X /* Build configuration list for PBXProject \"%s\" */;\n", &(m_pCollector->m_BaseConfigData), m_pCollector->GetProjectName().String() );
|
|
Write( "compatibilityVersion = \"Xcode 2.4\";\n" );
|
|
Write( "hasScannedForEncodings = 0;\n" );
|
|
Write( "mainGroup = %024X;\n", m_pCollector );
|
|
Write( "projectDirPath = \"\";\n" );
|
|
|
|
char sSrcRootRelative[MAX_PATH];
|
|
g_pVPC->ResolveMacrosInString( "$SRCDIR", sSrcRootRelative, sizeof( sSrcRootRelative ) );
|
|
V_FixSlashes( sSrcRootRelative, '/' );
|
|
|
|
Write( "projectRoot = \"%s\";\n", sSrcRootRelative );
|
|
Write( "targets = (\n" );
|
|
++m_nIndent;
|
|
Write( "%024X /* build with make */, \n", &CProjectGenerator_XCode::WriteLegacyTargets );
|
|
--m_nIndent;
|
|
Write( ");\n" );
|
|
--m_nIndent;
|
|
Write( "};" );
|
|
Write( "\n/* End PBXProject section */\n" );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteBuildFiles()
|
|
{
|
|
Write( "\n/* Begin PBXBuildFile section */\n" );
|
|
for ( int i=m_pCollector->m_Files.First(); i != m_pCollector->m_Files.InvalidIndex(); i=m_pCollector->m_Files.Next( i ) )
|
|
{
|
|
const char *pFilename = m_pCollector->m_Files[i]->GetName();
|
|
Write( "%024X /* %s */ = {isa = PBXBuildFile; fileRef = %024X /* %s */;};\n",
|
|
m_pCollector->m_Files[i],
|
|
pFilename, m_pCollector->m_Files[i]->GetName(),
|
|
pFilename, m_pCollector->m_Files[i]->GetName() );
|
|
}
|
|
Write( "\n/* End PBXBuildFile section */\n" );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteBuildConfigurations()
|
|
{
|
|
++m_nIndent;
|
|
CUtlVector< CUtlString > configNames;
|
|
m_pCollector->GetAllConfigurationNames( configNames );
|
|
|
|
Write( "\n/* Begin XCBuildConfiguration section */\n" );
|
|
FOR_EACH_VEC( configNames, iConfig )
|
|
{
|
|
Write( "%024X /* %s */ = {\n", &(configNames[iConfig]), configNames[iConfig].String() );
|
|
++m_nIndent;
|
|
Write( "isa = XCBuildConfiguration;\n" );
|
|
Write( "buildSettings = {\n" );
|
|
++m_nIndent;
|
|
Write( "COPY_PHASE_STRIP = %s;\n", ( V_strstr( configNames[iConfig].String(), "release" ) ? "YES" : "NO" ) );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
Write( "name = %s;\n", configNames[iConfig].String() );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
}
|
|
|
|
FOR_EACH_VEC( configNames, iConfig )
|
|
{
|
|
Write( "%024X /* %s */ = {\n", (byte*)&(configNames[iConfig])+1, configNames[iConfig].String() );
|
|
++m_nIndent;
|
|
Write( "isa = XCBuildConfiguration;\n" );
|
|
Write( "buildSettings = {\n" );
|
|
++m_nIndent;
|
|
Write( "PRODUCT_NAME = \"build with make\";\n" );
|
|
Write( "CFG = %s;\n", configNames[iConfig].String() );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
Write( "name = %s;\n", configNames[iConfig].String() );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
}
|
|
|
|
Write( "\n/* End XCBuildConfiguration section */\n" );
|
|
|
|
Write( "\n/* Begin XCBuildConfigurationList section */\n" );
|
|
Write( "%024X /* Build configuration list for PBXProject \"%s\" */ = {\n", &(m_pCollector->m_BaseConfigData), m_pCollector->GetProjectName().String() );
|
|
++m_nIndent;
|
|
Write( "isa = XCConfigurationList;\n" );
|
|
Write( "buildConfigurations = (\n" );
|
|
++m_nIndent;
|
|
FOR_EACH_VEC( configNames, iConfig )
|
|
{
|
|
Write( "%024X /* %s */,\n", &(configNames[iConfig]), configNames[iConfig].String() );
|
|
}
|
|
--m_nIndent;
|
|
Write( ");\n" );
|
|
Write( "defaultConfigurationIsVisible = 0;\n" );
|
|
Write( "defaultConfigurationName = %s;\n", configNames[0].String() );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
|
|
Write( "%024X /* Build configuration list for PBXLegacyTarget \"build with make\" */ = {\n", (byte*)&(m_pCollector->m_BaseConfigData)+1 );
|
|
++m_nIndent;
|
|
Write( "isa = XCConfigurationList;\n" );
|
|
Write( "buildConfigurations = (\n" );
|
|
++m_nIndent;
|
|
FOR_EACH_VEC( configNames, iConfig )
|
|
{
|
|
Write( "%024X /* %s */,\n", (byte*)&(configNames[iConfig])+1, configNames[iConfig].String() );
|
|
}
|
|
--m_nIndent;
|
|
Write( ");\n" );
|
|
Write( "defaultConfigurationIsVisible = 0;\n" );
|
|
Write( "defaultConfigurationName = %s;\n", configNames[0].String() );
|
|
--m_nIndent;
|
|
Write( "};" );
|
|
|
|
Write( "\n/* End XCBuildConfigurationList section */\n" );
|
|
|
|
--m_nIndent;
|
|
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteLegacyTargets( const char *pchMakefileName )
|
|
{
|
|
Write( "\n/* Begin PBXLegacyTarget section */\n" );
|
|
++m_nIndent;
|
|
Write( "%024X /* build with make */ = {\n", &CProjectGenerator_XCode::WriteLegacyTargets );
|
|
++m_nIndent;
|
|
Write( "isa = PBXLegacyTarget;\n");
|
|
Write( "buildArgumentsString = \"-f %s $(ACTION) MAKE_VERBOSE=1\";\n", pchMakefileName );
|
|
Write( "buildConfigurationList = %024X /* Build configuration list for PBXLegacyTarget \"build with make\" */;\n", (byte*)&(m_pCollector->m_BaseConfigData)+1 );
|
|
Write( "buildPhases = (\n" );
|
|
Write( ");\n" );
|
|
Write( "buildToolPath = /usr/bin/make;\n" );
|
|
char rgchCurDir[MAX_PATH];
|
|
getcwd( rgchCurDir, MAX_PATH );
|
|
Write( "buildWorkingDirectory = %s;\n", rgchCurDir );
|
|
Write( "dependencies = (\n" );
|
|
Write( ");\n");
|
|
Write( "name = \"build with make\";\n" );
|
|
Write( "passBuildSettingsInEnvironment = 1;\n" );
|
|
Write( "productName = \"build with make\";\n" );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
--m_nIndent;
|
|
Write( "\n/* End PBXLegacyTarget section */\n" );
|
|
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteFileReferences()
|
|
{
|
|
Write( "\n/* Begin PBXFileReference section */\n" );
|
|
++m_nIndent;
|
|
for ( int i=m_pCollector->m_Files.First(); i != m_pCollector->m_Files.InvalidIndex(); i=m_pCollector->m_Files.Next( i ) )
|
|
{
|
|
const char *pchExtension = V_GetFileExtension( m_pCollector->m_Files[i]->GetName() );
|
|
char rgchFileType[MAX_PATH];
|
|
if ( pchExtension && ( !Q_stricmp( pchExtension, "cpp" ) || !Q_stricmp( pchExtension, "h" ) || !Q_stricmp( pchExtension, "c" ) || !Q_stricmp( pchExtension, "cc" ) ) )
|
|
sprintf( rgchFileType, "sourcecode.cpp.%s", pchExtension );
|
|
else
|
|
sprintf( rgchFileType, "text.plain" );
|
|
|
|
char rgchFilePath[MAX_PATH];
|
|
Q_strncpy( rgchFilePath, m_pCollector->m_Files[i]->GetName(), sizeof( rgchFilePath ) );
|
|
Q_RemoveDotSlashes( rgchFilePath );
|
|
|
|
Write( "%024X /* %s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = %s; path = \"%s\"; sourceTree = \"<group>\"; };\n",
|
|
m_pCollector->m_Files[i],
|
|
rgchFilePath,
|
|
rgchFileType,
|
|
rgchFilePath
|
|
);
|
|
}
|
|
--m_nIndent;
|
|
Write( "\n/* End PBXFileReference section */\n" );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTrailer()
|
|
{
|
|
Write( "};\n" );
|
|
Write( "rootObject = %024X /* project object */;\n", this );
|
|
--m_nIndent;
|
|
Write( "}\n" );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteConfig( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTarget_Build( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTarget_Compile( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTarget_Rebuild( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTarget_Link( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteTarget_Debug( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteIncludes( CSpecificConfig *pConfig )
|
|
{
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteFilesFolder( const char *pFolderName, const char *pExtensions )
|
|
{
|
|
CUtlVector<char*> extensions;
|
|
V_SplitString( pExtensions, ";", extensions );
|
|
|
|
Write( "%024X /* %s */ = {\n", pFolderName, pFolderName );
|
|
++m_nIndent;
|
|
Write( "isa = PBXGroup;\n" );
|
|
Write( "children = (\n" );
|
|
++m_nIndent;
|
|
for ( int i=m_pCollector->m_Files.First(); i != m_pCollector->m_Files.InvalidIndex(); i=m_pCollector->m_Files.Next( i ) )
|
|
{
|
|
const char *pFilename = m_pCollector->m_Files[i]->GetName();
|
|
|
|
// Make sure this file's extension is one of the extensions they're asking for.
|
|
bool bValidExt = false;
|
|
const char *pFileExtension = V_GetFileExtension( pFilename );
|
|
if ( pFileExtension )
|
|
{
|
|
for ( int iExt=0; iExt < extensions.Count(); iExt++ )
|
|
{
|
|
const char *pTestExt = extensions[iExt];
|
|
|
|
if ( pTestExt[0] == '*' && pTestExt[1] == '.' && V_stricmp( pTestExt+2, pFileExtension ) == 0 )
|
|
{
|
|
bValidExt = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bValidExt )
|
|
{
|
|
char sFixedSlashes[MAX_PATH];
|
|
V_strncpy( sFixedSlashes, pFilename, sizeof( sFixedSlashes ) );
|
|
Write( "%024X /* %s */,\n", m_pCollector->m_Files[i], sFixedSlashes );
|
|
}
|
|
}
|
|
|
|
--m_nIndent;
|
|
Write( ");\n" );
|
|
Write( "name = \"%s\";\n", pFolderName );
|
|
Write( "sourceTree = \"<group>\";\n" );
|
|
--m_nIndent;
|
|
Write( "};\n" );
|
|
}
|
|
|
|
void CProjectGenerator_XCode::WriteFiles()
|
|
{
|
|
Write( "\n/* Begin PBXGroup section */\n" );
|
|
++m_nIndent;
|
|
WriteFilesFolder( k_pchSource, "*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl;*.m;*.mm" );
|
|
WriteFilesFolder( k_pchHeaders, "*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if" );
|
|
WriteFilesFolder( k_pchResources, "*.plist;*.strings;*.xib" );
|
|
WriteFilesFolder( k_pchVPCFiles, "*.vpc" );
|
|
--m_nIndent;
|
|
}
|