summaryrefslogtreecommitdiff
path: root/external/vpc/utils
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /external/vpc/utils
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'external/vpc/utils')
-rw-r--r--external/vpc/utils/vpc/Makefile298
-rw-r--r--external/vpc/utils/vpc/baseprojectdatacollector.cpp381
-rw-r--r--external/vpc/utils/vpc/baseprojectdatacollector.h130
-rw-r--r--external/vpc/utils/vpc/conditionals.cpp244
-rw-r--r--external/vpc/utils/vpc/config_general.cpp180
-rw-r--r--external/vpc/utils/vpc/configuration.cpp487
-rw-r--r--external/vpc/utils/vpc/dependencies.cpp1133
-rw-r--r--external/vpc/utils/vpc/dependencies.h197
-rw-r--r--external/vpc/utils/vpc/exprsimplifier.cpp324
-rw-r--r--external/vpc/utils/vpc/generatordefinition.cpp353
-rw-r--r--external/vpc/utils/vpc/generatordefinition.h130
-rw-r--r--external/vpc/utils/vpc/groupscript.cpp369
-rw-r--r--external/vpc/utils/vpc/ibaseprojectgenerator.h75
-rw-r--r--external/vpc/utils/vpc/ibasesolutiongenerator.h24
-rw-r--r--external/vpc/utils/vpc/macros.cpp167
-rw-r--r--external/vpc/utils/vpc/main.cpp2810
-rw-r--r--external/vpc/utils/vpc/p4sln.cpp273
-rw-r--r--external/vpc/utils/vpc/p4sln.h17
-rw-r--r--external/vpc/utils/vpc/projectgenerator_codelite.cpp156
-rw-r--r--external/vpc/utils/vpc/projectgenerator_codelite.h51
-rw-r--r--external/vpc/utils/vpc/projectgenerator_makefile.cpp1127
-rw-r--r--external/vpc/utils/vpc/projectgenerator_ps3.cpp1257
-rw-r--r--external/vpc/utils/vpc/projectgenerator_ps3.h47
-rw-r--r--external/vpc/utils/vpc/projectgenerator_ps3.inc137
-rw-r--r--external/vpc/utils/vpc/projectgenerator_vcproj.cpp1939
-rw-r--r--external/vpc/utils/vpc/projectgenerator_vcproj.h379
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32.cpp349
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32.h41
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32.inc252
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32_2010.cpp625
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32_2010.h54
-rw-r--r--external/vpc/utils/vpc/projectgenerator_win32_2010.inc299
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360.cpp343
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360.h41
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360.inc192
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360_2010.cpp596
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360_2010.h54
-rw-r--r--external/vpc/utils/vpc/projectgenerator_xbox360_2010.inc210
-rw-r--r--external/vpc/utils/vpc/projectscript.cpp2484
-rw-r--r--external/vpc/utils/vpc/scriptsource.cpp565
-rw-r--r--external/vpc/utils/vpc/scriptsource.h95
-rw-r--r--external/vpc/utils/vpc/solutiongenerator_codelite.cpp285
-rw-r--r--external/vpc/utils/vpc/solutiongenerator_makefile.cpp341
-rw-r--r--external/vpc/utils/vpc/solutiongenerator_win32.cpp370
-rw-r--r--external/vpc/utils/vpc/solutiongenerator_xcode.cpp2806
-rw-r--r--external/vpc/utils/vpc/sys_utils.cpp781
-rw-r--r--external/vpc/utils/vpc/sys_utils.h157
-rw-r--r--external/vpc/utils/vpc/vpc.h482
-rw-r--r--external/vpc/utils/vpc/vpc.sln22
-rw-r--r--external/vpc/utils/vpc/vpc.vcxproj237
-rw-r--r--external/vpc/utils/vpc/vpc.vcxproj.filters393
-rw-r--r--external/vpc/utils/vpc/vpc.xcodeproj/project.pbxproj529
-rw-r--r--external/vpc/utils/vpccrccheck/crccheck_shared.cpp590
-rw-r--r--external/vpc/utils/vpccrccheck/crccheck_shared.h34
-rw-r--r--external/vpc/utils/vpccrccheck/vpccrccheck.cpp16
-rw-r--r--external/vpc/utils/vpccrccheck/vpccrccheck.vpc33
56 files changed, 25961 insertions, 0 deletions
diff --git a/external/vpc/utils/vpc/Makefile b/external/vpc/utils/vpc/Makefile
new file mode 100644
index 0000000..1bf7b05
--- /dev/null
+++ b/external/vpc/utils/vpc/Makefile
@@ -0,0 +1,298 @@
+# Make command to use for dependencies
+SHELL=/bin/sh
+RM:=rm
+MKDIR:=mkdir
+OS:=$(shell uname)
+EXE_POSTFIX:=""
+
+
+# ---------------------------------------------------------------- #
+# Figure out if we're building in the Steam tree or not.
+# ---------------------------------------------------------------- #
+
+SRCROOT:=../..
+-include $(SRCROOT)/devtools/steam_def.mak
+
+
+# ---------------------------------------------------------------- #
+# Set paths to gcc.
+# ---------------------------------------------------------------- #
+
+CC:=gcc
+CXX:=g++
+
+ifeq ($(OS),Darwin)
+SDKROOT:=$(shell xcodebuild -sdk macosx -version Path)
+CC:=clang -m32
+CXX:=clang++ -m32
+EXE_POSTFIX:=_osx
+endif
+
+ifeq ($(OS),Linux)
+ifeq ($(wildcard /valve/bin/gcc),)
+CC:=gcc
+CXX:=g++
+else
+CC:=/valve/bin/gcc-4.7
+CXX:=/valve/bin/g++-4.7
+endif
+EXE_POSTFIX:=_linux
+endif
+
+ifneq ($(CC_OVERRIDE),)
+ CC:=$(CC_OVERRIDE)
+ CXX:=$(CPP_OVERRIDE)
+endif
+
+
+# ---------------------------------------------------------------- #
+# Lists of files.
+# ---------------------------------------------------------------- #
+
+VPC_SRC:= \
+ exprsimplifier.cpp \
+ groupscript.cpp \
+ conditionals.cpp \
+ macros.cpp \
+ projectscript.cpp \
+ scriptsource.cpp \
+ baseprojectdatacollector.cpp \
+ configuration.cpp \
+ dependencies.cpp \
+ main.cpp \
+ projectgenerator_makefile.cpp \
+ solutiongenerator_makefile.cpp \
+ solutiongenerator_xcode.cpp \
+ sys_utils.cpp \
+ ../vpccrccheck/crccheck_shared.cpp \
+ projectgenerator_codelite.cpp \
+ solutiongenerator_codelite.cpp \
+
+TIER0_SRC:= \
+ ../../tier0/assert_dialog.cpp \
+ ../../tier0/cpu_posix.cpp \
+ ../../tier0/cpu.cpp \
+ ../../tier0/dbg.cpp \
+ ../../tier0/fasttimer.cpp \
+ ../../tier0/mem.cpp \
+ ../../tier0/mem_helpers.cpp \
+ ../../tier0/memdbg.cpp \
+ ../../tier0/memstd.cpp \
+ ../../tier0/memvalidate.cpp \
+ ../../tier0/minidump.cpp \
+ ../../tier0/pch_tier0.cpp \
+ ../../tier0/threadtools.cpp \
+ ../../tier0/valobject.cpp \
+ ../../tier0/vprof.cpp
+
+
+TIER1_SRC:= \
+ ../../tier1/keyvalues.cpp \
+ ../../tier1/checksum_crc.cpp \
+ ../../tier1/checksum_md5.cpp \
+ ../../tier1/convar.cpp \
+ ../../tier1/generichash.cpp \
+ ../../tier1/interface.cpp \
+ ../../tier1/mempool.cpp \
+ ../../tier1/memstack.cpp \
+ ../../tier1/stringpool.cpp \
+ ../../tier1/utlbuffer.cpp \
+ ../../tier1/utlsymbol.cpp
+
+VSTDLIB_SRC:= \
+ ../../vstdlib/cvar.cpp \
+ ../../vstdlib/vstrtools.cpp \
+ ../../vstdlib/random.cpp
+
+
+ifeq "$(STEAM_BRANCH)" "1"
+ TIER0_SRC+= \
+ ../../tier0/tier0.cpp \
+ ../../tier0/platform_posix.cpp \
+ ../../tier0/validator.cpp \
+ ../../tier0/thread.cpp \
+ ../../tier0/pmelib.cpp \
+ ../../tier0/pme_posix.cpp \
+ ../../tier0/testthread.cpp \
+ ../../tier0/cpu_posix.cpp \
+ ../../tier0/memblockhdr.cpp
+
+ VSTDLIB_SRC+= \
+ ../../vstdlib/keyvaluessystem.cpp \
+ ../../vstdlib/qsort_s.cpp \
+ ../../vstdlib/strtools.cpp \
+ ../../vstdlib/stringnormalize.cpp \
+ ../../vstdlib/splitstring.cpp \
+ ../../vstdlib/commandline.cpp
+
+ INTERFACES_SRC=
+
+ BINLAUNCH_SRC =
+
+else
+
+ TIER0_SRC+= \
+ ../../tier0/platform_posix.cpp \
+ ../../tier0/pme_posix.cpp \
+ ../../tier0/commandline.cpp \
+ ../../tier0/win32consoleio.cpp \
+ ../../tier0/logging.cpp \
+ ../../tier0/tier0_strtools.cpp
+
+ TIER1_SRC+= \
+ ../../tier1/utlstring.cpp \
+ ../../tier1/tier1.cpp \
+ ../../tier1/characterset.cpp \
+ ../../tier1/splitstring.cpp \
+ ../../tier1/strtools.cpp \
+ ../../tier1/exprevaluator.cpp \
+
+ VSTDLIB_SRC+= \
+ ../../vstdlib/keyvaluessystem.cpp
+
+ INTERFACES_SRC= \
+ ../../interfaces/interfaces.cpp
+
+ BINLAUNCH_SRC = \
+
+endif
+
+
+SRC:=$(VPC_SRC) $(TIER0_SRC) $(TIER1_SRC) $(VSTDLIB_SRC) $(INTERFACES_SRC) $(BINLAUNCH_SRC)
+
+
+# -----Begin user-editable area-----
+
+# -----End user-editable area-----
+
+# If no configuration is specified, "Debug" will be used
+ifndef "CFG"
+CFG:=Release
+endif
+
+
+#
+# Configuration: Debug
+#
+ifeq "$(CFG)" "Debug"
+
+OUTDIR:=obj/$(OS)/debug
+CONFIG_DEPENDENT_FLAGS:=-O0 -g3 -ggdb
+
+else
+
+OUTDIR:=obj/$(OS)/release
+CONFIG_DEPENDENT_FLAGS:=-O3 -g1 -ggdb
+
+endif
+
+OBJS:=$(addprefix $(OUTDIR)/, $(subst ../../, ,$(SRC:.cpp=.o)))
+
+
+OUTFILE:=$(OUTDIR)/vpc
+CFG_INC:=-I../../public -I../../common -I../../public/tier0 \
+ -I../../public/tier1 -I../../public/tier2 -I../../public/vstdlib
+
+
+CFLAGS=-D_POSIX -DPOSIX -DGNUC -DNDEBUG $(CONFIG_DEPENDENT_FLAGS) -msse -mmmx -pipe -w -fpermissive -fPIC $(CFG_INC)
+ifeq "$(STEAM_BRANCH)" "1"
+CFLAGS+= -DSTEAM
+endif
+
+
+ifeq "$(OS)" "Darwin"
+CFLAGS+=-I$(SDKROOT)/usr/include/malloc
+CFLAGS+= -DOSX -D_OSX
+CFLAGS+= -arch i386 -fasm-blocks
+endif
+
+ifeq "$(OS)" "Linux"
+CFLAGS+= -DPLATFORM_LINUX -D_LINUX -DLINUX
+endif
+
+ifeq ($(CYGWIN),1)
+CFLAGS+=-D_CYGWIN -DCYGWIN -D_CYGWIN_WINDOWS_TARGET
+endif
+
+CFLAGS+= -DCOMPILER_GCC
+
+# the sed magic here adds the dependency file to the list of things that depend on the computed dependency
+# set, so if any of them change, the dependencies are re-made
+MAKEDEPEND=$(CXX) -M -MT $@ -MM $(CFLAGS) $< | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' > $(@:.o=.d)
+COMPILE=$(CXX) -c $(CFLAGS) -o $@ $<
+LINK=$(CXX) $(CONFIG_DEPENDENT_FLAGS) -o "$(OUTFILE)" $(OBJS) -ldl -lpthread
+
+ifeq "$(OS)" "Darwin"
+LINK+=-liconv -framework Foundation
+endif
+
+ifeq "$(OS)" "Darwin"
+LINK+= -arch i386
+endif
+
+
+# Build rules
+all: $(OUTFILE) ../../../../devtools/bin/vpc$(EXE_POSTFIX)
+
+../../../../devtools/bin/vpc$(EXE_POSTFIX) : $(OUTFILE)
+ cp "$(OUTFILE)" ../../../../devtools/bin/vpc$(EXE_POSTFIX)
+
+$(OUTFILE): Makefile $(OBJS)
+ $(LINK)
+
+
+# Rebuild this project
+rebuild: cleanall all
+
+# Clean this project
+clean:
+ $(RM) -f $(OUTFILE)
+ $(RM) -f $(OBJS)
+ $(RM) -f $(OBJS:.o=.d)
+ $(RM) -f ../../../../devtools/bin/vpc$(EXE_POSTFIX)
+
+# Clean this project and all dependencies
+cleanall: clean
+
+# magic rules - tread with caution
+-include $(OBJS:.o=.d)
+
+# Pattern rules
+$(OUTDIR)/%.o : %.cpp
+ -$(MKDIR) -p $(@D)
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+$(OUTDIR)/tier0/%.o : ../../tier0/%.cpp
+ -$(MKDIR) -p $(@D)
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+$(OUTDIR)/tier1/%.o : ../../tier1/%.cpp
+ -$(MKDIR) -p $(@D)
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+$(OUTDIR)/vstdlib/%.o : ../../vstdlib/%.cpp
+ -$(MKDIR) -p $(@D)
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+$(OUTDIR)/interfaces/%.o : ../../interfaces/%.cpp
+ if [ ! -d $(@D) ]; then $(MKDIR) $(@D); fi
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+$(OUTDIR)/utils/binlaunch/%.o : ../binlaunch/%.cpp
+ if [ ! -d $(@D) ]; then $(MKDIR) $(@D); fi
+ @$(MAKEDEPEND);
+ $(COMPILE)
+
+
+# the tags file) seems like more work than it's worth. feel free to fix that up
+# if it bugs you.
+TAGS:
+ @find . -name '*.cpp' -print0 | xargs -0 etags --declarations --ignore-indentation
+ @find . -name '*.h' -print0 | xargs -0 etags --language=c++ --declarations --ignore-indentation --append
+ @find . -name '*.c' -print0 | xargs -0 etags --declarations --ignore-indentation --append
+
diff --git a/external/vpc/utils/vpc/baseprojectdatacollector.cpp b/external/vpc/utils/vpc/baseprojectdatacollector.cpp
new file mode 100644
index 0000000..c6dcc35
--- /dev/null
+++ b/external/vpc/utils/vpc/baseprojectdatacollector.cpp
@@ -0,0 +1,381 @@
+//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "baseprojectdatacollector.h"
+#include "tier1/utlstack.h"
+#include "p4lib/ip4.h"
+
+static const char * const s_rgsAmbiguousPropertyNames[] =
+{
+ "$CommandLine",
+};
+
+// ------------------------------------------------------------------------------------------------ //
+// CSpecificConfig implementation.
+// ------------------------------------------------------------------------------------------------ //
+
+CSpecificConfig::CSpecificConfig( CSpecificConfig *pParentConfig )
+ : m_pParentConfig( pParentConfig )
+{
+ m_pKV = new KeyValues( "" );
+ m_bFileExcluded = false;
+ m_bIsSchema = false;
+ m_bIsDynamic = false;
+}
+
+CSpecificConfig::~CSpecificConfig()
+{
+ m_pKV->deleteThis();
+}
+
+const char* CSpecificConfig::GetConfigName()
+{
+ return m_pKV->GetName();
+}
+
+const char* CSpecificConfig::GetOption( const char *pOptionName )
+{
+ const char *pRet = m_pKV->GetString( pOptionName, NULL );
+ if ( pRet )
+ return pRet;
+
+ if ( m_pParentConfig )
+ return m_pParentConfig->m_pKV->GetString( pOptionName, NULL );
+
+ return NULL;
+}
+
+
+// ------------------------------------------------------------------------------------------------ //
+// CFileConfig implementation.
+// ------------------------------------------------------------------------------------------------ //
+
+CFileConfig::~CFileConfig()
+{
+ Term();
+}
+
+void CFileConfig::Term()
+{
+ m_Configurations.PurgeAndDeleteElements();
+}
+
+const char* CFileConfig::GetName()
+{
+ return m_Filename.String();
+}
+
+CSpecificConfig* CFileConfig::GetConfig( const char *pConfigName )
+{
+ int i = m_Configurations.Find( pConfigName );
+ if ( i == m_Configurations.InvalidIndex() )
+ return NULL;
+ else
+ return m_Configurations[i];
+}
+
+CSpecificConfig* CFileConfig::GetOrCreateConfig( const char *pConfigName, CSpecificConfig *pParentConfig )
+{
+ int i = m_Configurations.Find( pConfigName );
+ if ( i == m_Configurations.InvalidIndex() )
+ {
+ CSpecificConfig *pConfig = new CSpecificConfig( pParentConfig );
+ i = m_Configurations.Insert( pConfigName, pConfig );
+ }
+
+ return m_Configurations[i];
+}
+
+bool CFileConfig::IsExcludedFrom( const char *pConfigName )
+{
+ CSpecificConfig *pSpecificConfig = GetConfig( pConfigName );
+ if ( pSpecificConfig )
+ return pSpecificConfig->m_bFileExcluded;
+ else
+ return false;
+}
+
+bool CFileConfig::IsDynamicFile( const char *pConfigName )
+{
+ CSpecificConfig *pSpecificConfig = GetConfig( pConfigName );
+ if ( pSpecificConfig )
+ return pSpecificConfig->m_bIsDynamic;
+ else
+ return false;
+}
+
+
+// ------------------------------------------------------------------------------------------------ //
+// CBaseProjectDataCollector implementation.
+// ------------------------------------------------------------------------------------------------ //
+
+CBaseProjectDataCollector::CBaseProjectDataCollector( CRelevantPropertyNames *pNames ) : m_Files( k_eDictCompareTypeFilenames )
+{
+ m_RelevantPropertyNames.m_nNames = 0;
+ m_RelevantPropertyNames.m_pNames = NULL;
+
+ if ( pNames )
+ {
+ m_RelevantPropertyNames = *pNames;
+ }
+}
+
+CBaseProjectDataCollector::~CBaseProjectDataCollector()
+{
+ Term();
+}
+
+void CBaseProjectDataCollector::StartProject()
+{
+ for (int i = 0; i < m_RelevantPropertyNames.m_nNames; i++)
+ {
+ for (int j = 0; j < V_ARRAYSIZE(s_rgsAmbiguousPropertyNames); j++ )
+ {
+ if ( V_stricmp( m_RelevantPropertyNames.m_pNames[i], s_rgsAmbiguousPropertyNames[j] ) == 0 )
+ g_pVPC->VPCWarning( "Property name %s may occur in multiple contexts and should be fully qualified", m_RelevantPropertyNames.m_pNames[i] );
+ }
+ }
+ m_ProjectName = "UNNAMED";
+ m_CurFileConfig.Push( &m_BaseConfigData );
+ m_CurSpecificConfig.Push( NULL );
+}
+
+void CBaseProjectDataCollector::EndProject()
+{
+}
+
+void CBaseProjectDataCollector::Term()
+{
+ m_BaseConfigData.Term();
+ m_Files.PurgeAndDeleteElements();
+ m_CurFileConfig.Purge();
+ m_CurSpecificConfig.Purge();
+}
+
+CUtlString CBaseProjectDataCollector::GetProjectName()
+{
+ return m_ProjectName;
+}
+
+void CBaseProjectDataCollector::SetProjectName( const char *pProjectName )
+{
+ char tmpBuf[MAX_PATH];
+ V_strncpy( tmpBuf, pProjectName, sizeof( tmpBuf ) );
+ V_strlower( tmpBuf );
+ m_ProjectName = tmpBuf;
+}
+
+// Get a list of all configurations.
+void CBaseProjectDataCollector::GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames )
+{
+ configurationNames.Purge();
+ for ( int i=m_BaseConfigData.m_Configurations.First(); i != m_BaseConfigData.m_Configurations.InvalidIndex(); i=m_BaseConfigData.m_Configurations.Next(i) )
+ {
+ configurationNames.AddToTail( m_BaseConfigData.m_Configurations.GetElementName(i) );
+ }
+}
+
+void CBaseProjectDataCollector::StartConfigurationBlock( const char *pConfigName, bool bFileSpecific )
+{
+ CFileConfig *pFileConfig = m_CurFileConfig.Top();
+
+ // Find or add a new config block.
+ char sLowerCaseConfigName[MAX_PATH];
+ V_strncpy( sLowerCaseConfigName, pConfigName, sizeof( sLowerCaseConfigName ) );
+ V_strlower( sLowerCaseConfigName );
+
+ int index = pFileConfig->m_Configurations.Find( sLowerCaseConfigName );
+ if ( index == -1 )
+ {
+ CSpecificConfig *pParent = ( pFileConfig==&m_BaseConfigData ? NULL : m_BaseConfigData.GetOrCreateConfig( sLowerCaseConfigName, NULL ) );
+
+ CSpecificConfig *pConfig = new CSpecificConfig( pParent );
+ pConfig->m_bFileExcluded = false;
+ pConfig->m_pKV->SetName( sLowerCaseConfigName );
+ index = pFileConfig->m_Configurations.Insert( sLowerCaseConfigName, pConfig );
+ }
+
+ // Remember what the current config is.
+ m_CurSpecificConfig.Push( pFileConfig->m_Configurations[index] );
+}
+
+void CBaseProjectDataCollector::EndConfigurationBlock()
+{
+ m_CurSpecificConfig.Pop();
+}
+
+bool CBaseProjectDataCollector::StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip )
+{
+ m_CurPropertySection.Push( keyword );
+ return true;
+}
+
+void CBaseProjectDataCollector::HandleProperty( const char *pProperty, const char *pCustomScriptData )
+{
+ CFmtStr sQualifiedProperty( "%s%s%s", m_CurPropertySection.Count() ? g_pVPC->KeywordToName( m_CurPropertySection.Top() ) : "",
+ m_CurPropertySection.Count() ? "/" : "",
+ pProperty );
+ bool bSetQualifiedProperty = false;
+ int i;
+ for ( i=0; i < m_RelevantPropertyNames.m_nNames; i++ )
+ {
+ if ( V_stricmp( m_RelevantPropertyNames.m_pNames[i], pProperty ) == 0 )
+ break;
+ if ( V_stricmp( m_RelevantPropertyNames.m_pNames[i], sQualifiedProperty.Access() ) == 0 )
+ {
+ bSetQualifiedProperty = true;
+ break;
+ }
+ }
+ if ( i == m_RelevantPropertyNames.m_nNames )
+ {
+ // not found
+ return;
+ }
+
+ if ( pCustomScriptData )
+ {
+ g_pVPC->GetScript().PushScript( "HandleProperty( custom script data )", pCustomScriptData );
+ }
+
+ const char *pNextToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( pNextToken && pNextToken[0] != 0 )
+ {
+ // Pass in the previous value so the $base substitution works.
+ CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
+ const char *pBaseString = pConfig->m_pKV->GetString( bSetQualifiedProperty ? sQualifiedProperty.Access() : pProperty );
+ char buff[MAX_SYSTOKENCHARS];
+ if ( g_pVPC->GetScript().ParsePropertyValue( pBaseString, buff, sizeof( buff ) ) )
+ {
+ pConfig->m_pKV->SetString( bSetQualifiedProperty ? sQualifiedProperty.Access() : pProperty, buff );
+ }
+ }
+
+ if ( pCustomScriptData )
+ {
+ // Restore prior script state
+ g_pVPC->GetScript().PopScript();
+ }
+}
+
+void CBaseProjectDataCollector::EndPropertySection( configKeyword_e keyword )
+{
+ configKeyword_e kw;
+ m_CurPropertySection.Pop( kw );
+ Assert( kw == keyword );
+}
+
+void CBaseProjectDataCollector::StartFolder( const char *pFolderName )
+{
+}
+void CBaseProjectDataCollector::EndFolder()
+{
+}
+
+bool CBaseProjectDataCollector::StartFile( const char *pFilename, bool bWarnIfAlreadyExists )
+{
+ CFileConfig *pFileConfig = new CFileConfig;
+ pFileConfig->m_Filename = pFilename;
+ pFileConfig->m_nInsertOrder = m_Files.Count();
+ m_Files.Insert( pFilename, pFileConfig );
+
+ m_CurFileConfig.Push( pFileConfig );
+ m_CurSpecificConfig.Push( NULL );
+
+ char szFullPath[MAX_PATH];
+
+ V_GetCurrentDirectory( szFullPath, sizeof( szFullPath ) );
+ V_AppendSlash( szFullPath, sizeof( szFullPath ) );
+ V_strncat( szFullPath, pFilename, sizeof( szFullPath ) );
+ V_RemoveDotSlashes( szFullPath );
+
+#if 0
+ // Add file to Perforce if it isn't there already
+ if ( Sys_Exists( szFullPath ) )
+ {
+ if ( m_bP4AutoAdd && p4 && !p4->IsFileInPerforce( szFullPath ) )
+ {
+ p4->OpenFileForAdd( szFullPath );
+ VPCStatus( "%s automatically opened for add in default changelist.", szFullPath );
+
+ }
+ }
+ else
+ {
+ // g_pVPC->Warning( "%s not found on disk at location specified in project script.", szFullPath );
+ }
+#endif
+
+ return true;
+}
+
+void CBaseProjectDataCollector::EndFile()
+{
+ m_CurFileConfig.Pop();
+ m_CurSpecificConfig.Pop();
+}
+
+// This is actually just per-file configuration data.
+void CBaseProjectDataCollector::FileExcludedFromBuild( bool bExcluded )
+{
+ CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
+ pConfig->m_bFileExcluded = bExcluded;
+}
+
+void CBaseProjectDataCollector::FileIsSchema( bool bIsSchema )
+{
+ CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
+ pConfig->m_bIsSchema = bIsSchema;
+}
+
+void CBaseProjectDataCollector::FileIsDynamic( bool bIsDynamic )
+{
+ CSpecificConfig *pConfig = m_CurSpecificConfig.Top();
+ pConfig->m_bIsDynamic = bIsDynamic;
+}
+
+
+bool CBaseProjectDataCollector::RemoveFile( const char *pFilename )
+{
+ bool bRet = false;
+ int i = m_Files.Find( pFilename );
+ if ( i != m_Files.InvalidIndex() )
+ {
+ delete m_Files[i];
+ m_Files.RemoveAt( i );
+ bRet = true;
+ }
+ return bRet;
+}
+
+void CBaseProjectDataCollector::DoStandardVisualStudioReplacements( const char *pStartString, const char *pFullInputFilename, char *pOut, int outLen )
+{
+ // Decompose the input filename.
+ char sInputDir[MAX_PATH], sFileBase[MAX_PATH];
+ if ( !V_ExtractFilePath( pFullInputFilename, sInputDir, sizeof( sInputDir ) ) )
+ V_strcpy( sInputDir, "." );
+
+ V_FileBase( pFullInputFilename, sFileBase, sizeof( sFileBase ) );
+
+ // Handle $(InputPath), $(InputDir), $(InputName)
+ char *strings[2] =
+ {
+ (char*)stackalloc( outLen ),
+ (char*)stackalloc( outLen )
+ };
+
+ V_StrSubst( pStartString, "$(InputPath)", pFullInputFilename, strings[0], outLen );
+ V_StrSubst( strings[0], "$(InputDir)", sInputDir, strings[1], outLen );
+ V_StrSubst( strings[1], "$(InputName)", sFileBase, strings[0], outLen );
+ V_StrSubst( strings[0], "$(IntDir)", "$(OBJ_DIR)", strings[1], outLen );
+ V_StrSubst( strings[1], "$(InputFileName)", pFullInputFilename + V_strlen(sInputDir), strings[0], outLen );
+ V_StrSubst( strings[0], "$(ConfigurationName)", "${CONFIGURATION}", strings[1], outLen );
+ V_StrSubst( strings[1], "$(Configuration)", "${CONFIGURATION}", strings[0], outLen );
+
+ V_strncpy( pOut, strings[0], outLen );
+ V_FixSlashes( pOut, '/' );
+}
diff --git a/external/vpc/utils/vpc/baseprojectdatacollector.h b/external/vpc/utils/vpc/baseprojectdatacollector.h
new file mode 100644
index 0000000..543e732
--- /dev/null
+++ b/external/vpc/utils/vpc/baseprojectdatacollector.h
@@ -0,0 +1,130 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+//
+//=============================================================================
+
+#ifndef BASEPROJECTDATACOLLECTOR_H
+#define BASEPROJECTDATACOLLECTOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/keyvalues.h"
+#include "tier1/utlstack.h"
+
+class CSpecificConfig
+{
+public:
+ CSpecificConfig( CSpecificConfig *pParentConfig );
+ ~CSpecificConfig();
+
+ const char *GetConfigName();
+ const char *GetOption( const char *pOptionName );
+
+public:
+ CSpecificConfig *m_pParentConfig;
+ KeyValues *m_pKV;
+ bool m_bFileExcluded; // Is the file that holds this config excluded from the build?
+ bool m_bIsSchema; // Is this a schema file?
+ bool m_bIsDynamic; // Is this a schema file?
+};
+
+class CFileConfig
+{
+public:
+ ~CFileConfig();
+
+ void Term();
+ const char *GetName();
+ CSpecificConfig *GetConfig( const char *pConfigName );
+ CSpecificConfig *GetOrCreateConfig( const char *pConfigName, CSpecificConfig *pParentConfig );
+ bool IsExcludedFrom( const char *pConfigName );
+ bool IsDynamicFile( const char *pConfigName );
+
+public:
+ CUtlDict< CSpecificConfig*, int > m_Configurations;
+ CUtlString m_Filename; // "" if this is the config data for the whole project.
+ int m_nInsertOrder;
+};
+
+// This just holds the list of property names that we're supposed to scan for.
+class CRelevantPropertyNames
+{
+public:
+ const char **m_pNames;
+ int m_nNames;
+};
+
+//
+// This class is shared by the makefile and SlickEdit project file generator.
+// It just collects interesting file properties into KeyValues and then the project file generator
+// is responsible for using that data to write out a project file.
+//
+class CBaseProjectDataCollector : public IBaseProjectGenerator
+{
+// IBaseProjectGenerator implementation.
+public:
+
+ CBaseProjectDataCollector( CRelevantPropertyNames *pNames );
+ ~CBaseProjectDataCollector();
+
+ // Called before doing anything in a project (in g_pVPC->GetOutputFilename()).
+ virtual void StartProject();
+ virtual void EndProject();
+
+ // Access the project name.
+ virtual CUtlString GetProjectName();
+ virtual void SetProjectName( const char *pProjectName );
+
+ // Get a list of all configurations.
+ virtual void GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames );
+
+ // Configuration data is specified in between these calls and inside BeginPropertySection/EndPropertySection.
+ // If bFileSpecific is set, then the configuration data only applies to the last file added.
+ virtual void StartConfigurationBlock( const char *pConfigName, bool bFileSpecific );
+ virtual void EndConfigurationBlock();
+
+ // These functions are called when it enters a section like $Compiler, $Linker, etc.
+ // In between the BeginPropertySection/EndPropertySection, it'll call HandleProperty for any properties inside that section.
+ //
+ // If you pass pCustomScriptData to HandleProperty, it won't touch the global parsing state -
+ // it'll parse the platform filters and property value from pCustomScriptData instead.
+ virtual bool StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip = NULL );
+ virtual void HandleProperty( const char *pProperty, const char *pCustomScriptData = NULL );
+ virtual void EndPropertySection( configKeyword_e keyword );
+
+ // Files go in folders. The generator should maintain a stack of folders as they're added.
+ virtual void StartFolder( const char *pFolderName );
+ virtual void EndFolder();
+
+ // Add files. Any config blocks/properties between StartFile/EndFile apply to this file only.
+ // It will only ever have one active file.
+ virtual bool StartFile( const char *pFilename, bool bWarnIfAlreadyExists );
+ virtual void EndFile();
+
+ // This is actually just per-file configuration data.
+ virtual void FileExcludedFromBuild( bool bExcluded );
+ virtual void FileIsSchema( bool bIsSchema );
+ virtual void FileIsDynamic( bool bIsDynamic );
+
+ // Remove the specified file.
+ virtual bool RemoveFile( const char *pFilename ); // returns ture if a file was removed
+
+public:
+ // This is called in EndProject if bAutoCleanupAfterProject is set.
+ void Term();
+ static void DoStandardVisualStudioReplacements( const char *pStartString, const char *pFullInputFilename, char *pOut, int outLen );
+
+public:
+ CUtlString m_ProjectName;
+
+ CUtlDict< CFileConfig *, int > m_Files;
+ CFileConfig m_BaseConfigData;
+
+ CUtlStack< CFileConfig* > m_CurFileConfig; // Either m_BaseConfigData or one of the files.
+ CUtlStack< CSpecificConfig* > m_CurSpecificConfig; // Debug, release?
+ CUtlStack< configKeyword_e > m_CurPropertySection;
+ CRelevantPropertyNames m_RelevantPropertyNames;
+};
+
+#endif // BASEPROJECTDATACOLLECTOR_H
diff --git a/external/vpc/utils/vpc/conditionals.cpp b/external/vpc/utils/vpc/conditionals.cpp
new file mode 100644
index 0000000..f72376b
--- /dev/null
+++ b/external/vpc/utils/vpc/conditionals.cpp
@@ -0,0 +1,244 @@
+//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::SetupDefaultConditionals()
+{
+ //
+ // PLATFORM Conditionals
+ //
+ {
+ FindOrCreateConditional( "WIN32", true, CONDITIONAL_PLATFORM );
+ FindOrCreateConditional( "WIN64", true, CONDITIONAL_PLATFORM );
+
+ // LINUX is the platform but the VPC scripts use $LINUX and $DEDICATED
+ // (which we automatically create later).
+ FindOrCreateConditional( "LINUX32", true, CONDITIONAL_PLATFORM );
+ FindOrCreateConditional( "LINUX64", true, CONDITIONAL_PLATFORM );
+
+ FindOrCreateConditional( "OSX32", true, CONDITIONAL_PLATFORM );
+ FindOrCreateConditional( "OSX64", true, CONDITIONAL_PLATFORM );
+
+ FindOrCreateConditional( "X360", true, CONDITIONAL_PLATFORM );
+ FindOrCreateConditional( "PS3", true, CONDITIONAL_PLATFORM );
+ }
+
+ //
+ // CUSTOM conditionals
+ //
+ {
+ // setup default custom conditionals
+ FindOrCreateConditional( "PROFILE", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "RETAIL", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "CALLCAP", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "FASTCAP", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "CERT", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "MEMTEST", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "NOFPO", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "POSIX", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "LV", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "DEMO", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "NO_STEAM", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "DVDEMU", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "QTDEBUG", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "NO_CEG", true, CONDITIONAL_CUSTOM );
+ FindOrCreateConditional( "UPLOAD_CEG", true, CONDITIONAL_CUSTOM );
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const char *CVPC::GetTargetPlatformName()
+{
+ for ( int i = 0; i < m_Conditionals.Count(); i++ )
+ {
+ conditional_t *pConditional = &m_Conditionals[i];
+ if ( pConditional->type == CONDITIONAL_PLATFORM && pConditional->m_bDefined )
+ {
+ return pConditional->name.String();
+ }
+ }
+
+ // fatal - should have already been default set
+ Assert( 0 );
+ VPCError( "Unspecified platform." );
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Case Insensitive. Returns true if platform conditional has been marked
+// as defined.
+//-----------------------------------------------------------------------------
+bool CVPC::IsPlatformDefined( const char *pName )
+{
+ for ( int i=0; i<m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type == CONDITIONAL_PLATFORM && !V_stricmp( pName, m_Conditionals[i].name.String() ) )
+ {
+ return m_Conditionals[i].m_bDefined;
+ }
+
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Case Insensitive
+//-----------------------------------------------------------------------------
+conditional_t *CVPC::FindOrCreateConditional( const char *pName, bool bCreate, conditionalType_e type )
+{
+ for (int i=0; i<m_Conditionals.Count(); i++)
+ {
+ if ( !V_stricmp( pName, m_Conditionals[i].name.String() ) )
+ {
+ // found
+ return &m_Conditionals[i];
+ }
+ }
+
+ if ( !bCreate )
+ {
+ return NULL;
+ }
+
+ int index = m_Conditionals.AddToTail();
+
+ char tempName[256];
+ V_strncpy( tempName, pName, sizeof( tempName ) );
+
+ // primary internal use as lower case, but spewed to user as upper for style consistency
+ m_Conditionals[index].name = V_strlower( tempName );
+ m_Conditionals[index].upperCaseName = V_strupr( tempName );
+ m_Conditionals[index].type = type;
+
+ return &m_Conditionals[index];
+}
+
+void CVPC::SetConditional( const char *pString, bool bSet )
+{
+ VPCStatus( false, "Set Conditional: $%s = %s", pString, ( bSet ? "1" : "0" ) );
+
+ conditional_t *pConditional = FindOrCreateConditional( pString, true, CONDITIONAL_CUSTOM );
+ if ( !pConditional )
+ {
+ VPCError( "Failed to find or create $%s conditional", pString );
+ }
+
+ pConditional->m_bDefined = bSet;
+}
+
+//-----------------------------------------------------------------------------
+// Returns true if string has a conditional of the specified type
+//-----------------------------------------------------------------------------
+bool CVPC::ConditionHasDefinedType( const char* pCondition, conditionalType_e type )
+{
+ char symbol[MAX_SYSTOKENCHARS];
+
+ for ( int i=0; i<m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != type )
+ continue;
+
+ sprintf( symbol, "$%s", m_Conditionals[i].name.String() );
+ if ( V_stristr( pCondition, symbol ) )
+ {
+ // a define of expected type occurs in the conditional expression
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Callback for expression evaluator.
+//-----------------------------------------------------------------------------
+bool CVPC::ResolveConditionalSymbol( const char *pSymbol )
+{
+ int offset = 0;
+
+ if ( !V_stricmp( pSymbol, "$0" ) || !V_stricmp( pSymbol, "0" ) )
+ {
+ return false;
+ }
+ else if ( !V_stricmp( pSymbol, "$1" ) || !V_stricmp( pSymbol, "1" ) )
+ {
+ return true;
+ }
+
+ if ( pSymbol[0] == '$' )
+ {
+ offset = 1;
+ }
+
+ conditional_t *pConditional = FindOrCreateConditional( (char*)pSymbol+offset, false, CONDITIONAL_NULL );
+ if ( pConditional )
+ {
+ // game conditionals only resolve true when they are 'defined' and 'active'
+ // only one game conditional is expected to be active at a time
+ if ( pConditional->type == CONDITIONAL_GAME )
+ {
+ if ( !pConditional->m_bDefined )
+ {
+ return false;
+ }
+
+ return pConditional->m_bGameConditionActive;
+ }
+
+ // all other type of conditions are gated by their 'defined' state
+ return pConditional->m_bDefined;
+ }
+
+ // unknown conditional, defaults to false
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Callback for expression evaluator.
+//-----------------------------------------------------------------------------
+static bool ResolveSymbol( const char *pSymbol )
+{
+ return g_pVPC->ResolveConditionalSymbol( pSymbol );
+}
+
+//-----------------------------------------------------------------------------
+// Callback for expression evaluator.
+//-----------------------------------------------------------------------------
+static void SymbolSyntaxError( const char *pReason )
+{
+ // invoke internal syntax error hndling which spews script stack as well
+ g_pVPC->VPCSyntaxError( pReason );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::EvaluateConditionalExpression( const char *pExpression )
+{
+ char conditionalBuffer[MAX_SYSTOKENCHARS];
+ ResolveMacrosInConditional( pExpression, conditionalBuffer, sizeof( conditionalBuffer ) );
+
+ if ( !conditionalBuffer[0] )
+ {
+ // empty string, same as not having a conditional
+ return true;
+ }
+
+ bool bResult = false;
+ CExpressionEvaluator ExpressionHandler;
+ bool bValid = ExpressionHandler.Evaluate( bResult, conditionalBuffer, ::ResolveSymbol, ::SymbolSyntaxError );
+ if ( !bValid )
+ {
+ g_pVPC->VPCSyntaxError( "VPC Conditional Evaluation Error" );
+ }
+
+ return bResult;
+}
diff --git a/external/vpc/utils/vpc/config_general.cpp b/external/vpc/utils/vpc/config_general.cpp
new file mode 100644
index 0000000..90fdaa7
--- /dev/null
+++ b/external/vpc/utils/vpc/config_general.cpp
@@ -0,0 +1,180 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+bool VPC_Config_General_AdditionalOutputFiles( const char *pPropertyName )
+{
+ // Ignore this. We only care about it when looking at dependencies,
+ // and baseprojectdatacollector will get it in that case.
+ char buff[MAX_SYSTOKENCHARS];
+ ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) );
+ return true;
+}
+
+bool VPC_Config_General_OutputDirectory( const char *pPropertyName )
+{
+ SET_STRING_PROPERTY( pPropertyName, g_spConfig, get_OutputDirectory, put_OutputDirectory );
+}
+
+bool VPC_Config_General_IntermediateDirectory( const char *pPropertyName )
+{
+ SET_STRING_PROPERTY( pPropertyName, g_spConfig, get_IntermediateDirectory, put_IntermediateDirectory );
+}
+
+bool VPC_Config_General_ExtensionsToDeleteOnClean( const char *pPropertyName )
+{
+ SET_STRING_PROPERTY( pPropertyName, g_spConfig, get_DeleteExtensionsOnClean, put_DeleteExtensionsOnClean );
+}
+
+bool VPC_Config_General_BuildLogFile( const char *pPropertyName )
+{
+ SET_STRING_PROPERTY( pPropertyName, g_spConfig, get_BuildLogFile, put_BuildLogFile );
+}
+
+bool VPC_Config_General_InheritedProjectPropertySheets( const char *pPropertyName )
+{
+ SET_STRING_PROPERTY( pPropertyName, g_spConfig, get_InheritedPropertySheets, put_InheritedPropertySheets );
+}
+
+bool VPC_Config_General_ConfigurationType( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+
+ if ( !ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ ConfigurationTypes option = typeUnknown;
+ if ( !V_stricmp( buff, "Utility" ) )
+ option = typeUnknown;
+ else if ( !V_stricmp( buff, "Application (.exe)" ) || !V_stricmp( buff, "Title (.xex)" ) )
+ option = typeApplication;
+ else if ( !V_stricmp( buff, "Dynamic Library (.dll)" ) || !V_stricmp( buff, "Dynamic Library (.xex)" ) )
+ option = typeDynamicLibrary;
+ else if ( !V_stricmp( buff, "Static Library (.lib)" ) )
+ option = typeStaticLibrary;
+ else
+ VPC_SyntaxError();
+
+ SET_LIST_PROPERTY( pPropertyName, g_spConfig, get_ConfigurationType, put_ConfigurationType, ConfigurationTypes, option );
+}
+
+bool VPC_Config_General_UseOfMFC( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+
+ if ( !ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ useOfMfc option = useMfcStdWin;
+ if ( !V_stricmp( buff, "Use Standard Windows Libraries" ) )
+ option = useMfcStdWin;
+ else if ( !V_stricmp( buff, "Use MFC in a Static Library" ) )
+ option = useMfcStatic;
+ else if ( !V_stricmp( buff, "Use MFC in a Shared DLL" ) )
+ option = useMfcDynamic;
+ else
+ VPC_SyntaxError();
+
+ SET_LIST_PROPERTY( pPropertyName, g_spConfig, get_useOfMfc, put_useOfMfc, useOfMfc, option );
+}
+
+bool VPC_Config_General_UseOfATL( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+
+ if ( !ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ useOfATL option = useATLNotSet;
+ if ( !V_stricmp( buff, "Not Using ATL" ) )
+ option = useATLNotSet;
+ else if ( !V_stricmp( buff, "Static Link to ATL" ) )
+ option = useATLStatic;
+ else if ( !V_stricmp( buff, "Dynamic Link to ATL" ) )
+ option = useATLDynamic;
+ else
+ VPC_SyntaxError();
+
+ SET_LIST_PROPERTY( pPropertyName, g_spConfig, get_useOfATL, put_useOfATL, useOfATL, option );
+}
+
+bool VPC_Config_General_MinimizeCRTUseInATL( const char *pPropertyName )
+{
+ SET_BOOL_PROPERTY( pPropertyName, g_spConfig, get_ATLMinimizesCRunTimeLibraryUsage, put_ATLMinimizesCRunTimeLibraryUsage );
+}
+
+bool VPC_Config_General_CharacterSet( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+
+ if ( !ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ charSet option = charSetNotSet;
+ if ( !V_stricmp( buff, "Not Set" ) )
+ option = charSetNotSet;
+ else if ( !V_stricmp( buff, "Use Unicode Character Set" ) )
+ option = charSetUnicode;
+ else if ( !V_stricmp( buff, "Use Multi-Byte Character Set" ) )
+ option = charSetMBCS;
+ else
+ VPC_SyntaxError();
+
+ SET_LIST_PROPERTY( pPropertyName, g_spConfig, get_CharacterSet, put_CharacterSet, charSet, option );
+}
+
+bool VPC_Config_General_CommonLanguageRuntimeSupport( const char *pPropertyName )
+{
+ VPC_Error( "Setting '%s' Not Implemented", pPropertyName );
+ return false;
+}
+
+bool VPC_Config_General_WholeProgramOptimization( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+
+ if ( !ParsePropertyValue( &g_pScriptData, g_pScriptLine, NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ WholeProgramOptimizationTypes option = WholeProgramOptimizationNone;
+ if ( !V_stricmp( buff, "No Whole Program Optimization" ) )
+ option = WholeProgramOptimizationNone;
+ else if ( !V_stricmp( buff, "Use Link Time Code Generation" ) )
+ option = WholeProgramOptimizationLinkTimeCodeGen;
+ else if ( !V_stricmp( buff, "Profile Guided Optimization - Instrument" ) )
+ option = WholeProgramOptimizationPGOInstrument;
+ else if ( !V_stricmp( buff, "Profile Guided Optimization - Optimize" ) )
+ option = WholeProgramOptimizationPGOOptimize;
+ else if ( !V_stricmp( buff, "Profile Guided Optimization - Update" ) )
+ option = WholeProgramOptimizationPGOUpdate;
+ else
+ VPC_SyntaxError();
+
+ SET_LIST_PROPERTY( pPropertyName, g_spConfig, get_WholeProgramOptimization, put_WholeProgramOptimization, WholeProgramOptimizationTypes, option );
+}
+
+extern bool VPC_Config_IgnoreOption( const char *pPropertyName );
+
+property_t g_generalProperties[] =
+{
+ {g_pOption_AdditionalProjectDependencies, VPC_Config_IgnoreOption },
+ {g_pOption_AdditionalOutputFiles, VPC_Config_IgnoreOption },
+ {"$GameOutputFile", VPC_Config_IgnoreOption },
+ {"$OutputDirectory", VPC_Config_General_OutputDirectory },
+ {"$IntermediateDirectory", VPC_Config_General_IntermediateDirectory},
+ {"$ExtensionsToDeleteOnClean", VPC_Config_General_ExtensionsToDeleteOnClean},
+ {"$BuildLogFile", VPC_Config_General_BuildLogFile},
+ {"$InheritedProjectPropertySheets", VPC_Config_General_InheritedProjectPropertySheets},
+ {"$ConfigurationType", VPC_Config_General_ConfigurationType},
+ {"$UseOfMFC", VPC_Config_General_UseOfMFC, PLATFORM_WINDOWS},
+ {"$UseOfATL", VPC_Config_General_UseOfATL, PLATFORM_WINDOWS},
+ {"$MinimizeCRTUseInATL", VPC_Config_General_MinimizeCRTUseInATL, PLATFORM_WINDOWS},
+ {"$CharacterSet", VPC_Config_General_CharacterSet},
+ {"$CommonLanguageRuntimeSupport", VPC_Config_General_CommonLanguageRuntimeSupport, PLATFORM_WINDOWS},
+ {"$WholeProgramOptimization", VPC_Config_General_WholeProgramOptimization},
+ {NULL}
+};
diff --git a/external/vpc/utils/vpc/configuration.cpp b/external/vpc/utils/vpc/configuration.cpp
new file mode 100644
index 0000000..c822f22
--- /dev/null
+++ b/external/vpc/utils/vpc/configuration.cpp
@@ -0,0 +1,487 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+static KeywordName_t s_KeywordNameTable[] =
+{
+ {"$General", KEYWORD_GENERAL},
+ {"$Debugging", KEYWORD_DEBUGGING},
+ {"$Compiler", KEYWORD_COMPILER},
+ {"$SNCCompiler", KEYWORD_PS3_SNCCOMPILER},
+ {"$GCCCompiler", KEYWORD_PS3_GCCCOMPILER},
+ {"$Librarian", KEYWORD_LIBRARIAN},
+ {"$Linker", KEYWORD_LINKER},
+ {"$SNCLinker", KEYWORD_PS3_SNCLINKER},
+ {"$GCCLinker", KEYWORD_PS3_GCCLINKER},
+ {"$ManifestTool", KEYWORD_MANIFEST},
+ {"$XMLDocumentGenerator", KEYWORD_XMLDOCGEN},
+ {"$BrowseInformation", KEYWORD_BROWSEINFO},
+ {"$Resources", KEYWORD_RESOURCES},
+ {"$PreBuildEvent", KEYWORD_PREBUILDEVENT},
+ {"$PreLinkEvent", KEYWORD_PRELINKEVENT},
+ {"$PostBuildEvent", KEYWORD_POSTBUILDEVENT},
+ {"$CustomBuildStep", KEYWORD_CUSTOMBUILDSTEP},
+ {"$Xbox360ImageConversion", KEYWORD_XBOXIMAGE},
+ {"$ConsoleDeployment", KEYWORD_XBOXDEPLOYMENT},
+};
+
+const char *CVPC::KeywordToName( configKeyword_e keyword )
+{
+ COMPILE_TIME_ASSERT( ARRAYSIZE( s_KeywordNameTable ) == KEYWORD_MAX );
+
+ if ( keyword == KEYWORD_UNKNOWN )
+ {
+ return "???";
+ }
+
+ return s_KeywordNameTable[keyword].m_pName;
+}
+
+configKeyword_e CVPC::NameToKeyword( const char *pKeywordName )
+{
+ COMPILE_TIME_ASSERT( ARRAYSIZE( s_KeywordNameTable ) == KEYWORD_MAX );
+
+ for ( int i = 0; i < ARRAYSIZE( s_KeywordNameTable ); i++ )
+ {
+ if ( !V_stricmp( pKeywordName, s_KeywordNameTable[i].m_pName ) )
+ {
+ return s_KeywordNameTable[i].m_Keyword;
+ }
+ }
+
+ return KEYWORD_UNKNOWN;
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Config_Keyword
+//
+//-----------------------------------------------------------------------------
+void VPC_Config_Keyword( configKeyword_e keyword, const char *pkeywordToken )
+{
+ const char *pToken;
+
+ bool bShouldSkip = false;
+ if ( !g_pVPC->GetProjectGenerator()->StartPropertySection( keyword, &bShouldSkip ) )
+ {
+ g_pVPC->VPCSyntaxError( "Unsupported Keyword: %s for target platform", pkeywordToken );
+ }
+
+ if ( bShouldSkip )
+ {
+ pToken = g_pVPC->GetScript().PeekNextToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ g_pVPC->GetScript().SkipBracedSection();
+ }
+ else
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+
+ // Copy off the token name so HandleProperty() doesn't have to (or else the parser will overwrite it on the next token).
+ char tempTokenName[MAX_PATH];
+ V_strncpy( tempTokenName, pToken, sizeof( tempTokenName ) );
+
+ g_pVPC->GetProjectGenerator()->HandleProperty( tempTokenName );
+ }
+ }
+
+ g_pVPC->GetProjectGenerator()->EndPropertySection( keyword );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Configuration
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_Configuration()
+{
+ const char *pToken;
+ char szConfigName[MAX_PATH];
+ bool bAllowNextLine = false;
+ int i;
+ CUtlVector<CUtlString> configs;
+ char buff[MAX_SYSTOKENCHARS];
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ int index = configs.AddToTail();
+ configs[index] = pToken;
+
+ // check for another optional config
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] || !V_stricmp( pToken, "{" ) || !V_stricmp( pToken, "}" ) || (pToken[0] == '$') )
+ break;
+ }
+
+ // no configuration specified, use all known
+ if ( !configs.Count() )
+ {
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configs );
+ if ( !configs.Count() )
+ {
+ g_pVPC->VPCError( "Trying to parse a configuration block and no configs have been defined yet.\n[%s line:%d]", g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
+ }
+ }
+
+ // save parser state
+ CScriptSource scriptSource = g_pVPC->GetScript().GetCurrentScript();
+
+ for ( i=0; i<configs.Count(); i++ )
+ {
+ // restore parser state
+ g_pVPC->GetScript().RestoreScript( scriptSource );
+
+ V_strncpy( szConfigName, configs[i].String(), sizeof( szConfigName ) );
+
+ // get access objects
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( szConfigName, false );
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ while ( 1 )
+ {
+ g_pVPC->GetScript().SkipToValidToken();
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ continue;
+ }
+
+ if ( !V_stricmp( buff, "}" ) )
+ {
+ // end of section
+ break;
+ }
+
+ configKeyword_e keyword = g_pVPC->NameToKeyword( buff );
+ if ( keyword == KEYWORD_UNKNOWN )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ else
+ {
+ VPC_Config_Keyword( keyword, buff );
+ }
+ }
+
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_FileConfiguration
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_FileConfiguration()
+{
+ const char *pToken;
+ char szConfigName[MAX_PATH];
+ bool bAllowNextLine = false;
+ char buff[MAX_SYSTOKENCHARS];
+ CUtlVector< CUtlString > configurationNames;
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ strcpy( szConfigName, pToken );
+ configurationNames.AddToTail( pToken );
+
+ // check for another optional config
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] || !V_stricmp( pToken, "{" ) || !V_stricmp( pToken, "}" ) || (pToken[0] == '$') )
+ break;
+ }
+
+ // no configuration specified, use all known
+ if ( configurationNames.Count() == 0 )
+ {
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ }
+
+ // save parser state
+ CScriptSource scriptSource = g_pVPC->GetScript().GetCurrentScript();
+
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ // restore parser state
+ g_pVPC->GetScript().RestoreScript( scriptSource );
+
+ // Tell the generator we're about to feed it configuration data for this file.
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ while ( 1 )
+ {
+ g_pVPC->GetScript().SkipToValidToken();
+
+ pToken = g_pVPC->GetScript().PeekNextToken( true );
+ if ( pToken && pToken[0] && !V_stricmp( pToken, "$ExcludedFromBuild" ) )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ char buff[MAX_SYSTOKENCHARS];
+ if ( g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ {
+ g_pVPC->GetProjectGenerator()->FileExcludedFromBuild( Sys_StringToBool( buff ) );
+ }
+
+ continue;
+ }
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ continue;
+ }
+
+ if ( !V_stricmp( buff, "}" ) )
+ {
+ // end of section
+ break;
+ }
+
+ configKeyword_e keyword = g_pVPC->NameToKeyword( buff );
+ switch ( keyword )
+ {
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ case KEYWORD_RESOURCES:
+ case KEYWORD_CUSTOMBUILDSTEP:
+ VPC_Config_Keyword( keyword, buff );
+ break;
+ default:
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Just advances past config keywords without acting on them
+//
+//-----------------------------------------------------------------------------
+void VPC_Read_Config_Keywords( const char *pkeywordToken )
+{
+ const char *pToken;
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Read a configuration block that applies to an entire folder
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_FolderConfiguration( folderConfig_t *pFolderConfig )
+{
+ pFolderConfig->Clear();
+
+ const char *pToken;
+ char szConfigName[MAX_PATH];
+ bool bAllowNextLine = false;
+ char buff[MAX_SYSTOKENCHARS];
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ strcpy( szConfigName, pToken );
+ pFolderConfig->vecConfigurationNames.AddToTail( pToken );
+
+ // check for another optional config
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] || !V_stricmp( pToken, "{" ) || !V_stricmp( pToken, "}" ) || ( pToken[0] == '$' ) )
+ break;
+ }
+
+ // no configuration specified, use all known
+ if ( pFolderConfig->vecConfigurationNames.Count() == 0 )
+ {
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( pFolderConfig->vecConfigurationNames );
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ // save parser state so we remember where the block is. We'll refer back to it when handlign individual files.
+ pFolderConfig->scriptSource = g_pVPC->GetScript().GetCurrentScript();
+
+ // just read past all the tokens. We'll reparse this later, per file.
+ // it would be cool to parse just once, but leaf code in the project generator expects the parser to be in the right position and parses directly.
+ while ( 1 )
+ {
+ g_pVPC->GetScript().SkipToValidToken();
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ continue;
+ }
+
+ if ( !V_stricmp( buff, "}" ) )
+ {
+ // end of section
+ break;
+ }
+
+ configKeyword_e keyword = g_pVPC->NameToKeyword( buff );
+ switch ( keyword )
+ {
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ case KEYWORD_RESOURCES:
+ case KEYWORD_CUSTOMBUILDSTEP:
+ {
+ VPC_Read_Config_Keywords( buff );
+ }
+ break;
+ default:
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Apply a folder-wide configuration to an individual file
+//
+//-----------------------------------------------------------------------------
+void VPC_ApplyFolderConfigurationToFile( const folderConfig_t &folderConfig )
+{
+ char buff[MAX_SYSTOKENCHARS];
+ g_pVPC->GetScript().PushCurrentScript();
+
+ for ( int i = 0; i < folderConfig.vecConfigurationNames.Count(); i++ )
+ {
+ g_pVPC->GetScript().RestoreScript( folderConfig.scriptSource );
+
+ // Tell the generator we're about to feed it configuration data for this file.
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( folderConfig.vecConfigurationNames[i].String(), true );
+
+ while ( 1 )
+ {
+ g_pVPC->GetScript().SkipToValidToken();
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ continue;
+ }
+
+ if ( !V_stricmp( buff, "}" ) )
+ {
+ // end of section
+ break;
+ }
+
+ configKeyword_e keyword = g_pVPC->NameToKeyword( buff );
+ switch ( keyword )
+ {
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ case KEYWORD_RESOURCES:
+ case KEYWORD_CUSTOMBUILDSTEP:
+ VPC_Config_Keyword( keyword, buff );
+ break;
+ default:
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+
+ g_pVPC->GetScript().PopScript();
+} \ No newline at end of file
diff --git a/external/vpc/utils/vpc/dependencies.cpp b/external/vpc/utils/vpc/dependencies.cpp
new file mode 100644
index 0000000..b198741
--- /dev/null
+++ b/external/vpc/utils/vpc/dependencies.cpp
@@ -0,0 +1,1133 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "dependencies.h"
+#include "baseprojectdatacollector.h"
+#include "tier0/fasttimer.h"
+
+
+#define VPC_CRC_CACHE_VERSION 3
+
+extern char *g_IncludeSeparators[2];
+
+static const char *g_pDependencyRelevantProperties[] =
+{
+ g_pOption_AdditionalProjectDependencies,
+ g_pOption_AdditionalOutputFiles,
+ g_pOption_AdditionalIncludeDirectories,
+ g_pOption_GameOutputFile,
+ g_pOption_ImportLibrary,
+ g_pOption_OutputFile,
+};
+
+static CRelevantPropertyNames g_DependencyRelevantPropertyNames =
+{
+ g_pDependencyRelevantProperties,
+ V_ARRAYSIZE( g_pDependencyRelevantProperties )
+};
+
+
+bool IsSharedLibraryFile( const char *pFilename )
+{
+ const char *pExt = V_GetFileExtension( pFilename );
+ if ( pExt && ( V_stricmp( pExt, "so" ) == 0 || V_stricmp( pExt, "dylib" ) == 0 || V_stricmp( pExt, "dll" ) == 0 ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool IsLibraryFile( const char *pFilename )
+{
+ const char *pExt = V_GetFileExtension( pFilename );
+ if ( IsSharedLibraryFile( pFilename ) || ( pExt && ( V_stricmp( pExt, "lib" ) == 0 || V_stricmp( pExt, "a" ) == 0 ) ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static inline bool IsSourceFile( const char *pFilename )
+{
+ const char *pExt = V_GetFileExtension( pFilename );
+
+ if ( pExt && ( IsCFileExtension( pExt ) || IsHFileExtension( pExt ) ||
+ !V_stricmp( pExt, "rc" ) || !V_stricmp( pExt, "inc" ) ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+
+// ------------------------------------------------------------------------------------------------------- //
+// CDependency functions.
+// ------------------------------------------------------------------------------------------------------- //
+
+CDependency::CDependency( CProjectDependencyGraph *pDependencyGraph ) :
+ m_pDependencyGraph( pDependencyGraph )
+{
+ m_iDependencyMark = m_pDependencyGraph->m_iDependencyMark - 1;
+ m_bCheckedIncludes = false;
+ m_nCacheModificationTime = m_nCacheFileSize = 0;
+}
+
+CDependency::~CDependency()
+{
+}
+
+const char* CDependency::GetName() const
+{
+ return m_Filename.String();
+}
+
+bool CDependency::CompareAbsoluteFilename( const char *pAbsPath ) const
+{
+ return ( V_stricmp( m_Filename.String(), pAbsPath ) == 0 );
+}
+
+bool CDependency::DependsOn( CDependency *pTest, int flags )
+{
+ m_pDependencyGraph->ClearAllDependencyMarks();
+ CUtlVector<CUtlBuffer> callTreeOutputStack;
+ if ( FindDependency_Internal( callTreeOutputStack, pTest, flags, 1 ) )
+ {
+ if ( g_pVPC->IsShowDependencies() )
+ {
+ printf( "-------------------------------------------------------------------------------\n" );
+ printf( "%s\n", GetName() );
+ int i;
+ for( i = callTreeOutputStack.Count() - 1; i >= 0; i-- )
+ {
+ printf( ( const char * )callTreeOutputStack[i].Base() );
+ }
+ printf( "-------------------------------------------------------------------------------\n" );
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool CDependency::FindDependency_Internal( CUtlVector<CUtlBuffer> &callTreeOutputStack, CDependency *pTest, int flags, int depth )
+{
+ if ( pTest == this )
+ return true;
+
+ // Don't revisit us.
+ if ( HasBeenMarked() )
+ return false;
+
+ Mark();
+
+ // Don't recurse further?
+ if ( depth > 1 && !(flags & k_EDependsOnFlagRecurse) )
+ return false;
+
+ // Don't go into the children of libs if they don't want.
+ if ( !(flags & k_EDependsOnFlagTraversePastLibs) && m_Type == k_eDependencyType_Library )
+ return false;
+
+ // Go through everything I depend on. If any of those things
+ for ( int iDepList=0; iDepList < 2; iDepList++ )
+ {
+ if ( iDepList == 1 && !(flags & k_EDependsOnFlagCheckAdditionalDependencies) )
+ continue;
+
+ CUtlVector<CDependency*> &depList = (iDepList == 0 ? m_Dependencies : m_AdditionalDependencies);
+
+ for ( int i=0; i < depList.Count(); i++ )
+ {
+ CDependency *pChild = depList[i];
+ if ( pChild->FindDependency_Internal( callTreeOutputStack, pTest, flags, depth+1 ) )
+ {
+ if ( g_pVPC->IsShowDependencies() )
+ {
+ char buf[2048];
+ V_strncpy( buf, "depends on ", sizeof( buf ) );
+ V_strcat( buf, pChild->GetName(), sizeof( buf ) );
+ V_strcat( buf, "\n", sizeof( buf ) );
+ int n = callTreeOutputStack.AddToTail();
+ CUtlBuffer &b = callTreeOutputStack[n];
+ b.EnsureCapacity( V_strlen( buf ) + 2 );
+ b.PutString( buf );
+ b.PutChar( 0 );
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void CDependency::Mark()
+{
+ m_iDependencyMark = m_pDependencyGraph->m_iDependencyMark;
+}
+
+bool CDependency::HasBeenMarked()
+{
+ return m_iDependencyMark == m_pDependencyGraph->m_iDependencyMark;
+}
+
+
+CDependency_Project::CDependency_Project( CProjectDependencyGraph *pDependencyGraph )
+ : CDependency( pDependencyGraph )
+{
+ m_iProjectIndex = -1;
+}
+
+
+void CDependency_Project::StoreProjectParameters( const char *szScriptName )
+{
+ m_StoredOutputFilename = g_pVPC->GetOutputFilename();
+ V_GetCurrentDirectory( m_szStoredCurrentDirectory, sizeof( m_szStoredCurrentDirectory ) );
+ V_strncpy( m_szStoredScriptName, szScriptName, sizeof( m_szStoredScriptName ) );
+ m_StoredConditionalsActive.SetSize( g_pVPC->m_Conditionals.Count() );
+
+ for ( int iConditional=0; iConditional < g_pVPC->m_Conditionals.Count(); iConditional++ )
+ {
+ m_StoredConditionalsActive[iConditional] = g_pVPC->m_Conditionals[iConditional].m_bGameConditionActive;
+ }
+}
+
+
+void CDependency_Project::ExportProjectParameters()
+{
+ g_pVPC->SetOutputFilename( m_StoredOutputFilename.Get() );
+ V_SetCurrentDirectory( m_szStoredCurrentDirectory );
+
+ if ( m_StoredConditionalsActive.Count() > g_pVPC->m_Conditionals.Count() )
+ {
+ g_pVPC->VPCError( "ExportProjectParameters( %s ) - too many defines stored.", m_szStoredScriptName );
+ }
+
+ for ( int iConditional=0; iConditional < g_pVPC->m_Conditionals.Count(); iConditional++ )
+ {
+ g_pVPC->m_Conditionals[iConditional].m_bGameConditionActive = m_StoredConditionalsActive[iConditional];
+ }
+}
+
+int CDependency_Project::FindByProjectName( CUtlVector<CDependency_Project*> &projects, const char *pTestName )
+{
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pProject = projects[i];
+
+ if ( V_stricmp( pProject->m_ProjectName.String(), pTestName ) == 0 )
+ return i;
+ }
+
+ return -1;
+}
+
+
+// This is responsible for scanning a project file and pulling out:
+// - a list of libraries it uses
+// - the $AdditionalIncludeDirectories paths
+// - a list of source files it uses
+// - the name of the file it generates
+class CSingleProjectScanner : public CBaseProjectDataCollector
+{
+public:
+ typedef CBaseProjectDataCollector BaseClass;
+
+ CSingleProjectScanner() : CBaseProjectDataCollector( &g_DependencyRelevantPropertyNames )
+ {
+ m_bInLinker = false;
+ }
+
+ virtual void EndProject()
+ {
+ }
+
+ void ScanProjectFile( CProjectDependencyGraph *pGraph, const char *szScriptName, CDependency_Project *pProject )
+ {
+ // Someday we'll pass this interface down into VPC_ParseProjectScript instead of using the global.
+ IBaseProjectGenerator *pOldGenerator = g_pVPC->GetProjectGenerator();
+ g_pVPC->SetProjectGenerator( this );
+
+ // This has VPC parse the script and CBaseProjectDataCollector collects all the data into lists of the
+ // stuff we care about like source files and include paths.
+ m_ScriptName = szScriptName;
+ g_pVPC->ParseProjectScript( szScriptName, 0, true, false );
+
+ int iConfig = m_BaseConfigData.m_Configurations.First();
+ if ( iConfig != m_BaseConfigData.m_Configurations.InvalidIndex() )
+ {
+ CSpecificConfig *pConfig = m_BaseConfigData.m_Configurations[iConfig];
+
+ SetupIncludeDirectories( pConfig, szScriptName );
+ SetupFilesList( pGraph, pProject );
+ SetupImportLibrary( pGraph, pConfig, szScriptName );
+ SetupAdditionalProjectDependencies( pProject, pConfig );
+ SetupAdditionalOutputFiles( pProject, pConfig );
+
+ }
+
+ g_pVPC->SetProjectGenerator( pOldGenerator );
+ Term();
+ }
+
+ void SetupFilesList( CProjectDependencyGraph *pGraph, CDependency_Project *pProject )
+ {
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next( i ) )
+ {
+ CFileConfig *pFile = m_Files[i];
+
+ // If this file is excluded from all configs, then exclude it.
+ if ( pFile->m_Configurations.Count() > 0 )
+ {
+ int nExcluded = 0;
+ for ( int iSpecific=pFile->m_Configurations.First(); iSpecific != pFile->m_Configurations.InvalidIndex(); iSpecific=pFile->m_Configurations.Next( iSpecific ) )
+ {
+ CSpecificConfig *pTest = pFile->m_Configurations[iSpecific];
+ if ( pTest->m_bFileExcluded && !pTest->m_bIsSchema )
+ ++nExcluded;
+ }
+ if ( nExcluded == (int)m_BaseConfigData.m_Configurations.Count() )
+ continue;
+ }
+
+
+ // Make this an absolute path.
+ const char *pFilename = pFile->GetName();
+ char sAbsolutePath[MAX_PATH];
+ V_MakeAbsolutePath( sAbsolutePath, sizeof( sAbsolutePath ), pFilename );
+
+ // Don't bother with source files if we're not building the full dependency set.
+ if ( !pGraph->m_bFullDependencySet )
+ if ( IsSourceFile( sAbsolutePath ) )
+ continue;
+
+ // For source files, don't bother with files that don't exist. If we do create entries
+ // for files that don't exist, then they'll have a "cache file size"
+ if ( !Sys_Exists( sAbsolutePath ) && IsSourceFile( sAbsolutePath ) )
+ continue;
+
+ // Add an entry for this file.
+ CDependency *pDep = pGraph->FindOrCreateDependency( sAbsolutePath );
+ pProject->m_Dependencies.AddToTail( pDep );
+
+ // Add includes.
+ if ( pDep->m_Type == k_eDependencyType_SourceFile )
+ AddIncludesForFile( pGraph, pDep );
+ }
+ }
+
+ void AddIncludesForFile( CProjectDependencyGraph *pGraph, CDependency *pFile )
+ {
+ // Have we already parsed this file for its includes?
+ if ( pFile->m_bCheckedIncludes )
+ return;
+
+ pFile->m_bCheckedIncludes = true;
+
+ // Setup all the include paths we want to search.
+ CUtlVector<CUtlString> includeDirs;
+ char szDir[MAX_PATH];
+ if ( !V_ExtractFilePath( pFile->GetName(), szDir, sizeof( szDir ) ) )
+ g_pVPC->VPCError( "AddIncludesForFile: V_ExtractFilePath( %s ) failed.", pFile->GetName() );
+
+ includeDirs.AddToTail( szDir );
+ includeDirs.AddMultipleToTail( m_IncludeDirectories.Count(), m_IncludeDirectories.Base() );
+
+ // Get all the #include directives.
+ CUtlVector<CUtlString> includes;
+ GetIncludeFiles( pFile->GetName(), includes );
+ ++pGraph->m_nFilesParsedForIncludes;
+
+ // Now see which of them we can open.
+ for ( int iIncludeFile=0; iIncludeFile < includes.Count(); iIncludeFile++ )
+ {
+ for ( int iIncludeDir=0; iIncludeDir < includeDirs.Count(); iIncludeDir++ )
+ {
+ char szFullName[MAX_PATH];
+ V_ComposeFileName( includeDirs[iIncludeDir].String(), includes[iIncludeFile].String(), szFullName, sizeof( szFullName ) );
+
+ CDependency *pIncludeFile = pGraph->FindDependency( szFullName );
+ if ( !pIncludeFile )
+ {
+ if ( !Sys_Exists( szFullName ) )
+ continue;
+
+ // Find or add the dependency.
+ pIncludeFile = pGraph->FindOrCreateDependency( szFullName );
+ }
+ pFile->m_Dependencies.AddToTail( pIncludeFile );
+
+ // Recurse.
+ AddIncludesForFile( pGraph, pIncludeFile );
+ }
+ }
+ }
+
+ bool SeekToIncludeStart( const char* &pSearchPos )
+ {
+ while ( 1 )
+ {
+ ++pSearchPos;
+ if ( *pSearchPos == 0 || *pSearchPos == '\r' || *pSearchPos == '\n' )
+ return false;
+
+ if ( *pSearchPos == '\"' || *pSearchPos == '<' )
+ {
+ ++pSearchPos;
+ return true;
+ }
+ }
+ }
+
+ bool SeekToIncludeEnd( const char* &pSearchPos )
+ {
+ while ( 1 )
+ {
+ ++pSearchPos;
+ if ( *pSearchPos == 0 || *pSearchPos == '\r' || *pSearchPos == '\n' )
+ return false;
+
+ if ( *pSearchPos == '\"' || *pSearchPos == '>' )
+ return true;
+ }
+ }
+
+ void GetIncludeFiles( const char *pFilename, CUtlVector<CUtlString> &includes )
+ {
+ char *pFileData;
+ int ret = Sys_LoadFile( pFilename, (void**)&pFileData, false );
+ if ( ret == -1 )
+ {
+ if ( g_pVPC->IsVerbose() )
+ {
+ g_pVPC->VPCWarning( "GetIncludeFiles( %s ) - can't open file (included by project %s).", pFilename, m_ScriptName.String() );
+ }
+ return;
+ }
+
+ const char *pSearchPos = pFileData;
+ while ( 1 )
+ {
+ const char *pLookFor = "#include";
+ const char *pIncludeStatement = V_strstr( pSearchPos, pLookFor );
+ if ( !pIncludeStatement )
+ break;
+
+ pSearchPos = pIncludeStatement + V_strlen( pLookFor );
+
+ if ( !SeekToIncludeStart( pSearchPos ) )
+ continue;
+ const char *pFilenameStart = pSearchPos;
+
+ if ( !SeekToIncludeEnd( pSearchPos ) )
+ continue;
+ const char *pFilenameEnd = pSearchPos;
+
+ if ( (pFilenameEnd - pFilenameStart) > MAX_PATH-10 )
+ g_pVPC->VPCError( "Include statement too long in %s.", pFilename );
+
+ char szIncludeFilename[MAX_PATH], szFixed[MAX_PATH];
+ V_strncpy( szIncludeFilename, pFilenameStart, pFilenameEnd - pFilenameStart + 1 );
+
+ // Fixup double slashes.
+ V_StrSubst( szIncludeFilename, "\\\\", "\\", szFixed, sizeof( szFixed ) );
+ V_FixSlashes( szFixed );
+
+ includes.AddToTail( szFixed );
+ }
+
+ free( pFileData );
+ }
+
+ void SetupIncludeDirectories( CSpecificConfig *pConfig, const char *szScriptName )
+ {
+ if ( m_BaseConfigData.m_Configurations.Count() == 0 )
+ g_pVPC->VPCError( "No configurations for %s in project %s.", szScriptName, m_ScriptName.String() );
+
+ const char *pIncludes = pConfig->m_pKV->GetString( g_pOption_AdditionalIncludeDirectories, "" );
+ CSplitString relativeIncludeDirs( pIncludes, (const char**)g_IncludeSeparators, V_ARRAYSIZE( g_IncludeSeparators ) );
+
+ for ( int i=0; i < relativeIncludeDirs.Count(); i++ )
+ {
+ char sAbsolute[MAX_PATH];
+ V_MakeAbsolutePath( sAbsolute, sizeof( sAbsolute ), relativeIncludeDirs[i] );
+ m_IncludeDirectories.AddToTail( sAbsolute );
+ }
+ }
+
+ void SetupImportLibrary( CProjectDependencyGraph *pGraph, CSpecificConfig *pConfig, const char *szScriptName )
+ {
+ m_ImportLibrary = pConfig->m_pKV->GetString( g_pOption_ImportLibrary, NULL );
+ // XXX(JohnS): For projects that define a separate "GameOutputFile" step, that is the final product. This was
+ // kind of hackily added originally -- the $OutputFile directive was relative to the base directory,
+ // but some generators (XCode) put all their outputs into a object directory, then use
+ // $GameOutputFile to *actually* output.
+ m_LinkerOutputFile = pConfig->m_pKV->GetString( g_pOption_GameOutputFile, NULL );
+ if ( !m_LinkerOutputFile.Length() )
+ {
+ m_LinkerOutputFile = pConfig->m_pKV->GetString( g_pOption_OutputFile, NULL );
+ }
+ }
+
+ void SetupAdditionalProjectDependencies( CDependency_Project *pProject, CSpecificConfig *pConfig )
+ {
+ const char *pVal = pConfig->m_pKV->GetString( g_pOption_AdditionalProjectDependencies );
+ if ( pVal )
+ {
+ pProject->m_AdditionalProjectDependencies.Purge();
+
+ CSplitString outStrings ( pVal, ";" );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ char szProjectName[MAX_PATH];
+ sprintf( szProjectName, "%s", outStrings[i] );
+
+ if ( g_pVPC->IsDecorateProject() )
+ {
+ g_pVPC->DecorateProjectName( szProjectName );
+ }
+ pProject->m_AdditionalProjectDependencies.AddToTail( szProjectName );
+ }
+ }
+ }
+
+ void SetupAdditionalOutputFiles( CDependency_Project *pProject, CSpecificConfig *pConfig )
+ {
+ const char *pVal = pConfig->m_pKV->GetString( g_pOption_AdditionalOutputFiles );
+ if ( pVal )
+ {
+ pProject->m_AdditionalOutputFiles.Purge();
+
+ CSplitString outStrings( pVal, ";" );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ pProject->m_AdditionalOutputFiles.AddToTail( outStrings[i] );
+ }
+ }
+ }
+
+ virtual const char* GetProjectFileExtension()
+ {
+ return "UNUSED";
+ }
+
+protected:
+
+ virtual bool StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip )
+ {
+ m_bInLinker = ( keyword == KEYWORD_LINKER || keyword == KEYWORD_LIBRARIAN );
+ return true;
+ }
+
+ virtual void HandleProperty( const char *pProperty, const char *pCustomScriptData )
+ {
+ // We don't want the $OutputFile property from the $BrowseInformation section.
+ if ( V_stricmp( pProperty, g_pOption_OutputFile ) == 0 && !m_bInLinker )
+ return;
+
+ BaseClass::HandleProperty( pProperty, pCustomScriptData );
+ }
+
+ virtual void EndPropertySection( configKeyword_e keyword )
+ {
+ m_bInLinker = false;
+ }
+
+public:
+ // Project include directories. These strings are deleted when the object goes away.
+ CUtlVector<CUtlString> m_IncludeDirectories;
+ CUtlString m_ImportLibrary;
+ CUtlString m_LinkerOutputFile;
+ CUtlString m_ScriptName;
+ bool m_bInLinker;
+};
+
+
+CProjectDependencyGraph::CProjectDependencyGraph()
+{
+ m_iDependencyMark = 0;
+ m_bFullDependencySet = false;
+ m_bHasGeneratedDependencies = false;
+}
+
+
+void CProjectDependencyGraph::BuildProjectDependencies( int nBuildProjectDepsFlags, CUtlVector< CDependency_Project *> *pPhase1Projects )
+{
+ m_bFullDependencySet = ( ( nBuildProjectDepsFlags & BUILDPROJDEPS_FULL_DEPENDENCY_SET ) != 0 );
+ m_nFilesParsedForIncludes = 0;
+
+ if ( m_bFullDependencySet )
+ {
+ Log_Msg( LOG_VPC, "\nBuilding full dependency set (all sources and headers)..." );
+ }
+ else
+ {
+ Log_Msg( LOG_VPC, "\nBuilding partial dependency set (libs only)..." );
+ }
+
+ // Have it iterate ALL projects in the list, with whatever platform conditionals are around.
+ // When it visits a
+ CUtlVector<projectIndex_t> projectList;
+ CUtlVector<int> oldState;
+
+ if ( nBuildProjectDepsFlags & BUILDPROJDEPS_CHECK_ALL_PROJECTS )
+ {
+ // So iterate all projects.
+ projectList.SetSize( g_pVPC->m_Projects.Count() );
+ for ( int i=0; i < g_pVPC->m_Projects.Count(); i++ )
+ projectList[i] = i;
+
+ // Simulate /allgames but remember the old state too.
+ for ( int j=0; j<g_pVPC->m_Conditionals.Count(); j++ )
+ {
+ if ( g_pVPC->m_Conditionals[j].type == CONDITIONAL_GAME )
+ {
+ oldState.AddToTail( (j << 16) + (int)g_pVPC->m_Conditionals[j].m_bDefined );
+ g_pVPC->m_Conditionals[j].m_bDefined = true;
+ }
+ }
+ }
+ else
+ {
+ projectList.AddMultipleToTail( g_pVPC->m_TargetProjects.Count(), g_pVPC->m_TargetProjects.Base() );
+ }
+
+ // Load any prior results so we don't have to regenerate the whole cache (which can take a couple minutes).
+ char sCacheFile[MAX_PATH] = {0};
+ V_ComposeFileName( g_pVPC->GetSourcePath(), "vpc.cache", sCacheFile, sizeof( sCacheFile ) );
+ if ( m_bFullDependencySet )
+ {
+ if ( !LoadCache( sCacheFile ) )
+ {
+ Log_Msg( LOG_VPC, "\n\nNo vpc.cache file found.\nThis will take a minute to generate dependency info from all the sources.\nPut the kleenex down.\nNext time it will have a cache file and be fast.\n\n" );
+ }
+ }
+
+ CFastTimer timer;
+ timer.Start();
+ g_pVPC->IterateTargetProjects( projectList, this );
+ timer.End();
+
+ ResolveAdditionalProjectDependencies( pPhase1Projects );
+
+ // Restore the old game defines state?
+ if ( nBuildProjectDepsFlags & BUILDPROJDEPS_CHECK_ALL_PROJECTS )
+ {
+ for ( int i=0; i < oldState.Count(); i++ )
+ {
+ int iDefine = oldState[i] >> 16;
+ g_pVPC->m_Conditionals[iDefine].m_bDefined = ( (oldState[i] & 1) != 0 );
+ }
+ }
+
+ // Save the expensive work we did into a cache file so it can be used next time.
+ if ( m_bFullDependencySet )
+ {
+ SaveCache( sCacheFile );
+ }
+
+ Log_Msg( LOG_VPC, "\n\n" );
+ if ( m_nFilesParsedForIncludes > 0 )
+ {
+ Log_Msg( LOG_VPC, "%d files parsed in %.2f seconds for #includes.\n", m_nFilesParsedForIncludes, timer.GetDuration().GetSeconds() );
+ }
+
+ m_bHasGeneratedDependencies = true;
+}
+
+void CProjectDependencyGraph::ResolveAdditionalProjectDependencies( CUtlVector< CDependency_Project *> *pPhase1Projects )
+{
+ for ( int iMainProject=0; iMainProject < m_Projects.Count(); iMainProject++ )
+ {
+ CDependency_Project *pMainProject = m_Projects[iMainProject];
+
+ for ( int i=0; i < pMainProject->m_AdditionalProjectDependencies.Count(); i++ )
+ {
+ const char *pLookingFor = pMainProject->m_AdditionalProjectDependencies[i].String();
+
+ // Look for this project name among all the projects.
+ int j;
+ for ( j=0; j < m_Projects.Count(); j++ )
+ {
+ if ( V_stricmp( m_Projects[j]->m_ProjectName.String(), pLookingFor ) == 0 )
+ break;
+ }
+
+ if ( j == m_Projects.Count() )
+ {
+ //VPCError( "Project %s lists '%s' in its $AdditionalProjectDependencies, but there is no project by that name.", pMainProject->GetName(), pLookingFor );
+ continue;
+ }
+
+ if ( pMainProject->m_AdditionalDependencies.Find( m_Projects[j] ) == pMainProject->m_AdditionalDependencies.InvalidIndex() )
+ pMainProject->m_AdditionalDependencies.AddToTail( m_Projects[j] );
+ }
+
+
+ if ( pPhase1Projects != NULL )
+ {
+ //
+ // See if there's a project in phase 1 built from the same VPC, and, if so, add it as a dependency.
+ // This prevents a bunch of race conditions when projects are built in a distributed fashion
+ // (ala Incredibuild) and the projects step on each other.
+ //
+ const char *pFileName = pMainProject->m_Filename.String();
+
+ int j;
+ for ( j = 0; j < pPhase1Projects->Count(); j++ )
+ {
+ if ( V_stricmp( (*pPhase1Projects)[j]->m_Filename.String(), pFileName ) == 0)
+ {
+ break;
+ }
+ }
+ if ( j == pPhase1Projects->Count() )
+ {
+ continue;
+ }
+
+ if ( pMainProject->m_AdditionalDependencies.Find( (*pPhase1Projects)[j] ) == pMainProject->m_AdditionalDependencies.InvalidIndex() )
+ {
+ pMainProject->m_AdditionalDependencies.AddToTail( (*pPhase1Projects)[j] );
+ }
+ }
+ }
+}
+
+bool CProjectDependencyGraph::HasGeneratedDependencies() const
+{
+ return m_bHasGeneratedDependencies;
+}
+
+bool CProjectDependencyGraph::VisitProject( projectIndex_t iProject, const char *szProjectName )
+{
+ // Read in the project.
+ if ( !Sys_Exists( szProjectName ) )
+ {
+ return false;
+ }
+
+ // Add another dot for the pacifier.
+ Log_Msg( LOG_VPC, "." );
+
+ // Add this project.
+ CDependency_Project *pProject = new CDependency_Project( this );
+
+ char szAbsolute[MAX_PATH];
+ V_MakeAbsolutePath( szAbsolute, sizeof( szAbsolute ), szProjectName );
+ pProject->m_Filename = szAbsolute;
+
+ pProject->m_Type = k_eDependencyType_Project;
+ pProject->m_iProjectIndex = iProject;
+ m_Projects.AddToTail( pProject );
+ m_AllFiles.Insert( szAbsolute, pProject );
+
+ // Remember various parameters passed to us so we can regenerate this project without having
+ // to call VPC_IterateTargetProjects.
+ pProject->StoreProjectParameters( szProjectName );
+
+ char sAbsProjectFilename[MAX_PATH];
+ V_MakeAbsolutePath( sAbsProjectFilename, sizeof( sAbsProjectFilename ), g_pVPC->GetOutputFilename() );
+ pProject->m_ProjectFilename = sAbsProjectFilename;
+
+ // Scan the project file and get all its libs, cpp, and h files.
+ CSingleProjectScanner scanner;
+ scanner.ScanProjectFile( this, szAbsolute, pProject );
+ pProject->m_IncludeDirectories = scanner.m_IncludeDirectories;
+ pProject->m_ProjectName = scanner.m_ProjectName;
+
+ // Get a list of all files that depend on this project, starting with the .lib if it generates one.
+ CUtlVector<CUtlString> outputFiles;
+ outputFiles = pProject->m_AdditionalOutputFiles;
+
+ // Now note that the import library depends on this project.
+ // $(ImportLibrary) will be a lib in the case of DLLs that create libs (like tier0).
+ // $(OutputFile) will be a lib in the case of static libs (like tier1).
+ const char *pLinkerOutputFile = scanner.m_LinkerOutputFile.String();
+ const char *pImportLibrary = scanner.m_ImportLibrary.String();
+ if ( !IsLibraryFile( pImportLibrary ) )
+ {
+ pImportLibrary = pLinkerOutputFile;
+ }
+
+ if ( IsLibraryFile( pImportLibrary ) )
+ {
+ outputFiles.AddToTail( pImportLibrary );
+ }
+
+ // The string that we replace $(TargetName) with is the output project filename without the path or extension.
+ // That'll be something like "tier0_360".
+ char sTargetNameReplacement[MAX_PATH];
+ V_FileBase( pLinkerOutputFile, sTargetNameReplacement, sizeof( sTargetNameReplacement ) );
+
+ // Now add a CDependency for each file.
+ for ( int i=0; i < outputFiles.Count(); i++ )
+ {
+ const char *pFilename = outputFiles[i].String();
+
+ // Replace $(TargetName) and fixup the path.
+ char sReplaced[MAX_PATH], sAbsImportLibrary[MAX_PATH];
+ V_StrSubst( pFilename, "$(TargetName)", sTargetNameReplacement, sReplaced, sizeof( sReplaced ) );
+ V_MakeAbsolutePath( sAbsImportLibrary, sizeof( sAbsImportLibrary ), sReplaced );
+
+ CDependency *pImportLibrary = FindOrCreateDependency( sAbsImportLibrary );
+ pImportLibrary->m_Dependencies.AddToTail( pProject );
+ }
+
+ return true;
+}
+
+
+void CProjectDependencyGraph::GetProjectDependencyTree( projectIndex_t iProject, CUtlVector<projectIndex_t> &dependentProjects, bool bDownwards )
+{
+ // First add the project itself.
+ if ( dependentProjects.Find( iProject ) == dependentProjects.InvalidIndex() )
+ dependentProjects.AddToTail( iProject );
+
+ // Now add anything that depends on it.
+ for ( int i=0; i < m_Projects.Count(); i++)
+ {
+ CDependency_Project *pProject = m_Projects[i];
+
+ if ( pProject->m_iProjectIndex != iProject )
+ continue;
+
+ // Ok, this project/game/platform combo comes from iProject. Now find anything that depends on it.
+ for ( int iOther=0; iOther < m_Projects.Count(); iOther++ )
+ {
+ CDependency_Project *pOther = m_Projects[iOther];
+
+ if ( pOther->m_iProjectIndex == iProject )
+ continue;
+
+ bool bThereIsADependency;
+ if ( bDownwards )
+ bThereIsADependency = pProject->DependsOn( pOther, k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagCheckAdditionalDependencies | k_EDependsOnFlagRecurse | k_EDependsOnFlagTraversePastLibs );
+ else
+ bThereIsADependency = pOther->DependsOn( pProject, k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagCheckAdditionalDependencies | k_EDependsOnFlagRecurse | k_EDependsOnFlagTraversePastLibs );
+
+ if ( bThereIsADependency )
+ {
+ if ( dependentProjects.Find( pOther->m_iProjectIndex ) == dependentProjects.InvalidIndex() )
+ dependentProjects.AddToTail( pOther->m_iProjectIndex );
+ }
+ }
+ }
+}
+
+
+CDependency* CProjectDependencyGraph::FindDependency( const char *pFilename )
+{
+ int i = m_AllFiles.Find( pFilename );
+ if ( i == m_AllFiles.InvalidIndex() )
+ return NULL;
+ else
+ return m_AllFiles[i];
+}
+
+
+CDependency* CProjectDependencyGraph::FindOrCreateDependency( const char *pFilename )
+{
+ // Fix up stuff like blah/../blah
+ char sFixed[MAX_PATH];
+
+ V_FixupPathName( sFixed, sizeof( sFixed ), pFilename );
+ pFilename = sFixed;
+
+ CDependency *pDependency = FindDependency( pFilename );
+ if ( pDependency )
+ return pDependency;
+
+ // Couldn't find it. Create one.
+ pDependency = new CDependency( this );
+ pDependency->m_Filename = pFilename;
+ m_AllFiles.Insert( pFilename, pDependency );
+
+ Sys_FileInfo( pFilename, pDependency->m_nCacheFileSize, pDependency->m_nCacheModificationTime );
+
+ if ( IsSourceFile( pFilename ) )
+ pDependency->m_Type = k_eDependencyType_SourceFile;
+ else if ( IsLibraryFile( pFilename ) )
+ pDependency->m_Type = k_eDependencyType_Library;
+ else
+ pDependency->m_Type = k_eDependencyType_Unknown;
+
+ return pDependency;
+}
+
+
+void CProjectDependencyGraph::ClearAllDependencyMarks()
+{
+ if ( m_iDependencyMark == 0xFFFFFFFF )
+ {
+ m_iDependencyMark = 1;
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=m_AllFiles.Next(i) )
+ {
+ m_AllFiles[i]->m_iDependencyMark = 0;
+ }
+ }
+ else
+ {
+ // The 99.9999999% chance case.
+ ++m_iDependencyMark;
+ }
+}
+
+bool CProjectDependencyGraph::LoadCache( const char *pFilename )
+{
+ FILE *fp = fopen( pFilename, "rb" );
+ if ( !fp )
+ return false;
+
+ int version;
+ fread( &version, sizeof( version ), 1, fp );
+ if ( version != VPC_CRC_CACHE_VERSION )
+ {
+ g_pVPC->VPCWarning( "Invalid dependency cache file version in %s.", pFilename );
+ return false;
+ }
+
+ while ( 1 )
+ {
+ byte bMore;
+ if ( fread( &bMore, 1, 1, fp ) != 1 || bMore == 0 )
+ break;
+
+ CUtlString filename = ReadString( fp );
+ CDependency *pDep = FindOrCreateDependency( filename.String() );
+ if ( pDep->m_Dependencies.Count() != 0 )
+ g_pVPC->VPCError( "Cache loading dependency %s but it already exists!", filename.String() );
+
+ fread( &pDep->m_nCacheFileSize, sizeof( pDep->m_nCacheFileSize ), 1, fp );
+ fread( &pDep->m_nCacheModificationTime, sizeof( pDep->m_nCacheModificationTime ), 1, fp );
+
+ int nDependencies;
+ fread( &nDependencies, sizeof( nDependencies ), 1, fp );
+ pDep->m_Dependencies.SetSize( nDependencies );
+
+ for ( int iDependency=0; iDependency < nDependencies; iDependency++ )
+ {
+ CUtlString childDepName = ReadString( fp );
+ CDependency *pChildDep = FindOrCreateDependency( childDepName.String() );
+ pDep->m_Dependencies[iDependency] = pChildDep;
+ }
+ }
+
+ fclose( fp );
+
+ int nOriginalEntries = m_AllFiles.Count();
+
+ CheckCacheEntries();
+ RemoveDirtyCacheEntries();
+ MarkAllCacheEntriesValid();
+
+ Log_Msg( LOG_VPC, "\n\nLoaded %d valid dependency cache entries (%d were out of date).\n\n", m_AllFiles.Count(), nOriginalEntries-m_AllFiles.Count() );
+ return true;
+}
+
+bool CProjectDependencyGraph::SaveCache( const char *pFilename )
+{
+ FILE *fp = fopen( pFilename, "wb" );
+ if ( !fp )
+ return false;
+
+ // Write the version.
+ int version = VPC_CRC_CACHE_VERSION;
+ fwrite( &version, sizeof( version ), 1, fp );
+
+ // Write each file.
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=m_AllFiles.Next( i ) )
+ {
+ CDependency *pDep = m_AllFiles[i];
+
+ // We only care about source files.
+ if ( pDep->m_Type != k_eDependencyType_SourceFile )
+ continue;
+
+ // Write that there's a file here.
+ byte bYesThereIsAFileHere = 1;
+ fwrite( &bYesThereIsAFileHere, 1, 1, fp );
+
+ WriteString( fp, pDep->m_Filename );
+ fwrite( &pDep->m_nCacheFileSize, sizeof( pDep->m_nCacheFileSize ), 1, fp );
+ fwrite( &pDep->m_nCacheModificationTime, sizeof( pDep->m_nCacheModificationTime ), 1, fp );
+
+ int nDependencies = pDep->m_Dependencies.Count();
+ fwrite( &nDependencies, sizeof( nDependencies ), 1, fp );
+
+ for ( int iDependency=0; iDependency < pDep->m_Dependencies.Count(); iDependency++ )
+ {
+ WriteString( fp, pDep->m_Dependencies[iDependency]->m_Filename );
+ }
+ }
+
+ // Write a terminator.
+ byte bNoMore = 0;
+ fwrite( &bNoMore, 1, 1, fp );
+
+ fclose( fp );
+
+ Sys_CopyToMirror( pFilename );
+
+ return true;
+}
+
+void CProjectDependencyGraph::WriteString( FILE *fp, CUtlString &utlString )
+{
+ const char *pStr = utlString.String();
+ int len = V_strlen( pStr );
+ fwrite( &len, sizeof( len ), 1, fp );
+ fwrite( pStr, len, 1, fp );
+}
+
+CUtlString CProjectDependencyGraph::ReadString( FILE *fp )
+{
+ int len;
+ fread( &len, sizeof( len ), 1, fp );
+
+ char *pTemp = new char[len+1];
+ fread( pTemp, len, 1, fp );
+ pTemp[len] = 0;
+
+ CUtlString ret = pTemp;
+ delete [] pTemp;
+
+ return ret;
+}
+
+
+void CProjectDependencyGraph::CheckCacheEntries()
+{
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=m_AllFiles.Next( i ) )
+ {
+ CDependency *pDep = m_AllFiles[i];
+ pDep->m_bCacheDirty = false;
+
+ if ( pDep->m_Type != k_eDependencyType_SourceFile )
+ continue;
+
+ int64 fileSize, modTime;
+ if ( !Sys_FileInfo( pDep->m_Filename.String(), fileSize, modTime ) ||
+ pDep->m_nCacheFileSize != fileSize ||
+ pDep->m_nCacheModificationTime != modTime )
+ {
+ pDep->m_bCacheDirty = true;
+ }
+ }
+}
+
+void CProjectDependencyGraph::RemoveDirtyCacheEntries()
+{
+ // NOTE: This could be waaaay more efficient by pointing files at their parents and removing all the way
+ // up the chain rather than iterating over and over but this keeps the data structures simple.
+ bool bAnyDirty = true;
+ while ( bAnyDirty )
+ {
+ bAnyDirty = false;
+
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=m_AllFiles.Next( i ) )
+ {
+ CDependency *pDep = m_AllFiles[i];
+ if ( pDep->m_bCacheDirty )
+ continue;
+
+ // If any of its children are dirty, then mark this guy as dirty and make sure to remove the child.
+ for ( int iChild=0; iChild < pDep->m_Dependencies.Count(); iChild++ )
+ {
+ CDependency *pChild = pDep->m_Dependencies[iChild];
+ if ( pChild->m_bCacheDirty )
+ {
+ pDep->m_bCacheDirty = true;
+ bAnyDirty = true;
+ }
+ }
+ }
+ }
+
+ // Now that any dirty children have flagged their parents as dirty, we can remove them.
+ int iNext;
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=iNext )
+ {
+ iNext = m_AllFiles.Next( i );
+
+ if ( m_AllFiles[i]->m_bCacheDirty )
+ {
+ delete m_AllFiles[ i ];
+ m_AllFiles.RemoveAt( i );
+ }
+ }
+}
+
+
+void CProjectDependencyGraph::MarkAllCacheEntriesValid()
+{
+ for ( int i=m_AllFiles.First(); i != m_AllFiles.InvalidIndex(); i=m_AllFiles.Next( i ) )
+ {
+ CDependency *pDep = m_AllFiles[i];
+ pDep->m_bCheckedIncludes = true;
+ }
+}
+
+
+
+// This is called by VPC_IterateTargetProjects and all it does is look forf a
+class CGameFilterProjectIterator : public IProjectIterator
+{
+public:
+ virtual bool VisitProject( projectIndex_t iProject, const char *szProjectName )
+ {
+ char szAbsolute[MAX_PATH];
+ V_MakeAbsolutePath( szAbsolute, sizeof( szAbsolute ), szProjectName );
+
+ // Ok, we've got an (absolute) project filename. Search all the projects for one with that name.
+ bool bAdded = false;
+ for ( int i=0; i < m_pAllProjectsList->Count(); i++ )
+ {
+ CDependency_Project *pProject = m_pAllProjectsList->Element( i );
+
+ if ( pProject->CompareAbsoluteFilename( szAbsolute ) )
+ {
+ m_pOutProjectsList->AddToTail( pProject );
+ bAdded = true;
+ break;
+ }
+ }
+
+ if ( !bAdded )
+ {
+ g_pVPC->VPCError( "CGameFilterProjectIterator::VisitProject( %s ) - no project found by that name.", szProjectName );
+ return false;
+ }
+
+ return true;
+ }
+
+public:
+ const CUtlVector<CDependency_Project*> *m_pAllProjectsList;
+ CUtlVector<CDependency_Project*> *m_pOutProjectsList;
+};
+
+void CProjectDependencyGraph::TranslateProjectIndicesToDependencyProjects( CUtlVector<projectIndex_t> &projectList, CUtlVector<CDependency_Project*> &out )
+{
+ CGameFilterProjectIterator iterator;
+ iterator.m_pAllProjectsList = &m_Projects;
+ iterator.m_pOutProjectsList = &out;
+
+ g_pVPC->IterateTargetProjects( projectList, &iterator );
+}
diff --git a/external/vpc/utils/vpc/dependencies.h b/external/vpc/utils/vpc/dependencies.h
new file mode 100644
index 0000000..87ff41d
--- /dev/null
+++ b/external/vpc/utils/vpc/dependencies.h
@@ -0,0 +1,197 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DEPENDENCIES_H
+#define DEPENDENCIES_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+enum EDependencyType
+{
+ k_eDependencyType_SourceFile, // .cpp, .cxx, .h, .hxx
+ k_eDependencyType_Project, // this is a project file WITHOUT the target-specific extension (.mak, .vpj, .vcproj).
+ k_eDependencyType_Library, // this is a library file
+ k_eDependencyType_Unknown // Unrecognized file extension (probably .ico or .rc2 or somesuch).
+};
+
+class CProjectDependencyGraph;
+enum k_EDependsOnFlags
+{
+ k_EDependsOnFlagCheckNormalDependencies = 0x01,
+ k_EDependsOnFlagCheckAdditionalDependencies = 0x02,
+ k_EDependsOnFlagRecurse = 0x04,
+ k_EDependsOnFlagTraversePastLibs = 0x08
+};
+
+// Flags to CProjectDependencyGraph::BuildProjectDependencies.
+#define BUILDPROJDEPS_FULL_DEPENDENCY_SET 0x01 // This tells it to build a graph of all projects in the source tree _including_ all games.
+#define BUILDPROJDEPS_CHECK_ALL_PROJECTS 0x02 // If this is set, then it reads all .vpc files.
+ // If this is not set, then it only includes the files from the command line with the "vpc +tier0 *bitmap +client /tf" syntax
+
+class CDependency
+{
+friend class CProjectDependencyGraph;
+friend class CSingleProjectScanner;
+
+public:
+ CDependency( CProjectDependencyGraph *pDependencyGraph );
+ virtual ~CDependency();
+
+ // Flags are a combination of k_EDependsOnFlags.
+ bool DependsOn( CDependency *pTest, int flags=k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse );
+ const char* GetName() const;
+
+ // Returns true if the absolute filename of this thing (CDependency::m_Filename) matches the absolute path specified.
+ bool CompareAbsoluteFilename( const char *pAbsPath ) const;
+
+
+private:
+ bool FindDependency_Internal( CUtlVector<CUtlBuffer> &callTreeOutputStack, CDependency *pTest, int flags, int depth );
+ void Mark();
+ bool HasBeenMarked();
+
+public:
+ CUtlString m_Filename; // Full paths (slashes are platform dependent).
+ // This is the VPC filename for a project (use CDependency_Project::m_ProjectFilename for the VCPROJ/VPJ filename).
+ EDependencyType m_Type;
+
+ // Files that this guy depends on.
+ CUtlVector<CDependency*> m_Dependencies;
+
+ // Files added by $AdditionalProjectDependencies. This is in a separate list because we don't
+ // always want DependsOn() to check this.
+ CUtlVector<CDependency*> m_AdditionalDependencies;
+
+private:
+ CProjectDependencyGraph *m_pDependencyGraph;
+ unsigned int m_iDependencyMark;
+ bool m_bCheckedIncludes; // Set to true when we have checked all the includes for this.
+
+ // Cache info.
+ int64 m_nCacheFileSize;
+ int64 m_nCacheModificationTime;
+
+ // Used by the cache.
+ bool m_bCacheDirty; // File size or modification time don't match.
+};
+
+
+// This represents a project (.vcproj) file, NOT a project like a projectIndex_t.
+// There can be separate .vcproj files (and thus separate CDependency_Project) for each game and platform of a projectIndex_t.
+// If m_Type == k_eDependencyType_Project, then you can cast to this.
+class CDependency_Project : public CDependency
+{
+public:
+ typedef CDependency BaseClass;
+
+ CDependency_Project( CProjectDependencyGraph *pDependencyGraph );
+
+ // These functions read/write g_pVPC->GetOutputFilename() and such (all the m_xxStoredXXXX vars below).
+ void StoreProjectParameters( const char *szScriptName );
+ void ExportProjectParameters();
+
+ // Does a case-insensitive string compare against m_ProjectName.
+ // Returns -1 if not found or the index into projects.
+ static int FindByProjectName( CUtlVector<CDependency_Project*> &projects, const char *pTestName );
+
+
+public:
+ // Include directories for the project.
+ CUtlVector<CUtlString> m_IncludeDirectories;
+
+ // Straight out of the $AdditionalProjectDependencies key (split on semicolons).
+ CUtlVector<CUtlString> m_AdditionalProjectDependencies;
+
+ // Straight out of the $AdditionalOutputFiles key (split on semicolons).
+ CUtlVector<CUtlString> m_AdditionalOutputFiles;
+
+ CUtlString m_ProjectName; // This comes from the $Project key in the .vpc file.
+ CUtlString m_ProjectFilename; // Absolute path to the VCPROJ file (g_pVPC->GetOutputFilename() - see CDependency::m_Filename for the VPC filename).
+ CUtlString m_ImportLibrary;
+
+ // Note that there can be multiple CDependency_Projects with the same m_iProjectIndex.
+ projectIndex_t m_iProjectIndex;
+
+ // This is used by /p4sln. It uses this to call into VPC_ParseProjectScript. These are the values of g_pVPC->GetOutputFilename(), szScriptName,
+ // and the defines at the time of building this project.
+ CUtlString m_StoredOutputFilename;
+ char m_szStoredScriptName[MAX_PATH];
+ char m_szStoredCurrentDirectory[MAX_PATH];
+ CUtlVector<bool> m_StoredConditionalsActive;
+};
+
+
+// This class builds a graph of all dependencies, starting at the projects.
+class CProjectDependencyGraph : public IProjectIterator
+{
+friend class CDependency;
+
+public:
+ CProjectDependencyGraph();
+
+ // This is the main function to generate dependencies.
+ // nBuildProjectDepsFlags is a combination of BUILDPROJDEPS_ flags.
+ void BuildProjectDependencies( int nBuildProjectDepsFlags, CUtlVector< CDependency_Project *> *pPhase1Projects = NULL );
+
+ bool HasGeneratedDependencies() const;
+
+ CDependency* FindDependency( const char *pFilename );
+ CDependency* FindOrCreateDependency( const char *pFilename );
+
+ // Look for all projects (that we've scanned during BuildProjectDependencies) that depend on the specified project.
+ // If bDownwards is true, then it adds iProject and all projects that _it depends on_.
+ // If bDownwards is false, then it adds iProject and all projects that _depend on it_.
+ void GetProjectDependencyTree( projectIndex_t iProject, CUtlVector<projectIndex_t> &dependentProjects, bool bDownwards );
+
+ // This solves the central mismatch between the way VPC references projects and the way the CDependency stuff does.
+ //
+ // - VPC uses projectIndex_t, but a single projectIndex_t can turn into multiple games (server_tf, server_episodic, etc) in VPC_IterateTargetProjects.
+ // - The dependency code has a separate CDependency_Project for each game.
+ //
+ // This takes a bunch of project indices (usually m_targetProjects, which comes from the command line's "+this -that *theother" syntax),
+ // which are game-agnostic, and based on what games were specified on the command line, it builds the list of CDependency_Project*s.
+ void TranslateProjectIndicesToDependencyProjects( CUtlVector<projectIndex_t> &projectList, CUtlVector<CDependency_Project*> &out );
+
+// IProjectIterator overrides.
+protected:
+ virtual bool VisitProject( projectIndex_t iProject, const char *szProjectName );
+
+
+private:
+ void ClearAllDependencyMarks();
+
+ // Functions for the vpc.cache file management.
+ bool LoadCache( const char *pFilename );
+ bool SaveCache( const char *pFilename );
+ void WriteString( FILE *fp, CUtlString &utlString );
+ CUtlString ReadString( FILE *fp );
+
+ void CheckCacheEntries();
+ void RemoveDirtyCacheEntries();
+ void MarkAllCacheEntriesValid();
+
+ void ResolveAdditionalProjectDependencies( CUtlVector< CDependency_Project *> *pPhase1Projects = NULL );
+
+public:
+ // Projects and everything they depend on.
+ CUtlVector<CDependency_Project*> m_Projects;
+ CUtlDict<CDependency*,int> m_AllFiles; // All files go in here. They should never be duplicated. These are indexed by the full filename (except .lib files, which have that stripped off).
+ bool m_bFullDependencySet; // See bFullDepedencySet passed into BuildProjectDependencies.
+ int m_nFilesParsedForIncludes;
+
+private:
+ // Used when sweeping the dependency graph to prevent looping around forever.
+ unsigned int m_iDependencyMark;
+ bool m_bHasGeneratedDependencies; // Set to true after finishing BuildProjectDependencies.
+};
+
+
+bool IsLibraryFile( const char *pFilename );
+bool IsSharedLibraryFile( const char *pFilename );
+
+
+#endif // DEPENDENCIES_H
diff --git a/external/vpc/utils/vpc/exprsimplifier.cpp b/external/vpc/utils/vpc/exprsimplifier.cpp
new file mode 100644
index 0000000..d7cce05
--- /dev/null
+++ b/external/vpc/utils/vpc/exprsimplifier.cpp
@@ -0,0 +1,324 @@
+//===== Copyright (c) 1996-2006, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: ExprSimplifier builds a binary tree from an infix expression (in the
+// form of a character array).
+//
+//===========================================================================//
+#include "vpc.h"
+
+static ExprTree mExprTree; // Tree representation of the expression
+static char mCurToken; // Current token read from the input expression
+static const char *mExpression; // Array of the expression characters
+static int mCurPosition; // Current position in the input expression
+static char mIdentifier[MAX_IDENTIFIER_LEN]; // Stores the identifier string
+static GetSymbolProc_t g_pGetSymbolProc;
+
+//-----------------------------------------------------------------------------
+// Sets mCurToken to the next token in the input string. Skips all whitespace.
+//-----------------------------------------------------------------------------
+static char GetNextToken( void )
+{
+ // while whitespace, Increment CurrentPosition
+ while( mExpression[mCurPosition] == ' ' )
+ ++mCurPosition;
+
+ // CurrentToken = Expression[CurrentPosition]
+ mCurToken = mExpression[mCurPosition++];
+
+ return mCurToken;
+}
+
+
+//-----------------------------------------------------------------------------
+// Utility funcs
+//-----------------------------------------------------------------------------
+static void FreeNode( ExprNode *node )
+{
+ delete node;
+}
+
+static ExprNode *AllocateNode( void )
+{
+ return new ExprNode;
+}
+
+static void FreeTree( ExprTree& node )
+{
+ if(!node)
+ return;
+
+ FreeTree(node->left);
+ FreeTree(node->right);
+ FreeNode(node);
+ node = 0;
+}
+
+static bool IsConditional( const char token )
+{
+ char nextchar = ' ';
+ if ( token == OR_OP || token == AND_OP )
+ {
+ nextchar = mExpression[mCurPosition++];
+ if ( (token & nextchar) == token )
+ {
+ return true;
+ }
+ else
+ g_pVPC->VPCSyntaxError( "Bad expression token: %c %c", token, nextchar );
+ }
+
+ return false;
+}
+
+static bool IsNotOp( const char token )
+{
+ if ( token == NOT_OP )
+ return true;
+ else
+ return false;
+}
+
+static bool IsIdentifierOrConstant( const char token )
+{
+ bool success = false;
+ if ( token == '$' )
+ {
+ // store the entire identifier
+ int i = 0;
+ mIdentifier[i++] = token;
+ while( (isalnum( mExpression[mCurPosition] ) || mExpression[mCurPosition] == '_') && i < MAX_IDENTIFIER_LEN )
+ {
+ mIdentifier[i] = mExpression[mCurPosition];
+ ++mCurPosition;
+ ++i;
+ }
+
+ if ( i < MAX_IDENTIFIER_LEN - 1 )
+ {
+ mIdentifier[i] = '\0';
+ success = true;
+ }
+ }
+ else
+ {
+ if ( isdigit( token ) )
+ {
+ int i = 0;
+ mIdentifier[i++] = token;
+ while( isdigit( mExpression[mCurPosition] ) && ( i < MAX_IDENTIFIER_LEN ) )
+ {
+ mIdentifier[i] = mExpression[mCurPosition];
+ ++mCurPosition;
+ ++i;
+ }
+ if ( i < MAX_IDENTIFIER_LEN - 1 )
+ {
+ mIdentifier[i] = '\0';
+ success = true;
+ }
+ }
+ }
+
+ return success;
+}
+
+static void MakeExprNode( ExprTree &tree, char token, Kind kind, ExprTree left, ExprTree right )
+{
+ tree = AllocateNode();
+ tree->left = left;
+ tree->right = right;
+ tree->kind = kind;
+
+ switch ( kind )
+ {
+ case CONDITIONAL:
+ tree->data.cond = token;
+ break;
+ case LITERAL:
+ if ( isdigit( mIdentifier[0] ) )
+ {
+ tree->data.value = atoi( mIdentifier ) != 0;
+ }
+ else
+ {
+ tree->data.value = g_pGetSymbolProc( mIdentifier );
+ }
+ break;
+ case NOT:
+ break;
+ default:
+ g_pVPC->VPCError( "Error in ExpTree" );
+ }
+}
+
+static void MakeExpression( ExprTree& tree );
+//-----------------------------------------------------------------------------
+// Makes a factor :: { <expression> } | <identifier>.
+//-----------------------------------------------------------------------------
+static void MakeFactor( ExprTree& tree )
+{
+ if ( mCurToken == '(' )
+ {
+ // Get the next token
+ GetNextToken();
+
+ // Make an expression, setting Tree to point to it
+ MakeExpression( tree );
+ }
+ else if ( IsIdentifierOrConstant( mCurToken ) )
+ {
+ // Make a literal node, set Tree to point to it, set left/right children to NULL.
+ MakeExprNode( tree, mCurToken, LITERAL, NULL, NULL );
+ }
+ else if ( IsNotOp( mCurToken ) )
+ {
+ // do nothing
+ return;
+ }
+ else
+ {
+ // This must be a bad token
+ g_pVPC->VPCSyntaxError( "Bad expression token: %c", mCurToken );
+ }
+
+ // Get the next token
+ GetNextToken();
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes a term :: <factor> { <not> }.
+//-----------------------------------------------------------------------------
+static void MakeTerm( ExprTree& tree )
+{
+ // Make a factor, setting Tree to point to it
+ MakeFactor( tree );
+
+ // while the next token is !
+ while( IsNotOp( mCurToken ) )
+ {
+ // Make an operator node, setting left child to Tree and right to NULL. (Tree points to new node)
+ MakeExprNode( tree, mCurToken, NOT, tree, NULL );
+
+ // Get the next token.
+ GetNextToken();
+
+ // Make a factor, setting the right child of Tree to point to it.
+ MakeFactor(tree->right);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes a complete expression :: <term> { <cond> <term> }.
+//-----------------------------------------------------------------------------
+static void MakeExpression( ExprTree& tree )
+{
+ // Make a term, setting Tree to point to it
+ MakeTerm( tree );
+
+ // while the next token is a conditional
+ while ( IsConditional( mCurToken ) )
+ {
+ // Make a conditional node, setting left child to Tree and right to NULL. (Tree points to new node)
+ MakeExprNode( tree, mCurToken, CONDITIONAL, tree, NULL );
+
+ // Get the next token.
+ GetNextToken();
+
+ // Make a term, setting the right child of Tree to point to it.
+ MakeTerm( tree->right );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// returns true for success, false for failure
+//-----------------------------------------------------------------------------
+static bool BuildExpression( void )
+{
+ // Get the first token, and build the tree.
+ GetNextToken();
+
+ MakeExpression( mExprTree );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// returns the value of the node after resolving all children
+//-----------------------------------------------------------------------------
+static bool SimplifyNode( ExprTree& node )
+{
+ if( !node )
+ return false;
+
+ // Simplify the left and right children of this node
+ bool leftVal = SimplifyNode(node->left);
+ bool rightVal = SimplifyNode(node->right);
+
+ // Simplify this node
+ switch( node->kind )
+ {
+ case NOT:
+ // the child of '!' is always to the right
+ node->data.value = !rightVal;
+ break;
+
+ case CONDITIONAL:
+ if ( node->data.cond == AND_OP )
+ {
+ node->data.value = leftVal && rightVal;
+ }
+ else // OR_OP
+ {
+ node->data.value = leftVal || rightVal;
+ }
+ break;
+
+ default: // LITERAL
+ break;
+ }
+
+ // This node has beed resolved
+ node->kind = LITERAL;
+ return node->data.value;
+}
+
+
+//-----------------------------------------------------------------------------
+// Interface to solve a conditional expression. Returns false on failure.
+//-----------------------------------------------------------------------------
+bool EvaluateExpression( bool &result, const char *InfixExpression, GetSymbolProc_t pGetSymbolProc )
+{
+ if ( !InfixExpression )
+ return false;
+
+ g_pGetSymbolProc = pGetSymbolProc;
+
+ bool success = false;
+ mExpression = InfixExpression;
+ mExprTree = 0;
+ mCurPosition = 0;
+
+ // Building the expression tree will fail on bad syntax
+ if ( BuildExpression() )
+ {
+ success = true;
+ result = SimplifyNode( mExprTree );
+ }
+
+ FreeTree( mExprTree );
+ return success;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/vpc/utils/vpc/generatordefinition.cpp b/external/vpc/utils/vpc/generatordefinition.cpp
new file mode 100644
index 0000000..474cf3c
--- /dev/null
+++ b/external/vpc/utils/vpc/generatordefinition.cpp
@@ -0,0 +1,353 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+CGeneratorDefinition::CGeneratorDefinition()
+{
+ Clear();
+}
+
+void CGeneratorDefinition::Clear()
+{
+ m_pPropertyNames = NULL;
+ m_ScriptName.Clear();
+ m_NameString.Clear();
+ m_VersionString.Clear();
+ m_Tools.Purge();
+ m_ScriptCRC = 0;
+}
+
+void CGeneratorDefinition::IterateAttributesKey( ToolProperty_t *pProperty, KeyValues *pAttributesKV )
+{
+ const char *pAttributeName = pAttributesKV->GetName();
+ const char *pValue = pAttributesKV->GetString( "" );
+
+ //Msg( "Attribute name: %s\n", pAttributeName );
+
+ if ( !V_stricmp( pAttributeName, "type" ) )
+ {
+ if ( !V_stricmp( pValue, "bool" ) || !V_stricmp( pValue, "boolean" ) )
+ {
+ pProperty->m_nType = PT_BOOLEAN;
+ }
+ else if ( !V_stricmp( pValue, "string" ) )
+ {
+ pProperty->m_nType = PT_STRING;
+ }
+ else if ( !V_stricmp( pValue, "list" ) )
+ {
+ pProperty->m_nType = PT_LIST;
+ }
+ else if ( !V_stricmp( pValue, "int" ) || !V_stricmp( pValue, "integer" ) )
+ {
+ pProperty->m_nType = PT_INTEGER;
+ }
+ else if ( !V_stricmp( pValue, "ignore" ) || !V_stricmp( pValue, "none" ) )
+ {
+ pProperty->m_nType = PT_IGNORE;
+ }
+ else if ( !V_stricmp( pValue, "deprecated" ) || !V_stricmp( pValue, "donotuse" ) )
+ {
+ pProperty->m_nType = PT_DEPRECATED;
+ }
+ else
+ {
+ // unknown
+ g_pVPC->VPCError( "Unknown type '%s' in '%s'", pValue, pProperty->m_ParseString.Get() );
+ }
+ }
+ else if ( !V_stricmp( pAttributeName, "alias" ) )
+ {
+ pProperty->m_AliasString = pValue;
+ }
+ else if ( !V_stricmp( pAttributeName, "legacy" ) )
+ {
+ pProperty->m_LegacyString = pValue;
+ }
+ else if ( !V_stricmp( pAttributeName, "InvertOutput" ) )
+ {
+ pProperty->m_bInvertOutput = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "output" ) )
+ {
+ pProperty->m_OutputString = pValue;
+ }
+ else if ( !V_stricmp( pAttributeName, "fixslashes" ) )
+ {
+ pProperty->m_bFixSlashes = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "PreferSemicolonNoComma" ) )
+ {
+ pProperty->m_bPreferSemicolonNoComma = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "PreferSemicolonNoSpace" ) )
+ {
+ pProperty->m_bPreferSemicolonNoSpace = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "AppendSlash" ) )
+ {
+ pProperty->m_bAppendSlash = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "GlobalProperty" ) )
+ {
+ pProperty->m_bEmitAsGlobalProperty = pAttributesKV->GetBool();
+ }
+ else if ( !V_stricmp( pAttributeName, "ordinals" ) )
+ {
+ if ( pProperty->m_nType == PT_UNKNOWN )
+ {
+ pProperty->m_nType = PT_LIST;
+ }
+
+ for ( KeyValues *pKV = pAttributesKV->GetFirstSubKey(); pKV; pKV = pKV->GetNextKey() )
+ {
+ const char *pOrdinalName = pKV->GetName();
+ const char *pOrdinalValue = pKV->GetString();
+ if ( !pOrdinalValue[0] )
+ {
+ g_pVPC->VPCError( "Unknown ordinal value for name '%s' in '%s'", pOrdinalName, pProperty->m_ParseString.Get() );
+ }
+
+ int iIndex = pProperty->m_Ordinals.AddToTail();
+ pProperty->m_Ordinals[iIndex].m_ParseString = pOrdinalName;
+ pProperty->m_Ordinals[iIndex].m_ValueString = pOrdinalValue;
+ }
+ }
+ else
+ {
+ g_pVPC->VPCError( "Unknown attribute '%s' in '%s'", pAttributeName, pProperty->m_ParseString.Get() );
+ }
+}
+
+void CGeneratorDefinition::IteratePropertyKey( GeneratorTool_t *pTool, KeyValues *pPropertyKV )
+{
+ //Msg( "Property Key name: %s\n", pPropertyKV->GetName() );
+
+ int iIndex = pTool->m_Properties.AddToTail();
+ ToolProperty_t *pProperty = &pTool->m_Properties[iIndex];
+
+ pProperty->m_ParseString = pPropertyKV->GetName();
+
+ KeyValues *pKV = pPropertyKV->GetFirstSubKey();
+ if ( !pKV )
+ return;
+
+ for ( ;pKV; pKV = pKV->GetNextKey() )
+ {
+ IterateAttributesKey( pProperty, pKV );
+ }
+}
+
+void CGeneratorDefinition::IterateToolKey( KeyValues *pToolKV )
+{
+ //Msg( "Tool Key name: %s\n", pToolKV->GetName() );
+
+ // find or create
+ GeneratorTool_t *pTool = NULL;
+ for ( int i = 0; i < m_Tools.Count(); i++ )
+ {
+ if ( !V_stricmp( pToolKV->GetName(), m_Tools[i].m_ParseString ) )
+ {
+ pTool = &m_Tools[i];
+ break;
+ }
+ }
+ if ( !pTool )
+ {
+ int iIndex = m_Tools.AddToTail();
+ pTool = &m_Tools[iIndex];
+ }
+
+ pTool->m_ParseString = pToolKV->GetName();
+
+ KeyValues *pKV = pToolKV->GetFirstSubKey();
+ if ( !pKV )
+ return;
+
+ for ( ;pKV; pKV = pKV->GetNextKey() )
+ {
+ IteratePropertyKey( pTool, pKV );
+ }
+}
+
+void CGeneratorDefinition::AssignIdentifiers()
+{
+ CUtlVector< bool > usedPropertyNames;
+ int nTotalPropertyNames = 0;
+ while ( m_pPropertyNames[nTotalPropertyNames].m_nPropertyId >= 0 )
+ {
+ nTotalPropertyNames++;
+ }
+ usedPropertyNames.SetCount( nTotalPropertyNames );
+
+ // assign property identifiers
+ for ( int i = 0; i < m_Tools.Count(); i++ )
+ {
+ GeneratorTool_t *pTool = &m_Tools[i];
+
+ // assign the tool keyword
+ configKeyword_e keyword = g_pVPC->NameToKeyword( pTool->m_ParseString.Get() );
+ if ( keyword == KEYWORD_UNKNOWN )
+ {
+ g_pVPC->VPCError( "Unknown Tool Keyword '%s' in '%s'", pTool->m_ParseString.Get(), m_ScriptName.Get() );
+ }
+ pTool->m_nKeyword = keyword;
+
+ const char *pPrefix = m_NameString.Get();
+ const char *pToolName = pTool->m_ParseString.Get();
+ if ( pToolName[0] == '$' )
+ {
+ pToolName++;
+ }
+
+ for ( int j = 0; j < pTool->m_Properties.Count(); j++ )
+ {
+ ToolProperty_t *pProperty = &pTool->m_Properties[j];
+
+ if ( pProperty->m_nType == PT_IGNORE || pProperty->m_nType == PT_DEPRECATED )
+ {
+ continue;
+ }
+
+ const char *pPropertyName = pProperty->m_AliasString.Get();
+ if ( !pPropertyName[0] )
+ {
+ pPropertyName = pProperty->m_ParseString.Get();
+ }
+ if ( pPropertyName[0] == '$' )
+ {
+ pPropertyName++;
+ }
+
+ CUtlString prefixString = CFmtStr( "%s_%s", pPrefix, pToolName );
+
+ bool bFound = false;
+ for ( int k = 0; k < nTotalPropertyNames && !bFound; k++ )
+ {
+ if ( !V_stricmp( prefixString.Get(), m_pPropertyNames[k].m_pPrefixName ) )
+ {
+ if ( !V_stricmp( pPropertyName, m_pPropertyNames[k].m_pPropertyName ) )
+ {
+ pProperty->m_nPropertyId = m_pPropertyNames[k].m_nPropertyId;
+ bFound = true;
+ usedPropertyNames[k] = true;
+ }
+ }
+ }
+ if ( !bFound )
+ {
+ g_pVPC->VPCError( "Could not find PROPERTYNAME( %s, %s ) for %s", prefixString.Get(), pPropertyName, m_ScriptName.Get() );
+ }
+ }
+ }
+
+ if ( g_pVPC->IsVerbose() )
+ {
+ for ( int i = 0; i < usedPropertyNames.Count(); i++ )
+ {
+ if ( !usedPropertyNames[i] )
+ {
+ g_pVPC->VPCWarning( "Unused PROPERTYNAME( %s, %s ) in %s", m_pPropertyNames[i].m_pPrefixName, m_pPropertyNames[i].m_pPropertyName, m_ScriptName.Get() );
+ }
+ }
+ }
+}
+
+void CGeneratorDefinition::LoadDefinition( const char *pDefnitionName, PropertyName_t *pPropertyNames )
+{
+ Clear();
+
+ m_pPropertyNames = pPropertyNames;
+ g_pVPC->GetScript().PushScript( CFmtStr( "vpc_scripts\\definitions\\%s", pDefnitionName ) );
+
+ // project definitions are KV format
+ KeyValues *pScriptKV = new KeyValues( g_pVPC->GetScript().GetName() );
+
+ pScriptKV->LoadFromBuffer( g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetData() );
+
+ m_ScriptName = g_pVPC->GetScript().GetName();
+ m_ScriptCRC = CRC32_ProcessSingleBuffer( g_pVPC->GetScript().GetData(), strlen( g_pVPC->GetScript().GetData() ) );
+
+ m_NameString = pScriptKV->GetName();
+
+ KeyValues *pKV = pScriptKV->GetFirstSubKey();
+ for ( ;pKV; pKV = pKV->GetNextKey() )
+ {
+ const char *pKeyName = pKV->GetName();
+ if ( !V_stricmp( pKeyName, "version" ) )
+ {
+ m_VersionString = pKV->GetString();
+ }
+ else
+ {
+ IterateToolKey( pKV );
+ }
+ }
+
+ g_pVPC->GetScript().PopScript();
+ pScriptKV->deleteThis();
+
+ g_pVPC->VPCStatus( false, "Definition: '%s' Version: %s", m_NameString.Get(), m_VersionString.Get() );
+
+ AssignIdentifiers();
+}
+
+const char *CGeneratorDefinition::GetScriptName( CRC32_t *pCRC )
+{
+ if ( pCRC )
+ {
+ *pCRC = m_ScriptCRC;
+ }
+
+ return m_ScriptName.Get();
+}
+
+ToolProperty_t *CGeneratorDefinition::GetProperty( configKeyword_e keyword, const char *pPropertyName )
+{
+ for ( int i = 0; i < m_Tools.Count(); i++ )
+ {
+ GeneratorTool_t *pTool = &m_Tools[i];
+ if ( pTool->m_nKeyword != keyword )
+ continue;
+
+ for ( int j = 0; j < pTool->m_Properties.Count(); j++ )
+ {
+ ToolProperty_t *pToolProperty = &pTool->m_Properties[j];
+ if ( !V_stricmp( pToolProperty->m_ParseString.Get(), pPropertyName ) )
+ {
+ // found
+ return pToolProperty;
+ }
+ if ( !pToolProperty->m_LegacyString.IsEmpty() && !V_stricmp( pToolProperty->m_LegacyString.Get(), pPropertyName ) )
+ {
+ // found
+ return pToolProperty;
+ }
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/external/vpc/utils/vpc/generatordefinition.h b/external/vpc/utils/vpc/generatordefinition.h
new file mode 100644
index 0000000..839b8ec
--- /dev/null
+++ b/external/vpc/utils/vpc/generatordefinition.h
@@ -0,0 +1,130 @@
+//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
+//
+//
+//==================================================================================================
+
+#ifndef GENERATORDEFINITION_H
+#define GENERATORDEFINITION_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+struct PropertyName_t
+{
+ int m_nPropertyId;
+ const char *m_pPrefixName;
+ const char *m_pPropertyName;
+};
+
+enum configKeyword_e
+{
+ KEYWORD_UNKNOWN = -1,
+ KEYWORD_GENERAL,
+ KEYWORD_DEBUGGING,
+ KEYWORD_COMPILER,
+ KEYWORD_PS3_SNCCOMPILER,
+ KEYWORD_PS3_GCCCOMPILER,
+ KEYWORD_LIBRARIAN,
+ KEYWORD_LINKER,
+ KEYWORD_PS3_SNCLINKER,
+ KEYWORD_PS3_GCCLINKER,
+ KEYWORD_MANIFEST,
+ KEYWORD_XMLDOCGEN,
+ KEYWORD_BROWSEINFO,
+ KEYWORD_RESOURCES,
+ KEYWORD_PREBUILDEVENT,
+ KEYWORD_PRELINKEVENT,
+ KEYWORD_POSTBUILDEVENT,
+ KEYWORD_CUSTOMBUILDSTEP,
+ KEYWORD_XBOXIMAGE,
+ KEYWORD_XBOXDEPLOYMENT,
+ KEYWORD_MAX,
+};
+
+enum PropertyType_e
+{
+ PT_UNKNOWN = 0,
+ PT_BOOLEAN,
+ PT_STRING,
+ PT_INTEGER,
+ PT_LIST,
+ PT_IGNORE,
+ PT_DEPRECATED,
+};
+
+struct PropertyOrdinal_t
+{
+ CUtlString m_ParseString;
+ CUtlString m_ValueString;
+};
+
+struct ToolProperty_t
+{
+ ToolProperty_t()
+ {
+ m_nPropertyId = -1;
+ m_nType = PT_UNKNOWN;
+ m_bFixSlashes = false;
+ m_bEmitAsGlobalProperty = false;
+ m_bInvertOutput = false;
+ m_bAppendSlash = false;
+ m_bPreferSemicolonNoComma = false;
+ m_bPreferSemicolonNoSpace = false;
+ }
+
+ CUtlString m_ParseString;
+ CUtlString m_AliasString;
+ CUtlString m_LegacyString;
+ CUtlString m_OutputString;
+ CUtlVector< PropertyOrdinal_t > m_Ordinals;
+
+ int m_nPropertyId;
+ PropertyType_e m_nType;
+ bool m_bFixSlashes;
+ bool m_bEmitAsGlobalProperty;
+ bool m_bInvertOutput;
+ bool m_bAppendSlash;
+ bool m_bPreferSemicolonNoComma;
+ bool m_bPreferSemicolonNoSpace;
+};
+
+struct GeneratorTool_t
+{
+ GeneratorTool_t()
+ {
+ m_nKeyword = KEYWORD_UNKNOWN;
+ }
+
+ CUtlString m_ParseString;
+ CUtlVector< ToolProperty_t > m_Properties;
+ configKeyword_e m_nKeyword;
+};
+
+class CGeneratorDefinition
+{
+public:
+ CGeneratorDefinition();
+
+ void LoadDefinition( const char *pDefinitionName, PropertyName_t *pPropertyNames );
+ ToolProperty_t *GetProperty( configKeyword_e keyword, const char *pPropertyName );
+
+ const char *GetScriptName( CRC32_t *pCRC );
+
+private:
+ void AssignIdentifiers();
+ void IterateToolKey( KeyValues *pToolKV );
+ void IteratePropertyKey( GeneratorTool_t *pTool, KeyValues *pPropertyKV );
+ void IterateAttributesKey( ToolProperty_t *pProperty, KeyValues *pAttributesKV );
+ void Clear();
+
+ PropertyName_t *m_pPropertyNames;
+ CUtlString m_ScriptName;
+ CUtlString m_NameString;
+ CUtlString m_VersionString;
+ CUtlVector< GeneratorTool_t > m_Tools;
+ CRC32_t m_ScriptCRC;
+};
+
+
+
+#endif // GENERATORDEFINITION_H
diff --git a/external/vpc/utils/vpc/groupscript.cpp b/external/vpc/utils/vpc/groupscript.cpp
new file mode 100644
index 0000000..2593352
--- /dev/null
+++ b/external/vpc/utils/vpc/groupscript.cpp
@@ -0,0 +1,369 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+// This keyword works in both group and project scripts
+extern void VPC_SharedKeyword_Conditional();
+
+
+//-----------------------------------------------------------------------------
+// VPC_Group_FindOrCreateProject
+//
+//-----------------------------------------------------------------------------
+projectIndex_t VPC_Group_FindOrCreateProject( const char *pName, bool bCreate )
+{
+ for ( int i = 0; i < g_pVPC->m_Projects.Count(); i++ )
+ {
+ if ( !V_stricmp( pName, g_pVPC->m_Projects[i].name.String() ) )
+ {
+ return i;
+ }
+ }
+
+ if ( !bCreate )
+ return INVALID_INDEX;
+
+ int index = g_pVPC->m_Projects.AddToTail();
+ g_pVPC->m_Projects[index].name = pName;
+
+ return index;
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Group_CreateGroup
+//
+//-----------------------------------------------------------------------------
+groupIndex_t VPC_Group_CreateGroup()
+{
+ groupIndex_t index = g_pVPC->m_Groups.AddToTail();
+ return index;
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Group_FindOrCreateGroupTag
+//
+//-----------------------------------------------------------------------------
+groupTagIndex_t VPC_Group_FindOrCreateGroupTag( const char *pName, bool bCreate )
+{
+ for (int i=0; i<g_pVPC->m_GroupTags.Count(); i++)
+ {
+ if ( !V_stricmp( pName, g_pVPC->m_GroupTags[i].name.String() ) )
+ return i;
+ }
+
+ if ( !bCreate )
+ return INVALID_INDEX;
+
+ groupTagIndex_t index = g_pVPC->m_GroupTags.AddToTail();
+ g_pVPC->m_GroupTags[index].name = pName;
+
+ return index;
+}
+
+//-----------------------------------------------------------------------------
+// VPC_GroupKeyword_Games
+//
+//-----------------------------------------------------------------------------
+void VPC_GroupKeyword_Games()
+{
+ const char *pToken;
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ else
+ {
+ g_pVPC->FindOrCreateConditional( pToken, true, CONDITIONAL_GAME );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_GroupKeyword_Group
+//
+//-----------------------------------------------------------------------------
+void VPC_GroupKeyword_Group()
+{
+ const char *pToken;
+ bool bFirstToken = true;
+ groupIndex_t groupIndex;
+ projectIndex_t projectIndex;
+
+ groupIndex = VPC_Group_CreateGroup();
+
+ while ( 1 )
+ {
+ if ( !bFirstToken )
+ {
+ pToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ }
+ else
+ {
+ bFirstToken = false;
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ // specified tag now builds this group
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pToken, true );
+ g_pVPC->m_GroupTags[groupTagIndex].groups.AddToTail( groupIndex );
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ else
+ {
+ projectIndex = VPC_Group_FindOrCreateProject( pToken, false );
+ if ( projectIndex != INVALID_INDEX )
+ {
+ int index = g_pVPC->m_Groups[groupIndex].projects.AddToTail();
+ g_pVPC->m_Groups[groupIndex].projects[index] = projectIndex;
+ }
+ else
+ {
+ g_pVPC->VPCWarning( "No Project %s defined, ignoring.", pToken );
+ continue;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_GroupKeyword_Project
+//
+//-----------------------------------------------------------------------------
+void VPC_GroupKeyword_Project()
+{
+ const char *pToken;
+
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ if ( VPC_Group_FindOrCreateProject( pToken, false ) != INVALID_INDEX )
+ {
+ // already defined
+ g_pVPC->VPCWarning( "project %s already defined", pToken );
+ g_pVPC->VPCSyntaxError();
+ }
+
+ projectIndex_t projectIndex = VPC_Group_FindOrCreateProject( pToken, true );
+
+ // create a default group that contains just this project
+ groupIndex_t groupIndex = VPC_Group_CreateGroup();
+ g_pVPC->m_Groups[groupIndex].projects.AddToTail( projectIndex );
+
+ // create a default tag that matches the project name
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pToken, true );
+ g_pVPC->m_GroupTags[groupTagIndex].groups.AddToTail( groupIndex );
+ g_pVPC->m_GroupTags[groupTagIndex].bSameAsProject = true;
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ else
+ {
+ scriptIndex_t scriptIndex = g_pVPC->m_Projects[projectIndex].scripts.AddToTail();
+ g_pVPC->m_Projects[projectIndex].scripts[scriptIndex].name = pToken;
+
+ pToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( pToken && pToken[0] )
+ {
+ pToken = g_pVPC->GetScript().GetToken( false );
+ g_pVPC->m_Projects[projectIndex].scripts[scriptIndex].m_condition = pToken;
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// VPC_ParseGroupScript
+//
+//-----------------------------------------------------------------------------
+void VPC_ParseGroupScript( const char *pScriptName )
+{
+ char szScriptName[MAX_PATH];
+ const char *pToken;
+
+ // caller's pointer is aliased
+ strcpy( szScriptName, pScriptName );
+ V_FixSlashes( szScriptName );
+
+ g_pVPC->VPCStatus( false, "Parsing: %s", szScriptName );
+ g_pVPC->GetScript().PushScript( szScriptName );
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ // end of file
+ break;
+ }
+
+ if ( !V_stricmp( pToken, "$include" ) )
+ {
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ // end of file
+ g_pVPC->VPCSyntaxError();
+ }
+
+ // recurse into and run
+ VPC_ParseGroupScript( pToken );
+ }
+ else if ( !V_stricmp( pToken, "$games" ) )
+ {
+ VPC_GroupKeyword_Games();
+ }
+ else if ( !V_stricmp( pToken, "$group" ) )
+ {
+ VPC_GroupKeyword_Group();
+ }
+ else if ( !V_stricmp( pToken, "$project" ) )
+ {
+ VPC_GroupKeyword_Project();
+ }
+ else if ( !V_stricmp( pToken, "$Conditional" ) )
+ {
+ VPC_SharedKeyword_Conditional();
+ }
+ else
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+
+ g_pVPC->GetScript().PopScript();
+}
+
+//-----------------------------------------------------------------------------
+// Collect all the +XXX, remove all the -XXX
+// This allows removal to be the expected trumping operation.
+//-----------------------------------------------------------------------------
+void CVPC::GenerateBuildSet( CProjectDependencyGraph &dependencyGraph )
+{
+ // process +XXX commands
+ for ( int i = 0; i < m_BuildCommands.Count(); i++ )
+ {
+ const char *pCommand = m_BuildCommands[i].Get();
+ if ( pCommand[0] == '-' )
+ continue;
+
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pCommand+1, false );
+ if ( groupTagIndex == INVALID_INDEX )
+ continue;
+ groupTag_t *pGroupTag = &g_pVPC->m_GroupTags[groupTagIndex];
+
+ CUtlVector<projectIndex_t> projectsToAdd;
+
+ for ( int j=0; j<pGroupTag->groups.Count(); j++ )
+ {
+ group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]];
+ for ( int k=0; k<pGroup->projects.Count(); k++ )
+ {
+ projectIndex_t targetProject = pGroup->projects[k];
+ if ( pCommand[0] == '*' )
+ {
+ // Add this project and any projects that depend on it.
+ if ( !dependencyGraph.HasGeneratedDependencies() )
+ dependencyGraph.BuildProjectDependencies( BUILDPROJDEPS_CHECK_ALL_PROJECTS, m_pPhase1Projects );
+
+ dependencyGraph.GetProjectDependencyTree( targetProject, projectsToAdd, false );
+ }
+ else if ( pCommand[0] == '@' )
+ {
+ // Add this project and any projects that it depends on.
+ if ( !dependencyGraph.HasGeneratedDependencies() )
+ dependencyGraph.BuildProjectDependencies( BUILDPROJDEPS_CHECK_ALL_PROJECTS, m_pPhase1Projects );
+
+ dependencyGraph.GetProjectDependencyTree( targetProject, projectsToAdd, true );
+ }
+ else
+ {
+ projectsToAdd.AddToTail( targetProject );
+ }
+ }
+ }
+
+ // Add all the projects in the list.
+ for ( int j=0; j < projectsToAdd.Count(); j++ )
+ {
+ projectIndex_t targetProject = projectsToAdd[j];
+
+ if ( g_pVPC->m_TargetProjects.Find( targetProject ) == -1 )
+ {
+ g_pVPC->m_TargetProjects.AddToTail( targetProject );
+ }
+ }
+ }
+
+ // process -XXX commands, explicitly remove tagge projects
+ for ( int i=0; i<m_BuildCommands.Count(); i++ )
+ {
+ const char *pCommand = m_BuildCommands[i].Get();
+ if ( pCommand[0] == '+' || pCommand[0] == '*' || pCommand[0] == '@' )
+ continue;
+
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pCommand+1, false );
+ if ( groupTagIndex == INVALID_INDEX )
+ continue;
+ groupTag_t *pGroupTag = &g_pVPC->m_GroupTags[groupTagIndex];
+
+ for ( int j=0; j<pGroupTag->groups.Count(); j++ )
+ {
+ group_t *pGroup = &g_pVPC->m_Groups[pGroupTag->groups[j]];
+ for ( int k=0; k<pGroup->projects.Count(); k++ )
+ {
+ g_pVPC->m_TargetProjects.FindAndRemove( pGroup->projects[k] );
+ }
+ }
+ }
+}
diff --git a/external/vpc/utils/vpc/ibaseprojectgenerator.h b/external/vpc/utils/vpc/ibaseprojectgenerator.h
new file mode 100644
index 0000000..f267d7a
--- /dev/null
+++ b/external/vpc/utils/vpc/ibaseprojectgenerator.h
@@ -0,0 +1,75 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef IBASEPROJECTGENERATOR_H
+#define IBASEPROJECTGENERATOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+//
+// Usage:
+//
+// StartProject
+// StartConfigurationBlock
+// StartPropertySection
+// HandleProperty...
+// EndPropertySection
+// EndConfigurationBlock
+//
+// AddFile...
+// [inside each file it can do another configuration block as above]
+// [also, files can be put in folders with StartFolder/AddFolder]
+// EndProject
+//
+class IBaseProjectGenerator
+{
+public:
+ // What file extension does this use? (vcproj, mak, vpj).
+ virtual const char* GetProjectFileExtension() = 0;
+
+ // Called before doing anything in a project (in g_pVPC->GetOutputFilename()).
+ virtual void StartProject() = 0;
+ virtual void EndProject() = 0;
+
+ // Access the project name.
+ virtual CUtlString GetProjectName() = 0;
+ virtual void SetProjectName( const char *pProjectName ) = 0;
+
+ // Get a list of all configurations.
+ virtual void GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames ) = 0;
+
+ // Configuration data is specified in between these calls and inside BeginPropertySection/EndPropertySection.
+ // If bFileSpecific is set, then the configuration data only applies to the last file added.
+ virtual void StartConfigurationBlock( const char *pConfigName, bool bFileSpecific ) = 0;
+ virtual void EndConfigurationBlock() = 0;
+
+ // These functions are called when it enters a section like $Compiler, $Linker, etc.
+ // In between the BeginPropertySection/EndPropertySection, it'll call HandleProperty for any properties inside that section.
+ virtual bool StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip = NULL ) = 0;
+ virtual void HandleProperty( const char *pProperty, const char *pCustomScriptData=NULL ) = 0;
+ virtual void EndPropertySection( configKeyword_e keyword ) = 0;
+
+ // Files go in folders. The generator should maintain a stack of folders as they're added.
+ virtual void StartFolder( const char *pFolderName ) = 0;
+ virtual void EndFolder() = 0;
+
+ // Add files. Any config blocks/properties between StartFile/EndFile apply to this file only.
+ // It will only ever have one active file.
+ virtual bool StartFile( const char *pFilename, bool bWarnIfAlreadyExists ) = 0;
+ virtual void EndFile() = 0;
+
+ // This is actually just per-file configuration data.
+ virtual void FileExcludedFromBuild( bool bExcluded ) = 0;
+ virtual void FileIsSchema( bool bIsSchema ) = 0; // Mark the current file as schema.
+ virtual void FileIsDynamic( bool bIsDynamic ) = 0; // Mark the current file as dynamic.
+
+ // Remove the specified file. return true if success
+ virtual bool RemoveFile( const char *pFilename ) = 0;
+};
+
+#endif // IBASEPROJECTGENERATOR_H
diff --git a/external/vpc/utils/vpc/ibasesolutiongenerator.h b/external/vpc/utils/vpc/ibasesolutiongenerator.h
new file mode 100644
index 0000000..cb566cf
--- /dev/null
+++ b/external/vpc/utils/vpc/ibasesolutiongenerator.h
@@ -0,0 +1,24 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef IBASESOLUTIONGENERATOR_H
+#define IBASESOLUTIONGENERATOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "dependencies.h"
+
+
+class IBaseSolutionGenerator
+{
+public:
+ virtual void GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects ) = 0;
+};
+
+
+#endif // IBASESOLUTIONGENERATOR_H
diff --git a/external/vpc/utils/vpc/macros.cpp b/external/vpc/utils/vpc/macros.cpp
new file mode 100644
index 0000000..feb518d
--- /dev/null
+++ b/external/vpc/utils/vpc/macros.cpp
@@ -0,0 +1,167 @@
+//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+void CVPC::SetMacro( const char *pName, const char *pValue, bool bSetupDefineInProjectFile )
+{
+ // Setup the macro.
+ VPCStatus( false, "Set Macro: $%s = %s", pName, pValue );
+
+ macro_t *pMacro = FindOrCreateMacro( pName, true, pValue );
+ pMacro->m_bSetupDefineInProjectFile = bSetupDefineInProjectFile;
+ pMacro->m_bInternalCreatedMacro = true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+macro_t *CVPC::FindOrCreateMacro( const char *pName, bool bCreate, const char *pValue )
+{
+ for ( int i = 0; i < m_Macros.Count(); i++ )
+ {
+ if ( !V_stricmp( pName, m_Macros[i].name.String() ) )
+ {
+ if ( pValue && V_stricmp( pValue, m_Macros[i].value.String() ) )
+ {
+ // update
+ m_Macros[i].value = pValue;
+ }
+
+ return &m_Macros[i];
+ }
+ }
+
+ if ( !bCreate )
+ {
+ return NULL;
+ }
+
+ int index = m_Macros.AddToTail();
+ m_Macros[index].name = pName;
+ m_Macros[index].value = pValue;
+
+ return &m_Macros[index];
+}
+
+int CVPC::GetMacrosMarkedForCompilerDefines( CUtlVector< macro_t* > &macroDefines )
+{
+ macroDefines.Purge();
+
+ for ( int i = 0; i < m_Macros.Count(); i++ )
+ {
+ if ( m_Macros[i].m_bSetupDefineInProjectFile )
+ {
+ macroDefines.AddToTail( &m_Macros[i] );
+ }
+ }
+
+ return macroDefines.Count();
+}
+
+static int __cdecl SortMacrosByNameLength( const macro_t *lhs, const macro_t *rhs )
+{
+ if ( lhs->name.Length() < rhs->name.Length() )
+ return 1;
+ if ( lhs->name.Length() > rhs->name.Length() )
+ return -1;
+ return 0;
+}
+
+void CVPC::ResolveMacrosInStringInternal( char const *pString, char *pOutBuff, int outBuffSize, bool bStringIsConditional )
+{
+ char macroName[MAX_SYSTOKENCHARS];
+ char buffer1[MAX_SYSTOKENCHARS];
+ char buffer2[MAX_SYSTOKENCHARS];
+ int i;
+
+ // ensure a "greedy" match by sorting longest to shortest
+ m_Macros.Sort( SortMacrosByNameLength );
+
+ // iterate and resolve user macros until all macros resolved
+ strcpy( buffer1, pString );
+ bool bDone;
+ do
+ {
+ bDone = true;
+ bool bDoReplace = true;
+ for ( i=0; i<m_Macros.Count(); i++ )
+ {
+ sprintf( macroName, "$%s", m_Macros[i].name.String() );
+ const char *pFound = V_stristr( buffer1, macroName );
+ if ( pFound && bStringIsConditional )
+ {
+ // if expanding a conditional, give conditionals priority over macros
+ // i.e. if the string we've found begins both a macro and conditional,
+ // don't expand the macro
+ for ( int j = 0; j < m_Conditionals.Count(); j++ )
+ {
+ if ( V_stristr( pFound+1, m_Conditionals[j].name.String() ) == pFound+1 )
+ {
+ bDoReplace = false;
+ // the warning is super chatty about $LINUX and $POSIX
+ if ( V_stricmp( macroName, "$LINUX" ) && V_stricmp( macroName, "$POSIX" ) )
+ g_pVPC->VPCWarning( "Not replacing macro %s with its value (%s) in conditional %s\n", macroName, m_Macros[i].value.Length() ? m_Macros[i].value.String() : "null" , pFound );
+ break;
+ }
+ }
+ }
+
+ // can't use ispunct as '|' and '&' are punctuation, but we dont want to warn on them
+ if ( pFound && bStringIsConditional && bDoReplace &&
+ ( isalnum( pFound[strlen(macroName)] ) || pFound[strlen(macroName)] == '_' ) )
+ g_pVPC->VPCWarning( "Replacing macro %s with its value (%s) in conditional %s\n", macroName, m_Macros[i].value.Length() ? m_Macros[i].value.String() : "null" , pFound );
+
+ if ( bDoReplace && Sys_ReplaceString( buffer1, macroName, m_Macros[i].value.String(), buffer2, sizeof( buffer2 ) ) )
+ {
+ bDone = false;
+ }
+ strcpy( buffer1, buffer2 );
+ }
+ }
+ while ( !bDone );
+
+ int len = strlen( buffer1 );
+ if ( outBuffSize < len )
+ len = outBuffSize;
+ memcpy( pOutBuff, buffer1, len );
+ pOutBuff[len] = '\0';
+}
+
+void CVPC::ResolveMacrosInString( char const *pString, char *pOutBuff, int outBuffSize )
+{
+ ResolveMacrosInStringInternal( pString, pOutBuff, outBuffSize, false );
+}
+
+void CVPC::ResolveMacrosInConditional( char const *pString, char *pOutBuff, int outBuffSize )
+{
+ ResolveMacrosInStringInternal( pString, pOutBuff, outBuffSize, true );
+}
+
+void CVPC::RemoveScriptCreatedMacros()
+{
+ for ( int i=0; i < m_Macros.Count(); i++ )
+ {
+ if ( !m_Macros[i].m_bInternalCreatedMacro )
+ {
+ m_Macros.Remove( i );
+ --i;
+ }
+ }
+}
+
+const char *CVPC::GetMacroValue( const char *pName )
+{
+ for ( int i = 0; i < m_Macros.Count(); i++ )
+ {
+ if ( !V_stricmp( pName, m_Macros[i].name.String() ) )
+ {
+ return m_Macros[i].value.String();
+ }
+ }
+
+ // not found
+ return "";
+}
diff --git a/external/vpc/utils/vpc/main.cpp b/external/vpc/utils/vpc/main.cpp
new file mode 100644
index 0000000..0caa9c9
--- /dev/null
+++ b/external/vpc/utils/vpc/main.cpp
@@ -0,0 +1,2810 @@
+//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+#include "dependencies.h"
+#include "p4sln.h"
+#include "ilaunchabledll.h"
+#include <time.h>
+
+DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_VPC, "VPC" );
+
+CVPC *g_pVPC;
+
+class CBaseProjectDataCollector;
+CUtlVector<CBaseProjectDataCollector*> g_vecPGenerators;
+
+// Stuff that we might encounter in a vpc file that parts of vpc care about
+const char *g_pOption_ImportLibrary = "$ImportLibrary";
+const char *g_pOption_OutputFile = "$OutputFile";
+const char *g_pOption_GameOutputFile = "$GameOutputFile";
+const char *g_pOption_AdditionalIncludeDirectories = "$AdditionalIncludeDirectories";
+const char *g_pOption_AdditionalProjectDependencies = "$AdditionalProjectDependencies";
+const char *g_pOption_AdditionalOutputFiles = "$AdditionalOutputFiles";
+const char *g_pOption_PreprocessorDefinitions = "$PreprocessorDefinitions";
+char *g_IncludeSeparators[2] = {";",","};
+
+#ifdef POSIX
+#define _unlink unlink
+#define _stat stat
+#endif
+
+CVPC::CVPC()
+{
+ m_pP4Module = NULL;
+ m_pFilesystemModule = NULL;
+
+ m_nArgc = 0;
+ m_ppArgv = NULL;
+
+ m_bVerbose = false;
+ m_bQuiet = false;
+ m_bUsageOnly = false;
+ m_bHelp = false;
+ m_bSpewPlatforms = false;
+ m_bSpewGames = false;
+ m_bSpewGroups = false;
+ m_bSpewProjects = false;
+ m_bIgnoreRedundancyWarning = false;
+ m_bSpewProperties = false;
+ m_bTestMode = false;
+ m_bGeneratedProject = false;
+ m_bAnyProjectQualified = false;
+ m_bForceGenerate = false;
+ m_bNoPosixPCH = false;
+ m_bEnableVpcGameMacro = true;
+ m_bDecorateProject = false;
+ m_bShowDeps = false;
+ m_bP4AutoAdd = false;
+ m_bP4SlnCheckEverything = false;
+ m_bInMkSlnPass = false;
+ m_bShowCaseIssues = false;
+ m_bVerboseMakefile = false;
+ m_bP4SCC = false;
+ m_b32BitTools = false;
+
+#ifdef VPC_SCC_INTEGRATION
+ m_bP4SCC = true;
+#endif
+ if ( getenv( "VPC_SRCCTL" ) != NULL )
+ {
+ m_bP4SCC = V_atoi( getenv( "VPC_SRCCTL" ) ) != 0;
+ }
+
+#ifdef WIN32
+ m_eVSVersion = k_EVSVersion_2015;
+ m_bUseVS2010FileFormat = true;
+ m_bUseUnity = false;
+#else
+ m_eVSVersion = k_EVSVersion_Invalid;
+ m_bUseVS2010FileFormat = false;
+ m_bUseUnity = false;
+#endif
+
+ m_FilesMissing = 0;
+
+ // need to check files by default, otherwise dependency failure (due to missing file) cause needles rebuilds
+ m_bCheckFiles = true;
+
+ m_pProjectGenerator = NULL;
+ m_pSolutionGenerator = NULL;
+
+#ifdef OSX
+ m_bForceIterate = true;
+#else
+ m_bForceIterate = false;
+#endif
+
+ m_pPhase1Projects = NULL;
+}
+
+CVPC::~CVPC()
+{
+ // BUGBUG: There is probably some actual cleanup to be done here.
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::Init( int argc, char **argv )
+{
+ m_nArgc = argc;
+ m_ppArgv = argv;
+
+ // vpc operates tersely by preferred company opinion
+ // verbosity necessary for debugging
+ m_bVerbose = ( HasCommandLineParameter( "/v" ) || HasCommandLineParameter( "/verbose" ) );
+ m_bQuiet = ( HasCommandLineParameter( "/q" ) ||
+ HasCommandLineParameter( "/quiet" ) ||
+ ( getenv( "VPC_QUIET" ) && V_stricmp( getenv( "VPC_QUIET" ), "0" ) ) );
+
+#ifndef STEAM
+ // We don't really need to pop the logging state since the process will terminate when we're done.
+ LoggingSystem_PushLoggingState();
+
+ m_LoggingListener.m_bQuietPrintf = m_bQuiet;
+ LoggingSystem_RegisterLoggingListener( &m_LoggingListener );
+#endif
+
+ // needs to occur early and before any other expensive setup, a crc check just exits with an error code used by caller
+ InProcessCRCCheck();
+
+ LoadPerforceInterface();
+
+ // vpc may have been run from wrong location, restart self
+ bool bIsRestart = false;
+ if ( RestartFromCorrectLocation( &bIsRestart ) )
+ {
+ // successfully ran under restart condition, all done
+ return false;
+ }
+ if ( bIsRestart )
+ {
+ // this process is the restart child, cull the internal private restart guard option
+ // otherwise it gets confused as a build option
+ m_nArgc--;
+ }
+
+ Log_Msg( LOG_VPC, "VPC - Valve Project Creator For " );
+ Log_Msg( LOG_VPC, "Visual Studio, Xbox 360, PlayStation 3, " );
+ Log_Msg( LOG_VPC, "Xcode and Make (Build: %s %s)\n", __DATE__, __TIME__ );
+ Log_Msg( LOG_VPC, "(C) Copyright 1996-2015, Valve Corporation, All rights reserved.\n" );
+ Log_Msg( LOG_VPC, "\n" );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::Shutdown( bool bHasError )
+{
+ if ( !bHasError )
+ {
+ GetScript().EnsureScriptStackEmpty();
+ }
+
+ if ( !m_TempGroupScriptFilename.IsEmpty() )
+ {
+ // delete temp work file
+ _unlink( m_TempGroupScriptFilename.Get() );
+ m_TempGroupScriptFilename.Clear();
+ }
+
+ UnloadPerforceInterface();
+}
+
+#if defined( STANDALONE_VPC )
+class CP4;
+extern CP4 s_p4;
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::LoadPerforceInterface()
+{
+ if ( p4 )
+ {
+ // already loaded
+ return true;
+ }
+
+#if defined( STANDALONE_VPC )
+ p4 = (IP4*)&s_p4;
+ return (p4 != NULL);
+#else
+
+ //
+ // Try to load p4lib.dll and the filesystem since the p4lib relies on it
+ //
+ char p4libdll[MAX_PATH];
+ char filesystemdll[MAX_PATH];
+
+#ifdef _WIN32
+ // Don't require them to have game\bin in their path. Since we know where vpc.exe is,
+ // point directly to p4lib.dll in its rightful place.
+ char szModuleBinPath[MAX_PATH];
+ GetModuleFileName( NULL, szModuleBinPath, sizeof( szModuleBinPath ) );
+ V_ExtractFilePath( szModuleBinPath, p4libdll, sizeof( p4libdll ) );
+ V_AppendSlash( p4libdll, sizeof( p4libdll ) );
+ V_strncpy( filesystemdll, p4libdll, sizeof( filesystemdll ) );
+ V_strncat( p4libdll, "..\\..\\..\\game\\bin\\p4lib.dll", sizeof( p4libdll ) );
+ V_strncat( filesystemdll, "..\\..\\..\\game\\bin\\filesystem_stdio.dll", sizeof( filesystemdll ) );
+#else
+ V_strncpy( p4libdll, "p4lib", sizeof( p4libdll ) );
+ V_strncpy( filesystemdll, "filesystem_stdio", sizeof( filesystemdll ) );
+#endif
+
+ if ( !Sys_LoadInterface( p4libdll, P4_INTERFACE_VERSION, &m_pP4Module, (void**)&p4 ) )
+ {
+#ifdef _WIN32
+ // This always fails on non-Windows build machines -- the warning is
+ // annoying and not helpful.
+ VPCWarning( "Unable to get Perforce interface from p4lib.dll." );
+#endif
+ return false;
+ }
+
+ // Let the P4 module get its interface to the filesystem - hate this
+
+ // This method is not available in portal2, but is in source2.
+ // p4->SetVerbose( false );
+ m_pFilesystemModule = Sys_LoadModule( filesystemdll );
+ p4->Connect( Sys_GetFactory( m_pFilesystemModule ) );
+
+ return true;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::UnloadPerforceInterface()
+{
+ // Unload P4 if it was loaded
+ if ( m_pP4Module )
+ {
+ Sys_UnloadModule( m_pP4Module );
+ m_pP4Module = NULL;
+ }
+
+ if ( m_pFilesystemModule )
+ {
+ Sys_UnloadModule( m_pFilesystemModule );
+ m_pFilesystemModule = NULL;
+ }
+}
+
+
+bool VPC_Config_IgnoreOption( const char *pPropertyName )
+{
+ char buff[MAX_SYSTOKENCHARS];
+ g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::VPCError( const char* format, ... )
+{
+ va_list argptr;
+ char msg[MAX_SYSPRINTMSG];
+
+ va_start( argptr,format );
+ vsprintf( msg,format,argptr );
+ va_end( argptr );
+
+ // spew in red
+ Log_Warning( LOG_VPC, Color( 255, 0, 0, 255 ), "ERROR: %s\n", msg );
+
+ // dump the script stack to assist in user understading of the include chain
+ GetScript().SpewScriptStack();
+
+ // do proper shutdown in an error context
+ Shutdown( true );
+
+ // errors are expected to be fatal by all calling code
+ // otherwise it would have been a warning
+ exit( 1 );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::VPCSyntaxError( const char* format, ... )
+{
+ va_list argptr;
+ char msg[MAX_SYSPRINTMSG];
+
+ va_start( argptr, format );
+ if ( format )
+ {
+ vsprintf( msg, format, argptr );
+ }
+ va_end( argptr );
+
+ if ( format )
+ {
+ Log_Warning( LOG_VPC, Color( 255, 0, 0, 255 ), "Bad Syntax: %s\n", msg );
+ }
+
+ // syntax errors are fatal
+ VPCError( "Bad Syntax in '%s' line:%d\n", GetScript().GetName(), GetScript().GetLine() );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::VPCWarning( const char* format, ... )
+{
+ va_list argptr;
+ char msg[MAX_SYSPRINTMSG];
+
+ va_start( argptr,format );
+ vsprintf( msg,format,argptr );
+ va_end( argptr );
+
+ if ( m_bIgnoreRedundancyWarning )
+ {
+ if ( V_stristr( msg, "matches default setting" ) )
+ return;
+ if ( V_stristr( msg, "already exists in project" ) )
+ return;
+ }
+
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "WARNING: %s\n", msg );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::VPCStatus( bool bAlwaysSpew, const char* format, ... )
+{
+ if ( m_bQuiet )
+ return;
+
+ va_list argptr;
+ char msg[MAX_SYSPRINTMSG];
+
+ va_start( argptr,format );
+ vsprintf( msg,format,argptr );
+ va_end( argptr );
+
+ if ( bAlwaysSpew || m_bVerbose )
+ {
+ Log_Msg( LOG_VPC, "%s\n", msg );
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int CVPC::GetProjectsInGroup( CUtlVector< projectIndex_t > &projectList, const char *pGroupName )
+{
+ projectList.RemoveAll();
+
+ // Find the specified group
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( pGroupName, false );
+
+ if ( groupTagIndex != INVALID_INDEX )
+ {
+ FOR_EACH_VEC( m_GroupTags[groupTagIndex].groups, m )
+ {
+ FOR_EACH_VEC( m_Groups[m_GroupTags[groupTagIndex].groups[m]].projects, n )
+ {
+ projectList.AddToTail( m_Groups[m_GroupTags[groupTagIndex].groups[m]].projects[n] );
+ }
+ }
+ }
+
+ return projectList.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Checks to ensure the bin path is in the same tree as the vpc_scripts
+// Returns true if bin path valid
+//-----------------------------------------------------------------------------
+#if !defined( POSIX )
+bool CVPC::CheckBinPath( char *pOutBinPath, int outBinPathSize )
+{
+ char szScriptPath[MAX_PATH];
+ char szDirectory[MAX_PATH];
+ char szLastDirectory[MAX_PATH];
+
+ // non destructively determine the vpc_scripts directory
+ bool bFound = false;
+ szLastDirectory[0] = '\0';
+ szScriptPath[0] = '\0';
+ V_GetCurrentDirectory( szDirectory, sizeof( szDirectory ) );
+ while ( 1 )
+ {
+ V_ComposeFileName( szDirectory, "vpc_scripts", szScriptPath, sizeof( szScriptPath ) );
+ struct _stat statBuf;
+ if ( _stat( szScriptPath, &statBuf ) != -1 )
+ {
+ bFound = true;
+ break;
+ }
+
+ // previous dir
+ V_ComposeFileName( szDirectory, "..", szScriptPath, sizeof( szScriptPath ) );
+
+ char fullPath[MAX_PATH];
+ if ( _fullpath( fullPath, szScriptPath, sizeof( fullPath ) ) )
+ {
+ V_strncpy( szDirectory, fullPath, sizeof( szDirectory ) );
+ }
+
+ if ( !V_stricmp( szDirectory, szLastDirectory ) )
+ {
+ // can back up no further
+ break;
+ }
+ strcpy( szLastDirectory, szDirectory );
+ }
+
+ if ( !bFound )
+ {
+ VPCError( "Failed to determine source directory from current path. Expecting 'vpc_scripts' in source path." );
+ }
+
+ char szSourcePath[MAX_PATH];
+ strcpy( szSourcePath, szDirectory );
+
+ // check to ensure that executeable and src directory are in the same tree
+ // executeable needs to be tightly bound to its vpc_scripts
+ char szModuleBinPath[MAX_PATH];
+ GetModuleFileName( NULL, szModuleBinPath, sizeof( szModuleBinPath ) );
+
+ // cannot trust output from GetModuleFileName(), occasionally has ./ or ../ screwing up comparisons
+ V_RemoveDotSlashes( szModuleBinPath, '\\' );
+ V_strlower( szModuleBinPath );
+ V_strncpy( pOutBinPath, szModuleBinPath, outBinPathSize );
+
+ // allowed to run from a root "devbin", for use with junctions
+ if ( Sys_StringPatternMatch( "?:\\devbin\\vpc.exe", szModuleBinPath ) )
+ return true;
+
+ char *pString = V_stristr( szModuleBinPath, "\\devtools\\bin\\" );
+ if ( pString )
+ {
+ // source dirs should match
+ char chSave = *pString;
+ *pString = '\0';
+ bool bSame = V_stricmp( szSourcePath, szModuleBinPath ) == 0;
+ *pString = chSave;
+
+ if ( bSame )
+ {
+ return true;
+ }
+ }
+ else
+ {
+ VPCError( "Executable not running from 'devtools/bin' but from unexpected directory '%s'", szModuleBinPath );
+ }
+
+ // mismatched, wierd bin patch could have been a result of user's environment path
+ // use expected source path which is based on user's cwd to get the real bin path
+ V_strncpy( pOutBinPath, szSourcePath, outBinPathSize );
+ V_strncat( pOutBinPath, "\\devtools\\bin\\vpc.exe", outBinPathSize );
+ struct _stat statBuf;
+ if ( _stat( pOutBinPath, &statBuf ) == -1 )
+ {
+ VPCError( "Correct executeable missing, should be at '%s'", pOutBinPath );
+ }
+
+ // yikes, wrong executeable was started, agreed behavior was to restart based on user's cwd
+ // REALLY want users to see this, it indicates a possible hazard of using the wrong vpc
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "********************************************************************************\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "Wrong Executable '%s' Running!\nRestarting at '%s'\n", szModuleBinPath, pOutBinPath );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "********************************************************************************\n" );
+
+ return false;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::DetermineSourcePath()
+{
+ char szSourcePath[MAX_PATH];
+ char szLastDirectory[MAX_PATH];
+
+ char szOldPath[MAX_PATH];
+ V_GetCurrentDirectory( szOldPath, sizeof( szOldPath ) );
+
+ // find vpc_scripts from cwd
+ szLastDirectory[0] = '\0';
+ bool bFound = false;
+ while ( 1 )
+ {
+ V_GetCurrentDirectory( szSourcePath, sizeof( szSourcePath ) );
+ if ( !V_stricmp( szSourcePath, szLastDirectory ) )
+ {
+ // can back up no further
+ break;
+ }
+ V_strncpy( szLastDirectory, szSourcePath, sizeof( szLastDirectory ) );
+
+ char szTestDir[MAX_PATH];
+ V_ComposeFileName( szSourcePath, "vpc_scripts", szTestDir, sizeof( szTestDir ) );
+ struct _stat statBuf;
+ if ( _stat( szTestDir, &statBuf ) != -1 )
+ {
+ bFound = true;
+ break;
+ }
+
+ // previous dir
+ char szPrevDir[MAX_PATH];
+ V_ComposeFileName( szSourcePath, "..", szPrevDir, sizeof( szPrevDir ) );
+ V_SetCurrentDirectory( szPrevDir );
+ }
+
+ if ( !bFound )
+ {
+ VPCError( "Failed to determine source directory from current path. Expecting 'vpc_scripts' in source path." );
+ }
+
+ // Remember the source path and restore the path to where it was.
+ m_SourcePath = szSourcePath;
+ V_SetCurrentDirectory( szOldPath );
+
+ // always emit source path, identifies MANY redundant user problems
+ // users can easily run from an unintended place due to botched path, mangled directories, etc
+ Log_Msg( LOG_VPC, "Source Path: %s\n", m_SourcePath.Get() );
+}
+
+//-----------------------------------------------------------------------------
+// Sets the working directory to .../vpc_scripts as all scripts are
+// guaranteed relative to the vpc script directory.
+//-----------------------------------------------------------------------------
+void CVPC::SetDefaultSourcePath()
+{
+ V_SetCurrentDirectory( m_SourcePath.Get() );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::IsProjectCurrent( const char *pOutputFilename, bool bSpewStatus )
+{
+ // default is project is stale
+ if ( !Sys_Exists( pOutputFilename ) )
+ {
+ return false;
+ }
+
+ if ( Is2010() && !Sys_Exists( CFmtStr( "%s.filters", pOutputFilename ) ) )
+ {
+ return false;
+ }
+
+ char errorString[1024];
+ bool bCRCValid = VPC_CheckProjectDependencyCRCs( pOutputFilename, m_SupplementalCRCString.Get(), errorString, sizeof( errorString ) );
+
+ if ( bSpewStatus )
+ {
+ if ( bCRCValid )
+ {
+ VPCStatus( true, "Valid: '%s' Passes CRC Checks.", pOutputFilename );
+ }
+ else
+ {
+ VPCStatus( true, "Stale: '%s' Requires Rebuild. [%s]", pOutputFilename, errorString );
+ }
+ }
+
+ return bCRCValid;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::SpewUsage( void )
+{
+ // skip header if user requested specific detail
+ bool bNoHeader =
+ m_bSpewPlatforms ||
+ m_bSpewGames ||
+ m_bSpewProjects ||
+ m_bSpewGroups ||
+ m_bSpewProperties ||
+ m_BuildCommands.Count();
+
+ if ( !bNoHeader )
+ {
+ Log_Msg( LOG_VPC, "\n" );
+
+ if ( !m_bHelp )
+ {
+ // terse
+ Log_Msg( LOG_VPC, "Type vpc /h for help...\n" );
+ }
+ else
+ {
+ // verbose
+ Log_Msg( LOG_VPC, "usage: vpc [options] <+/-/*project or group>\n");
+
+ Log_Msg( LOG_VPC, "\n" );
+ Log_Msg( LOG_VPC, "Examples:\n" );
+
+ Log_Msg( LOG_VPC, "\n" );
+ Log_Msg( LOG_VPC, " Single .vcproj generation:\n" );
+ Log_Msg( LOG_VPC, " vpc +client /hl2 <-- Creates a Win32 .vcproj for the HL2 client.\n" );
+ Log_Msg( LOG_VPC, " vpc +shaderapi /x360 <-- Creates a Xbox360 .vcproj for the shaderapi.\n" );
+
+ Log_Msg( LOG_VPC, "\n" );
+ Log_Msg( LOG_VPC, " Multiple .vcproj generation - Multiple Projects for Games and Platforms:\n" );
+ Log_Msg( LOG_VPC, " vpc +client /hl2 /tf <-- Creates ALL the Win32 .vcprojs for the HL2 and TF client.\n" );
+ Log_Msg( LOG_VPC, " vpc +gamedlls /allgames <-- Creates ALL the Win32 .vcprojs for client and server for all GAMES.\n" );
+ Log_Msg( LOG_VPC, " vpc +tools -tier0 /win32 /x360 <-- Creates ALL the Win32 and Xbox360 .vcprojs for the tool projects but not the tier0 project.\n" );
+
+ Log_Msg( LOG_VPC, "\n" );
+ Log_Msg( LOG_VPC, " Use +/- to add or remove projects or groups.\n");
+ Log_Msg( LOG_VPC, " Use * to add a project and all projects that depend on it.\n");
+ Log_Msg( LOG_VPC, " Use @ to add a project and all projects that it depends on.\n");
+ Log_Msg( LOG_VPC, " Use /h spew final target build set only (no .vcproj created).\n");
+ Log_Msg( LOG_VPC, "\n" );
+ Log_Msg( LOG_VPC, " Further details can be found on Valve Internal Wiki on VPC.\n" );
+
+ Log_Msg( LOG_VPC, "\n--- OPTIONS ---\n" );
+ Log_Msg( LOG_VPC, "[/q]: Quiet mode (quiet mode is automatically on if the VPC_QUIET environment variable is set)\n" );
+ Log_Msg( LOG_VPC, "[/v]: Verbose\n" );
+ Log_Msg( LOG_VPC, "[/f]: Force generate .vcproj, otherwise use crc checks\n" );
+ Log_Msg( LOG_VPC, "[/dp]: Decorate project names with platform\n" );
+ Log_Msg( LOG_VPC, "[/testmode]: Override output .vcproj file to be named 'test.vcproj'\n" );
+#ifdef VPC_SCC_INTEGRATION
+ Log_Msg( LOG_VPC, "[/nosrcctl]: Disable P4SCC source control integration - can also set environment variable VPC_SRCCTL to 0\n" );
+#else
+ Log_Msg( LOG_VPC, "[/srcctl]: Enable P4SCC source control integration - can also set environment variable VPC_SRCCTL to 1\n" );
+#endif
+ Log_Msg( LOG_VPC, "[/mirror]: <path> - Mirror output files to specified path. Used for A:B testing.\n" );
+ Log_Msg( LOG_VPC, "[/2015]: Generate projects and solutions for Visual Studio 2015 [default]\n" );
+ Log_Msg( LOG_VPC, "[/2013]: Generate projects and solutions for Visual Studio 2013\n" );
+ Log_Msg( LOG_VPC, "[/2012]: Generate projects and solutions for Visual Studio 2012\n" );
+ Log_Msg( LOG_VPC, "[/2010]: Generate projects and solutions for Visual Studio 2010\n" );
+ Log_Msg( LOG_VPC, "[/2005]: Generate projects and solutions for Visual Studio 2005\n" );
+ Log_Msg( LOG_VPC, "[/2008]: Generate projects and solutions for Visual Studio 2008\n" );
+ Log_Msg( LOG_VPC, "[/windows]: Generate projects for both Win32 and Win64\n" );
+ Log_Msg( LOG_VPC, "[/unity]: Enable unity file generation\n" );
+ Log_Msg( LOG_VPC, "[/32bittools]: Specify 32-bit toolchain in VC++ even when compiling 64 bit target\n" );
+
+ Log_Msg( LOG_VPC, "\n--- Help ---\n" );
+ Log_Msg( LOG_VPC, "[/h]: Help\n" );
+ Log_Msg( LOG_VPC, "[/?]: Help\n" );
+ Log_Msg( LOG_VPC, "[/platforms]: Spew Platforms\n" );
+ Log_Msg( LOG_VPC, "[/games]: Spew Games\n" );
+ Log_Msg( LOG_VPC, "[/projects]: Spew Projects\n" );
+ Log_Msg( LOG_VPC, "[/groups]: Spew Groups\n" );
+ Log_Msg( LOG_VPC, "[/properties]: Spew VS2005 Properties\n" );
+
+ Log_Msg( LOG_VPC, "\n--- Conditionals ---\n" );
+ Log_Msg( LOG_VPC, "[/profile]: Set Reserved $PROFILE=1\n" );
+ Log_Msg( LOG_VPC, "[/retail]: Set Reserved $RETAIL=1\n" );
+ Log_Msg( LOG_VPC, "[/callcap]: Set Reserved $CALLCAP=1\n" );
+ Log_Msg( LOG_VPC, "[/fastcap]: Set Reserved $FASTCAP=1\n" );
+ Log_Msg( LOG_VPC, "[/memtest]: Set Reserved $MEMTEST=1\n" );
+ Log_Msg( LOG_VPC, "[/nofpo]: Set Reserved $NOFPO=1\n" );
+ Log_Msg( LOG_VPC, "[/lv]: Set Reserved $LV=1\n" );
+ Log_Msg( LOG_VPC, "[/demo]: Set Reserved $DEMO=1\n" );
+ Log_Msg( LOG_VPC, "[/no_steam]: Set Reserved $NO_STEAM=1\n" );
+ Log_Msg( LOG_VPC, "[/qtdebug]: Set Reserved $QTDEBUG=1\n" );
+ Log_Msg( LOG_VPC, "[/no_ceg]: Set Reserved $NO_CEG=1\n" );
+ Log_Msg( LOG_VPC, "[/upload_ceg]: Set Reserved $UPLOAD_CEG=1\n" );
+
+ Log_Msg( LOG_VPC, "\n--- Other ---\n" );
+ Log_Msg( LOG_VPC, "[/mksln]: <.sln filename> - make a solution file\n" );
+ Log_Msg( LOG_VPC, "[/p4sln]: <.sln filename> <changelists...> - make a solution file based on\n" );
+ Log_Msg( LOG_VPC, " the changelist. Changelists can be specific numbers, 0 or \"default\"\n" );
+ Log_Msg( LOG_VPC, " for the default changelist, or \"all\" for all active changelists.\n" );
+ Log_Msg( LOG_VPC, "[/nop4add]: Don't automatically add project files to Perforce\n" );
+ Log_Msg( LOG_VPC, "[/slnitems]: <filename> - adds all files listed in <filename> to generated\n" );
+ Log_Msg( LOG_VPC, " solutions\n" );
+ Log_Msg( LOG_VPC, "[/showdeps]: Show an example dependency chain for each project that depends\n" );
+ Log_Msg( LOG_VPC, " on your p4 change list(s). Use with /p4sln.\n" );
+ Log_Msg( LOG_VPC, "[/checkfiles]: Check for the existence of files in $file commands. For debugging vpc files.\n" );
+ Log_Msg( LOG_VPC, " Only works if the currrent directory is the project directory.\n" );
+// Log_Msg( LOG_VPC, "[/novpcgame]: Disable reserved vpc macro $VPCGAME and $VPCGAMECAPS.\n" );
+// Log_Msg( LOG_VPC, " By default if a single game is specified on command line, then that specified\n" );
+// Log_Msg( LOG_VPC, " game name will be used as a value for $VPCGAME and $VPCGAMECAPS macros.\n" );
+ Log_Msg( LOG_VPC, "[/define:xxx]: Enable a custom conditional $XXX to use for quick testing in VPC files.\n" );
+ }
+ }
+
+ if ( m_Conditionals.Count() && m_bSpewPlatforms )
+ {
+ bool bFirstDefine = false;
+ for ( int i = 0; i < m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != CONDITIONAL_PLATFORM )
+ continue;
+ if ( !bFirstDefine )
+ {
+ Log_Msg( LOG_VPC, "\n--- PLATFORMS ---\n" );
+ bFirstDefine = true;
+ }
+ Log_Msg( LOG_VPC, "%s%s\n", m_Conditionals[i].upperCaseName.String(), m_Conditionals[i].m_bDefined ? " = 1" : "" );
+ }
+ }
+
+ if ( m_Conditionals.Count() && m_bSpewGames )
+ {
+ bool bFirstGame = false;
+ for ( int i = 0; i < m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != CONDITIONAL_GAME )
+ continue;
+ if ( !bFirstGame )
+ {
+ Log_Msg( LOG_VPC, "\n--- GAMES ---\n" );
+ bFirstGame = true;
+ }
+ Log_Msg( LOG_VPC, "%s%s\n", m_Conditionals[i].upperCaseName.String(), m_Conditionals[i].m_bDefined ? " = 1" : "" );
+ }
+ }
+
+ if ( m_Projects.Count() && m_bSpewProjects )
+ {
+ // spew all sorted projects
+ Log_Msg( LOG_VPC, "\n--- PROJECTS ---\n" );
+ CUtlRBTree< const char * > sorted( 0, 0, CaselessStringLessThan );
+ for ( int i = 0; i < m_Projects.Count(); i++ )
+ {
+ sorted.Insert( m_Projects[i].name.String() );
+ }
+ for ( int i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) )
+ {
+ Log_Msg( LOG_VPC, "[+/-] %s\n", sorted[i] );
+ }
+ }
+
+ if ( g_pVPC->m_GroupTags.Count() && m_bSpewGroups )
+ {
+ // spew all sorted groups
+ Log_Msg( LOG_VPC, "\n--- GROUPS ---\n" );
+ CUtlRBTree< const char * > sorted( 0, 0, CaselessStringLessThan );
+ for ( int i = 0; i < g_pVPC->m_GroupTags.Count(); i++ )
+ {
+ if ( !g_pVPC->m_GroupTags[i].bSameAsProject )
+ {
+ sorted.Insert( g_pVPC->m_GroupTags[i].name.String() );
+ }
+ }
+ for ( int i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) )
+ {
+ Log_Msg( LOG_VPC, "[+/-] %s\n", sorted[i] );
+ }
+ }
+
+#if 0
+#if defined( _WIN32 )
+ if ( m_bSpewProperties )
+ {
+ for ( int i = 0; i < KEYWORD_MAX; i++ )
+ {
+ VPC_Config_SpewProperties( (configKeyword_e)i );
+ }
+ }
+#endif
+#endif
+
+ if ( m_BuildCommands.Count() )
+ {
+ // spew details about each command
+ Log_Msg( LOG_VPC, "\nUser Build Commands:\n" );
+ Log_Msg( LOG_VPC, "--------------------\n" );
+ for ( int i = 0; i < m_BuildCommands.Count(); i++ )
+ {
+ Log_Msg( LOG_VPC, "%s\n", m_BuildCommands[i].String() );
+ groupTagIndex_t groupTagIndex = VPC_Group_FindOrCreateGroupTag( m_BuildCommands[i].Get()+1, false );
+ if ( groupTagIndex == INVALID_INDEX )
+ {
+ Log_Msg( LOG_VPC, " ??? (Unknown Group)\n" );
+ }
+ else
+ {
+ groupTag_t *pGroupTag = &g_pVPC->m_GroupTags[groupTagIndex];
+ for (int j=0; j<pGroupTag->groups.Count(); j++ )
+ {
+ group_t *pGroup = &m_Groups[pGroupTag->groups[j]];
+ for ( int k=0; k<pGroup->projects.Count(); k++ )
+ {
+ Log_Msg( LOG_VPC, " %s\n", m_Projects[pGroup->projects[k]].name.String() );
+ }
+ }
+ }
+ }
+
+ Log_Msg( LOG_VPC, "\nTarget Projects:\n" );
+ Log_Msg( LOG_VPC, "----------------\n" );
+ if ( m_TargetProjects.Count() )
+ {
+ for ( int i=0; i<m_TargetProjects.Count(); i++ )
+ {
+ Log_Msg( LOG_VPC, "%s\n", m_Projects[m_TargetProjects[i]].name.String() );
+ }
+ }
+ else
+ {
+ Log_Msg( LOG_VPC, "Empty Set (no output)\n" );
+ }
+
+ Log_Msg( LOG_VPC, "\nTarget Games:\n" );
+ Log_Msg( LOG_VPC, "-------------\n" );
+ bool bHasDefine = false;
+ for ( int i=0; i<m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != CONDITIONAL_GAME )
+ continue;
+ if ( m_Conditionals[i].m_bDefined )
+ {
+ Log_Msg( LOG_VPC, "$%s = 1\n", m_Conditionals[i].upperCaseName.String() );
+ bHasDefine = true;
+ }
+ }
+ if ( !bHasDefine )
+ {
+ Log_Msg( LOG_VPC, "No Game Set!\n" );
+ }
+
+ Log_Msg( LOG_VPC, "\nTarget Platforms:\n" );
+ Log_Msg( LOG_VPC, "-----------------\n" );
+ bHasDefine = false;
+ for ( int i=0; i<m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != CONDITIONAL_PLATFORM )
+ continue;
+ if ( m_Conditionals[i].m_bDefined )
+ {
+ Log_Msg( LOG_VPC, "$%s = 1\n", m_Conditionals[i].upperCaseName.String() );
+ bHasDefine = true;
+ }
+ }
+ if ( !bHasDefine )
+ {
+ Log_Msg( LOG_VPC, "No Platform Set!\n" );
+ }
+
+ Log_Msg( LOG_VPC, "\nCustom Conditionals:\n" );
+ Log_Msg( LOG_VPC, "---------------------\n" );
+ bHasDefine = false;
+ for ( int i=0; i<m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type != CONDITIONAL_CUSTOM )
+ continue;
+ if ( m_Conditionals[i].m_bDefined )
+ {
+ Log_Msg( LOG_VPC, "$%s = 1\n", m_Conditionals[i].upperCaseName.String() );
+ bHasDefine = true;
+ }
+ }
+ if ( !bHasDefine )
+ {
+ Log_Msg( LOG_VPC, "No Custom Defines Set!\n" );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::HandleSingleCommandLineArg( const char *pArg )
+{
+ if ( ( pArg[0] == '-' ) || ( pArg[0] == '/' ) )
+ {
+ // skip past arg prefix
+ const char *pArgName = pArg+1;
+
+ // check options
+ if ( !V_stricmp( pArgName, "h" ) || !V_stricmp( pArgName, "?" ) || !V_stricmp( pArgName, "help" ) )
+ {
+ m_bHelp = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "v" ) || !V_stricmp( pArgName, "verbose" ) )
+ {
+ m_bVerbose = true;
+ }
+ else if ( !V_stricmp( pArgName, "testmode" ) || !V_stricmp( pArgName, "test" ) )
+ {
+ m_bTestMode = true;
+ }
+ else if ( !V_stricmp( pArgName, "f" ) || !V_stricmp( pArgName, "force" ) )
+ {
+ m_bForceGenerate = true;
+ }
+ else if ( !V_stricmp( pArgName, "no_posix_pch" ) )
+ {
+ // Not implemented for win32 generators since those just pass through raw options :-/
+ m_bNoPosixPCH = true;
+ // Ensure this changes CRC. Ideally it would only change if anything ended up using the PCH conditional
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "novpcgame" ) )
+ {
+ m_bEnableVpcGameMacro = false;
+ }
+ else if ( !V_stricmp( pArgName, "checkfiles" ) )
+ {
+ m_bCheckFiles = true;
+ }
+ else if ( !V_stricmp( pArgName, "nocheckfiles" ) )
+ {
+ m_bCheckFiles = false;
+ }
+ else if ( !V_stricmp( pArgName, "showcaseissues" ) || !V_stricmp( pArgName, "showcase" ) )
+ {
+ m_bShowCaseIssues = true;
+ }
+ else if ( !V_stricmp( pArgName, "dp" ) )
+ {
+ m_bDecorateProject = true;
+ }
+ else if ( char const *szActualDecorateName = StringAfterPrefix( pArgName, "decorate:" ) )
+ {
+ m_bDecorateProject = true;
+ m_strDecorate = szActualDecorateName;
+ }
+ else if ( !V_stricmp( pArgName, "dedicated" ) )
+ {
+ m_bDedicatedBuild = true;
+ m_bAppendSrvToDedicated = true;
+ m_bUseValveBinDir = true;
+ }
+ else if ( !V_stricmp( pArgName, "use_valve_bin" ) )
+ {
+ m_bUseValveBinDir = true;
+ }
+ else if ( !V_stricmp( pArgName, "platforms" ) || !V_stricmp( pArgName, "plats" ) )
+ {
+ m_bSpewPlatforms = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "games" ) )
+ {
+ m_bSpewGames = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "projects" ) )
+ {
+ m_bSpewProjects = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "groups" ) )
+ {
+ m_bSpewGroups = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "properties" ) )
+ {
+ m_bSpewProperties = true;
+ m_bUsageOnly = true;
+ }
+ else if ( !V_stricmp( pArgName, "allgames" ) )
+ {
+ // shortcut for all games defined
+ for ( int j=0; j<m_Conditionals.Count(); j++ )
+ {
+ if ( m_Conditionals[j].type == CONDITIONAL_GAME )
+ {
+ m_Conditionals[j].m_bDefined = true;
+ }
+ }
+ }
+ else if ( !V_stricmp( pArgName, "showdeps" ) )
+ {
+ m_bShowDeps = true;
+ }
+ else if ( !V_stricmp( pArgName, "nop4add" ) )
+ {
+ m_bP4AutoAdd = false;
+ }
+ else if ( !V_stricmp( pArgName, "2005" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2005;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "2008" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2008;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "2010" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2010;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "2012" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2012;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "2013" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2013;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "2015" ) )
+ {
+ m_eVSVersion = k_EVSVersion_2015;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "nounity" ) )
+ {
+ m_bUseUnity = false;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "unity" ) )
+ {
+ m_bUseUnity = true;
+ m_ExtraOptionsCRCString += pArgName;
+ }
+ else if ( !V_stricmp( pArgName, "verbosemakefile" ) )
+ {
+ m_bVerboseMakefile = true;
+ }
+ else if ( char const *szActualDefineName = StringAfterPrefix( pArgName, "define:" ) )
+ {
+ // allow setting custom defines straight from command line
+ conditional_t *pConditional = FindOrCreateConditional( szActualDefineName, true, CONDITIONAL_CUSTOM );
+ if ( pConditional )
+ {
+ pConditional->m_bDefined = true;
+
+ m_ExtraOptionsCRCString += "/define:"; // force this into additional CRC string
+ m_ExtraOptionsCRCString += pConditional->name.Get(); // force this into additional CRC string
+ }
+ }
+ else if ( !V_stricmp( pArgName, "32bittools" ) )
+ {
+ m_b32BitTools = true; // use 32-bit toolchain even when building 64-bit targets
+ m_ExtraOptionsCRCString += pArgName; // Make sure these options affect the CRC.
+ }
+ else if ( !V_stricmp( pArgName, "nosrcctl" ) )
+ {
+ m_bP4SCC = false;
+ m_ExtraOptionsCRCString += pArgName; // Make sure these options affect the CRC.
+ }
+ else if ( !V_stricmp( pArgName, "srcctl" ) )
+ {
+ m_bP4SCC = true;
+ m_ExtraOptionsCRCString += pArgName; // Make sure these options affect the CRC.
+ }
+ else
+ {
+ // not a recognized option, try conditionals
+ // find in list of conditionals
+ conditional_t *pConditional = FindOrCreateConditional( pArgName, false, CONDITIONAL_NULL );
+ if ( !pConditional )
+ {
+ // not a recognized conditional, add to build commands
+ int index = m_BuildCommands.AddToTail();
+ m_BuildCommands[index] = pArg;
+ }
+ else
+ {
+ // found conditional, mark as defined
+ pConditional->m_bDefined = true;
+ }
+ }
+ }
+ else if ( pArg[0] == '+' || pArg[0] == '*' || pArg[0] == '@' )
+ {
+ // add to build commands
+ int index = m_BuildCommands.AddToTail();
+ m_BuildCommands[index] = pArg;
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::ParseBuildOptions( int argc, char *argv[] )
+{
+ m_bDedicatedBuild = false;
+ m_bAppendSrvToDedicated = false;
+ m_bUseValveBinDir = false;
+
+ // parse options
+ // prefer +??? or -??? prefix syntax for groups and /??? for options because less confusing for new vpc users
+ // for ease we will support -??? prefix syntax for matched options as well
+ for ( int i = 1; i < argc; i++ )
+ {
+ const char *pArg = argv[i];
+
+ if ( !V_stricmp( pArg, "/mksln" ) )
+ {
+ if ( !m_P4SolutionFilename.IsEmpty() )
+ {
+ VPCError( "Can't use /mksln with /p4sln." );
+ }
+
+ if ( (i+1) >= argc )
+ {
+ VPCError( "/mksln requires a filename after it." );
+ }
+
+ // If the next parameter is a standard + or - or / or * parameter, then we take that to be the name of the solution file.
+ // So vpc /mksln +engine would generate engine.sln.
+ if ( argv[i+1][0] == '+' || argv[i+1][0] == '-' || argv[i+1][0] == '/' || argv[i+1][0] == '*' || argv[i+1][0] == '@' )
+ {
+ m_MKSolutionFilename = &argv[i+1][1];
+ }
+ else
+ {
+ m_MKSolutionFilename = argv[i+1];
+ ++i;
+ }
+ }
+ else if ( !V_stricmp( pArg, "/p4sln" ) )
+ {
+ if ( !m_MKSolutionFilename.IsEmpty() )
+ {
+ VPCError( "Can't use /mksln with /p4sln." );
+ }
+
+ // Get the solution filename.
+ ++i;
+ if ( i >= argc || argv[i][0] == '+' || argv[i][0] == '-' || argv[i][0] == '/' || argv[i][0] == '*' || argv[i][0] == '@' )
+ {
+ VPCError( "%s <solution filename> <changelist number> [ [restrict_to_group] ].", pArg );
+ }
+
+ m_P4SolutionFilename = argv[i];
+
+ // Get the changelist number.
+ while ( 1 )
+ {
+ ++i;
+
+ // No more args?
+ if ( i >= argc )
+ break;
+
+ // Special syntax for including all changelists.
+ if ( V_stricmp( argv[i], "all" ) == 0 )
+ {
+ m_iP4Changelists.AddToTail( -1 );
+ continue;
+ }
+
+ // Special syntax for including default changelists.
+ if ( V_stricmp( argv[i], "default" ) == 0 )
+ {
+ m_iP4Changelists.AddToTail( 0 );
+ continue;
+ }
+
+ // This arg isn't a changelist number?
+ if ( argv[i][0] < '0' || argv[i][0] > '9' )
+ {
+ --i;
+ break;
+ }
+
+ // Add the changelist number.
+ m_iP4Changelists.AddToTail( atoi( argv[i] ) );
+ }
+
+ // Make sure at least one changelist number was specified.
+ if ( m_iP4Changelists.Count() == 0 )
+ {
+ VPCError( "%s <solution filename> <changelist number> [additional changelist numbers] [ [restrict_to_group] ].", pArg );
+ }
+
+ // Get the group restriction.
+ while ( 1 )
+ {
+ ++i;
+
+ // No more args?
+ if ( i >= argc )
+ break;
+
+ if ( argv[i][0] != '[' || argv[i][V_strlen( argv[i] ) - 1] != ']' )
+ {
+ // This arg isn't a group name
+ --i;
+ break;
+ }
+
+ // strip the braces
+ CUtlString groupName = argv[i];
+ int nLastChar = groupName.Length() - 1;
+ groupName = groupName.Slice( 1, nLastChar );
+
+ // Add the restricted group name
+ m_P4GroupRestrictions.AddToTail( groupName );
+ }
+ }
+ else if ( !V_stricmp( pArg, "/slnitems" ) )
+ {
+ // Get the solution items filename
+ ++i;
+ if ( i >= argc || argv[i][0] == '+' || argv[i][0] == '-' || argv[i][0] == '/' || argv[i][0] == '*' || argv[i][0] == '@' )
+ {
+ VPCError( "/slnitems <solution items filename>." );
+ }
+
+ m_SolutionItemsFilename = argv[i];
+ }
+ else if ( !V_stricmp( pArg, "/mirror" ) )
+ {
+ // force an output mirror, used for A:B comparison runs
+ ++i;
+ if ( i >= argc || argv[i][0] == '+' || argv[i][0] == '-' || argv[i][0] == '/' || argv[i][0] == '*' || argv[i][0] == '@' )
+ {
+ VPCError( "/mirror <absolute path>." );
+ }
+
+ m_OutputMirrorString = argv[i];
+ if ( !m_OutputMirrorString.IsEmpty() && !V_IsAbsolutePath( m_OutputMirrorString.Get() ) )
+ {
+ VPCError( "/mirror <path> requires an absolute path specification." );
+ }
+ }
+ else
+ {
+ HandleSingleCommandLineArg( pArg );
+ }
+ }
+
+ // If they did /p4sln but didn't specify any build commands, then have it check everything.
+ if ( m_iP4Changelists.Count() > 0 && m_BuildCommands.Count() == 0 )
+ {
+ m_bP4SlnCheckEverything = true;
+ }
+
+ CheckForInstalledXDK();
+}
+
+//-----------------------------------------------------------------------------
+// Generate a string supplemental to CRC data, derived from command-line options,
+// so varying certain command-line options can cause .VCPROJ rebuilds.
+//-----------------------------------------------------------------------------
+void CVPC::GenerateOptionsCRCString()
+{
+ m_SupplementalCRCString = "_";
+
+ conditional_t *pConditional = FindOrCreateConditional( "PROFILE", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Pr";
+ }
+
+ pConditional = FindOrCreateConditional( "RETAIL", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Rt";
+ }
+
+ pConditional = FindOrCreateConditional( "CALLCAP", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Cc";
+ }
+
+ pConditional = FindOrCreateConditional( "FASTCAP", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Fc";
+ }
+
+ pConditional = FindOrCreateConditional( "MEMTEST", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Mt";
+ }
+
+ pConditional = FindOrCreateConditional( "NOFPO", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Nf";
+ }
+
+ pConditional = FindOrCreateConditional( "LV", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Lv";
+ }
+
+ pConditional = FindOrCreateConditional( "DEMO", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Dm";
+ }
+
+ pConditional = FindOrCreateConditional( "NO_STEAM", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Ns";
+ }
+
+ pConditional = FindOrCreateConditional( "QTDEBUG", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Qt";
+ }
+
+ pConditional = FindOrCreateConditional( "NO_CEG", false, CONDITIONAL_NULL );
+
+ //
+ // !!NEVER INTEGRATE THIS CHANGE TO REL BRANCHES!!
+ // !!THIS TURNS OF CEG FOR NON-REL BRANCHES!!
+ // -Jeep & AaronN
+ //
+ //if ( pConditional && pConditional->m_bDefined )
+ if ( pConditional )
+ {
+ pConditional->m_bDefined = true;
+ m_SupplementalCRCString += "Nc";
+ }
+
+ pConditional = FindOrCreateConditional( "UPLOAD_CEG", false, CONDITIONAL_NULL );
+ if ( pConditional && pConditional->m_bDefined )
+ {
+ m_SupplementalCRCString += "Uc";
+ }
+
+ if ( !m_ExtraOptionsCRCString.IsEmpty() )
+ {
+ m_SupplementalCRCString += CFmtStr( "_%s_", m_ExtraOptionsCRCString.Get() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Restart self from correct location and re-run. Returns FALSE if not applicable,
+// otherwise TRUE if restart occurred.
+//-----------------------------------------------------------------------------
+bool CVPC::RestartFromCorrectLocation( bool *pIsChild )
+{
+#if defined( POSIX )
+ return false;
+#else
+ // recursive restart guard
+ // restart is a hidden internal param, always the last argument
+ // presence identifies spawned process
+ bool bIsRestart = false;
+ if ( !V_stricmp( m_ppArgv[m_nArgc-1], "/restart" ) )
+ {
+ bIsRestart = true;
+ }
+ *pIsChild = bIsRestart;
+
+ char szBinPath[MAX_PATH];
+ if ( !CheckBinPath( szBinPath, sizeof( szBinPath ) ) )
+ {
+ if ( bIsRestart )
+ {
+ VPCError( "Cyclical Restart: Tell A Programmer!, Aborting." );
+ }
+
+ // replicate arguments, add -restart as a recursion guard for the new process
+ char *newArgs[128];
+ if ( m_nArgc >= V_ARRAYSIZE( newArgs ) - 2 )
+ {
+ VPCError( "Excessive Arguments: Tell A Programmer!, Aborting." );
+ }
+ int i;
+ for ( i = 0; i < m_nArgc; i++ )
+ {
+ newArgs[i] = m_ppArgv[i];
+ }
+ newArgs[i++] = "/restart";
+ newArgs[i++] = NULL;
+
+ // restart using synchronous semantic, async semantic causes wierd hang
+ int status = _spawnv( _P_WAIT, szBinPath, newArgs );
+ if ( !status )
+ {
+ // called process exited normally
+ return true;
+ }
+ else if ( status > 0 )
+ {
+ // called process exited with error, pass it along
+ exit( status );
+ }
+
+ // called process could not be started
+ VPCError( "Restart of '%s' failed\n", szBinPath );
+ }
+
+ // process is running from correct location
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::CheckForInstalledXDK()
+{
+#ifndef POSIX
+ if ( !IsPlatformDefined( "X360" ) )
+ {
+ // caller not doing any 360 work, so ignore
+ return;
+ }
+
+ // quick and dirty early check for 360 XDK ability
+ // can only detect simplistic condition, VPC can't validate a perfect XDK/MSDEV installation
+ bool bHasXDK = false;
+ const char *pXDK = getenv( "XEDK" );
+ if ( pXDK && pXDK[0] )
+ {
+ // look for expected compiler
+ char fullPath[MAX_PATH];
+ V_strncpy( fullPath, pXDK, sizeof( fullPath ) );
+ V_AppendSlash( fullPath, sizeof( fullPath ) );
+ V_strncat( fullPath, "bin\\win32\\cl.exe", sizeof( fullPath ) );
+ int fileSize = Sys_FileLength( fullPath, false );
+ if ( fileSize > 0 )
+ {
+ bHasXDK = true;
+ }
+ }
+ if ( !bHasXDK )
+ {
+ VPCError( "Cannot Build For Xbox 360, XDK is missing or damaged. Remove /x360 from command line." );
+ }
+#endif
+}
+
+void CVPC::CreateOutputFilename( project_t *pProject, const char *pchPlatform, const char *pchPhase, const char *pGameName, const char *pchExtension )
+{
+ const char *pProjectFileNamePrefix = m_bTestMode ? "test" : pProject->name.String();
+
+ m_OutputFilename = pProjectFileNamePrefix;
+
+ if ( pchPlatform && pchPlatform[0] )
+ {
+ // non-pc platforms get decorated
+ m_OutputFilename += "_";
+ m_OutputFilename += pchPlatform;
+ }
+
+ if( m_bAppendSrvToDedicated )
+ {
+ // Add _srv to the temp lib path. Ie: tier0/obj_tier0_linux32_srv
+ m_OutputFilename += "_srv";
+ }
+
+ if ( pchPhase && pchPhase[0] )
+ {
+ m_OutputFilename += "_";
+ m_OutputFilename += pchPhase;
+ }
+
+ if ( pGameName && pGameName[0] )
+ {
+ // game projects get decorated
+ m_OutputFilename += "_";
+ m_OutputFilename += pGameName;
+ }
+
+ if ( m_bDecorateProject )
+ {
+ char rgchDecorate[256] = "";
+ DecorateProjectName( rgchDecorate );
+ m_OutputFilename += rgchDecorate;
+ }
+
+ if ( pchExtension && pchExtension[0] )
+ {
+ m_OutputFilename += ".";
+ m_OutputFilename += pchExtension;
+ }
+}
+
+bool CVPC::BuildTargetProject( IProjectIterator *pIterator, projectIndex_t projectIndex, script_t *pProjectScript, const char *pGameName )
+{
+ // evaluate the project's script conditional which determines game/platform
+ if ( !EvaluateConditionalExpression( pProjectScript->m_condition.String() ) )
+ {
+ // conditionals prevent this project from consideration
+ return false;
+ }
+
+ // set once anything is expected to output
+ m_bAnyProjectQualified = true;
+
+ if ( !m_Projects.IsValidIndex( projectIndex ) )
+ {
+ // unexpected bad project index
+ Assert( 0 );
+ return false;
+ }
+ project_t *pProject = &m_Projects[projectIndex];
+
+ // track the internal project name, unaffected by user name mangling
+ m_ProjectName = pProject->name.String();
+ m_LoadAddressName = pProject->name.String();
+
+ // win32 projects are the most prevalent, so by popular demand they have no decoration
+ // all other platforms use their platform name as a suffix
+ const char *pPlatformName = NULL;
+ if ( !IsPlatformDefined( "win32" ) )
+ {
+ pPlatformName = GetTargetPlatformName();
+ }
+
+ //
+ // If we're doing multiple build phases, decorate the project
+ // names to indicate which phase they build in, and always include
+ // the platform.
+ //
+ const char *pPhaseName = NULL;
+ if ( FindOrCreateConditional( "phase2", false, CONDITIONAL_CUSTOM ) )
+ {
+ pPlatformName = GetTargetPlatformName();
+ pPhaseName = "phase2";
+ }
+ else if ( FindOrCreateConditional( "phase1", false, CONDITIONAL_CUSTOM ) )
+ {
+ pPlatformName = GetTargetPlatformName();
+ pPhaseName = "phase1";
+ }
+
+ // create a decorated project filename based on project/game/platform/etc
+ CreateOutputFilename(
+ pProject,
+ pPlatformName,
+ pPhaseName,
+ pGameName,
+ g_pVPC->GetProjectGenerator()->GetProjectFileExtension() );
+
+ // each vpc script is written with paths relative to their base
+ // force each script needs to start relative to their script location
+ // this allows vpc to be invoked anywhere, but the groups resolve their projects correctly
+ char szScriptPath[MAX_PATH];
+ V_ComposeFileName( g_pVPC->GetStartDirectory(), pProjectScript->name.String(), szScriptPath, sizeof( szScriptPath ) );
+ V_StripFilename( szScriptPath );
+ m_ProjectPath = szScriptPath;
+ V_SetCurrentDirectory( szScriptPath );
+
+ // build it
+ char szScriptName[MAX_PATH];
+ Sys_StripPath( pProjectScript->name.String(), szScriptName );
+ return pIterator->VisitProject( projectIndex, szScriptName );
+}
+
+//-----------------------------------------------------------------------------
+// Iterate and build each of the projects. Game projects can themselves be
+// auto-iterated to apply each of their mod variant.
+//-----------------------------------------------------------------------------
+void CVPC::IterateTargetProjects( CUtlVector<projectIndex_t> &projectList, IProjectIterator *pIterator )
+{
+ m_bGeneratedProject = false;
+ m_bAnyProjectQualified = false;
+
+ if ( !projectList.Count() )
+ {
+ // nothing to do
+ return;
+ }
+
+ for ( int nProject = 0; nProject < projectList.Count(); nProject++ )
+ {
+ project_t *pProject = &m_Projects[projectList[nProject]];
+
+ // each project can have 1 or more scripts that are predicated by game/platform conditionals (i.e. client or server)
+ for ( int nScript = 0; nScript < pProject->scripts.Count(); nScript++ )
+ {
+ script_t *pProjectScript = &pProject->scripts[nScript];
+
+ // occurrence of game condition(s) dictates iteration behavior
+ // client/server would have multiple game conditions
+ bool bHasGameCondition = g_pVPC->ConditionHasDefinedType( pProjectScript->m_condition.String(), CONDITIONAL_GAME );
+
+ if ( !bHasGameCondition )
+ {
+ // no game condition
+ BuildTargetProject( pIterator, projectList[nProject], pProjectScript, NULL );
+ }
+ else
+ {
+ // auto iterate through all defined game conditionals, setting each in turn
+ // this provides for building say client for all mod(s) that it can support
+ for ( int nTargetGame = 0; nTargetGame < m_Conditionals.Count(); nTargetGame++ )
+ {
+ if ( m_Conditionals[nTargetGame].type != CONDITIONAL_GAME || !m_Conditionals[nTargetGame].m_bDefined )
+ {
+ // the game conditions must be defined to be considered
+ // i.e. the user has specified to build /hl2 /tf2, but not /portal
+ continue;
+ }
+
+ // only one game condition is active during project generation
+ for ( int k = 0; k < m_Conditionals.Count(); k++ )
+ {
+ // unmark all game conditionals
+ if ( m_Conditionals[k].type == CONDITIONAL_GAME )
+ {
+ m_Conditionals[k].m_bGameConditionActive = false;
+ }
+ }
+ m_Conditionals[nTargetGame].m_bGameConditionActive = true;
+
+ BuildTargetProject( pIterator, projectList[nProject], pProjectScript, m_Conditionals[nTargetGame].name.String() );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Build all the projects in m_targetProjects.
+//-----------------------------------------------------------------------------
+bool CVPC::BuildTargetProjects()
+{
+ class CDefaultProjectIterator : public IProjectIterator
+ {
+ public:
+ virtual bool VisitProject( projectIndex_t iProject, const char *pScriptPath )
+ {
+ Log_Msg( LOG_VPC, "\n" );
+
+ // check project's crc signature
+ if ( !g_pVPC->IsForceGenerate() && g_pVPC->IsProjectCurrent( g_pVPC->GetOutputFilename(), true ) && !g_pVPC->IsForceIterate() )
+ {
+ // valid, does not need to build
+ return false;
+ }
+
+ return g_pVPC->ParseProjectScript( pScriptPath, 0, false, true );
+ }
+ };
+
+ if ( !m_TargetProjects.Count() )
+ {
+ VPCError( "No recognized project(s) to build. Use /h or /projects or /groups to spew more info." );
+ }
+
+ /* At this point we might've built the project dependency graph, which increments the missing file count
+ * if *any* project in your VPC directory has a missing file, so we reset it here to get the accurate count.
+ */
+ ResetMissingFilesCount();
+
+ CDefaultProjectIterator iterator;
+ IterateTargetProjects( m_TargetProjects, &iterator );
+
+ if ( GetMissingFilesCount() > 0 )
+ {
+ VPCError( "%d files missing. VPC failed.\n", GetMissingFilesCount() );
+ }
+
+ // Catch user attention to notify lack of any expected output
+ // Novice users would not be aware of expected conditionals
+ if ( !m_bGeneratedProject && !m_bAnyProjectQualified )
+ {
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "----------------------------\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "!!! No Project Generated !!!\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "----------------------------\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "Possibly missing game, platform, or other conditional expected by script.\n" );
+ Log_Warning( LOG_VPC, Color( 255, 255, 0, 255 ), "Use /h verify desired target build set.\n" );
+
+ return false;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Find the project that corresponds to the specified vcproj and setup
+// to build that project.
+//-----------------------------------------------------------------------------
+void CVPC::FindProjectFromVCPROJ( const char *pScriptNameVCProj )
+{
+ // caller is specifying the output vcproj, i.e. via tool shortcut from within MSDEV to re-gen
+ // use the vpc standardized output vcproj name to determine re-gen parameters
+ // mod and platform will be seperated by '_' after the project name
+ // resolve to correct project, best will be longest match, due to project names like foo_? and foo_bar_?
+ char szProject[MAX_PATH];
+ unsigned int bestLen = 0;
+ for ( int i = 0; i < m_Projects.Count(); i++ )
+ {
+ if ( V_stristr( pScriptNameVCProj, m_Projects[i].name.String() ) )
+ {
+ if ( bestLen < strlen( m_Projects[i].name.String() ) )
+ {
+ bestLen = strlen( m_Projects[i].name.String() );
+ strcpy( szProject, m_Projects[i].name.String() );
+ }
+ }
+ }
+ if ( bestLen == 0 )
+ {
+ VPCError( "Could not resolve '%s' to any known projects", pScriptNameVCProj );
+ }
+
+ // skip past known project
+ char szBuffer[MAX_PATH];
+ V_StripExtension( pScriptNameVCProj + strlen( szProject ), szBuffer, sizeof( szBuffer ) );
+
+ // each token is seperated by '_'
+ int numTokens = 0;
+ char *pToken = szBuffer;
+ char *pStart = pToken;
+ char szTokens[2][MAX_PATH];
+ while ( numTokens < 2 )
+ {
+ if ( pStart[0] == '_' )
+ {
+ pStart++;
+ pToken = strchr( pStart, '_' );
+ if ( !pToken )
+ {
+ strcpy( szTokens[numTokens++], pStart );
+ break;
+ }
+ else
+ {
+ strncpy( szTokens[numTokens], pStart, pToken-pStart );
+ szTokens[numTokens][pToken-pStart] = '\0';
+ numTokens++;
+ pStart = pToken;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // re-build a commandline
+ int localArgc = 0;
+ char *localArgv[16];
+ char argBuffers[16][MAX_PATH];
+ for ( int i=0; i<V_ARRAYSIZE( localArgv ); i++ )
+ {
+ localArgv[i] = argBuffers[i];
+ }
+ strcpy( localArgv[localArgc++], "vpc.exe" );
+ sprintf( localArgv[localArgc++], "+%s", szProject );
+ for ( int i=0; i<numTokens; i++ )
+ {
+ sprintf( localArgv[localArgc++], "/%s", szTokens[i] );
+ }
+
+ ParseBuildOptions( localArgc, localArgv );
+}
+
+//-----------------------------------------------------------------------------
+// This sets up various defines that are funneled into the .vpc script and the #defines in the engine.
+//
+// VPC makes a distinction between defines and macros (defines are just binary on/off things that are used like this:
+// $File "blah.cpp" [$somedefine]
+//
+// macros are used for substitutions like this:
+// $File "blah.$SOMEMACRO"
+//-----------------------------------------------------------------------------
+void CVPC::SetMacrosAndConditionals()
+{
+ // Find the target platform.
+ conditional_t *pPlatformConditional = NULL;
+ for ( int i = 0; i < m_Conditionals.Count(); i++ )
+ {
+ if ( m_Conditionals[i].type == CONDITIONAL_PLATFORM && m_Conditionals[i].m_bDefined )
+ {
+ pPlatformConditional = &m_Conditionals[i];
+ break;
+ }
+ }
+
+ // Only one platform is allowed to be defined.
+ for ( int i = 0; i < m_Conditionals.Count(); i++ )
+ {
+ if ( &m_Conditionals[i] != pPlatformConditional && m_Conditionals[i].type == CONDITIONAL_PLATFORM && m_Conditionals[i].m_bDefined )
+ {
+ // no no no, the user is not allowed to build multiple platforms simultaneously
+ // this prior feature really confused/crapped up the code, so absolutely not supporting that
+ VPCWarning( "Detected multiple target platforms...Disabling '%s'", m_Conditionals[i].name.String() );
+ m_Conditionals[i].m_bDefined = false;
+ }
+ }
+
+ if ( !pPlatformConditional )
+ {
+ // no user specified platform defined, defaults to primary vpc.exe built platform
+#if defined( WIN32 )
+ pPlatformConditional = FindOrCreateConditional( "WIN32", false, CONDITIONAL_PLATFORM );
+#elif defined( OSX )
+ pPlatformConditional = FindOrCreateConditional( "OSX32", false, CONDITIONAL_PLATFORM );
+#elif defined( LINUX )
+ pPlatformConditional = FindOrCreateConditional( "LINUX32", false, CONDITIONAL_PLATFORM );
+#elif defined( CYGWIN )
+ pPlatformConditional = FindOrCreateConditional( "CYGWIN", false, CONDITIONAL_PLATFORM );
+#else
+#error "Unsupported platform."
+#endif
+ pPlatformConditional->m_bDefined = true;
+ }
+
+ // Cache the platform name so that we can use it without dereferencing pPlatformConditional
+ CUtlString cVPCPlatform = pPlatformConditional->name;
+ // pPlatformConditional is a pointer into a container and it may be
+ // invalidated by future changes. NULLing the pointer is the only sure
+ // way to prevent programmers from using the invalid pointer.
+ pPlatformConditional = NULL;
+ VPCStatus( true, "Target Platform: %s", cVPCPlatform.String() );
+
+ // src_main doesn't want this #define because it conflicts with Python's SDK.
+ // It really should be called something else that won't conflict with the rest of the world.
+ bool bIncludePlatformDefineInProjects = false;
+#ifdef STEAM
+ bIncludePlatformDefineInProjects = true;
+#endif
+
+ SetMacro( "PLATFORM", cVPCPlatform.String(), bIncludePlatformDefineInProjects );
+
+ // DO NOT INTEGRATE OR TAKE THIS - THIS IS TEMP PORTING GLUE.
+ // This define will not exist in the Source2 branch.
+ SetMacro( "SOURCE1", "1", true );
+
+ // create reserved $QUOTE - used for embedding quotes, or use msdev's &quot
+ SetMacro( "QUOTE", "\"", false );
+
+ if ( !V_stricmp( cVPCPlatform.String(), "WIN32" ) || !V_stricmp( cVPCPlatform.String(), "WIN64" ) || !V_stricmp( cVPCPlatform.String(), "X360" ) )
+ {
+ // VS2010 is strictly win32/xbox360
+ switch ( m_eVSVersion )
+ {
+ case k_EVSVersion_2015:
+ m_ExtraOptionsCRCString += "VS2015";
+ SetConditional( "VS2015", true );
+
+ // temporarily allow VS2013 conditionals also as there are many. Will fix.
+ SetConditional( "VS2013", true );
+
+ m_bUseVS2010FileFormat = true;
+ break;
+
+ case k_EVSVersion_2013:
+ m_ExtraOptionsCRCString += "VS2013";
+ SetConditional( "VS2013", true );
+ m_bUseVS2010FileFormat = true;
+ break;
+
+ case k_EVSVersion_2012:
+ m_ExtraOptionsCRCString += "VS2012";
+ SetConditional( "VS2012", true );
+ m_bUseVS2010FileFormat = true;
+ break;
+
+ case k_EVSVersion_2010:
+ m_ExtraOptionsCRCString += "VS2010";
+ SetConditional( "VS2010", true );
+ m_bUseVS2010FileFormat = true;
+ break;
+
+ case k_EVSVersion_2008:
+ m_ExtraOptionsCRCString += "VS2008";
+ SetConditional( "VS2005", true ); // use 2005 defines
+ m_bUseVS2010FileFormat = false;
+ break;
+
+ default:
+ m_ExtraOptionsCRCString += "VS2005";
+ SetConditional( "VS2005", true );
+ m_bUseVS2010FileFormat = false;
+ break;
+ }
+ }
+
+ // create and define various other platform related helper conditionals andmacros
+ if ( V_stricmp( cVPCPlatform.String(), "WIN32" ) == 0 || V_stricmp( cVPCPlatform.String(), "WIN64" ) == 0 )
+ {
+ if ( V_stricmp( cVPCPlatform.String(), "WIN32" ) == 0 )
+ {
+ SetMacro( "PLATSUBDIR", "\\win32", false );
+ }
+ else
+ {
+ SetMacro( "PLATSUBDIR", "\\win64", false );
+ }
+ SetConditional( "WINDOWS" );
+
+ SetMacro( "_DLL_EXT", ".dll", true );
+ SetMacro( "_IMPLIB_EXT", ".lib", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "", false );
+
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", ".lib", false );
+
+ SetMacro( "_EXE_EXT", ".exe", false );
+
+ SetMacro( "_EXTERNAL_DLL_EXT", ".dll", true );
+ SetMacro( "_EXTERNAL_IMPLIB_EXT", ".lib", false );
+ SetMacro( "_EXTERNAL_STATICLIB_EXT", ".lib", false );
+
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "X360" ) == 0 )
+ {
+ SetMacro( "PLATSUBDIR", "\\x360", false );
+
+ SetMacro( "_DLL_EXT", "_360.dll", true );
+ SetMacro( "_IMPLIB_EXT", "_360.lib", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "", false );
+
+ SetMacro( "_IMPLIB_DLL_PREFIX", "", false );
+
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", "_360.lib", false );
+
+ SetMacro( "_EXE_EXT", ".exe", false );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "PS3" ) == 0 )
+ {
+ SetMacro( "PLATSUBDIR", "\\ps3", false );
+
+ SetMacro( "_DLL_EXT", "_ps3.sprx", true );
+ SetMacro( "_IMPLIB_EXT", "_ps3.lib", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "", false );
+
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", "_ps3.lib", false );
+
+ SetMacro( "_EXE_EXT", ".self", false );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "LINUX32" ) == 0 || V_stricmp( cVPCPlatform.String(), "LINUX64" ) == 0 )
+ {
+ bool IsLinux32 = ( V_stricmp( cVPCPlatform.String(), "LINUX32" ) == 0 );
+
+ SetMacro( "PLATSUBDIR", IsLinux32 ? "\\linux32" : "\\linux64", false );
+
+ SetConditional( "LINUXALL" );
+ if ( m_bDedicatedBuild )
+ {
+ SetConditional( "DEDICATED" );
+ }
+ SetConditional( "POSIX" );
+
+ SetMacro( "LINUX", "1", true );
+ SetMacro( "_LINUX", "1", true );
+ SetMacro( "POSIX", "1", true );
+ SetMacro( "_POSIX", "1", true );
+
+ const char *str3264 = IsLinux32 ? "" : "64";
+ const char *strSrv = m_bAppendSrvToDedicated ? "_srv" : "";
+ CFmtStrN<128> strDso( "%s%s.so", strSrv, str3264 );
+ CFmtStrN<128> strLib( "%s%s.a", strSrv, str3264 );
+
+ SetMacro( "_DLL_EXT", strDso.Access(), true );
+ SetMacro( "_IMPLIB_EXT", strDso.Access(), false );
+ SetMacro( "_STATICLIB_EXT", strLib.Access(), false );
+
+ // Extensions for external dependencies like libsteam_api.so (not libsteam_api_ds.so).
+ // VPC_Keyword_Folder in projectscript.cpp will check for ImpLibExternal or LibExternal and
+ // use these prefixes instead of _ds.so if they exist.
+ SetMacro( "_EXTERNAL_DLL_EXT", ".so", true );
+ SetMacro( "_EXTERNAL_IMPLIB_EXT", ".so", false );
+ SetMacro( "_EXTERNAL_STATICLIB_EXT", ".a", false );
+
+ //SetMacro( "_STATICLIB_PREFIX", "lib", false );
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "lib", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "lib", false );
+ SetMacro( "_EXE_EXT", "", false );
+ SetMacro( "_SYM_EXT", ".dbg", false );
+
+ SetConditional( "GL" );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "OSX32" ) == 0 || V_stricmp( cVPCPlatform.String(), "OSX64" ) == 0 )
+ {
+ if ( V_stricmp( cVPCPlatform.String(), "OSX32" ) == 0 )
+ {
+ SetMacro( "PLATSUBDIR", "\\osx32", false );
+ }
+ else
+ {
+ SetMacro( "PLATSUBDIR", "\\osx64", false );
+ }
+
+ SetConditional( "OSXALL" );
+ if ( m_bDedicatedBuild )
+ {
+ SetConditional( "DEDICATED" );
+ }
+ SetConditional( "POSIX" );
+ SetMacro( "_POSIX", "1", true );
+
+ SetMacro( "_DLL_EXT", ".dylib", true );
+ SetMacro( "_IMPLIB_EXT", ".dylib", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "lib", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "lib", false );
+
+ //SetMacro( "_STATICLIB_PREFIX", "lib", false );
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", ".a", false );
+
+ SetMacro( "_EXE_EXT", "", false );
+ SetMacro( "_SYM_EXT", ".dSYM", false );
+
+ SetMacro( "_EXTERNAL_DLL_EXT", ".dylib", true );
+ SetMacro( "_EXTERNAL_IMPLIB_EXT", ".dylib", false );
+ SetMacro( "_EXTERNAL_STATICLIB_EXT", ".a", false );
+
+ // Mac defaults to GL on
+ SetConditional( "GL" );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "IOS" ) == 0 )
+ {
+ SetConditional( "OSXALL" );
+ if ( m_bDedicatedBuild )
+ {
+ SetConditional( "DEDICATED" );
+ }
+ SetConditional( "POSIX" );
+ SetMacro( "_POSIX", "1", true );
+
+ SetConditional( "IOS" );
+ SetMacro( "_IOS", "1", true );
+ SetMacro( "IOS", "1", true );
+
+ SetMacro( "_DLL_EXT", "_ios.dylib", true );
+ SetMacro( "_IMPLIB_EXT", "_ios.dylib", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "lib", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "lib", false );
+
+ //SetMacro( "_STATICLIB_PREFIX", "lib", false );
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", "_ios.a", false );
+
+ SetMacro( "_EXE_EXT", "", false );
+
+ SetMacro( "_EXTERNAL_DLL_EXT", "_ios.dylib", true );
+ SetMacro( "_EXTERNAL_IMPLIB_EXT", "_ios.dylib", false );
+ SetMacro( "_EXTERNAL_STATICLIB_EXT", "_ios.a", false );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "ANDROID" ) == 0 )
+ {
+ SetConditional( "LINUXALL" );
+ if ( m_bDedicatedBuild )
+ {
+ SetConditional( "DEDICATED" );
+ }
+ SetConditional( "POSIX" );
+ SetConditional( "ANDROID" );
+
+ SetMacro( "LINUX", "1", true );
+ SetMacro( "_LINUX", "1", true );
+ SetMacro( "POSIX", "1", true );
+ SetMacro( "_POSIX", "1", true );
+ SetMacro( "ANDROID", "1", true );
+ SetMacro( "_ANDROID", "1", true );
+
+ SetMacro( "_DLL_EXT", "_an.so", true );
+ SetMacro( "_IMPLIB_EXT", "_an.so", false );
+
+ SetMacro( "_IMPLIB_PREFIX", "lib", false );
+ SetMacro( "_IMPLIB_DLL_PREFIX", "lib", false );
+
+ SetMacro( "_STATICLIB_PREFIX", "lib", false );
+ SetMacro( "_STATICLIB_EXT", "_an.a", false );
+
+ SetMacro( "_EXE_EXT", "", false );
+
+ SetMacro( "_EXTERNAL_DLL_EXT", "_an.so", true );
+ SetMacro( "_EXTERNAL_IMPLIB_EXT", "_an.so", false );
+ SetMacro( "_EXTERNAL_STATICLIB_EXT", "_an.a", false );
+
+ // and is a cross-compiled target
+ SetConditional( "CROSS_COMPILED" );
+ SetMacro( "CROSS_COMPILED", "1", true );
+ SetMacro( "_CROSS_COMPILED", "1", true );
+
+ SetConditional( "GL" );
+ }
+ else if ( V_stricmp( cVPCPlatform.String(), "CYGWIN" ) == 0 )
+ {
+ SetMacro( "PLATSUBDIR", "\\cygwin", false );
+
+ SetConditional( "CYGWIN" );
+ SetConditional( "CYGWIN_WINDOWS_TARGET" );
+ SetConditional( "DEDICATED" );
+ SetConditional( "POSIX" );
+
+ SetMacro( "CYGWIN", "1", true );
+ SetMacro( "_CYGWIN", "1", true );
+ SetMacro( "CYGWIN_WINDOWS_TARGET", "1", true );
+ SetMacro( "_CYGWIN_WINDOWS_TARGET", "1", true );
+ SetMacro( "POSIX", "1", true );
+ SetMacro( "_POSIX", "1", true );
+
+ SetMacro( "_DLL_EXT", ".dll", true );
+ SetMacro( "_IMPLIB_EXT", ".dll.a", false );
+
+ SetMacro( "_IMPLIB_DLL_PREFIX", "", false );
+ SetMacro( "_IMPLIB_PREFIX", "lib", false );
+
+ //SetMacro( "_STATICLIB_PREFIX", "lib", false );
+ SetMacro( "_STATICLIB_PREFIX", "", false );
+ SetMacro( "_STATICLIB_EXT", ".a", false );
+
+ SetMacro( "_EXE_EXT", ".exe", false );
+ }
+
+ // DO NOT INTEGRATE OR TAKE THIS - THIS IS TEMP PORTING GLUE.
+ {
+ // CERT has been decided to be a platform permutation of RETAIL.
+ // The DOTA S1 scripts are not in a clean enough condition to place this logic there.
+ // The S2 scripts have it there along with similar common concepts.
+ conditional_t *pRetailConditional = FindOrCreateConditional( "RETAIL", false, CONDITIONAL_CUSTOM );
+ if ( pRetailConditional && pRetailConditional->m_bDefined && ( !V_stricmp( cVPCPlatform.String(), "X360" ) || !V_stricmp( cVPCPlatform.String(), "PS3" ) ) )
+ {
+ // CERT is a restricted console RETAIL concept, with publisher dictated rules, there is no CERT process for non-console platforms.
+ SetConditional( "CERT" );
+ }
+ }
+
+
+ // Set VPCGAME macro based on target game
+ if ( m_bEnableVpcGameMacro )
+ {
+ int nGameDefineIndex = -1;
+ for ( int iOtherGameDefine = 0; iOtherGameDefine < m_Conditionals.Count(); ++ iOtherGameDefine )
+ {
+ if ( m_Conditionals[iOtherGameDefine].type == CONDITIONAL_GAME &&
+ m_Conditionals[iOtherGameDefine].m_bDefined )
+ {
+ if ( nGameDefineIndex == -1 )
+ {
+ nGameDefineIndex = iOtherGameDefine;
+ }
+ else
+ {
+ // uh-oh, multiple games defined for target build
+ // can't set VPCGAME accurately
+ nGameDefineIndex = -2;
+ }
+ }
+ }
+
+ SetMacro( "VPCGAME", ( nGameDefineIndex >= 0 ) ? m_Conditionals[nGameDefineIndex].name.Get() : "valve", true );
+ SetMacro( "VPCGAMECAPS", ( nGameDefineIndex >= 0 ) ? m_Conditionals[nGameDefineIndex].upperCaseName.Get() : "VALVE", true );
+
+ // force this into additional CRC string
+ m_ExtraOptionsCRCString += CFmtStr( "/vpcgame:%s", GetMacroValue( "VPCGAME" ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Decorate project name
+//-----------------------------------------------------------------------------
+void CVPC::DecorateProjectName( char *pchProjectName )
+{
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( "PLATFORM", false, NULL );
+ if ( pMacro )
+ {
+ char szPlatform[MAX_PATH];
+ sprintf( szPlatform, " (%s)", pMacro->value.String() );
+ strcat( pchProjectName, szPlatform );
+ }
+
+ const char *pchDecorate = g_pVPC->GetDecorateString();
+ if ( pchDecorate && V_strlen( pchDecorate ) > 0 )
+ {
+ strcat( pchProjectName, pchDecorate );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Checks for command line /params ( +/- used for projects, so ICommandLine() not suitable)
+//-----------------------------------------------------------------------------
+bool CVPC::HasCommandLineParameter( const char *pParamName )
+{
+ for ( int i=1; i < m_nArgc; i++ )
+ {
+ if ( V_stricmp( m_ppArgv[i], pParamName ) == 0 )
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::HasP4SLNCommand()
+{
+ return HasCommandLineParameter( "/p4sln" );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::HandleP4SLN( IBaseSolutionGenerator *pSolutionGenerator )
+{
+#ifdef WIN32
+ // If they want to generate a solution based on a Perforce changelist, adjust m_targetProjects and set it up like /mksln had been passed in.
+ if ( m_iP4Changelists.Count() == 0 )
+ return false;
+
+ if ( !pSolutionGenerator )
+ {
+ VPCError( "No solution generator exists for this platform." );
+ }
+
+ // Figure out where to put the solution file.
+ char szFullSolutionPath[MAX_PATH];
+ if ( V_IsAbsolutePath( m_P4SolutionFilename.Get() ) )
+ {
+ V_strncpy( szFullSolutionPath, m_P4SolutionFilename.Get(), sizeof( szFullSolutionPath ) );
+ }
+ else
+ {
+ V_ComposeFileName( g_pVPC->GetStartDirectory(), m_P4SolutionFilename.Get(), szFullSolutionPath, sizeof( szFullSolutionPath ) );
+ }
+
+ CProjectDependencyGraph dependencyGraph;
+ GenerateSolutionForPerforceChangelist( dependencyGraph, m_iP4Changelists, pSolutionGenerator, szFullSolutionPath );
+ return true;
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::GetProjectDependencies( CUtlVector<CDependency_Project *> &referencedProjects )
+{
+ bool bInSlnPass = m_bInMkSlnPass;
+
+ m_bInMkSlnPass = true;
+
+ // Find out what depends on what.
+ if ( !m_dependencyGraph.HasGeneratedDependencies() )
+ {
+ m_dependencyGraph.BuildProjectDependencies( 0, m_pPhase1Projects );
+ }
+
+ // GenerateBuildSet basically generates what we want, except it uses projectIndex_t's, meaning that
+ // we don't know what subset of games we should use until we've called VPC_IterateTargetProjects.
+ m_dependencyGraph.TranslateProjectIndicesToDependencyProjects( m_TargetProjects, referencedProjects );
+
+ m_bInMkSlnPass = bInSlnPass;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::HandleMKSLN( IBaseSolutionGenerator *pSolutionGenerator )
+{
+ if ( m_MKSolutionFilename.IsEmpty() )
+ {
+ return;
+ }
+
+ m_bInMkSlnPass = true;
+
+ if ( !pSolutionGenerator )
+ {
+ VPCError( "No solution generator exists for this platform." );
+ }
+
+ // Find out what depends on what.
+ if ( !m_dependencyGraph.HasGeneratedDependencies() )
+ {
+ m_dependencyGraph.BuildProjectDependencies( 0 );
+ }
+
+ // GenerateBuildSet basically generates what we want, except it uses projectIndex_t's, meaning that
+ // we don't know what subset of games we should use until we've called VPC_IterateTargetProjects.
+ CUtlVector<CDependency_Project*> referencedProjects;
+ m_dependencyGraph.TranslateProjectIndicesToDependencyProjects( m_TargetProjects, referencedProjects );
+
+ // Generate a solution file.
+ char szFullSolutionPath[MAX_PATH];
+ if ( V_IsAbsolutePath( m_MKSolutionFilename.Get() ) )
+ {
+ V_strncpy( szFullSolutionPath, m_MKSolutionFilename.Get(), sizeof( szFullSolutionPath ) );
+ }
+ else
+ {
+ V_ComposeFileName( g_pVPC->GetStartDirectory(), m_MKSolutionFilename.Get(), szFullSolutionPath, sizeof( szFullSolutionPath ) );
+ }
+
+ if ( m_pPhase1Projects != NULL )
+ {
+ referencedProjects.AddVectorToTail( *m_pPhase1Projects );
+ }
+
+ pSolutionGenerator->GenerateSolutionFile( szFullSolutionPath, referencedProjects );
+
+ m_bInMkSlnPass = false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CVPC::SetupGenerators()
+{
+ extern IBaseSolutionGenerator *GetSolutionGenerator_Win32();
+ extern IBaseProjectGenerator *GetWin32ProjectGenerator();
+ extern IBaseProjectGenerator *GetWin32ProjectGenerator_2010();
+ extern IBaseProjectGenerator *GetPS3ProjectGenerator();
+ extern IBaseProjectGenerator *GetXbox360ProjectGenerator();
+ extern IBaseProjectGenerator *GetXbox360ProjectGenerator_2010();
+ extern IBaseProjectGenerator *GetMakefileProjectGenerator();
+ extern IBaseSolutionGenerator *GetMakefileSolutionGenerator();
+ extern IBaseProjectGenerator *GetXcodeProjectGenerator();
+ extern IBaseSolutionGenerator *GetXcodeSolutionGenerator();
+
+ bool bIsLinux = IsPlatformDefined( "LINUX32" ) || IsPlatformDefined( "LINUX64" );
+ bool bIsOSX = IsPlatformDefined( "OSX32" ) || IsPlatformDefined( "OSX64" );
+
+#if defined( WIN32 )
+ // Under Windows we have the ability to generate makefiles so if they specified a linux config,
+ // or if they're building the (non-SRCDS) dedicated server, then use the makefile generator
+ conditional_t *pConditional = FindOrCreateConditional( "DEDICATED", false, CONDITIONAL_CUSTOM );
+
+ bool bUseMakefile = bIsLinux || ( pConditional && pConditional->m_bDefined );
+ bool bUseXcode = bIsOSX;
+
+ if ( bUseMakefile )
+ {
+ Log_Msg( LOG_VPC, "\n** Detected Linux platform. Using Makefile generator.\n" );
+ }
+
+ if ( bUseMakefile )
+ {
+ m_pProjectGenerator = GetMakefileProjectGenerator();
+ m_pSolutionGenerator = GetMakefileSolutionGenerator();
+ }
+ else if ( bUseXcode )
+ {
+ m_pProjectGenerator = GetXcodeProjectGenerator();
+ m_pSolutionGenerator = GetXcodeSolutionGenerator();
+ m_bForceIterate = true;
+ }
+ else
+ {
+ if ( IsPlatformDefined( "PS3" ) )
+ {
+ m_pProjectGenerator = GetPS3ProjectGenerator();
+ m_pSolutionGenerator = GetSolutionGenerator_Win32();
+ }
+ else if ( IsPlatformDefined( "X360" ) )
+ {
+ if ( m_bUseVS2010FileFormat )
+ {
+ Log_Msg( LOG_VPC, Color( 0, 255, 255, 255 ), "Generating for Visual Studio 2010.\n" );
+ m_pProjectGenerator = GetXbox360ProjectGenerator_2010();
+ }
+ else
+ {
+ m_pProjectGenerator = GetXbox360ProjectGenerator();
+ }
+ m_pSolutionGenerator = GetSolutionGenerator_Win32();
+ }
+ else
+ {
+ // spew what we are generating
+ const char *pchLogLine = "Generating for Visual Studio 2005.\n";
+ if ( m_eVSVersion == k_EVSVersion_2015 )
+ pchLogLine = "Generating for Visual Studio 2015.\n";
+ else if ( m_eVSVersion == k_EVSVersion_2013 )
+ pchLogLine = "Generating for Visual Studio 2013.\n";
+ else if ( m_eVSVersion == k_EVSVersion_2012 )
+ pchLogLine = "Generating for Visual Studio 2012.\n";
+ else if ( m_eVSVersion == k_EVSVersion_2010 )
+ pchLogLine = "Generating for Visual Studio 2010.\n";
+
+ Log_Msg( LOG_VPC, Color( 0, 255, 255, 255 ), pchLogLine );
+
+ // pick a project generator
+ if ( m_bUseVS2010FileFormat )
+ m_pProjectGenerator = GetWin32ProjectGenerator_2010();
+ else
+ m_pProjectGenerator = GetWin32ProjectGenerator();
+
+ m_pSolutionGenerator = GetSolutionGenerator_Win32();
+ }
+ }
+#else
+ if ( bIsLinux )
+ {
+ // Linux always uses the makefile project generator.
+ m_pProjectGenerator = GetMakefileProjectGenerator();
+ m_pSolutionGenerator = GetMakefileSolutionGenerator();
+ }
+ if ( bIsOSX )
+ {
+ m_pProjectGenerator = GetXcodeProjectGenerator();
+ m_pSolutionGenerator = GetXcodeSolutionGenerator();
+ }
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Since Steam's VPC builds tier0 and vstdlib directly in, Steam uses vpc.exe as the CRC checker.
+// Source uses vpccrccheck.exe to do this.
+//-----------------------------------------------------------------------------
+void CVPC::InProcessCRCCheck()
+{
+ for ( int i = 1; i<m_nArgc; i++ )
+ {
+ if ( !V_stricmp( m_ppArgv[i], "-crc" ) || !V_stricmp( m_ppArgv[i], "-crc2" ) )
+ {
+ // caller wants the crc check only
+ int ret = VPC_CommandLineCRCChecks( m_nArgc, m_ppArgv );
+ exit( ret );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const char *CVPC::BuildTempGroupScript( const char *pVPCScriptName )
+{
+ char projectName[MAX_PATH];
+ V_StripExtension( pVPCScriptName, projectName, sizeof( projectName ) );
+
+ char szCurrentDirectory[MAX_PATH];
+ V_GetCurrentDirectory( szCurrentDirectory, sizeof( szCurrentDirectory ) );
+
+ // caller is specifying an explicit VPC, i.e. not a project from the default group
+ // create a temporary group file that mimics a VGC, that points to the current dir's VPC
+
+ // Generate a really crappy temp filename
+ uint32 tmpHash = rand();
+ for ( const char *c = pVPCScriptName ; *c ; ++c )
+ tmpHash = tmpHash * 257 + *c;
+ uint32 tmpTime = time( NULL );
+
+ char tempGroupScriptFilename[MAX_PATH];
+ V_ComposeFileName( szCurrentDirectory, CFmtStr( "%08x%08xvgc.tmp", tmpHash, tmpTime ), tempGroupScriptFilename, sizeof( tempGroupScriptFilename ) );
+ m_TempGroupScriptFilename = tempGroupScriptFilename;
+
+ // build the temp group script
+ FILE *fp = fopen( m_TempGroupScriptFilename.Get(), "w+t" );
+ if ( !fp )
+ {
+ VPCError( "Could not open temp file '%s'. Tell a Programmer.\n", m_TempGroupScriptFilename.Get() );
+ }
+
+ char vpcScriptFilename[MAX_PATH];
+ V_ComposeFileName( szCurrentDirectory, pVPCScriptName, vpcScriptFilename, sizeof( vpcScriptFilename ) );
+
+ // the actual vpc must be relative to the source path
+ const char *pVPCFilename = StringAfterPrefix( vpcScriptFilename, m_SourcePath.Get() );
+ if ( !pVPCFilename )
+ {
+ VPCError( "Script %s is not in source path %s\n", vpcScriptFilename, m_SourcePath.Get() );
+ }
+
+ if ( pVPCFilename[0] == '\\' )
+ {
+ pVPCFilename++;
+ }
+
+ fprintf( fp, "$Project \"%s\"\n", projectName );
+ fprintf( fp, "{\n" );
+ fprintf( fp, "\"%s\"\n", pVPCFilename );
+ fprintf( fp, "}\n" );
+ fclose( fp );
+
+ // fake a build command
+ char buildCommand[MAX_PATH];
+ V_snprintf( buildCommand, sizeof( buildCommand ), "+%s", projectName );
+ int index = m_BuildCommands.AddToTail();
+ m_BuildCommands[index] = buildCommand;
+
+ return m_TempGroupScriptFilename.Get();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int CVPC::ProcessCommandLine()
+{
+ SetupDefaultConditionals();
+
+ DetermineSourcePath();
+
+ // possible extensions determine operation mode beyond expected normal user case
+ bool bScriptIsVGC = false;
+ bool bScriptIsVPC = false;
+ bool bScriptIsVCProj = false;
+ bool bHasBuildCommand = false;
+ const char *pScriptName = NULL;
+ const char *pScriptNameVCProj = NULL;
+
+ for ( int i = 1; i < m_nArgc; i++ )
+ {
+ const char *pArg = m_ppArgv[i];
+ if ( V_stristr( pArg, ".vgc" ) )
+ {
+ // caller explicitly providing group
+ pScriptName = pArg;
+ bScriptIsVGC = true;
+ bHasBuildCommand = true;
+ break;
+ }
+ else if ( V_stristr( pArg, ".vpc" ) )
+ {
+ // caller is using a local vpc, i.e. one that is not hooked into the groups
+ pScriptName = pArg;
+ bScriptIsVPC = true;
+ bHasBuildCommand = true;
+ break;
+ }
+ else
+ {
+ if ( V_stristr( pArg, ".vcproj" ) || V_stristr( pArg, ".vcxproj" ) )
+ {
+ // caller wants to re-gen the vcproj, this is commonly used by MSDEV to re-gen
+ pScriptNameVCProj = pArg;
+ bScriptIsVCProj = true;
+ bHasBuildCommand = true;
+ break;
+ }
+ }
+ }
+
+ for ( int i = 1; i < m_nArgc; i++ )
+ {
+ if ( m_ppArgv[i][0] == '-' || m_ppArgv[i][0] == '+' || m_ppArgv[i][0] == '*' || m_ppArgv[i][0] == '@' )
+ {
+ bHasBuildCommand = true;
+ break;
+ }
+ }
+
+ if ( bScriptIsVPC )
+ {
+ pScriptName = BuildTempGroupScript( pScriptName );
+ bScriptIsVPC = false;
+ bScriptIsVGC = true;
+ }
+
+ if ( !bScriptIsVGC )
+ {
+ // no script, use default group
+ pScriptName = "vpc_scripts\\default.vgc";
+ bScriptIsVGC = true;
+ }
+
+ // set the current directory, it is to be expected src, i.e. .\vpc_scripts\..
+ SetDefaultSourcePath();
+
+ char szCurrentDirectory[MAX_PATH];
+ V_GetCurrentDirectory( szCurrentDirectory, sizeof( szCurrentDirectory ) );
+ m_StartDirectory = szCurrentDirectory;
+
+ // parse and build tables from group script that options will reference
+ if ( bScriptIsVGC )
+ {
+ VPC_ParseGroupScript( pScriptName );
+ }
+
+ if ( bScriptIsVCProj )
+ {
+ // this is commonly used as an extern tool in MSDEV to re-vpc in place
+ // caller is msdev providing the vcproj name, solve to determine which project and generate
+ FindProjectFromVCPROJ( pScriptNameVCProj );
+ }
+ else
+ {
+ ParseBuildOptions( m_nArgc, m_ppArgv );
+ }
+
+ // set macros and conditionals derived from command-line options
+ SetMacrosAndConditionals();
+
+ // generate a CRC string derived from command-line options
+ GenerateOptionsCRCString();
+
+ SetupGenerators();
+
+ // filter user's build commands
+ // generate list of build targets
+ CProjectDependencyGraph dependencyGraph;
+ GenerateBuildSet( dependencyGraph );
+
+ if ( !bHasBuildCommand && !HasP4SLNCommand() )
+ {
+ // spew usage
+ m_bUsageOnly = true;
+ }
+
+ if ( m_bUsageOnly )
+ {
+ // spew only
+ SpewUsage();
+ return 0;
+ }
+
+#ifdef WIN32
+ if ( HandleP4SLN( m_pSolutionGenerator ) )
+ {
+ return 0;
+ }
+#endif
+
+ // iterate and build target projects
+ if ( !BuildTargetProjects() )
+ {
+ // build failure
+ return 0;
+ }
+
+ // now that we have valid project files, can generate solution
+ HandleMKSLN( m_pSolutionGenerator );
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// main
+//
+//-----------------------------------------------------------------------------
+
+// VPC is a DLL in Source.
+#if defined(STANDALONE_VPC) || defined(OSX) || defined(LINUX)
+int main( int argc, char **argv )
+#else
+int vpcmain( int argc, char **argv )
+#endif
+{
+ bool bWindowsTwoPhase = false;
+
+ for ( int i = 0; i < argc; i++ )
+ {
+ if ( V_stricmp( "/windows", argv[i] ) == 0 )
+ {
+ bWindowsTwoPhase = true;
+ break;
+ }
+ }
+
+ int nRetVal;
+ g_pVPC = new CVPC();
+
+ if ( bWindowsTwoPhase )
+ {
+ //
+ // We're going to do some grotesque hackery by manipulating
+ // the command line arguments.
+ //
+ // First we're going to generate a VPC object to generate all the
+ // 32-bit .vcxproj files but not write a solution file. Then
+ // we'll run it for the 64-bit .vcxproj files, then write a solution
+ // file containing both (if a solution file was requested).
+ //
+ // To accomplish this, subtract the /windows parameter (and /MKSLN if present), run, extract
+ // the list of generated project files, add a /WIN64 (and put /MKSLN back if necessary)
+ // and pass in the generated project file list.
+ //
+ bool bBuildSolution = false;
+ char szSolutionFile[_MAX_PATH];
+ nRetVal = -1;
+
+ char *newargs[128] = { NULL };
+ int cParms = 0;
+
+ //
+ // Do the 32-bit VPC, capturing the list of project files produced.
+ //
+ Assert( argc <= V_ARRAYSIZE( newargs ) );
+ for ( int i = 0; i < argc; i++ )
+ {
+ char *pszArg = argv[i];
+
+ if ( !V_stricmp( pszArg, "/windows" ) || !V_stricmp( pszArg, "/dp" ) )
+ {
+ // Skip
+ }
+ else if ( !V_stricmp( pszArg, "/mksln" ) && ( i + 1 < argc ) )
+ {
+ // If the next parameter is a standard + or - or / or * parameter, then we take that to be the name of the solution file.
+ // So vpc /mksln +engine would generate engine.sln.
+ if ( argv[i+1][0] == '+' || argv[i+1][0] == '-' || argv[i+1][0] == '/' || argv[i+1][0] == '*' || argv[i+1][0] == '@' )
+ {
+ V_strncpy( szSolutionFile, &argv[i + 1][1], sizeof(szSolutionFile) );
+ }
+ else
+ {
+ V_strncpy( szSolutionFile, argv[i + 1], sizeof(szSolutionFile) );
+ i++;
+ }
+ bBuildSolution = true;
+
+ }
+ else
+ {
+ newargs[ cParms++ ] = pszArg;
+ }
+ }
+
+ //
+ // Add a /dp parameter to decorate the 32-bit project names with (win32). This
+ // makes it easier to differentiate between projects in the solution explorer.
+ //
+ newargs[ cParms++ ] = "/dp";
+
+ //
+ // Add a define for PHASE1 for any VPC files that need to be aware of that sort
+ // of thing.
+ //
+ newargs[ cParms++ ] = "/define:PHASE1";
+
+ if ( !g_pVPC->Init( cParms, newargs ) )
+ {
+ return 0;
+ }
+
+ nRetVal = g_pVPC->ProcessCommandLine();
+
+ if ( nRetVal != 0 )
+ {
+ return nRetVal;
+ }
+
+ //
+ // Grab a list of all the project files that got generated by this pass,
+ // we will stuff these into the solution file later. If we aren't
+ // building a solution, then don't bother.
+ //
+ CUtlVector<CDependency_Project*> referencedProjects;
+ if ( bBuildSolution )
+ {
+ g_pVPC->GetProjectDependencies( referencedProjects );
+ }
+
+ //
+ // Now reconstruct the command line with the 64-bit flag and the solution file added
+ // back in.
+ //
+ // Decrement cParms to eat the /dp and /define we added before.
+ //
+ cParms--;
+ cParms--;
+ newargs[ cParms++ ] = "/win64";
+
+ //
+ // Add a define for PHASE2 for any VPC files that need to be aware of that sort
+ // of thing. Example: Projects that generate headers-only and are not bitness
+ // specific.
+ //
+ newargs[ cParms++ ] = "/define:PHASE2";
+
+ if ( bBuildSolution )
+ {
+ newargs[ cParms++ ] = "/mksln";
+ newargs[ cParms++ ] = szSolutionFile;
+ }
+
+ g_pVPC->Shutdown();
+ delete g_pVPC;
+ g_pVPC = new CVPC();
+
+ if ( !g_pVPC->Init( cParms, newargs ) )
+ {
+ return 0;
+ }
+
+ if ( bBuildSolution )
+ {
+ g_pVPC->SetPhase1Projects( &referencedProjects );
+ }
+
+ nRetVal = g_pVPC->ProcessCommandLine();
+ }
+ else
+ {
+ if ( !g_pVPC->Init( argc, argv ) )
+ {
+ return 0;
+ }
+
+ nRetVal = g_pVPC->ProcessCommandLine();
+ }
+
+ g_pVPC->Shutdown();
+
+ return nRetVal;
+}
+
+// VPC is a DLL in Source.
+#if !(defined(STANDALONE_VPC) || defined(OSX) || defined(LINUX))
+#include "ilaunchabledll.h"
+
+// VPC is launched by vpc.exe, which is a copy of binlaunch.exe.
+// All binlaunch does is setup the path to game\bin and load an ILaunchableDLL
+// interface out of a DLL with the same name as the exe.
+class CVPCLaunchableDLL : public ILaunchableDLL
+{
+public:
+ // All vpc.exe does is load the vpc DLL and run this.
+ virtual int main( int argc, char **argv )
+ {
+ return vpcmain( argc, argv );
+ }
+};
+
+EXPOSE_SINGLE_INTERFACE( CVPCLaunchableDLL, ILaunchableDLL, LAUNCHABLE_DLL_INTERFACE_VERSION );
+#endif
+
+
diff --git a/external/vpc/utils/vpc/p4sln.cpp b/external/vpc/utils/vpc/p4sln.cpp
new file mode 100644
index 0000000..6b23a21
--- /dev/null
+++ b/external/vpc/utils/vpc/p4sln.cpp
@@ -0,0 +1,273 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "p4lib/ip4.h"
+
+// fix filenames that have double backslashes at the start
+// (Perforce will return this if the root of a clientspec is e.g. "D:\")
+static const char* FixPerforceFilename( const char *filename )
+{
+ if ( filename && V_strlen( filename ) > 2 && !V_strnicmp( filename + 1, ":\\\\", 3 ) )
+ {
+ // strip out the first backslash
+ static char newFilename[MAX_PATH];
+ V_snprintf( newFilename, sizeof(newFilename), "%c:%s",
+ filename[0],
+ &filename[3]
+ );
+
+ return newFilename;
+ }
+ return filename;
+}
+
+static void GetChangelistFilenames( CUtlVector<int> &changelists, CUtlVector<CUtlString> &changelistFilenames )
+{
+ // P4 interface didn't initalize in main - abort
+ if ( !p4 )
+ {
+ g_pVPC->VPCWarning( "P4SLN: Perforce interface not available. Unable to generate solution from the given Perforce changelist." );
+ return;
+ }
+
+ CUtlVector<P4File_t> fileList;
+ int changeListIndex = 0;
+ if ( changelists.Count() )
+ {
+ changeListIndex = changelists[0];
+ }
+ if ( changeListIndex == -1 )
+ {
+ p4->GetOpenedFileList( fileList, false );
+ }
+ else if ( changeListIndex == 0 )
+ {
+ p4->GetOpenedFileList( fileList, true );
+ }
+ else
+ {
+ CUtlVector<P4File_t> partialFileList;
+
+ FOR_EACH_VEC( changelists, i )
+ {
+ p4->GetFileListInChangelist( changelists[i], partialFileList );
+
+ FOR_EACH_VEC( partialFileList, j )
+ {
+ fileList.AddToTail( partialFileList[j] );
+ }
+ }
+ }
+
+ // If -1 is in the changelist index, then include all.
+ bool bIncludeAllChangelists = ( changelists.Find( -1 ) != changelists.InvalidIndex() );
+
+ for ( int i=0; i < fileList.Count(); i++ )
+ {
+ if ( bIncludeAllChangelists || changelists.Find( fileList[i].m_iChangelist ) != changelists.InvalidIndex() )
+ {
+ const char *pFilename = p4->String( fileList[i].m_sLocalFile );
+
+ const char *pNewFilename = FixPerforceFilename( pFilename );
+
+ changelistFilenames.AddToTail( pNewFilename );
+ }
+ }
+}
+
+static void AddAdditionalDependencies( CUtlVector<CDependency_Project*> &projects, CUtlVector<CDependency_Project*> &allProjects )
+{
+ for ( int nProject=0; nProject < projects.Count(); nProject++ )
+ {
+ CDependency_Project *pCurProject = projects[nProject];
+
+ // Look at all the $AdditionalProjectDependencies projects for this one.
+ for ( int nDependency=0; nDependency < pCurProject->m_AdditionalProjectDependencies.Count(); nDependency++ )
+ {
+ const char *pLookingFor = pCurProject->m_AdditionalProjectDependencies[nDependency].String();
+
+ // Search for a match in allProjects.
+ int nFound = CDependency_Project::FindByProjectName( allProjects, pLookingFor );
+ if ( nFound == -1 )
+ {
+ g_pVPC->VPCError( "P4SLN: Project %s lists '%s' in its $AdditionalProjectDependencies, but there is no project by that name.", pCurProject->GetName(), pLookingFor );
+ }
+ else
+ {
+ // Got a match.
+ CDependency_Project *pFound = allProjects[nFound];
+ int nTest = projects.Find( pFound );
+ if ( nTest == projects.InvalidIndex() )
+ {
+ projects.AddToTail( pFound );
+ }
+ }
+ }
+ }
+}
+
+static void GetProjectsDependingOnFiles( CProjectDependencyGraph &dependencyGraph, CUtlVector<CUtlString> &filenames, CUtlVector<CDependency_Project*> &projects )
+{
+ // Now figure out the projects that depend on each of these files.
+ for ( int iFile=0; iFile < filenames.Count(); iFile++ )
+ {
+ CDependency *pFile = dependencyGraph.FindDependency( filenames[iFile].String() );
+ if ( !pFile )
+ {
+ char szRelative[MAX_PATH];
+ if ( !V_MakeRelativePath( filenames[iFile].String(), g_pVPC->GetSourcePath(), szRelative, sizeof( szRelative ) ) )
+ {
+ V_strncpy( szRelative, filenames[iFile].String(), sizeof( szRelative ) );
+ }
+
+ // This probably means their build commands on the command line didn't include
+ // any projects that included this file.
+ g_pVPC->VPCWarning( "%s is not found in the projects searched.", szRelative );
+ continue;
+ }
+
+ // Now see which projects depend on this file.
+ for ( int iProject=0; iProject < dependencyGraph.m_Projects.Count(); iProject++ )
+ {
+ CDependency_Project *pProject = dependencyGraph.m_Projects[iProject];
+
+ if ( pProject->DependsOn( pFile, k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse | k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckAdditionalDependencies ) )
+ {
+ if ( projects.Find( pProject ) == -1 )
+ projects.AddToTail( pProject );
+ }
+ }
+ }
+
+ // generate the group restrictions
+ // the user can explicitly provide a set of groups to narrow the wide dependency target
+ CUtlVector< CUtlString > groupRestrictions;
+ groupRestrictions = g_pVPC->m_P4GroupRestrictions;
+ if ( !groupRestrictions.Count() )
+ {
+ // the default restriction is to the "everything" group
+ groupRestrictions.AddToTail( "everything" );
+ }
+
+ CUtlVector< projectIndex_t > allowedProjectIndices;
+ if ( groupRestrictions.Count() )
+ {
+ // get all of the allowed projects by iterating the restrict-to-groups
+ for ( int i = 0; i < groupRestrictions.Count(); i++ )
+ {
+ CUtlVector< projectIndex_t > projectIndices;
+ if ( !g_pVPC->GetProjectsInGroup( projectIndices, groupRestrictions[i].Get() ) )
+ {
+ g_pVPC->VPCError( "No projects found in group '%s'.", groupRestrictions[i].Get() );
+ }
+
+ // aggregate into wider list
+ for ( int j = 0; j < projectIndices.Count(); j++ )
+ {
+ allowedProjectIndices.AddToTail( projectIndices[j] );
+ }
+ }
+ }
+
+ // Make sure that each of the dependent projects are members of the restricted groups, otherwise prevent their inclusion.
+ CUtlVector< int > doomedProjectIndices;
+ if ( allowedProjectIndices.Count() )
+ {
+ for ( int j = 0; j < projects.Count(); j++ )
+ {
+ // find the target project in the allowed set
+ if ( allowedProjectIndices.Find( projects[j]->m_iProjectIndex ) == allowedProjectIndices.InvalidIndex() )
+ {
+ // the target project is not in the allowed set
+ // add in descending order so indices can be properly removed below from largest index to smallest
+ doomedProjectIndices.AddToHead( j );
+ }
+ }
+
+ // Remove the projects that are not part of the restrict-to-groups
+ // Indexes were added in descending order, so removal is actually from the end, truncating the set
+ for ( int j = 0; j < doomedProjectIndices.Count(); j++ )
+ {
+ projects.Remove( doomedProjectIndices[j] );
+ }
+ }
+}
+
+
+static void UpdateProjects( CUtlVector<CDependency_Project*> &projects )
+{
+ for ( int iProject=0; iProject < projects.Count(); iProject++ )
+ {
+ Log_Msg( LOG_VPC, "\n" );
+
+ CDependency_Project *pDependency = projects[iProject];
+ pDependency->ExportProjectParameters();
+
+ if ( g_pVPC->IsForceGenerate() || !g_pVPC->IsProjectCurrent( g_pVPC->GetOutputFilename(), true ) )
+ {
+ project_t *pProject = &g_pVPC->m_Projects[ pDependency->m_iProjectIndex ];
+ g_pVPC->SetProjectName( pProject->name.String() );
+ g_pVPC->SetLoadAddressName( pProject->name.String() );
+
+ g_pVPC->ParseProjectScript( pDependency->m_szStoredScriptName, 0, false, true );
+ }
+ }
+}
+
+class CStringCaseLess
+{
+public:
+ bool Less( const char *lhs, const char *rhs, void *pCtx )
+ {
+ return ( V_stricmp( lhs, rhs ) < 0 ? true : false );
+ }
+};
+
+void GenerateSolutionForPerforceChangelist( CProjectDependencyGraph &dependencyGraph, CUtlVector<int> &changelists, IBaseSolutionGenerator *pGenerator, const char *pSolutionFilename )
+{
+ // We want to check against ALL projects in projects.vgc.
+ int nDepFlags = BUILDPROJDEPS_FULL_DEPENDENCY_SET | BUILDPROJDEPS_CHECK_ALL_PROJECTS;
+ dependencyGraph.BuildProjectDependencies( nDepFlags );
+
+ // Get the list of files from Perforce.
+ CUtlVector<CUtlString> filenames;
+ GetChangelistFilenames( changelists, filenames );
+
+ // Get the list of projects that depend on these files.
+ CUtlVector<CDependency_Project*> projects;
+ GetProjectsDependingOnFiles( dependencyGraph, filenames, projects );
+
+ // Add g_targetProjects, which will include any other projects that they added on the command line with +tier0 *engine syntax.
+ CUtlVector<CDependency_Project*> commandLineProjects;
+ dependencyGraph.TranslateProjectIndicesToDependencyProjects( g_pVPC->m_TargetProjects, commandLineProjects );
+ for ( int i=0; i < commandLineProjects.Count(); i++ )
+ {
+ if ( projects.Find( commandLineProjects[i] ) == projects.InvalidIndex() )
+ projects.AddToTail( commandLineProjects[i] );
+ }
+
+ // Make sure the latest .vcproj files are generated.
+ UpdateProjects( projects );
+
+ // List the projects.
+ CUtlSortVector< CUtlString, CStringCaseLess > sortedProjectNames;
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ sortedProjectNames.InsertNoSort( projects[i]->GetName() );
+ }
+ sortedProjectNames.RedoSort();
+
+ Msg( "Dependent projects: \n\n" );
+ for ( int i=0; i < sortedProjectNames.Count(); i++ )
+ {
+ Msg( "%s\n", sortedProjectNames[i].Get() );
+ }
+
+ // Write the solution file.
+ pGenerator->GenerateSolutionFile( pSolutionFilename, projects );
+}
+
diff --git a/external/vpc/utils/vpc/p4sln.h b/external/vpc/utils/vpc/p4sln.h
new file mode 100644
index 0000000..70cea10
--- /dev/null
+++ b/external/vpc/utils/vpc/p4sln.h
@@ -0,0 +1,17 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef P4SLN_H
+#define P4SLN_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+void GenerateSolutionForPerforceChangelist( CProjectDependencyGraph &dependencyGraph, CUtlVector<int> &changelists, IBaseSolutionGenerator *pGenerator, const char *pSolutionFilename );
+
+
+#endif // P4SLN_H
diff --git a/external/vpc/utils/vpc/projectgenerator_codelite.cpp b/external/vpc/utils/vpc/projectgenerator_codelite.cpp
new file mode 100644
index 0000000..aae6660
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_codelite.cpp
@@ -0,0 +1,156 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "projectgenerator_codelite.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";
+
+void CProjectGenerator_CodeLite::GenerateCodeLiteProject( CBaseProjectDataCollector *pCollector, const char *pOutFilename, const char *pMakefileFilename )
+{
+ char szProjectFile[MAX_PATH];
+ sprintf( szProjectFile, "%s.project", pOutFilename );
+
+ g_pVPC->VPCStatus( true, "Saving CodeLite project for: '%s' File: '%s'", pCollector->GetProjectName().String(), szProjectFile );
+
+ m_fp = fopen( szProjectFile, "wt" );
+
+ m_nIndent = 0;
+ m_pCollector = pCollector;
+ m_pMakefileFilename = pMakefileFilename;
+
+ Write( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
+ Write( "<CodeLite_Project Name=\"%s\" InternalType=\"\">\n", pCollector->GetProjectName().String() );
+ {
+ ++m_nIndent;
+ Write( "<Description/>\n" );
+ Write( "<Dependencies/>\n" );
+ Write( "<Settings Type=\"Dynamic Library\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<GlobalSettings>\n" );
+ ++m_nIndent;
+ Write( "<Compiler Options=\"\" C_Options=\"\">\n" );
+ ++m_nIndent;
+ Write( "<IncludePath Value=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</Compiler>\n" );
+ Write( "<Linker Options=\"\">\n" );
+ ++m_nIndent;
+ Write( "<LibraryPath Value=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</Linker>\n" );
+ Write( "<ResourceCompiler Options=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</GlobalSettings>\n" );
+ Write( "<Configuration Name=\"Debug\" CompilerType=\"gnu g++\" DebuggerType=\"GNU gdb debugger\" Type=\"Dynamic Library\" BuildCmpWithGlobalSettings=\"append\" BuildLnkWithGlobalSettings=\"append\" BuildResWithGlobalSettings=\"append\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<CustomBuild Enabled=\"yes\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<RebuildCommand>make CFG=debug -f %s clean all</RebuildCommand>\n", pMakefileFilename );
+ Write( "<CleanCommand>make CFG=debug -f %s clean</CleanCommand>\n", pMakefileFilename );
+ Write( "<BuildCommand>make CFG=debug -f %s -j `getconf _NPROCESSORS_ONLN`</BuildCommand>\n", pMakefileFilename );
+ Write( "<WorkingDirectory>$(ProjectPath)</WorkingDirectory>\n" );
+ --m_nIndent;
+ }
+ Write( "</CustomBuild>\n" );
+ --m_nIndent;
+ }
+ Write( "</Configuration>\n" );
+
+ Write( "<Configuration Name=\"Release\" CompilerType=\"gnu g++\" DebuggerType=\"GNU gdb debugger\" Type=\"Dynamic Library\" BuildCmpWithGlobalSettings=\"append\" BuildLnkWithGlobalSettings=\"append\" BuildResWithGlobalSettings=\"append\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<CustomBuild Enabled=\"yes\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<RebuildCommand>make -f %s clean all</RebuildCommand>\n", pMakefileFilename );
+ Write( "<CleanCommand>make -f %s clean</CleanCommand>\n", pMakefileFilename );
+ Write( "<BuildCommand>make -f %s -j `getconf _NPROCESSORS_ONLN`</BuildCommand>\n", pMakefileFilename );
+ Write( "<WorkingDirectory>$(ProjectPath)</WorkingDirectory>\n" );
+ --m_nIndent;
+ }
+ Write( "</CustomBuild>\n" );
+ --m_nIndent;
+ }
+ Write( "</Configuration>\n" );
+ --m_nIndent;
+ }
+ Write( "</Settings>\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;
+ }
+ --m_nIndent;
+ }
+ Write( "</CodeLite_Project>\n" );
+ fclose( m_fp );
+}
+
+void CProjectGenerator_CodeLite::WriteFilesFolder( const char *pFolderName, const char *pExtensions ) {
+ CUtlVector<char*> extensions;
+ V_SplitString( pExtensions, ";", extensions );
+
+ Write( "<VirtualDirectory Name=\"%s\">\n", pFolderName );
+ {
+ ++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( "<File Name=\"%s\"/>\n", sFixedSlashes );
+ }
+ }
+ --m_nIndent;
+ }
+ Write( "</VirtualDirectory>\n");
+}
+
+void CProjectGenerator_CodeLite::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, " " );
+
+ fprintf( m_fp, "%s", sOut );
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_codelite.h b/external/vpc/utils/vpc/projectgenerator_codelite.h
new file mode 100644
index 0000000..6f81e56
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_codelite.h
@@ -0,0 +1,51 @@
+//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_CODELITE_H
+#define PROJECTGENERATOR_CODELITE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "baseprojectdatacollector.h"
+
+class CProjectGenerator_CodeLite
+{
+public:
+
+ void GenerateCodeLiteProject( CBaseProjectDataCollector *pCollector, const char *pOutFilename, const char *pMakefileFilename );
+
+private:
+
+ void Write( const char *pMsg, ... );
+ void WriteHeader();
+ void WriteFileReferences();
+ void WriteProject( const char *pchMakefileName );
+ void WriteBuildFiles();
+ void WriteBuildConfigurations();
+ void WriteLegacyTargets( const char *pchMakefileName );
+ void WriteTrailer();
+ void WriteConfig( CSpecificConfig *pConfig );
+ void WriteTarget_Build( CSpecificConfig *pConfig );
+ void WriteTarget_Compile( CSpecificConfig *pConfig );
+ void WriteTarget_Rebuild( CSpecificConfig *pConfig );
+ void WriteTarget_Link( CSpecificConfig *pConfig );
+ void WriteTarget_Debug( CSpecificConfig *pConfig );
+ void WriteIncludes( CSpecificConfig *pConfig );
+ void WriteFilesFolder( const char *pFolderName, const char *pExtensions );
+ void WriteFiles();
+
+private:
+ CBaseProjectDataCollector *m_pCollector;
+ FILE *m_fp;
+ const char *m_pMakefileFilename;
+ int m_nIndent;
+};
+
+
+
+#endif // PROJECTGENERATOR_CODELITE_H
diff --git a/external/vpc/utils/vpc/projectgenerator_makefile.cpp b/external/vpc/utils/vpc/projectgenerator_makefile.cpp
new file mode 100644
index 0000000..07f995b
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_makefile.cpp
@@ -0,0 +1,1127 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "baseprojectdatacollector.h"
+#include "tier1/utlstack.h"
+#include "projectgenerator_codelite.h"
+
+static const char *k_pszBase_Makefile = "$(SRCROOT)/devtools/makefile_base_posix.mak";
+
+static const char *g_pOption_BufferSecurityCheck = "$BufferSecurityCheck";
+static const char *g_pOption_CustomBuildStepCommandLine = "$CustomBuildStep/$CommandLine";
+static const char *g_pOption_PostBuildEventCommandLine = "$PostBuildEvent/$CommandLine";
+static const char *g_pOption_CompileAs = "$CompileAs";
+static const char *g_pOption_ConfigurationType = "$ConfigurationType";
+static const char *g_pOption_Description = "$Description";
+static const char *g_pOption_EntryPoint = "$EntryPoint";
+static const char *g_pOption_ExtraCompilerFlags = "$GCC_ExtraCompilerFlags";
+static const char *g_pOption_ExtraLinkerFlags = "$GCC_ExtraLinkerFlags";
+static const char *g_pOption_CustomVersionScript = "$GCC_CustomVersionScript";
+static const char *g_pOption_ForceInclude = "$ForceIncludes";
+static const char *g_pOption_IgnoreAllDefaultLibraries = "$IgnoreAllDefaultLibraries";
+static const char *g_pOption_LocalFrameworks = "$LocalFrameworks";
+static const char *g_pOption_LowerCaseFileNames = "$LowerCaseFileNames";
+static const char *g_pOption_OptimizerLevel = "$OptimizerLevel";
+static const char *g_pOption_AdditionalDependencies = "$AdditionalDependencies";
+static const char *g_pOption_Outputs = "$Outputs";
+static const char *g_pOption_PrecompiledHeader = "$Create/UsePrecompiledHeader";
+static const char *g_pOption_PrecompiledHeaderFile = "$PrecompiledHeaderFile";
+static const char *g_pOption_SymbolVisibility = "$SymbolVisibility";
+static const char *g_pOption_SystemFrameworks = "$SystemFrameworks";
+static const char *g_pOption_SystemLibraries = "$SystemLibraries";
+static const char *g_pOption_UsePCHThroughFile = "$Create/UsePCHThroughFile";
+static const char *g_pOption_TargetCopies = "$TargetCopies";
+static const char *g_pOption_TreatWarningsAsErrors = "$TreatWarningsAsErrors";
+
+// These are the only properties we care about for makefiles.
+static const char *g_pRelevantProperties[] =
+{
+ g_pOption_AdditionalIncludeDirectories,
+ g_pOption_CompileAs,
+ g_pOption_OptimizerLevel,
+ g_pOption_OutputFile,
+ g_pOption_GameOutputFile,
+ g_pOption_SymbolVisibility,
+ g_pOption_PreprocessorDefinitions,
+ g_pOption_ConfigurationType,
+ g_pOption_ImportLibrary,
+ g_pOption_PrecompiledHeader,
+ g_pOption_UsePCHThroughFile,
+ g_pOption_PrecompiledHeaderFile,
+ g_pOption_CustomBuildStepCommandLine,
+ g_pOption_PostBuildEventCommandLine,
+ g_pOption_AdditionalDependencies,
+ g_pOption_Outputs,
+ g_pOption_Description,
+ g_pOption_SystemLibraries,
+ g_pOption_SystemFrameworks,
+ g_pOption_LocalFrameworks,
+ g_pOption_ExtraCompilerFlags,
+ g_pOption_ExtraLinkerFlags,
+ g_pOption_CustomVersionScript,
+ g_pOption_EntryPoint,
+ g_pOption_IgnoreAllDefaultLibraries,
+ g_pOption_BufferSecurityCheck,
+ g_pOption_ForceInclude,
+ g_pOption_TargetCopies,
+ g_pOption_TreatWarningsAsErrors,
+ g_pOption_LowerCaseFileNames,
+};
+
+
+static CRelevantPropertyNames g_RelevantPropertyNames =
+{
+ g_pRelevantProperties,
+ V_ARRAYSIZE( g_pRelevantProperties )
+};
+
+void MakeFriendlyProjectName( char *pchProject );
+
+void V_MakeAbsoluteCygwinPath( char *pOut, int outLen, const char *pRelativePath )
+{
+ // While generating makefiles under Win32, we must translate drive letters like c:\
+ // to Cygwin-style paths like /cygdrive/c/
+#ifdef _WIN32
+ char tmp[MAX_PATH];
+ V_MakeAbsolutePath( tmp, sizeof( tmp ), pRelativePath );
+ V_FixSlashes( tmp, '/' );
+
+ if ( tmp[0] != 0 && tmp[1] == ':' && tmp[2] == '/' )
+ {
+ // Ok, this is an absolute path
+ V_snprintf( pOut, outLen, "/cygdrive/%c/", tmp[0] );
+ V_strncat( pOut, &tmp[3], outLen );
+ }
+ else
+#endif // _WIN32
+ {
+ V_MakeAbsolutePath( pOut, outLen, pRelativePath );
+ V_RemoveDotSlashes( pOut );
+ }
+}
+
+// caller is responsible for free'ing (or leaking) the allocated buffer
+static const char* UsePOSIXSlashes( const char *pStr )
+{
+ int len = V_strlen( pStr ) + 2;
+ char *str = (char*)malloc(len*sizeof(char));
+ V_strncpy( str, pStr, len );
+ for ( int i = 0; i < len; i++ )
+ {
+ if ( str[i] == '\\' )
+ {
+ // allow escaping of bash special characters
+ if ( i+1 < len && ( str[i+1] != '"' && str[i+1] != '$' &&
+ str[i+1] != '\'' && str[i+1] != '\\' ) )
+ str[i] = '/';
+ }
+ if ( str[i] == '\0' )
+ break;
+ }
+ return str;
+}
+
+
+// pExt should be the bare extension without the . in front. i.e. "h", "cpp", "lib".
+static inline bool CheckExtension( const char *pFilename, const char *pExt )
+{
+ Assert( pExt[0] != '.' );
+
+ int nFilenameLen = V_strlen( pFilename );
+ int nExtensionLen = V_strlen( pExt );
+
+ return (nFilenameLen > nExtensionLen && pFilename[nFilenameLen-nExtensionLen-1] == '.' && V_stricmp( &pFilename[nFilenameLen-nExtensionLen], pExt ) == 0 );
+}
+
+
+static bool CheckExtensions( const char *pFilename, const char **ppExtensions )
+{
+ for ( int i=0; ppExtensions[i] != NULL; i++ )
+ {
+ if ( CheckExtension( pFilename, ppExtensions[i] ) )
+ return true;
+ }
+ return false;
+}
+
+
+static void GetObjFilenameForFile( const char *pConfigName, const char *pFilename, char *pOut, int maxLen )
+{
+ char sBaseFilename[MAX_PATH];
+ V_FileBase( pFilename, sBaseFilename, sizeof( sBaseFilename ) );
+ //V_strlower( sBaseFilename );
+
+ // We had .cxx files -> .oxx, but this macro:
+ // GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P)
+ // was turning into -MF blah.oxx, which led to blah.oxx containing the file dependencies.
+ // This obviously failed to link. Quick fix is to just have .cxx -> .o like everything else.
+ //$ const char *pObjExtension = (CheckExtension( pFilename, "cxx" ) ? "oxx" : "o");
+ const char *pObjExtension = "o";
+
+ V_snprintf( pOut, maxLen, "$(OBJ_DIR)/%s.%s", sBaseFilename, pObjExtension );
+}
+
+
+// This class drastically accelerates looking up which file creates which precompiled header.
+class CPrecompiledHeaderAccel
+{
+public:
+ void Setup( CUtlDict<CFileConfig*,int> &files, CFileConfig *pBaseConfig )
+ {
+ for ( int i=files.First(); i != files.InvalidIndex(); i=files.Next( i ) )
+ {
+ CFileConfig *pFile = files[i];
+
+ for ( int iSpecific=pFile->m_Configurations.First(); iSpecific != pFile->m_Configurations.InvalidIndex(); iSpecific=pFile->m_Configurations.Next( iSpecific ) )
+ {
+ CSpecificConfig *pSpecific = pFile->m_Configurations[iSpecific];
+ if ( pSpecific->m_bFileExcluded )
+ continue;
+
+ // Does this file create a precompiled header?
+ const char *pPrecompiledHeaderOption = pSpecific->GetOption( g_pOption_PrecompiledHeader );
+ if ( pPrecompiledHeaderOption && V_stristr( pPrecompiledHeaderOption, "Create" ) )
+ {
+ // Ok, which header do we scan through?
+ const char *pUsePCHThroughFile = pSpecific->GetOption( g_pOption_UsePCHThroughFile );
+ if ( !pUsePCHThroughFile )
+ {
+ g_pVPC->VPCError( "File %s creates a precompiled header in config %s but no UsePCHThroughFile option specified.", pFile->m_Filename.String(), pSpecific->GetConfigName() );
+ }
+
+ char sLookup[1024];
+ V_snprintf( sLookup, sizeof( sLookup ), "%s__%s", pSpecific->GetConfigName(), pUsePCHThroughFile );
+
+ if ( m_Lookup.Find( sLookup ) != m_Lookup.InvalidIndex() )
+ {
+ g_pVPC->VPCError( "File %s has UsePCHThroughFile of %s but another file already does.", pFile->m_Filename.String(), pUsePCHThroughFile );
+ }
+
+ m_Lookup.Insert( sLookup, pFile );
+ }
+ }
+ }
+ }
+
+ CFileConfig* FindFileThatCreatesPrecompiledHeader( const char *pConfigName, const char *pUsePCHThroughFile )
+ {
+ char sLookup[1024];
+ V_snprintf( sLookup, sizeof( sLookup ), "%s__%s", pConfigName, pUsePCHThroughFile );
+
+ int i = m_Lookup.Find( sLookup );
+ if ( i == m_Lookup.InvalidIndex() )
+ return NULL;
+ else
+ return m_Lookup[i];
+ }
+
+private:
+ // This indexes whatever file creates a certain precompiled header for a certain config.
+ // These are indexed as <config name>_<pchthroughfile>.
+ // So an entry might look like release_cbase.h
+ CUtlDict<CFileConfig*,int> m_Lookup;
+};
+
+
+
+class CProjectGenerator_Makefile : public CBaseProjectDataCollector
+{
+public:
+
+ typedef CBaseProjectDataCollector BaseClass;
+
+ CProjectGenerator_Makefile() : BaseClass( &g_RelevantPropertyNames )
+ {
+ }
+
+ virtual void Setup()
+ {
+ }
+
+ virtual const char* GetProjectFileExtension()
+ {
+ return "mak";
+ }
+
+ virtual void EndProject()
+ {
+ const char *pMakefileFilename = g_pVPC->GetOutputFilename();
+
+ CUtlString strProjectName = GetProjectName();
+ bool bProjectIsCurrent = g_pVPC->IsProjectCurrent( pMakefileFilename, false );
+ if ( g_pVPC->IsForceGenerate() || !bProjectIsCurrent )
+ {
+ g_pVPC->VPCStatus( true, "Saving makefile project for: '%s' File: '%s'", strProjectName.String(), g_pVPC->GetOutputFilename() );
+ WriteMakefile( pMakefileFilename );
+ }
+
+ const char *pTargetPlatformName = g_pVPC->GetTargetPlatformName();
+ if ( !pTargetPlatformName )
+ g_pVPC->VPCError( "GetTargetPlatformName failed." );
+
+ if ( !V_stricmp( pTargetPlatformName, "LINUX32" ) || !V_stricmp( pTargetPlatformName, "LINUX64" ) )
+ {
+ if ( g_pVPC->IsForceGenerate() || !bProjectIsCurrent )
+ {
+ // Write a CodeLite project as well.
+ char sFilename[MAX_PATH];
+ V_StripExtension( g_pVPC->GetOutputFilename(), sFilename, sizeof( sFilename ) );
+ CProjectGenerator_CodeLite codeLiteGenerator;
+ codeLiteGenerator.GenerateCodeLiteProject( this, sFilename, pMakefileFilename );
+ }
+ Term();
+ }
+ else
+ {
+ Term();
+ }
+ }
+
+ void WriteSourceFilesList( FILE *fp, const char *pListName, const char **pExtensions, const char *pConfigName )
+ {
+ fprintf( fp, "%s= \\\n", pListName );
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = m_Files[i];
+ if ( pFileConfig->IsExcludedFrom( pConfigName ) )
+ continue;
+
+ const char *pFilename = m_Files[i]->m_Filename.String();
+ if ( CheckExtensions( pFilename, pExtensions ) )
+ {
+ if ( m_bForceLowerCaseFileName )
+ fprintf( fp, " %s \\\n", UsePOSIXSlashes( V_strlower((char *)pFilename) ) );
+ else
+ fprintf( fp, " %s \\\n", UsePOSIXSlashes( pFilename ) );
+ }
+ }
+ fprintf( fp, "\n\n" );
+ }
+
+ void WriteNonConfigSpecificStuff( FILE *fp )
+ {
+ fprintf( fp, "ifneq \"$(LINUX_TOOLS_PATH)\" \"\"\n" );
+ fprintf( fp, "TOOL_PATH = $(LINUX_TOOLS_PATH)/\n" );
+ fprintf( fp, "endif\n\n" );
+
+ // NAME
+ char szName[256];
+ V_strncpy( szName, m_ProjectName.String(), sizeof(szName) );
+ MakeFriendlyProjectName( szName );
+ fprintf( fp, "NAME=%s\n", szName );
+
+ // SRCDIR
+ char sSrcRootRelative[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( "$SRCDIR", sSrcRootRelative, sizeof( sSrcRootRelative ) );
+
+ fprintf( fp, "SRCROOT=%s\n", UsePOSIXSlashes( sSrcRootRelative ) );
+
+ // TargetPlatformName
+ const char *pTargetPlatformName;
+ // forestw: if PLATFORM macro exists we should use its value, this accommodates overrides of PLATFORM in .vpc files
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( "PLATFORM", false, NULL );
+ if ( pMacro )
+ pTargetPlatformName = pMacro->value.String();
+ else
+ pTargetPlatformName = g_pVPC->GetTargetPlatformName();
+ if ( !pTargetPlatformName )
+ g_pVPC->VPCError( "GetTargetPlatformName failed." );
+ fprintf( fp, "TARGET_PLATFORM=%s\n", pTargetPlatformName );
+ fprintf( fp, "TARGET_PLATFORM_EXT=%s\n", g_pVPC->IsDedicatedBuild() ? "_srv" : "" );
+ fprintf( fp, "USE_VALVE_BINDIR=%s\n", ( g_pVPC->UseValveBinDir() ? "1" : "0" ) );
+
+ fprintf( fp, "PWD:=$(shell $(TOOL_PATH)pwd)\n" );
+
+
+ // Select debug config if no config is specified.
+ fprintf( fp, "# If no configuration is specified, \"release\" will be used.\n" );
+ fprintf( fp, "ifeq \"$(CFG)\" \"\"\n" );
+ fprintf( fp, "\tCFG = release\n" );
+ fprintf( fp, "endif\n\n" );
+ }
+
+ struct Filename_t
+ {
+ char szFilename[MAX_PATH];
+ int iBasename;
+ };
+
+ class FileSortSortFunc
+ {
+ public:
+ bool Less( const CFileConfig * const & src1, const CFileConfig * const & src2, void *pCtx )
+ {
+ return src1->m_nInsertOrder < src2->m_nInsertOrder;
+ }
+ };
+
+ void WriteVpcMacroDefines( CSpecificConfig *pConfig, FILE *fp )
+ {
+ // Add VPC macros marked to become defines.
+ CUtlVector< macro_t* > macroDefines;
+ g_pVPC->GetMacrosMarkedForCompilerDefines( macroDefines );
+ for ( int i=0; i < macroDefines.Count(); i++ )
+ {
+ macro_t *pMacro = macroDefines[i];
+ fprintf( fp, "-D%s=%s ", pMacro->name.String(), pMacro->value.String() );
+ }
+ }
+
+ void WriteConfigSpecificStuff( CSpecificConfig *pConfig, FILE *fp, CPrecompiledHeaderAccel *pAccel, CSpecificConfig *pConfig1 )
+ {
+ KeyValues *pKV = pConfig->m_pKV;
+
+ // If we've got a pConfig1, then that means pConfig0 == pConfig1, except for $PreprocessorDefinitions. So don't special
+ // case anything other than that one section.
+ if( !pConfig1 )
+ {
+ fprintf( fp, "#\n#\n# CFG=%s\n#\n#\n\n", pConfig->GetConfigName() );
+ fprintf( fp, "ifeq \"$(CFG)\" \"%s\"\n\n", pConfig->GetConfigName() );
+ }
+
+ // GCC_ExtraCompilerFlags
+ // Hopefully, they don't ever need to use backslashes because we're turning them into forward slashes here.
+ // If that does become a problem, we can put some token around the pathnames we need to be fixed up and leave the rest alone.
+ fprintf( fp, "GCC_ExtraCompilerFlags=%s\n", UsePOSIXSlashes( pKV->GetString( g_pOption_ExtraCompilerFlags, "" ) ) );
+
+ // GCC_ExtraLinkerFlags
+ fprintf( fp, "GCC_ExtraLinkerFlags=%s\n", pKV->GetString( g_pOption_ExtraLinkerFlags, "" ) );
+
+ // GCC_CustomVersionScript
+ fprintf( fp, "GCC_CustomVersionScript=%s\n", pKV->GetString( g_pOption_CustomVersionScript, "" ) );
+
+ // EntryPoint
+ fprintf( fp, "EntryPoint=%s\n", pKV->GetString( g_pOption_EntryPoint, "" ) );
+
+ // IgnoreAllDefaultLibraries
+ fprintf( fp, "IgnoreAllDefaultLibraries=%s\n", pKV->GetString( g_pOption_IgnoreAllDefaultLibraries, "no" ) );
+
+ // BufferSecurityCheck
+ fprintf( fp, "BufferSecurityCheck=%s\n", pKV->GetString( g_pOption_BufferSecurityCheck, "Yes" ) );
+
+ // SymbolVisibility
+ fprintf( fp, "SymbolVisibility=%s\n", pKV->GetString( g_pOption_SymbolVisibility, "hidden" ) );
+
+ // TreatWarningsAsErrors
+ fprintf( fp, "TreatWarningsAsErrors=%s\n", pKV->GetString( g_pOption_TreatWarningsAsErrors, "false" ) );
+
+ // OptimizerLevel
+ fprintf( fp, "OptimizerLevel=%s\n", pKV->GetString( g_pOption_OptimizerLevel, "$(SAFE_OPTFLAGS_GCC_422)" ) );
+
+ // system libraries
+ {
+ fprintf( fp, "SystemLibraries=" );
+ {
+ CSplitString libs( pKV->GetString( g_pOption_SystemLibraries ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < libs.Count(); i++ )
+ {
+ fprintf( fp, "-l%s ", libs[i] );
+ }
+ }
+ if ( !V_stricmp( g_pVPC->GetTargetPlatformName(), "OSX32" ) || !V_stricmp( g_pVPC->GetTargetPlatformName(), "OSX64" ) )
+ {
+ char rgchFrameworkCompilerFlags[1024]; rgchFrameworkCompilerFlags[0] = '\0';
+ CSplitString systemFrameworks( pKV->GetString( g_pOption_SystemFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < systemFrameworks.Count(); i++ )
+ {
+ fprintf( fp, "-framework %s ", systemFrameworks[i] );
+ }
+ CSplitString localFrameworks( pKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkName[MAX_PATH];
+ V_StripExtension( V_UnqualifiedFileName( localFrameworks[i] ), rgchFrameworkName, sizeof( rgchFrameworkName ) );
+ V_StripFilename( localFrameworks[i] );
+ fprintf( fp, "-F%s ", localFrameworks[i] );
+ fprintf( fp, "-framework %s ", rgchFrameworkName );
+ strcat( rgchFrameworkCompilerFlags, "-F" );
+ strcat( rgchFrameworkCompilerFlags, localFrameworks[i] );
+ }
+ fprintf( fp, "\n" );
+ if ( rgchFrameworkCompilerFlags[0] )
+ // the colon here is important - and should probably get percolated to more places in our generated
+ // makefiles - it means to perform the assignment once, rather than at evaluation time
+ fprintf( fp, "GCC_ExtraCompilerFlags:=$(GCC_ExtraCompilerFlags) %s\n", rgchFrameworkCompilerFlags );
+ }
+ else
+ fprintf( fp, "\n" );
+ }
+
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( "_DLL_EXT", false, NULL );
+ if ( pMacro )
+ fprintf( fp, "DLL_EXT=%s\n", pMacro->value.String() );
+
+ pMacro = g_pVPC->FindOrCreateMacro( "_SYM_EXT", false, NULL );
+ if ( pMacro )
+ fprintf( fp, "SYM_EXT=%s\n", pMacro->value.String() );
+
+ // ForceIncludes
+ {
+ CSplitString outStrings( pKV->GetString( g_pOption_ForceInclude ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ fprintf( fp, "FORCEINCLUDES= " );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ if ( V_strlen( outStrings[i] ) > 2 )
+ fprintf( fp, "-include %s ", UsePOSIXSlashes( outStrings[i] ) );
+ }
+ }
+ fprintf( fp, "\n" );
+
+ // DEFINES
+ if( !pConfig1 )
+ {
+ CSplitString outStrings( pKV->GetString( g_pOption_PreprocessorDefinitions ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ fprintf( fp, "DEFINES= " );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ fprintf( fp, "-D%s ", outStrings[i] );
+ }
+
+ WriteVpcMacroDefines( pConfig, fp );
+ fprintf( fp, "\n" );
+ }
+ else
+ {
+ // pConfig0 and pConfig1 are the same other than this section. So write just this one out something like:
+ // ifeq "$(CFG)" "debug"
+ // DEFINES += -DDEBUG -D_DEBUG -DPOSIX ...
+ // else
+ // DEFINES += -DNDEBUG -DPOSIX ...
+ // endif
+ fprintf( fp, "ifeq \"$(CFG)\" \"%s\"\n", pConfig->GetConfigName() );
+
+ CSplitString outStrings0( pKV->GetString( g_pOption_PreprocessorDefinitions ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ fprintf( fp, "DEFINES += " );
+ for ( int i=0; i < outStrings0.Count(); i++ )
+ {
+ fprintf( fp, "-D%s ", outStrings0[i] );
+ }
+ WriteVpcMacroDefines( pConfig, fp );
+
+ fprintf( fp, "\nelse\n" );
+
+ CSplitString outStrings1( pConfig1->m_pKV->GetString( g_pOption_PreprocessorDefinitions ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ fprintf( fp, "DEFINES += " );
+ for ( int i=0; i < outStrings1.Count(); i++ )
+ {
+ fprintf( fp, "-D%s ", outStrings1[i] );
+ }
+ WriteVpcMacroDefines( pConfig1, fp );
+
+ fprintf( fp, "\nendif\n" );
+ }
+
+ // INCLUDEDIRS
+ {
+ CSplitString outStrings( pKV->GetString( g_pOption_AdditionalIncludeDirectories ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ fprintf( fp, "INCLUDEDIRS += " );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ char sDir[MAX_PATH];
+ V_strncpy( sDir, outStrings[i], sizeof( sDir ) );
+ if ( !V_stricmp( sDir, "$(IntDir)" ) )
+ V_strncpy( sDir, "$(OBJ_DIR)", sizeof( sDir ) );
+
+ V_FixSlashes( sDir, '/' );
+ fprintf( fp, "%s ", sDir );
+ }
+ fprintf( fp, "\n" );
+ }
+ // CONFTYPE
+ if ( V_stristr( pKV->GetString( g_pOption_ConfigurationType ), "dll" ) )
+ {
+ fprintf( fp, "CONFTYPE=dll\n" );
+
+ // Write ImportLibrary for dll (so) builds.
+ const char *pRelative = pKV->GetString( g_pOption_ImportLibrary, "" );
+ fprintf( fp, "IMPORTLIBRARY=%s\n", UsePOSIXSlashes( pRelative ) );
+ }
+ else if ( V_stristr( pKV->GetString( g_pOption_ConfigurationType ), "lib" ) )
+ {
+ fprintf( fp, "CONFTYPE=lib\n" );
+ }
+ else if ( V_stristr( pKV->GetString( g_pOption_ConfigurationType ), "exe" ) )
+ {
+ fprintf( fp, "CONFTYPE=exe\n" );
+ }
+ else
+ {
+ fprintf( fp, "CONFTYPE=***UNKNOWN***\n" );
+ }
+
+ // GameOutputFile is where it copies OutputFile to.
+ fprintf( fp, "GAMEOUTPUTFILE=%s\n", UsePOSIXSlashes( pKV->GetString( g_pOption_GameOutputFile, "" ) ) );
+
+ // TargetCopies are where OutputFile copies are placed.
+ fprintf( fp, "TARGETCOPIES=%s\n", UsePOSIXSlashes( pKV->GetString( g_pOption_TargetCopies, "" ) ) );
+
+ // OutputFile is where it builds to.
+ char szFixedOutputFile[MAX_PATH];
+ V_strncpy( szFixedOutputFile, pKV->GetString( g_pOption_OutputFile ), sizeof( szFixedOutputFile ) );
+ V_FixSlashes( szFixedOutputFile, '/' );
+ // This file uses a custom build step.
+ char sFormattedOutputFile[MAX_PATH];
+ char szAbsPath[MAX_PATH];
+ V_MakeAbsolutePath( szAbsPath, sizeof(szAbsPath), szFixedOutputFile );
+ DoStandardVisualStudioReplacements( szFixedOutputFile, szAbsPath, sFormattedOutputFile, sizeof( sFormattedOutputFile ) );
+
+ fprintf( fp, "OUTPUTFILE=%s\n", sFormattedOutputFile );
+
+ fprintf( fp, "\n\n" );
+
+ // post build event
+ char rgchPostBuildCommand[2048]; rgchPostBuildCommand[0] = '\0';
+ if ( pKV->GetString( g_pOption_PostBuildEventCommandLine, NULL ) )
+ {
+ V_strncpy( rgchPostBuildCommand, pKV->GetString( g_pOption_PostBuildEventCommandLine, NULL ), sizeof( rgchPostBuildCommand ) );
+ // V_StripPrecedingAndTrailingWhitespace( rgchPostBuildCommand );
+ }
+ if ( V_strlen( rgchPostBuildCommand ) )
+ fprintf( fp, "POSTBUILDCOMMAND=%s\n", UsePOSIXSlashes( rgchPostBuildCommand ) );
+ else
+ fprintf( fp, "POSTBUILDCOMMAND=/bin/true\n" );
+
+ fprintf( fp, "\n\n" );
+
+
+ // Write all the filenames.
+ const char *sSourceFileExtensions[] = { "cpp", "cxx", "cc", "c", "mm", NULL };
+ fprintf( fp, "\n" );
+ WriteSourceFilesList( fp, "CPPFILES", (const char**)sSourceFileExtensions, pConfig->GetConfigName() );
+
+ // LIBFILES
+ char sImportLibraryFile[MAX_PATH];
+ const char *pRelative = pKV->GetString( g_pOption_ImportLibrary, "" );
+ V_strncpy( sImportLibraryFile, UsePOSIXSlashes( pRelative ), sizeof( sImportLibraryFile ) );
+ V_RemoveDotSlashes( sImportLibraryFile );
+
+ char sOutputFile[MAX_PATH];
+ const char *pOutputFile = pKV->GetString( g_pOption_OutputFile, "" );
+ V_strncpy( sOutputFile, UsePOSIXSlashes( pOutputFile ), sizeof( sOutputFile ) );
+ V_RemoveDotSlashes( sOutputFile );
+
+ fprintf( fp, "LIBFILES = \\\n" );
+
+ // Get original order the link files were specified in the .vpc files. See:
+ // http://stackoverflow.com/questions/45135/linker-order-gcc
+ // TL;DR. Gcc does a single pass through the list of libraries to resolve references.
+ // If library A depends on symbols in library B, library A should appear first so we
+ // need to restore the original order to allow users to control link order via
+ // their .vpc files.
+ CUtlSortVector< CFileConfig *, FileSortSortFunc > OriginalSort;
+
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = m_Files[i];
+ OriginalSort.InsertNoSort( pFileConfig );
+ }
+ OriginalSort.RedoSort();
+
+
+ CUtlVector< Filename_t > ImportLib;
+ CUtlVector< Filename_t > StaticLib;
+
+ for ( int i=0; i < OriginalSort.Count(); i++ )
+ {
+ CFileConfig *pFileConfig = OriginalSort[i];
+ if ( pFileConfig->IsExcludedFrom( pConfig->GetConfigName() ) )
+ continue;
+
+ Filename_t Filename;
+
+ Filename.iBasename = 0;
+
+ V_strncpy( Filename.szFilename, UsePOSIXSlashes( pFileConfig->m_Filename.String() ), sizeof( Filename.szFilename ) );
+ const char *pFilename = Filename.szFilename;
+ if ( IsLibraryFile( pFilename ) )
+ {
+ char *pchFileName = (char*)V_strrchr( pFilename, '/' ) + 1;
+ if (( !sImportLibraryFile[0] || V_stricmp( sImportLibraryFile, pFilename )) && // only link this as a library if it isn't our own output!
+ ( !sOutputFile[0] || V_stricmp( sOutputFile, pFilename)))
+ {
+ char szExt[32];
+ V_ExtractFileExtension( pFilename, szExt, sizeof(szExt) );
+ if (!( !V_stricmp( g_pVPC->GetTargetPlatformName(), "OSX32" ) || !V_stricmp( g_pVPC->GetTargetPlatformName(), "OSX64" ) ) &&
+ IsLibraryFile( pFilename ) && (pchFileName-1) && pchFileName[0] == 'l' && pchFileName[1] == 'i' && pchFileName[2] == 'b'
+ && szExt[0] != 'a' ) // its a lib ext but not an archive file, link like a library
+ {
+ *(pchFileName-1) = 0;
+
+ // Cygwin import libraries use ".dll.a", so get rid of any file extensions here.
+ char *pExt;
+ while ( 1 )
+ {
+ pExt = (char*)V_strrchr( pchFileName, '.' );
+ if ( !pExt || V_strrchr( pchFileName, '/' ) > pExt || V_strrchr( pchFileName, '\\' ) > pExt )
+ break;
+
+ *pExt = 0;
+ }
+
+ // +3 to dodge the lib ext
+ Filename.iBasename = ( pchFileName - pFilename ) + 3;
+ ImportLib.AddToTail( Filename );
+ }
+ else
+ {
+ StaticLib.AddToTail( Filename );
+ }
+ }
+ }
+ }
+
+ // Spew static libs out first, then import libraries. Otherwise things like bsppack
+ // will fail to link because libvstdlib.so came before tier1.a.
+ for( int i = 0; i < StaticLib.Count(); i++ )
+ {
+ fprintf( fp, " %s \\\n", StaticLib[ i ].szFilename );
+ }
+ for( int i = 0; i < ImportLib.Count(); i++ )
+ {
+ fprintf( fp, " -L%s -l%s \\\n", ImportLib[ i ].szFilename, &ImportLib[ i ].szFilename[ ImportLib[ i ].iBasename ] ); // +3 to dodge the lib ext
+ }
+
+ fprintf( fp, "\n\n" );
+
+ fprintf( fp, "LIBFILENAMES = \\\n" );
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = m_Files[i];
+ if ( pFileConfig->IsExcludedFrom( pConfig->GetConfigName() ) )
+ continue;
+
+ const char *pFilename = pFileConfig->m_Filename.String();
+ if ( IsLibraryFile( pFilename ) )
+ {
+ if (( !sImportLibraryFile[0] || V_stricmp( sImportLibraryFile, pFilename ) ) && // only link this as a library if it isn't our own output!
+ ( !sOutputFile[0] || V_stricmp( sOutputFile, pFilename)))
+ {
+ fprintf( fp, " %s \\\n", UsePOSIXSlashes( pFilename ) );
+ }
+ }
+ }
+
+ fprintf( fp, "\n\n" );
+
+
+ CUtlVector< CUtlString > otherDependencies;
+ static const char *sDependenciesSeparators[] = { ";", "\r", "\n" };
+
+ // Scan the list of files for any generated dependencies so we can pull them up front
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = m_Files[i];
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( pConfig->GetConfigName(), pConfig );
+
+ if ( pFileConfig->IsExcludedFrom( pConfig->GetConfigName() ) )
+ {
+ continue;
+ }
+
+ const char *pCustomBuildCommandLine = pFileSpecificData->GetOption( g_pOption_CustomBuildStepCommandLine );
+ const char *pOutputFile = pFileSpecificData->GetOption( g_pOption_Outputs );
+ if ( pOutputFile && pCustomBuildCommandLine && V_strlen( pCustomBuildCommandLine ) > 0 )
+ {
+ char szTempFilename[MAX_PATH];
+ V_strncpy( szTempFilename, UsePOSIXSlashes( pFileConfig->m_Filename.String() ), sizeof( szTempFilename ) );
+ const char *pFilename = szTempFilename;
+
+ // This file uses a custom build step.
+ char sFormattedOutputFile[8192];
+ char szAbsPath[MAX_PATH];
+ V_MakeAbsolutePath( szAbsPath, sizeof(szAbsPath), pFilename );
+ DoStandardVisualStudioReplacements( pOutputFile, szAbsPath, sFormattedOutputFile, sizeof( sFormattedOutputFile ) );
+
+ CSplitString outFiles( sFormattedOutputFile, sDependenciesSeparators, sizeof( sDependenciesSeparators ) / sizeof( sDependenciesSeparators[ 0 ] ) );
+
+ for ( int i = 0; i < outFiles.Count(); i ++ )
+ {
+ const char *pchOneFile = outFiles[ i ];
+ if ( *pchOneFile == '\0' )
+ {
+ continue;
+ }
+ // Remember this as a dependency so the executable will depend on it.
+ if ( otherDependencies.Find( pchOneFile ) == otherDependencies.InvalidIndex() )
+ otherDependencies.AddToTail( pchOneFile );
+ }
+ }
+ }
+
+ WriteOtherDependencies( fp, otherDependencies );
+ fprintf( fp, "\n\n" );
+
+ // Include the base makefile before the rules to build the .o files.
+ // Do this after we output otherDependencies definition since $(OTHER_DEPENDENCIES) is a dependency of all: target
+ const char *sMakeFileDependency = "";
+ bool bCondPOSIX = g_pVPC->FindOrCreateConditional( "POSIX", false, CONDITIONAL_NULL ) != NULL;
+ fprintf( fp, "# Include the base makefile now.\n" );
+ if ( bCondPOSIX )
+ {
+ sMakeFileDependency = k_pszBase_Makefile;
+ fprintf( fp, "include %s\n\n\n", sMakeFileDependency );
+ }
+
+ // Now write the rules to build the .o files.
+ // .o files go in [project dir]/obj/[config]/[base filename]
+ for ( int i=m_Files.First(); i != m_Files.InvalidIndex(); i=m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = m_Files[i];
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( pConfig->GetConfigName(), pConfig );
+
+ if ( pFileConfig->IsExcludedFrom( pConfig->GetConfigName() ) )
+ {
+ continue;
+ }
+
+ char szTempFilename[MAX_PATH];
+ V_strncpy( szTempFilename, UsePOSIXSlashes( pFileConfig->m_Filename.String() ), sizeof( szTempFilename ) );
+ const char *pFilename = szTempFilename;
+
+ // Custom build steps??
+ const char *pCustomBuildCommandLine = pFileSpecificData->GetOption( g_pOption_CustomBuildStepCommandLine );
+ const char *pOutputFile = pFileSpecificData->GetOption( g_pOption_Outputs );
+ if ( pOutputFile && pCustomBuildCommandLine && V_strlen( pCustomBuildCommandLine ) > 0 )
+ {
+ // This file uses a custom build step.
+ char sFormattedOutputFile[8192];
+ char sFormattedCommandLine[8192];
+ char sFormattedDependencies[8192];
+ DoStandardVisualStudioReplacements( pCustomBuildCommandLine, UsePOSIXSlashes( pFilename ), \
+ sFormattedCommandLine, sizeof( sFormattedCommandLine ) );
+ DoStandardVisualStudioReplacements( pOutputFile, UsePOSIXSlashes( pFilename ), \
+ sFormattedOutputFile, sizeof( sFormattedOutputFile ) );
+
+
+ // AdditionalDependencies only applies to custom build steps, not normal compilation steps
+ const char *pAdditionalDeps = pFileSpecificData->GetOption( g_pOption_AdditionalDependencies );
+ if ( pAdditionalDeps )
+ DoStandardVisualStudioReplacements( pAdditionalDeps, szAbsPath, sFormattedDependencies, sizeof( sFormattedDependencies ) );
+ else
+ sFormattedDependencies[0] = 0;
+
+ CSplitString additionalDeps( sFormattedDependencies, sDependenciesSeparators, sizeof( sDependenciesSeparators ) / sizeof( sDependenciesSeparators[0] ) );
+ FOR_EACH_VEC_BACK( additionalDeps, i )
+ {
+ const char *pchOneFile = additionalDeps[i];
+ if ( *pchOneFile == '\0' )
+ {
+ additionalDeps.Remove( i );
+ }
+ }
+
+ CSplitString outFiles( sFormattedOutputFile, sDependenciesSeparators, sizeof( sDependenciesSeparators ) / sizeof( sDependenciesSeparators[ 0 ] ) );
+ FOR_EACH_VEC_BACK( outFiles, i )
+ {
+ const char *pchOneFile = outFiles[ i ];
+ if ( *pchOneFile == '\0' )
+ {
+ outFiles.Remove( i );
+ }
+ }
+
+ char rgchIntermediateFile[MAX_PATH];
+ rgchIntermediateFile[0] = 0;
+
+ // ABSPATH NOTE
+ //
+ // Make will not do what we expect with ../../this/dir/foo.cpp, and these are often the result of nested macros
+ // in VPC files, so ensure we are giving make absolute paths for our targets via $(abspath ...)
+
+ if ( outFiles.Count() == 1 )
+ {
+ // one output file: create a standard rule -- output : input \n \t command
+ fprintf( fp, "\n$(abspath %s) ", outFiles[0] );
+ }
+ else
+ {
+ // multiple output files: DO NOT DO THIS -- output output output : input \n \t command
+ // as this will cause up to three parallel invocations of command!
+ // best-practice workaround is to create a temp intermediate file
+ static int s_uniqueId = 0;
+ V_snprintf( rgchIntermediateFile, sizeof(rgchIntermediateFile), "$(OBJ_DIR)/_custombuildstep_%d.touchfile", s_uniqueId );
+ fprintf( fp, "\n%s ", rgchIntermediateFile );
+ ++s_uniqueId;
+
+ V_strcat( sFormattedCommandLine, CFmtStrMax( "\n@touch %s", rgchIntermediateFile ), sizeof(sFormattedCommandLine) );
+ }
+ // Outputs dependent on input file and .mak file
+ fprintf( fp, ": $(abspath %s) %s", UsePOSIXSlashes( pFilename ), g_pVPC->GetOutputFilename() );
+ FOR_EACH_VEC( additionalDeps, i )
+ {
+ fprintf( fp, " %s", additionalDeps[i] );
+ }
+ /// XXX(JohnS): Was this double-added as an accident, or is there some arcane make reason to have it be the
+ /// first and last dep?
+ fprintf( fp, " $(abspath %s)\n", UsePOSIXSlashes( pFilename ) );
+ const char *pDescription = pFileSpecificData->GetOption( g_pOption_Description );
+ DoStandardVisualStudioReplacements( pDescription, UsePOSIXSlashes( pFilename ), \
+ sFormattedOutputFile, sizeof( sFormattedOutputFile ) );
+
+ fprintf( fp, "\t @echo \"%s\";mkdir -p $(OBJ_DIR) 2> /dev/null;\n", sFormattedOutputFile );
+
+ static const char *sSeparators[] = { "\r", "\n" };
+ CSplitString outLines( sFormattedCommandLine, sSeparators, sizeof( sSeparators ) / sizeof( sSeparators[ 0 ] ) );
+ for ( int i = 0; i < outLines.Count(); ++i )
+ {
+ const char *pchOneLine = outLines[ i ];
+ if ( *pchOneLine == '\0' )
+ {
+ continue;
+ }
+ fprintf( fp, "\t %s\n", pchOneLine );
+ }
+ fprintf( fp, "\n" );
+
+ // for multiple output files, create a dependency between output files and intermediate file + makefile
+ if ( outFiles.Count() > 1 )
+ {
+ FOR_EACH_VEC( outFiles, i )
+ {
+ // See ABSPATH NOTE above
+ fprintf( fp, "$(abspath %s) : %s %s\n\t @touch %s\n\n", outFiles[i], rgchIntermediateFile, g_pVPC->GetOutputFilename(), outFiles[i] );
+ }
+ }
+ }
+ else if ( CheckExtensions( pFilename, (const char**)sSourceFileExtensions ) )
+ {
+ char sObjFilename[MAX_PATH];
+ GetObjFilenameForFile( pConfig->GetConfigName(), pFilename, sObjFilename, sizeof( sObjFilename ) );
+
+ // Get the base obj filename for the .P file.
+ char sPFileBase[MAX_PATH];
+ V_StripExtension( sObjFilename, sPFileBase, sizeof( sPFileBase ) );
+
+ fprintf( fp, "\nifneq (clean, $(findstring clean, $(MAKECMDGOALS)))\n" );
+ fprintf( fp, "-include %s.P\n", sPFileBase );
+ fprintf( fp, "endif\n" );
+
+ bool bUsedPrecompiledHeader = false;
+
+ // Handle precompiled header options.
+ const char *pPrecompiledHeaderOption = pFileSpecificData->GetOption( g_pOption_PrecompiledHeader );
+ const char *pUsePCHThroughFile = pFileSpecificData->GetOption( g_pOption_UsePCHThroughFile );
+
+ if ( !g_pVPC->IsPosixPCHDisabled() && pPrecompiledHeaderOption && pUsePCHThroughFile )
+ {
+ char sIncludeFilename[MAX_PATH];
+ const char *pHeaderFileName = V_GetFileName( pUsePCHThroughFile );
+ V_snprintf( sIncludeFilename, sizeof( sIncludeFilename ), "$(OBJ_DIR)/%s", pHeaderFileName );
+
+ // Note that we use $(abspath ...) for most things, but the provided PCH file (pUsePCHThroughFile)
+ // is actually a include filename -- that is, it is meant to be found the same way #include "pch"
+ // would be. We use make's vpath directive to tell it to resolve this file relative to the
+ // INCLUDEDIRS list we conveniently have, (starting with PWD to mimic c/c++ include searching), but
+ // that means we have to be careful to always reference it as a dependency the same way.
+ //
+ // However, since we explicitly opt-in to files using said PCH, we can just specifically set the PCH
+ // as a dependency of every file that has opted-in to use it, so we don't run into issues with
+ // things like the compiler's -MD dependencies referring to it differently.
+ if ( V_stristr( pPrecompiledHeaderOption, "Not Using" ) )
+ {
+ // Don't do anything special if this file doesn't want to use a precompiled header.
+ }
+ else if ( V_stristr( pPrecompiledHeaderOption, "Create" ) )
+ {
+ // Compile pUsePCHThroughFile and output it to obj/<config>/filename.h.gch
+ fprintf( fp, "\n%s.gch : %s $(PWD)/%s %s $(OTHER_DEPENDENCIES)\n",
+ sIncludeFilename, pUsePCHThroughFile, g_pVPC->GetOutputFilename(), sMakeFileDependency );
+ fprintf( fp, "\t$(PRE_COMPILE_FILE)\n" );
+ fprintf( fp, "\t$(COMPILE_PCH) $(POST_COMPILE_FILE)\n" );
+
+ // include the .P it spits out, ensuring it is marked as depending on the gch build finishing so
+ // we don't include a stale one.
+ fprintf( fp, "\n%s.P : %s.gch\n", sIncludeFilename, sIncludeFilename );
+ fprintf( fp, "\nvpath %s . $(INCLUDEDIRS)\n", pUsePCHThroughFile );
+ fprintf( fp, "\nifneq (clean, $(findstring clean, $(MAKECMDGOALS)))\n" );
+ fprintf( fp, "include %s.P\n", sIncludeFilename );
+ fprintf( fp, "endif\n" );
+
+ // Create obj/<config>/filename.h as well, depending on the GCH so it is re-copied when we
+ // recompile it.
+ //
+ // Because we pass this as -include <foo> to the compiler, this allows conditions where the PCH
+ // cannot be used to fall back to the compiler simply using the .h, rather than failing
+ // entirely.
+ fprintf( fp, "\n%s : %s %s.gch $(PWD)/%s %s\n",
+ sIncludeFilename, pUsePCHThroughFile, sIncludeFilename, g_pVPC->GetOutputFilename(), sMakeFileDependency );
+ fprintf( fp, "\tcp -f $< %s\n", sIncludeFilename );
+ }
+ else if ( V_stristr( pPrecompiledHeaderOption, "Use" ) )
+ {
+ CFileConfig *pCreator = pAccel->FindFileThatCreatesPrecompiledHeader( pConfig->GetConfigName(), pUsePCHThroughFile );
+ if ( pCreator && !pCreator->IsExcludedFrom( pConfig->GetConfigName() ) )
+ {
+ const char *pCompileAsOption = pFileSpecificData->GetOption( g_pOption_CompileAs );
+ fprintf( fp, "\n%s : TARGET_PCH_FILE = %s\n", sObjFilename, sIncludeFilename );
+ fprintf( fp, "%s : $(abspath %s) %s.gch %s $(PWD)/%s %s\n",
+ sObjFilename, UsePOSIXSlashes( pFilename ), sIncludeFilename, sIncludeFilename,
+ g_pVPC->GetOutputFilename(), sMakeFileDependency );
+ fprintf( fp, "\t$(PRE_COMPILE_FILE)\n" );
+ if ( pCompileAsOption && strstr( pCompileAsOption, "(/TC)" ) ) // Compile as C code (/TC)
+ {
+ fprintf( fp, "\t$(COMPILE_FILE_WITH_PCH_C) $(POST_COMPILE_FILE)\n" );
+ }
+ else
+ {
+ fprintf( fp, "\t$(COMPILE_FILE_WITH_PCH) $(POST_COMPILE_FILE)\n" );
+ }
+ bUsedPrecompiledHeader = true;
+ }
+ }
+ }
+
+ if ( !bUsedPrecompiledHeader )
+ {
+ const char *pCompileAsOption = pFileSpecificData->GetOption( g_pOption_CompileAs );
+ fprintf( fp, "\n%s : $(abspath %s) $(PWD)/%s %s $(OTHER_DEPENDENCIES)\n",
+ sObjFilename, UsePOSIXSlashes( pFilename ), g_pVPC->GetOutputFilename(), sMakeFileDependency );
+ fprintf( fp, "\t$(PRE_COMPILE_FILE)\n" );
+ if ( pCompileAsOption && strstr( pCompileAsOption, "(/TC)" ) ) // Compile as C code (/TC)
+ {
+ fprintf( fp, "\t$(COMPILE_FILE_C) $(POST_COMPILE_FILE)\n" );
+ }
+ else
+ {
+ fprintf( fp, "\t$(COMPILE_FILE) $(POST_COMPILE_FILE)\n" );
+ }
+ }
+ }
+ }
+
+ if( !pConfig1 )
+ {
+ fprintf( fp, "\n\nendif # (CFG=%s)\n\n", pConfig->GetConfigName() );
+ fprintf( fp, "\n\n" );
+ }
+ }
+
+ void WriteOtherDependencies( FILE *fp, CUtlVector< CUtlString > &otherDependencies )
+ {
+ fprintf( fp, "\nOTHER_DEPENDENCIES = \\\n" );
+ for ( int i=0; i < otherDependencies.Count(); i++ )
+ {
+ fprintf( fp, "\t$(abspath %s)%s\n", UsePOSIXSlashes( otherDependencies[i].String() ),
+ (i == otherDependencies.Count()-1) ? "" : " \\" );
+ }
+ fprintf( fp, "\n\n" );
+ fprintf( fp, "-include $(OBJ_DIR)/_other_deps.P\n" );
+ }
+
+ bool CheckReleaseDebugConfigsAreSame()
+ {
+ if ( g_pVPC->IsVerboseMakefile() )
+ return false;
+
+ // Go through two configs and check to see that all the strings except the defines are the same.
+ // If so, we can write the entire makefile and only special case the $PreprocessorDefinitions portion.
+ // Makes for a much simpler makefile to read and modify when testing various flags, etc.
+ if( m_BaseConfigData.m_Configurations.Count() == 2 )
+ {
+ CSpecificConfig *pConfig0 = m_BaseConfigData.m_Configurations[0];
+ CSpecificConfig *pConfig1 = m_BaseConfigData.m_Configurations[1];
+ KeyValues *pKV0 = pConfig0->m_pKV;
+ KeyValues *pKV1 = pConfig1->m_pKV;
+
+ KeyValues *val0 = pKV0->GetFirstValue();
+ KeyValues *val1 = pKV1->GetFirstValue();
+ for( ;; )
+ {
+ // If one has run out and the other hasn't, bail.
+ if( !val0 != !val1 )
+ break;
+
+ if( !val0 )
+ {
+ // We've hit the end of both keyvalues, and everything was the same.
+ Assert( !val1 );
+ return true;
+ }
+
+ // If the datatypes aren't strings or aren't the same, bail.
+ if( ( val0->GetDataType() != KeyValues::TYPE_STRING ) || ( val0->GetDataType() != val1->GetDataType() ) )
+ break;
+
+ // If the keynames differ, bail.
+ if( V_strcmp( val0->GetName(), val1->GetName() ) )
+ break;
+
+ // If this isn't the $PreprocessorDefinitions key, check the values.
+ if( V_strcmp( val0->GetName(), g_pOption_PreprocessorDefinitions ) )
+ {
+ if( V_strcmp( val0->GetString(), val1->GetString() ) )
+ break;
+
+ // look for visual studio macros and assume those evaluate to config specific values
+ if ( V_strstr( val0->GetString(), "$(" ) )
+ break;
+ }
+
+ // Next.
+ val0 = val0->GetNextValue();
+ val1 = val1->GetNextValue();
+ }
+ }
+
+ return false;
+ }
+
+ void WriteMakefile( const char *pFilename )
+ {
+ FILE *fp = fopen( pFilename, "wt" );
+
+ CPrecompiledHeaderAccel accel;
+ accel.Setup( m_Files, &m_BaseConfigData );
+
+ m_bForceLowerCaseFileName = false;
+
+ // Write all the non-config-specific stuff.
+ WriteNonConfigSpecificStuff( fp );
+
+ bool bReleaseDebugAreSame = CheckReleaseDebugConfigsAreSame();
+ if( bReleaseDebugAreSame )
+ {
+ // If the two configs are the same except for $PreprocessorDefinitions, then call
+ // WriteConfigSpecificStuff() once with both configs.
+ Assert( m_BaseConfigData.m_Configurations.Count() == 2 );
+ CSpecificConfig *pConfig0 = m_BaseConfigData.m_Configurations[0];
+ CSpecificConfig *pConfig1 = m_BaseConfigData.m_Configurations[1];
+
+ // Make sure we always have "release" second (ie, the default case).
+ if( !V_stricmp( pConfig0->GetConfigName(), "release" ) )
+ {
+ CSpecificConfig *pConfigTemp = pConfig0;
+ pConfig0 = pConfig1;
+ pConfig1 = pConfigTemp;
+ }
+
+ m_bForceLowerCaseFileName = pConfig0->m_pKV->GetBool( g_pOption_LowerCaseFileNames, false );
+ WriteConfigSpecificStuff( pConfig0, fp, &accel, pConfig1 );
+ }
+ else
+ {
+ // Write each config out.
+ for ( int i=m_BaseConfigData.m_Configurations.First(); i != m_BaseConfigData.m_Configurations.InvalidIndex(); i=m_BaseConfigData.m_Configurations.Next( i ) )
+ {
+ CSpecificConfig *pConfig = m_BaseConfigData.m_Configurations[i];
+ m_bForceLowerCaseFileName = pConfig->m_pKV->GetBool( g_pOption_LowerCaseFileNames, false );
+ WriteConfigSpecificStuff( pConfig, fp, &accel, NULL );
+ }
+ }
+
+ fclose( fp );
+ Sys_CopyToMirror( pFilename );
+ }
+
+ bool m_bForceLowerCaseFileName;
+};
+
+static CProjectGenerator_Makefile g_ProjectGenerator_Makefile;
+IBaseProjectGenerator* GetMakefileProjectGenerator()
+{
+ return &g_ProjectGenerator_Makefile;
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_ps3.cpp b/external/vpc/utils/vpc/projectgenerator_ps3.cpp
new file mode 100644
index 0000000..c3b4641
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_ps3.cpp
@@ -0,0 +1,1257 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#undef PROPERTYNAME
+#define PROPERTYNAME( X, Y ) { X##_##Y, #X, #Y },
+static PropertyName_t s_PS3PropertyNames[] =
+{
+ #include "projectgenerator_ps3.inc"
+ { -1, NULL, NULL }
+};
+
+IBaseProjectGenerator* GetPS3ProjectGenerator()
+{
+ static CProjectGenerator_PS3 *s_pProjectGenerator = NULL;
+ if ( !s_pProjectGenerator )
+ {
+ s_pProjectGenerator = new CProjectGenerator_PS3();
+ }
+
+ return s_pProjectGenerator->GetProjectGenerator();
+}
+
+CProjectGenerator_PS3::CProjectGenerator_PS3()
+{
+ m_pVCProjGenerator = new CVCProjGenerator();
+ m_pVCProjGenerator->SetupGeneratorDefinition( this, "ps3.def", s_PS3PropertyNames );
+}
+
+bool CProjectGenerator_PS3::WriteFile( CProjectFile *pFile )
+{
+ m_XMLWriter.PushNode( "File" );
+ m_XMLWriter.Write( CFmtStrMax( "RelativePath=\"%s\"", pFile->m_Name.Get() ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int i = 0; i < pFile->m_Configs.Count(); i++ )
+ {
+ if ( !WriteConfiguration( pFile->m_Configs[i] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteFolder( CProjectFolder *pFolder )
+{
+ m_XMLWriter.PushNode( "Filter" );
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_XMLWriter.FixupXMLString( pFolder->m_Name.Get() ) ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WritePreBuildEventTool( CPreBuildEventTool *pPreBuildEventTool )
+{
+ if ( !pPreBuildEventTool )
+ {
+ // not an error, some tools n/a for aconfig
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCPreBuildEventTool\"" );
+
+ for ( int i = 0; i < pPreBuildEventTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pPreBuildEventTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_PREBUILDEVENT_CommandLine:
+ m_XMLWriter.Write( CFmtStrMax( "CommandLine=\"%s\"", m_XMLWriter.FixupXMLString( pPreBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_PREBUILDEVENT_Description:
+ m_XMLWriter.Write( CFmtStrMax( "Description=\"%s\"", pPreBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_PREBUILDEVENT_ExcludedFromBuild:
+ m_XMLWriter.Write( CFmtStrMax( "ExcludedFromBuild=\"%s\"", BoolStringToTrueFalseString( pPreBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+ }
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteCustomBuildTool( CCustomBuildTool *pCustomBuildTool )
+{
+ if ( !pCustomBuildTool )
+ {
+ // not an error, some tools n/a for aconfig
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCCustomBuildTool\"" );
+
+ for ( int i = 0; i < pCustomBuildTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pCustomBuildTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_CUSTOMBUILDSTEP_CommandLine:
+ m_XMLWriter.Write( CFmtStrMax( "CommandLine=\"%s\"", m_XMLWriter.FixupXMLString( pCustomBuildTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_CUSTOMBUILDSTEP_Description:
+ m_XMLWriter.Write( CFmtStrMax( "Description=\"%s\"", pCustomBuildTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_CUSTOMBUILDSTEP_Outputs:
+ m_XMLWriter.Write( CFmtStrMax( "Outputs=\"%s\"", pCustomBuildTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_CUSTOMBUILDSTEP_AdditionalDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalDependencies=\"%s\"", pCustomBuildTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+ }
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteSNCCompilerTool( CCompilerTool *pCompilerTool )
+{
+ if ( !pCompilerTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCCLCompilerTool\"" );
+
+ // aggregates or purges state as needed
+ CUtlString additionalOptions = "";
+
+ for ( int i = 0; i < pCompilerTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ int nOrdinalValue = atoi( pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() );
+
+ switch ( pCompilerTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_SNCCOMPILER_AdditionalIncludeDirectories:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalIncludeDirectories=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCCOMPILER_PreprocessorDefinitions:
+ m_XMLWriter.Write( CFmtStrMax( "PreprocessorDefinitions=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCCOMPILER_ForceIncludes:
+ m_XMLWriter.Write( CFmtStrMax( "ForcedIncludeFiles=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCCOMPILER_GenerateDebugInformation:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-g ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_Warnings:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xdiag=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_TreatMessagesAsErrors:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xquit=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_DisableSpecificWarnings:
+ m_XMLWriter.Write( CFmtStrMax( "DisableSpecificWarnings=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCCOMPILER_ObjectFileName:
+ m_XMLWriter.Write( CFmtStrMax( "ObjectFile=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCCOMPILER_CallprofHierarchicalProfiling:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xcallprof=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_OptimizationLevel:
+ if ( nOrdinalValue == 0 )
+ {
+ // lack of any -0<x> means -O0
+ additionalOptions += " ";
+ }
+ else if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-O1 ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-O2 ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-Os ";
+ }
+ else if ( nOrdinalValue == 4 )
+ {
+ additionalOptions += "-Od ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_FastMath:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xfastmath=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_RelaxAliasChecking:
+ if ( nOrdinalValue >= 0 )
+ {
+ additionalOptions += CFmtStrMax( "-Xrelaxalias=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_BranchlessCompares:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xbranchless=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_UnrollLoops:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xunrollssa=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_AssumeAlignedPointers:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Xassumecorrectalignment=1 ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_AssumeCorrectSign:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Xassumecorrectsign=1 ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_TOCPointerPreservation:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-Xnotocrestore=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_InitializedDataPlacement:
+ additionalOptions += CFmtStrMax( "-Xbss=%d ", nOrdinalValue );
+ break;
+
+ case PS3_SNCCOMPILER_PromoteFPConstantsToDoubles:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Xfltconst=8 ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_CCPPDialect:
+ if ( nOrdinalValue )
+ {
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-Xc=ansi ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-Xc=arm ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-Xc=cp ";
+ }
+ else if ( nOrdinalValue == 4 )
+ {
+ additionalOptions += "-Xc=cfront ";
+ }
+ else if ( nOrdinalValue == 5 )
+ {
+ additionalOptions += "-Xc=knr ";
+ }
+ }
+ break;
+
+ case PS3_SNCCOMPILER_CPPExceptionsAndRTTIUsage:
+ if ( nOrdinalValue == 0 )
+ {
+ additionalOptions += "-Xc-=rtti -Xc-=exceptions ";
+ }
+ else if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-Xc+=rtti -Xc-=exceptions ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-Xc+=rtti -Xc+=exceptions ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_DefaultCharUnsigned:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Xchar=unsigned ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_DefaultFPConstantsAsTypeFloat:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Xsingleconst=1 ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_BuiltInDefinitionForWCHAR_TType:
+ if ( nOrdinalValue == 0 )
+ {
+ additionalOptions += "-Xwchart=uint ";
+ }
+ else if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-Xwchart=ulong ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-Xwchart=ushort ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-Xwchart=uchar ";
+ }
+ else if ( nOrdinalValue == 4 )
+ {
+ additionalOptions += "-Xwchart=int ";
+ }
+ else if ( nOrdinalValue == 5 )
+ {
+ additionalOptions += "-Xwchart=long ";
+ }
+ else if ( nOrdinalValue == 6 )
+ {
+ additionalOptions += "-Xwchart=short ";
+ }
+ else if ( nOrdinalValue == 7 )
+ {
+ additionalOptions += "-Xwchart=char ";
+ }
+ else if ( nOrdinalValue == 8 )
+ {
+ additionalOptions += "-Xwchart=schar ";
+ }
+ break;
+
+ case PS3_SNCCOMPILER_CreateUsePrecompiledHeader:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += CFmtStrMax( "--create_pch=&quot;%s&quot; ", pCompilerTool->m_PropertyStates.GetProperty( PS3_SNCCOMPILER_PrecompiledHeaderFile )->m_StringValue );
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "--pch --pch_dir=&quot;$(IntDir)&quot; ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += CFmtStrMax( "--use_pch=&quot;%s&quot; ", pCompilerTool->m_PropertyStates.GetProperty( PS3_SNCCOMPILER_PrecompiledHeaderFile )->m_StringValue );
+ }
+ break;
+
+ case PS3_SNCCOMPILER_PrecompiledHeaderFile:
+ // already accounted for
+ break;
+
+ case PS3_SNCCOMPILER_AdditionalOptions:
+ if ( !pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.IsEmpty() )
+ {
+ additionalOptions += pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue;
+ additionalOptions += " ";
+ }
+ break;
+ }
+ }
+
+ if ( !additionalOptions.IsEmpty() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalOptions=\"%s\"", additionalOptions.Get() ) );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteGCCCompilerTool( CCompilerTool *pCompilerTool )
+{
+ if ( !pCompilerTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCCLCompilerTool\"" );
+
+ // aggregates or purges state as needed
+ CUtlString additionalOptions = "";
+
+ for ( int i = 0; i < pCompilerTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ int nOrdinalValue = atoi( pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() );
+
+ switch ( pCompilerTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_GCCCOMPILER_AdditionalIncludeDirectories:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalIncludeDirectories=\"%s\"", m_XMLWriter.FixupXMLString( pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_GCCCOMPILER_PreprocessorDefinitions:
+ m_XMLWriter.Write( CFmtStrMax( "PreprocessorDefinitions=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCCOMPILER_ForceIncludes:
+ m_XMLWriter.Write( CFmtStrMax( "ForcedIncludeFiles=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCCOMPILER_GenerateDebugInformation:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-g ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_Warnings:
+ if ( nOrdinalValue == 0 )
+ {
+ additionalOptions += "-w ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-Wall ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_ExtraWarnings:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Wextra ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_WarnLoadHitStores:
+ break;
+
+ case PS3_GCCCOMPILER_WarnMicrocodedInstruction:
+ break;
+
+ case PS3_GCCCOMPILER_TreatWarningsAsErrors:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Werror ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_ObjectFileName:
+ m_XMLWriter.Write( CFmtStrMax( "ObjectFile=\"%s\"", pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCCOMPILER_CallprofHierarchicalProfiling:
+ break;
+
+ case PS3_GCCCOMPILER_SPURSUsage:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-mspurs-job-initialize ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-mspurs-job ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-mspurs-task ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_OptimizationLevel:
+ if ( nOrdinalValue == 0 )
+ {
+ additionalOptions += "-O0 ";
+ }
+ else if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-O1 ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-O2 ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-O3 ";
+ }
+ else if ( nOrdinalValue == 4 )
+ {
+ additionalOptions += "-Os ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_FastMath:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-ffast-math ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_NoStrictAliasing:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fno-strict-aliasing ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_UnrollLoops:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-funroll-loops ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_InlineFunctionSizeLimit:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += CFmtStrMax( "-finline-limit=%d ", nOrdinalValue );
+ }
+ break;
+
+ case PS3_GCCCOMPILER_TOCUsage:
+ break;
+
+ case PS3_GCCCOMPILER_SaveRestoreFunctions:
+ break;
+
+ case PS3_GCCCOMPILER_GenerateMicrocodedInstructions:
+ break;
+
+ case PS3_GCCCOMPILER_PositionIndependentCode:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fpic ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_FunctionSections:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-ffunction-sections ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_DataSections:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fdata-sections ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_StackCheck:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fstack-check ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_CPPExceptionsAndRTTIUsage:
+ if ( nOrdinalValue == 0 )
+ {
+ additionalOptions += "-fno-exceptions -fno-rtti ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_CheckANSICompliance:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-ansi ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_DefaultCharSigned:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fsigned-char ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_Permissive:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fpermissive ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_EnableMSExtensions:
+ break;
+
+ case PS3_GCCCOMPILER_RelaxCPPCompliance:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fsource-402 ";
+ }
+ break;
+
+ case PS3_GCCCOMPILER_AdditionalOptions:
+ if ( !pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue.IsEmpty() )
+ {
+ additionalOptions += pCompilerTool->m_PropertyStates.m_Properties[i].m_StringValue;
+ additionalOptions += " ";
+ }
+ break;
+ }
+ }
+
+ if ( !additionalOptions.IsEmpty() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalOptions=\"%s\"", additionalOptions.Get() ) );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WritePreLinkEventTool( CPreLinkEventTool *pPreLinkEventTool )
+{
+ if ( !pPreLinkEventTool )
+ {
+ // not an error, some tools n/a for aconfig
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCPreLinkEventTool\"" );
+
+ for ( int i = 0; i < pPreLinkEventTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pPreLinkEventTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_PRELINKEVENT_CommandLine:
+ m_XMLWriter.Write( CFmtStrMax( "CommandLine=\"%s\"", m_XMLWriter.FixupXMLString( pPreLinkEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_PRELINKEVENT_Description:
+ m_XMLWriter.Write( CFmtStrMax( "Description=\"%s\"", pPreLinkEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_PRELINKEVENT_ExcludedFromBuild:
+ m_XMLWriter.Write( CFmtStrMax( "ExcludedFromBuild=\"%s\"", BoolStringToTrueFalseString( pPreLinkEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+ }
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteSNCLinkerTool( CLinkerTool *pLinkerTool )
+{
+ if ( !pLinkerTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCLinkerTool\"" );
+
+ // aggregates or purges state as needed
+ CUtlString additionalOptions = "";
+
+ for ( int i = 0; i < pLinkerTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ int nOrdinalValue = atoi( pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() );
+
+ switch ( pLinkerTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_SNCLINKER_OutputFile:
+ m_XMLWriter.Write( CFmtStrMax( "OutputFile=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_OutputFormat:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-oformat=fself ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-oformat=fself_npdrm ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-oformat=prx -prx-with-runtime ";
+ }
+ else if ( nOrdinalValue == 4 )
+ {
+ additionalOptions += "-oformat=fsprx -prx-with-runtime ";
+ }
+ break;
+
+ case PS3_SNCLINKER_AdditionalDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalDependencies=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_AdditionalLibraryDirectories:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalLibraryDirectories=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_IgnoreAllDefaultLibraries:
+ if ( nOrdinalValue )
+ {
+ m_XMLWriter.Write( "IgnoreAllDefaultLibraries=\"true\"" );
+ }
+ break;
+
+ case PS3_SNCLINKER_UsingExceptionHandling:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "--exceptions ";
+ }
+ break;
+
+ case PS3_SNCLINKER_TOCPointerElimination:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "--notocrestore ";
+ }
+ break;
+
+ case PS3_SNCLINKER_ForceSymbolReferences:
+ m_XMLWriter.Write( CFmtStrMax( "ForceSymbolReferences=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_CallprofHierarchicalProfiling:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "--callprof ";
+ }
+ break;
+
+ case PS3_SNCLINKER_DebugInfoAndSymbolStripping:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-S ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-s ";
+ }
+ break;
+
+ case PS3_SNCLINKER_UnusedFunctionAndDataStripping:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-strip-unused ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-strip-unused-data ";
+ }
+ break;
+
+ case PS3_SNCLINKER_ImportLibrary:
+ m_XMLWriter.Write( CFmtStrMax( "ImportLibrary=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_GenerateMapFile:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += CFmtStrMax( "-Map=&quot;%s&quot; ", pLinkerTool->m_PropertyStates.GetProperty( PS3_SNCLINKER_MapFileName )->m_StringValue );
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += CFmtStrMax( "-Map=&quot;%s&quot; -sn-full-map ", pLinkerTool->m_PropertyStates.GetProperty( PS3_SNCLINKER_MapFileName )->m_StringValue );
+ }
+ break;
+
+ case PS3_SNCLINKER_MapFileName:
+ m_XMLWriter.Write( CFmtStrMax( "MapFileName=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_SNCLINKER_LinkLibraryDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "LinkLibraryDependencies=\"%s\"", BoolStringToTrueFalseString( pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_SNCLINKER_AdditionalOptions:
+ if ( !pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.IsEmpty() )
+ {
+ additionalOptions += pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue;
+ additionalOptions += " ";
+ }
+ break;
+ }
+ }
+
+ if ( !additionalOptions.IsEmpty() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalOptions=\"%s\"", additionalOptions.Get() ) );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteGCCLinkerTool( CLinkerTool *pLinkerTool )
+{
+ if ( !pLinkerTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCLinkerTool\"" );
+
+ // aggregates or purges state as needed
+ CUtlString additionalOptions = "";
+
+ for ( int i = 0; i < pLinkerTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ int nOrdinalValue = atoi( pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() );
+
+ switch ( pLinkerTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_GCCLINKER_OutputFile:
+ m_XMLWriter.Write( CFmtStrMax( "OutputFile=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCLINKER_AdditionalDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalDependencies=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCLINKER_AdditionalLibraryDirectories:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalLibraryDirectories=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCLINKER_ImportLibrary:
+ m_XMLWriter.Write( CFmtStrMax( "ImportLibrary=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCLINKER_SPURSUsage:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += "-mspurs-job-initialize ";
+ }
+ else if ( nOrdinalValue == 2 )
+ {
+ additionalOptions += "-mspurs-job ";
+ }
+ else if ( nOrdinalValue == 3 )
+ {
+ additionalOptions += "-mspurs-task ";
+ }
+ break;
+
+ case PS3_GCCLINKER_PositionIndependentCode:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-fpic ";
+ }
+ break;
+
+ case PS3_GCCLINKER_EmitRelocations:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Wl,-q ";
+ }
+ break;
+
+ case PS3_GCCLINKER_GarbageCollection:
+ if ( nOrdinalValue )
+ {
+ additionalOptions += "-Wl,--gc-sections ";
+ }
+ break;
+
+ case PS3_GCCLINKER_GenerateMapFile:
+ if ( nOrdinalValue == 1 )
+ {
+ additionalOptions += CFmtStrMax( "-Map=&quot;%s&quot; ", pLinkerTool->m_PropertyStates.GetProperty( PS3_GCCLINKER_MapFileName )->m_StringValue );
+ }
+ break;
+
+ case PS3_GCCLINKER_MapFileName:
+ m_XMLWriter.Write( CFmtStrMax( "MapFileName=\"%s\"", pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GCCLINKER_LinkLibraryDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "LinkLibraryDependencies=\"%s\"", BoolStringToTrueFalseString( pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_SNCLINKER_AdditionalOptions:
+ if ( !pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue.IsEmpty() )
+ {
+ additionalOptions += pLinkerTool->m_PropertyStates.m_Properties[i].m_StringValue;
+ additionalOptions += " ";
+ }
+ break;
+ }
+ }
+
+ if ( !additionalOptions.IsEmpty() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalOptions=\"%s\"", additionalOptions.Get() ) );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteLibrarianTool( CLibrarianTool *pLibrarianTool )
+{
+ if ( !pLibrarianTool )
+ {
+ // not an error, some tools n/a for aconfig
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCLibrarianTool\"" );
+
+ for ( int i = 0; i < pLibrarianTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pLibrarianTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_LIBRARIAN_OutputFile:
+ m_XMLWriter.Write( CFmtStrMax( "OutputFile=\"%s\"", pLibrarianTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+ case PS3_LIBRARIAN_AdditionalDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "AdditionalDependencies=\"%s\"", pLibrarianTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+ case PS3_LIBRARIAN_WholeArchive:
+ // can't decode, seems broken
+ break;
+ case PS3_LIBRARIAN_LinkLibraryDependencies:
+ m_XMLWriter.Write( CFmtStrMax( "LinkLibraryDependencies=\"%s\"", BoolStringToTrueFalseString( pLibrarianTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+ }
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WritePostBuildEventTool( CPostBuildEventTool *pPostBuildEventTool )
+{
+ if ( !pPostBuildEventTool )
+ {
+ // not an error, some tools n/a for aconfig
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( "Name=\"VCPostBuildEventTool\"" );
+
+ for ( int i = 0; i < pPostBuildEventTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pPostBuildEventTool->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_POSTBUILDEVENT_CommandLine:
+ m_XMLWriter.Write( CFmtStrMax( "CommandLine=\"%s\"", m_XMLWriter.FixupXMLString( pPostBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_POSTBUILDEVENT_Description:
+ m_XMLWriter.Write( CFmtStrMax( "Description=\"%s\"", pPostBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_POSTBUILDEVENT_ExcludedFromBuild:
+ m_XMLWriter.Write( CFmtStrMax( "ExcludedFromBuild=\"%s\"", BoolStringToTrueFalseString( pPostBuildEventTool->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+ }
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+const char *CProjectGenerator_PS3::BoolStringToTrueFalseString( const char *pValue )
+{
+ return Sys_StringToBool( pValue ) ? "true" : "false";
+}
+
+bool CProjectGenerator_PS3::WriteConfiguration( CProjectConfiguration *pConfig )
+{
+ if ( pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( "FileConfiguration" );
+ }
+ else
+ {
+ m_XMLWriter.PushNode( "Configuration" );
+ }
+
+ const char *pOutputName = "???";
+ if ( !V_stricmp( pConfig->m_Name.Get(), "debug" ) )
+ {
+ if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_SNC )
+ {
+ pOutputName = "PS3SNCDebug|Win32";
+ }
+ else if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_GCC )
+ {
+ pOutputName = "PS3GCCDebug|Win32";
+ }
+ }
+ else if ( !V_stricmp( pConfig->m_Name.Get(), "release" ) )
+ {
+ if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_SNC )
+ {
+ pOutputName = "PS3SNCRelease|Win32";
+ }
+ else if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_GCC )
+ {
+ pOutputName = "PS3GCCRelease|Win32";
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", pOutputName ) );
+
+ // write configuration properties
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ switch ( pConfig->m_PropertyStates.m_Properties[i].m_pToolProperty->m_nPropertyId )
+ {
+ case PS3_GENERAL_ConfigurationType:
+ m_XMLWriter.Write( CFmtStrMax( "ConfigurationType=\"%s\"", pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GENERAL_ExcludedFromBuild:
+ m_XMLWriter.Write( CFmtStrMax( "ExcludedFromBuild=\"%s\"", BoolStringToTrueFalseString( pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) ) );
+ break;
+
+ case PS3_GENERAL_OutputDirectory:
+ m_XMLWriter.Write( CFmtStrMax( "OutputDirectory=\"%s\"", pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GENERAL_IntermediateDirectory:
+ m_XMLWriter.Write( CFmtStrMax( "IntermediateDirectory=\"%s\"", pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GENERAL_ExtensionsToDeleteOnClean:
+ m_XMLWriter.Write( CFmtStrMax( "DeleteExtensionsOnClean=\"%s\"", pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GENERAL_BuildLogFile:
+ m_XMLWriter.Write( CFmtStrMax( "BuildLogFile=\"%s\"", pConfig->m_PropertyStates.m_Properties[i].m_StringValue.Get() ) );
+ break;
+
+ case PS3_GENERAL_SystemIncludeDependencies:
+ // ignoring
+ break;
+
+ case PS3_GENERAL_SaveDebuggerPropertiesInProject:
+ // ignoring
+ break;
+ }
+ }
+
+ m_XMLWriter.Write( ">" );
+
+ if ( !WritePreBuildEventTool( pConfig->GetPreBuildEventTool() ) )
+ return false;
+
+ if ( !WriteCustomBuildTool( pConfig->GetCustomBuildTool() ) )
+ return false;
+
+ if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_SNC )
+ {
+ if ( !WriteSNCCompilerTool( pConfig->GetCompilerTool() ) )
+ return false;
+ }
+ else if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_GCC )
+ {
+ if ( !WriteGCCCompilerTool( pConfig->GetCompilerTool() ) )
+ return false;
+ }
+
+ if ( !WritePreLinkEventTool( pConfig->GetPreLinkEventTool() ) )
+ return false;
+
+ if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_SNC )
+ {
+ if ( !WriteSNCLinkerTool( pConfig->GetLinkerTool() ) )
+ return false;
+ }
+ else if ( m_pVCProjGenerator->GetVSIType() == PS3_VSI_TYPE_GCC )
+ {
+ if ( !WriteGCCLinkerTool( pConfig->GetLinkerTool() ) )
+ return false;
+ }
+
+ if ( !WriteLibrarianTool( pConfig->GetLibrarianTool() ) )
+ return false;
+
+ if ( !WritePostBuildEventTool( pConfig->GetPostBuildEventTool() ) )
+ return false;
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::WriteToXML()
+{
+ m_XMLWriter.PushNode( "VisualStudioProject" );
+ m_XMLWriter.Write( "ProjectType=\"Visual C++\"" );
+ m_XMLWriter.Write( "Version=\"8.00\"" );
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_pVCProjGenerator->GetProjectName().Get() ) );
+ m_XMLWriter.Write( CFmtStrMax( "ProjectGUID=\"%s\"", m_pVCProjGenerator->GetGUIDString().Get() ) );
+ m_XMLWriter.Write( CFmtStrMax( "RootNamespace=\"%s\"", m_pVCProjGenerator->GetProjectName().Get() ) );
+ if ( g_pVPC->BUseP4SCC() )
+ m_XMLWriter.Write( "SccProjectName=\"Perforce Project\"\nSccLocalPath=\"..\"\nSccProvider=\"MSSCCI:Perforce SCM\"\n" );
+ m_XMLWriter.Write( ">" );
+
+ m_XMLWriter.PushNode( "Platforms" );
+ m_XMLWriter.PushNode( "Platform" );
+ m_XMLWriter.Write( "Name=\"win32\"" );
+ m_XMLWriter.PopNode( false );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "ToolFiles" );
+ m_XMLWriter.PopNode( true );
+
+ CUtlVector< CUtlString > configurationNames;
+ m_pVCProjGenerator->GetAllConfigurationNames( configurationNames );
+
+ // write the root configurations
+ m_XMLWriter.PushNode( "Configurations" );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteConfiguration( pConfiguration ) )
+ return false;
+ }
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "References" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "Files" );
+
+ CProjectFolder *pRootFolder = m_pVCProjGenerator->GetRootFolder();
+ for ( int iIndex = pRootFolder->m_Folders.Head(); iIndex != pRootFolder->m_Folders.InvalidIndex(); iIndex = pRootFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pRootFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pRootFolder->m_Files.Head(); iIndex != pRootFolder->m_Files.InvalidIndex(); iIndex = pRootFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pRootFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "Globals" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_PS3::Save( const char *pOutputFilename )
+{
+ if ( !m_XMLWriter.Open( pOutputFilename ) )
+ return false;
+
+ bool bValid = WriteToXML();
+
+ m_XMLWriter.Close();
+
+ if ( bValid )
+ {
+ // Not sure what this file does or why, but we emit it and
+ // its part of a default SN project. The custom build steps
+ // were copied are hosted in all the vpc ps3 base scripts.
+ FILE *fp = fopen( "vsi.nul", "wt" );
+ if ( fp )
+ {
+ fprintf( fp, "SN Visual Studio Integration\n" );
+ fprintf( fp, "IMPORTANT: Do not remove the custom build step for this file\n" );
+ fclose( fp );
+ }
+ }
+
+ return bValid;
+}
+
+
+
diff --git a/external/vpc/utils/vpc/projectgenerator_ps3.h b/external/vpc/utils/vpc/projectgenerator_ps3.h
new file mode 100644
index 0000000..c217af5
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_ps3.h
@@ -0,0 +1,47 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_PS3_H
+#define PROJECTGENERATOR_PS3_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define PROPERTYNAME( X, Y ) X##_##Y,
+enum PS3Properties_e
+{
+ #include "projectgenerator_ps3.inc"
+};
+
+class CProjectGenerator_PS3 : public IVCProjWriter
+{
+public:
+ CProjectGenerator_PS3();
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pVCProjGenerator; }
+
+ virtual bool Save( const char *pOutputFilename );
+
+private:
+ bool WriteToXML();
+ bool WriteFolder( CProjectFolder *pFolder );
+ bool WriteFile( CProjectFile *pFile );
+ bool WriteConfiguration( CProjectConfiguration *pConfig );
+ bool WritePreBuildEventTool( CPreBuildEventTool *pPreBuildEventTool );
+ bool WriteCustomBuildTool( CCustomBuildTool *pCustomBuildTool );
+ bool WriteSNCCompilerTool( CCompilerTool *pCompilerTool );
+ bool WriteGCCCompilerTool( CCompilerTool *pCompilerTool );
+ bool WriteSNCLinkerTool( CLinkerTool *pLinkerTool );
+ bool WriteGCCLinkerTool( CLinkerTool *pLinkerTool );
+ bool WritePreLinkEventTool( CPreLinkEventTool *pPreLinkEventTool );
+ bool WriteLibrarianTool( CLibrarianTool *pLibrarianTool );
+ bool WritePostBuildEventTool( CPostBuildEventTool *pPostBuildEventTool );
+ const char *BoolStringToTrueFalseString( const char *pValue );
+
+ CXMLWriter m_XMLWriter;
+ CVCProjGenerator *m_pVCProjGenerator;
+};
+
+#endif // PROJECTGENERATOR_PS3_H
diff --git a/external/vpc/utils/vpc/projectgenerator_ps3.inc b/external/vpc/utils/vpc/projectgenerator_ps3.inc
new file mode 100644
index 0000000..1f337f5
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_ps3.inc
@@ -0,0 +1,137 @@
+
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Property Enumerations
+//
+//=====================================================================================//
+
+// Config
+PROPERTYNAME( PS3_GENERAL, ConfigurationType )
+PROPERTYNAME( PS3_GENERAL, ExcludedFromBuild )
+PROPERTYNAME( PS3_GENERAL, OutputDirectory )
+PROPERTYNAME( PS3_GENERAL, IntermediateDirectory )
+PROPERTYNAME( PS3_GENERAL, ExtensionsToDeleteOnClean )
+PROPERTYNAME( PS3_GENERAL, BuildLogFile )
+PROPERTYNAME( PS3_GENERAL, SystemIncludeDependencies )
+PROPERTYNAME( PS3_GENERAL, SaveDebuggerPropertiesInProject )
+
+// GCC Compiler
+PROPERTYNAME( PS3_GCCCOMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( PS3_GCCCOMPILER, PreprocessorDefinitions )
+PROPERTYNAME( PS3_GCCCOMPILER, ForceIncludes )
+PROPERTYNAME( PS3_GCCCOMPILER, GenerateDebugInformation )
+PROPERTYNAME( PS3_GCCCOMPILER, Warnings )
+PROPERTYNAME( PS3_GCCCOMPILER, ExtraWarnings )
+PROPERTYNAME( PS3_GCCCOMPILER, WarnLoadHitStores )
+PROPERTYNAME( PS3_GCCCOMPILER, WarnMicrocodedInstruction )
+PROPERTYNAME( PS3_GCCCOMPILER, TreatWarningsAsErrors )
+PROPERTYNAME( PS3_GCCCOMPILER, ObjectFileName )
+PROPERTYNAME( PS3_GCCCOMPILER, CallprofHierarchicalProfiling )
+PROPERTYNAME( PS3_GCCCOMPILER, SPURSUsage )
+PROPERTYNAME( PS3_GCCCOMPILER, OptimizationLevel )
+PROPERTYNAME( PS3_GCCCOMPILER, FastMath )
+PROPERTYNAME( PS3_GCCCOMPILER, NoStrictAliasing )
+PROPERTYNAME( PS3_GCCCOMPILER, UnrollLoops )
+PROPERTYNAME( PS3_GCCCOMPILER, InlineFunctionSizeLimit )
+PROPERTYNAME( PS3_GCCCOMPILER, TOCUsage )
+PROPERTYNAME( PS3_GCCCOMPILER, SaveRestoreFunctions )
+PROPERTYNAME( PS3_GCCCOMPILER, GenerateMicrocodedInstructions )
+PROPERTYNAME( PS3_GCCCOMPILER, PositionIndependentCode )
+PROPERTYNAME( PS3_GCCCOMPILER, FunctionSections )
+PROPERTYNAME( PS3_GCCCOMPILER, DataSections )
+PROPERTYNAME( PS3_GCCCOMPILER, StackCheck )
+PROPERTYNAME( PS3_GCCCOMPILER, CPPExceptionsAndRTTIUsage )
+PROPERTYNAME( PS3_GCCCOMPILER, CheckANSICompliance )
+PROPERTYNAME( PS3_GCCCOMPILER, DefaultCharSigned )
+PROPERTYNAME( PS3_GCCCOMPILER, Permissive )
+PROPERTYNAME( PS3_GCCCOMPILER, EnableMSExtensions )
+PROPERTYNAME( PS3_GCCCOMPILER, RelaxCPPCompliance )
+PROPERTYNAME( PS3_GCCCOMPILER, AdditionalOptions )
+
+// Librarian
+PROPERTYNAME( PS3_LIBRARIAN, OutputFile )
+PROPERTYNAME( PS3_LIBRARIAN, AdditionalDependencies )
+PROPERTYNAME( PS3_LIBRARIAN, WholeArchive )
+PROPERTYNAME( PS3_LIBRARIAN, LinkLibraryDependencies )
+
+// GCC Linker
+PROPERTYNAME( PS3_GCCLINKER, OutputFile )
+PROPERTYNAME( PS3_GCCLINKER, AdditionalDependencies )
+PROPERTYNAME( PS3_GCCLINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( PS3_GCCLINKER, ImportLibrary )
+PROPERTYNAME( PS3_GCCLINKER, SPURSUsage )
+PROPERTYNAME( PS3_GCCLINKER, PositionIndependentCode )
+PROPERTYNAME( PS3_GCCLINKER, EmitRelocations )
+PROPERTYNAME( PS3_GCCLINKER, GarbageCollection )
+PROPERTYNAME( PS3_GCCLINKER, GenerateMapFile )
+PROPERTYNAME( PS3_GCCLINKER, MapFileName )
+PROPERTYNAME( PS3_GCCLINKER, LinkLibraryDependencies )
+PROPERTYNAME( PS3_GCCLINKER, AdditionalOptions )
+
+// SNC Compiler
+PROPERTYNAME( PS3_SNCCOMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( PS3_SNCCOMPILER, PreprocessorDefinitions )
+PROPERTYNAME( PS3_SNCCOMPILER, ForceIncludes )
+PROPERTYNAME( PS3_SNCCOMPILER, GenerateDebugInformation )
+PROPERTYNAME( PS3_SNCCOMPILER, Warnings )
+PROPERTYNAME( PS3_SNCCOMPILER, TreatMessagesAsErrors )
+PROPERTYNAME( PS3_SNCCOMPILER, DisableSpecificWarnings )
+PROPERTYNAME( PS3_SNCCOMPILER, ObjectFileName )
+PROPERTYNAME( PS3_SNCCOMPILER, CallprofHierarchicalProfiling )
+PROPERTYNAME( PS3_SNCCOMPILER, OptimizationLevel )
+PROPERTYNAME( PS3_SNCCOMPILER, FastMath )
+PROPERTYNAME( PS3_SNCCOMPILER, RelaxAliasChecking )
+PROPERTYNAME( PS3_SNCCOMPILER, BranchlessCompares )
+PROPERTYNAME( PS3_SNCCOMPILER, UnrollLoops )
+PROPERTYNAME( PS3_SNCCOMPILER, AssumeAlignedPointers )
+PROPERTYNAME( PS3_SNCCOMPILER, AssumeCorrectSign )
+PROPERTYNAME( PS3_SNCCOMPILER, TOCPointerPreservation )
+PROPERTYNAME( PS3_SNCCOMPILER, InitializedDataPlacement )
+PROPERTYNAME( PS3_SNCCOMPILER, PromoteFPConstantsToDoubles )
+PROPERTYNAME( PS3_SNCCOMPILER, CCPPDialect )
+PROPERTYNAME( PS3_SNCCOMPILER, CPPExceptionsAndRTTIUsage )
+PROPERTYNAME( PS3_SNCCOMPILER, DefaultCharUnsigned )
+PROPERTYNAME( PS3_SNCCOMPILER, DefaultFPConstantsAsTypeFloat )
+PROPERTYNAME( PS3_SNCCOMPILER, BuiltInDefinitionForWCHAR_TType )
+PROPERTYNAME( PS3_SNCCOMPILER, CreateUsePrecompiledHeader )
+PROPERTYNAME( PS3_SNCCOMPILER, PrecompiledHeaderFile )
+PROPERTYNAME( PS3_SNCCOMPILER, AdditionalOptions )
+
+// SNC Linker
+PROPERTYNAME( PS3_SNCLINKER, OutputFile )
+PROPERTYNAME( PS3_SNCLINKER, OutputFormat )
+PROPERTYNAME( PS3_SNCLINKER, AdditionalDependencies )
+PROPERTYNAME( PS3_SNCLINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( PS3_SNCLINKER, IgnoreAllDefaultLibraries )
+PROPERTYNAME( PS3_SNCLINKER, UsingExceptionHandling )
+PROPERTYNAME( PS3_SNCLINKER, TOCPointerElimination )
+PROPERTYNAME( PS3_SNCLINKER, ForceSymbolReferences )
+PROPERTYNAME( PS3_SNCLINKER, CallprofHierarchicalProfiling )
+PROPERTYNAME( PS3_SNCLINKER, DebugInfoAndSymbolStripping )
+PROPERTYNAME( PS3_SNCLINKER, UnusedFunctionAndDataStripping )
+PROPERTYNAME( PS3_SNCLINKER, ImportLibrary )
+PROPERTYNAME( PS3_SNCLINKER, GenerateMapFile )
+PROPERTYNAME( PS3_SNCLINKER, MapFileName )
+PROPERTYNAME( PS3_SNCLINKER, LinkLibraryDependencies )
+PROPERTYNAME( PS3_SNCLINKER, AdditionalOptions )
+
+// Pre Build
+PROPERTYNAME( PS3_PREBUILDEVENT, CommandLine )
+PROPERTYNAME( PS3_PREBUILDEVENT, Description )
+PROPERTYNAME( PS3_PREBUILDEVENT, ExcludedFromBuild )
+
+// Pre Link
+PROPERTYNAME( PS3_PRELINKEVENT, CommandLine )
+PROPERTYNAME( PS3_PRELINKEVENT, Description )
+PROPERTYNAME( PS3_PRELINKEVENT, ExcludedFromBuild )
+
+// Post Build
+PROPERTYNAME( PS3_POSTBUILDEVENT, CommandLine )
+PROPERTYNAME( PS3_POSTBUILDEVENT, Description )
+PROPERTYNAME( PS3_POSTBUILDEVENT, ExcludedFromBuild )
+
+// Custom Build
+PROPERTYNAME( PS3_CUSTOMBUILDSTEP, CommandLine )
+PROPERTYNAME( PS3_CUSTOMBUILDSTEP, Description )
+PROPERTYNAME( PS3_CUSTOMBUILDSTEP, Outputs )
+PROPERTYNAME( PS3_CUSTOMBUILDSTEP, AdditionalDependencies )
diff --git a/external/vpc/utils/vpc/projectgenerator_vcproj.cpp b/external/vpc/utils/vpc/projectgenerator_vcproj.cpp
new file mode 100644
index 0000000..60a3bcf
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_vcproj.cpp
@@ -0,0 +1,1939 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+CProjectFile::CProjectFile( CVCProjGenerator *pGenerator, const char *pFilename )
+{
+ m_pGenerator = pGenerator;
+ m_Name = pFilename;
+}
+
+CProjectFile::~CProjectFile()
+{
+ m_Configs.PurgeAndDeleteElements();
+}
+
+bool CProjectFile::GetConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
+{
+ if ( !pConfigName || !pConfigName[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad configuration name." );
+ }
+
+ if ( ppConfig )
+ {
+ // assume not found
+ *ppConfig = NULL;
+ }
+
+ for ( int i = 0; i < m_Configs.Count(); i++ )
+ {
+ if ( !V_stricmp( m_Configs[i]->m_Name.Get(), pConfigName ) )
+ {
+ // found
+ if ( ppConfig )
+ {
+ *ppConfig = m_Configs[i];
+ }
+ return true;
+ }
+ }
+
+ // not found
+ return false;
+}
+
+bool CProjectFile::AddConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
+{
+ if ( ppConfig )
+ {
+ // assume not found
+ *ppConfig = NULL;
+ }
+
+ if ( GetConfiguration( pConfigName, NULL ) )
+ {
+ // found, cannot add duplicate
+ return false;
+ }
+
+ // add in alphabetic order
+ CProjectConfiguration *pNewConfig = new CProjectConfiguration( m_pGenerator, pConfigName, m_Name.Get() );
+
+ int iIndex = 0;
+ for ( iIndex = 0; iIndex < m_Configs.Count(); iIndex++ )
+ {
+ if ( V_stricmp( pConfigName, m_Configs[iIndex]->m_Name.Get() ) < 0 )
+ {
+ m_Configs.InsertBefore( iIndex, pNewConfig );
+ break;
+ }
+ }
+ if ( iIndex == m_Configs.Count() )
+ {
+ m_Configs.AddToTail( pNewConfig );
+ }
+
+ if ( ppConfig )
+ {
+ *ppConfig = pNewConfig;
+ }
+ return true;
+}
+
+bool CProjectFile::RemoveConfiguration( CProjectConfiguration *pConfiguration )
+{
+ for ( int i = 0; i < m_Configs.Count(); i++ )
+ {
+ if ( m_Configs[i] == pConfiguration )
+ {
+ m_Configs.Remove( i );
+ delete pConfiguration;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+CProjectFolder::CProjectFolder( CVCProjGenerator *pGenerator, const char *pFolderName )
+{
+ m_pGenerator = pGenerator;
+ m_Name = pFolderName;
+}
+
+CProjectFolder::~CProjectFolder()
+{
+ m_Folders.PurgeAndDeleteElements();
+ m_Files.PurgeAndDeleteElements();
+}
+
+bool CProjectFolder::GetFolder( const char *pFolderName, CProjectFolder **pFolder )
+{
+ if ( pFolder )
+ {
+ // assume not found
+ *pFolder = NULL;
+ }
+
+ if ( !pFolderName || !pFolderName[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad folder name." );
+ }
+
+ for ( int iIndex = m_Folders.Head(); iIndex != m_Folders.InvalidIndex(); iIndex = m_Folders.Next( iIndex ) )
+ {
+ if ( !V_stricmp( m_Folders[iIndex]->m_Name.Get(), pFolderName ) )
+ {
+ // found
+ if ( pFolder )
+ {
+ *pFolder = m_Folders[iIndex];
+ }
+ return true;
+ }
+ }
+
+ // not found
+ return false;
+}
+
+bool CProjectFolder::AddFolder( const char *pFolderName, CProjectFolder **pFolder )
+{
+ if ( pFolder )
+ {
+ // assume not added
+ *pFolder = NULL;
+ }
+
+ if ( GetFolder( pFolderName, NULL ) )
+ {
+ // found, cannot add duplicate
+ return false;
+ }
+
+ CProjectFolder *pNewFolder = new CProjectFolder( m_pGenerator, pFolderName );
+
+ // maintain sorted ascending alphabetic order
+ int iIndex;
+ for ( iIndex = m_Folders.Head(); iIndex != m_Folders.InvalidIndex(); iIndex = m_Folders.Next( iIndex ) )
+ {
+ if ( V_stricmp( pFolderName, m_Folders[iIndex]->m_Name.Get() ) < 0 )
+ {
+ m_Folders.InsertBefore( iIndex, pNewFolder );
+ break;
+ }
+ }
+ if ( iIndex == m_Folders.InvalidIndex() )
+ {
+ m_Folders.AddToTail( pNewFolder );
+ }
+
+ if ( pFolder )
+ {
+ *pFolder = pNewFolder;
+ }
+ return true;
+}
+
+void CProjectFolder::AddFile( const char *pFilename, CProjectFile **ppFile )
+{
+ if ( !pFilename || !pFilename[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad filename." );
+ }
+
+ CProjectFile *pNewFile = new CProjectFile( m_pGenerator, pFilename );
+
+ // maintain sorted ascending alphabetic order
+ int iIndex;
+ for ( iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
+ {
+ if ( g_pVPC->IsPlatformDefined( "PS3" ) )
+ {
+ // temporary legacy behavior for diff ease until I can be sure project generation is equivalent
+ iIndex = m_Files.InvalidIndex();
+ break;
+ }
+
+ // the COM layer for WIN32 sorted by filename only, and NOT the entire path
+ if ( V_stricmp( V_GetFileName( pFilename ), V_GetFileName( m_Files[iIndex]->m_Name.Get() ) ) < 0 )
+ {
+ m_Files.InsertBefore( iIndex, pNewFile );
+ break;
+ }
+ }
+ if ( iIndex == m_Files.InvalidIndex() )
+ {
+ m_Files.AddToTail( pNewFile );
+ }
+
+ if ( ppFile )
+ {
+ *ppFile = pNewFile;
+ }
+}
+
+bool CProjectFolder::FindFile( const char *pFilename )
+{
+ if ( !pFilename || !pFilename[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad filename." );
+ }
+
+ for ( int iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
+ {
+ if ( !V_stricmp( m_Files[iIndex]->m_Name.Get(), pFilename ) )
+ {
+ // found
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CProjectFolder::RemoveFile( const char *pFilename )
+{
+ if ( !pFilename || !pFilename[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad filename." );
+ }
+
+ for ( int iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
+ {
+ if ( !V_stricmp( m_Files[iIndex]->m_Name.Get(), pFilename ) )
+ {
+ // found, remove
+ delete m_Files[iIndex];
+ m_Files.Unlink( iIndex );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CPropertyStateLessFunc::Less( const int& lhs, const int& rhs, void *pContext )
+{
+ int lhsPropertyId = (( CPropertyStates* )pContext)->m_Properties[lhs].m_pToolProperty->m_nPropertyId;
+ int rhsPropertyId = (( CPropertyStates* )pContext)->m_Properties[rhs].m_pToolProperty->m_nPropertyId;
+
+ return lhsPropertyId < rhsPropertyId;
+}
+
+CPropertyStates::CPropertyStates()
+{
+ m_PropertiesInOutputOrder.SetLessContext( this );
+}
+
+PropertyState_t *CPropertyStates::GetProperty( int nPropertyId )
+{
+ for ( int i = 0 ; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty->m_nPropertyId == nPropertyId )
+ {
+ return &m_Properties[i];
+ }
+ }
+
+ return NULL;
+}
+
+PropertyState_t *CPropertyStates::GetProperty( const char *pPropertyName )
+{
+ if ( pPropertyName[0] == '$' )
+ {
+ pPropertyName++;
+ }
+
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ const char *pParseString = m_Properties[i].m_pToolProperty->m_ParseString.Get();
+ if ( pParseString[0] == '$' )
+ {
+ pParseString++;
+ }
+ if ( !V_stricmp( pPropertyName, pParseString ) )
+ {
+ return &m_Properties[i];
+ }
+
+ const char *pLegacyString = m_Properties[i].m_pToolProperty->m_LegacyString.Get();
+ if ( pLegacyString[0] )
+ {
+ if ( pLegacyString[0] == '$' )
+ {
+ pLegacyString++;
+ }
+ if ( !V_stricmp( pPropertyName, pLegacyString ) )
+ {
+ return &m_Properties[i];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+bool CPropertyStates::SetStringProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ // find possible current value
+ const char *pCurrentValue = NULL;
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentValue = m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+
+ if ( !pCurrentValue && pRootTool )
+ {
+ // fallback to root tool's config to find current value
+ for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+ }
+
+ // feed in current value to resolve $BASE
+ // possibly culled or tokenized new value
+ char buff[MAX_SYSTOKENCHARS];
+ if ( !g_pVPC->GetScript().ParsePropertyValue( pCurrentValue, buff, sizeof( buff ) ) )
+ return true;
+
+ if ( pToolProperty->m_bFixSlashes )
+ {
+ V_FixSlashes( buff );
+ }
+
+ if ( pToolProperty->m_bPreferSemicolonNoComma )
+ {
+ CUtlString buffCopy = buff;
+ V_StrSubst( buffCopy.Get(), ",", ";", buff, sizeof( buff ), false );
+ }
+
+ if ( pToolProperty->m_bPreferSemicolonNoSpace )
+ {
+ CUtlString buffCopy = buff;
+ V_StrSubst( buffCopy.Get(), " ", ";", buff, sizeof( buff ), false );
+ }
+
+ if ( pToolProperty->m_bAppendSlash )
+ {
+ int len = strlen( buff );
+ if ( len >= 1 && buff[len-1] != '\\' )
+ {
+ V_strncat( buff, "\\", sizeof( buff ) );
+ }
+ }
+
+ if ( !V_stricmp( pToolProperty->m_ParseString.Get(), "$CommandLine" ) && !V_strnicmp( buff, "echo ", 5 ) )
+ {
+ // the COM layer auto appended a CR-LF for a command line with an echo
+ int len = strlen( buff );
+ if ( ( len >= 1 && buff[len-1] != '\n' ) &&
+ ( len >= 12 && V_stricmp( buff + len - 12, "&#x0D;&#x0A;" ) ) )
+ {
+ V_strncat( buff, "\n", sizeof( buff ) );
+ }
+ }
+
+ if ( pCurrentValue && !V_stricmp( pCurrentValue, buff ) )
+ {
+ g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
+ }
+
+ if ( pCurrentValue )
+ {
+ // update existing state
+ // always replace or add strings due to case changes
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ m_Properties[i].m_StringValue = buff;
+ return true;
+ }
+ }
+ }
+
+ // add
+ int iIndex = m_Properties.AddToTail();
+ m_Properties[iIndex].m_pToolProperty = pToolProperty;
+ m_Properties[iIndex].m_StringValue = buff;
+
+ m_PropertiesInOutputOrder.Insert( iIndex );
+
+ return true;
+}
+
+bool CPropertyStates::SetListProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ char buff[MAX_SYSTOKENCHARS];
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ // resolve the parsed token to an expected ordinal
+ const char *pNewOrdinalValue = NULL;
+ for ( int i = 0; i < pToolProperty->m_Ordinals.Count() ;i++ )
+ {
+ if ( !V_stricmp( pToolProperty->m_Ordinals[i].m_ParseString.Get(), buff ) )
+ {
+ pNewOrdinalValue = pToolProperty->m_Ordinals[i].m_ValueString.Get();
+ break;
+ }
+ }
+
+ if ( !pNewOrdinalValue && !V_stricmp( buff, "default" ) )
+ {
+ // allow "default" if not explicitly provided
+ // same as empty, state stays unaffected
+ return true;
+ }
+
+ if ( !pNewOrdinalValue )
+ {
+ g_pVPC->VPCSyntaxError( "Unknown Ordinal for %s", pToolProperty->m_ParseString.Get() );
+ }
+
+ // find possible current value
+ const char *pCurrentOrdinalValue = NULL;
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+
+ if ( !pCurrentOrdinalValue && pRootTool )
+ {
+ // fallback to root tool's config to find current value
+ for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+ }
+
+ if ( pCurrentOrdinalValue && !V_stricmp( pCurrentOrdinalValue, pNewOrdinalValue ) )
+ {
+ g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
+ }
+
+ if ( pCurrentOrdinalValue )
+ {
+ // update existing state
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ m_Properties[i].m_OrdinalString = buff;
+ m_Properties[i].m_StringValue = pNewOrdinalValue;
+ return true;
+ }
+ }
+ }
+
+ // add
+ int iIndex = m_Properties.AddToTail();
+ m_Properties[iIndex].m_pToolProperty = pToolProperty;
+ m_Properties[iIndex].m_OrdinalString = buff;
+ m_Properties[iIndex].m_StringValue = pNewOrdinalValue;
+
+ m_PropertiesInOutputOrder.Insert( iIndex );
+
+ return true;
+}
+
+bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool, bool bEnabled )
+{
+ const char *pNewOrdinalValue = bEnabled ? "1" :"0";
+
+ // find possible current value
+ const char *pCurrentOrdinalValue = NULL;
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+
+ if ( !pCurrentOrdinalValue && pRootTool )
+ {
+ // fallback to root tool's config to find current value
+ for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+ }
+
+ if ( pCurrentOrdinalValue && !V_stricmp( pCurrentOrdinalValue, pNewOrdinalValue ) )
+ {
+ g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
+ }
+
+ if ( pCurrentOrdinalValue )
+ {
+ // update existing state
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ m_Properties[i].m_StringValue = pNewOrdinalValue;
+ return true;
+ }
+ }
+ }
+
+ // add
+ int iIndex = m_Properties.AddToTail();
+ m_Properties[iIndex].m_pToolProperty = pToolProperty;
+ m_Properties[iIndex].m_StringValue = pNewOrdinalValue;
+
+ m_PropertiesInOutputOrder.Insert( iIndex );
+
+ return true;
+}
+
+bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ char buff[MAX_SYSTOKENCHARS];
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ return SetBoolProperty( pToolProperty, pRootTool, Sys_StringToBool( buff ) );
+}
+
+bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, bool bEnabled )
+{
+ return SetBoolProperty( pToolProperty, NULL, bEnabled );
+}
+
+bool CPropertyStates::SetIntegerProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ char buff[MAX_SYSTOKENCHARS];
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
+ return true;
+
+ // ensure the parsed token is a real integer and not just quietly mapped to 0
+ int nParsedValue = atoi( buff );
+ if ( V_stricmp( CFmtStr( "%d", nParsedValue ), buff ) )
+ {
+ g_pVPC->VPCSyntaxError( "Unrecognized integer value: %s", buff );
+ }
+
+ // find possible current value
+ const char *pCurrentOrdinalValue = NULL;
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+
+ if ( !pCurrentOrdinalValue && pRootTool )
+ {
+ // fallback to root tool's config to find current value
+ for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
+ {
+ if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
+ break;
+ }
+ }
+ }
+
+ if ( pCurrentOrdinalValue && ( atoi( pCurrentOrdinalValue ) == atoi( buff ) ) )
+ {
+ g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
+ }
+
+ if ( pCurrentOrdinalValue )
+ {
+ // update existing state
+ for ( int i = 0; i < m_Properties.Count(); i++ )
+ {
+ if ( m_Properties[i].m_pToolProperty == pToolProperty )
+ {
+ m_Properties[i].m_StringValue = buff;
+ return true;
+ }
+ }
+ }
+
+ // add
+ int iIndex = m_Properties.AddToTail();
+ m_Properties[iIndex].m_pToolProperty = pToolProperty;
+ m_Properties[iIndex].m_StringValue = buff;
+
+ m_PropertiesInOutputOrder.Insert( iIndex );
+
+ return true;
+}
+
+bool CPropertyStates::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ bool bHandled = false;
+ switch ( pToolProperty->m_nType )
+ {
+ case PT_BOOLEAN:
+ bHandled = SetBoolProperty( pToolProperty, pRootTool );
+ break;
+
+ case PT_STRING:
+ bHandled = SetStringProperty( pToolProperty, pRootTool );
+ break;
+
+ case PT_INTEGER:
+ bHandled = SetIntegerProperty( pToolProperty, pRootTool );
+ break;
+
+ case PT_LIST:
+ bHandled = SetListProperty( pToolProperty, pRootTool );
+ break;
+
+ case PT_IGNORE:
+ bHandled = true;
+ g_pVPC->GetScript().SkipRestOfLine();
+ break;
+
+ case PT_DEPRECATED:
+ g_pVPC->VPCError( "SetProperty: Property %s has been deprecated and is no longer supported!", pToolProperty->m_ParseString.Get() );
+ break;
+
+ default:
+ g_pVPC->VPCError( "SetProperty: Unknown type for %s - requires implementation", pToolProperty->m_ParseString.Get() );
+ }
+
+ return bHandled;
+}
+
+static bool FilesSortLessFunc( CProjectFile* const &pLHS, CProjectFile* const &pRHS )
+{
+ return CaselessStringLessThan( pLHS->m_Name.Get(), pRHS->m_Name.Get() );
+}
+
+CProjectConfiguration::CProjectConfiguration( CVCProjGenerator *pGenerator, const char *pConfigName, const char *pFilename )
+{
+ m_pGenerator = pGenerator;
+ m_Name = pConfigName;
+ m_bIsFileConfig = ( pFilename != NULL );
+
+ m_pDebuggingTool = NULL;
+ m_pCompilerTool = NULL;
+ m_pLibrarianTool = NULL;
+ m_pLinkerTool = NULL;
+ m_pManifestTool = NULL;
+ m_pXMLDocGenTool = NULL;
+ m_pBrowseInfoTool = NULL;
+ m_pResourcesTool = NULL;
+ m_pPreBuildEventTool = NULL;
+ m_pPreLinkEventTool = NULL;
+ m_pPostBuildEventTool = NULL;
+ m_pCustomBuildTool = NULL;
+ m_pXboxImageTool = NULL;
+ m_pXboxDeploymentTool = NULL;
+
+ if ( !m_bIsFileConfig )
+ {
+ m_pDebuggingTool = new CDebuggingTool( pGenerator );
+ m_pCompilerTool = new CCompilerTool( pGenerator, pConfigName, false );
+ m_pLibrarianTool = new CLibrarianTool( pGenerator );
+ m_pLinkerTool = new CLinkerTool( pGenerator );
+ m_pManifestTool = new CManifestTool( pGenerator );
+ m_pXMLDocGenTool = new CXMLDocGenTool( pGenerator );
+ m_pBrowseInfoTool = new CBrowseInfoTool( pGenerator );
+ m_pResourcesTool = new CResourcesTool( pGenerator );
+ m_pPreBuildEventTool = new CPreBuildEventTool( pGenerator );
+ m_pPreLinkEventTool = new CPreLinkEventTool( pGenerator );
+ m_pPostBuildEventTool = new CPostBuildEventTool( pGenerator );
+ m_pCustomBuildTool = new CCustomBuildTool( pGenerator, pConfigName, false );
+ m_pXboxImageTool = new CXboxImageTool( pGenerator );
+ m_pXboxDeploymentTool = new CXboxDeploymentTool( pGenerator );
+ }
+ else
+ {
+ // a file's config can only be the compiler or the custom build tool
+ const char *pExtension = V_GetFileExtension( pFilename );
+ bool bIsCPP = IsCFileExtension( pExtension );
+ bool bIsLib = pExtension && !V_stricmp( pExtension, "lib" );
+ if ( bIsCPP )
+ {
+ m_pCompilerTool = new CCompilerTool( pGenerator, pConfigName, true );
+ }
+ else if ( bIsLib )
+ {
+ m_pLibrarianTool = new CLibrarianTool( pGenerator );
+ }
+ else
+ {
+ m_pCustomBuildTool = new CCustomBuildTool( pGenerator, pConfigName, true );
+ }
+ }
+}
+
+CProjectConfiguration::~CProjectConfiguration()
+{
+ delete m_pDebuggingTool;
+ delete m_pCompilerTool;
+ delete m_pLibrarianTool;
+ delete m_pLinkerTool;
+ delete m_pManifestTool;
+ delete m_pXMLDocGenTool;
+ delete m_pBrowseInfoTool;
+ delete m_pResourcesTool;
+ delete m_pPreBuildEventTool;
+ delete m_pPreLinkEventTool;
+ delete m_pPostBuildEventTool;
+ delete m_pCustomBuildTool;
+ delete m_pXboxImageTool;
+ delete m_pXboxDeploymentTool;
+}
+
+bool CProjectConfiguration::IsEmpty()
+{
+ if ( m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pDebuggingTool && m_pDebuggingTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pCompilerTool && m_pCompilerTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pLibrarianTool && m_pLibrarianTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pLinkerTool && m_pLinkerTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pManifestTool && m_pManifestTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pXMLDocGenTool && m_pXMLDocGenTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pBrowseInfoTool && m_pBrowseInfoTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pResourcesTool && m_pResourcesTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pPreBuildEventTool && m_pPreBuildEventTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pPreLinkEventTool && m_pPreLinkEventTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pPostBuildEventTool && m_pPostBuildEventTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pCustomBuildTool && m_pCustomBuildTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pXboxImageTool && m_pXboxImageTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ if ( m_pXboxDeploymentTool && m_pXboxDeploymentTool->m_PropertyStates.m_Properties.Count() )
+ return false;
+
+ return true;
+}
+
+bool CProjectConfiguration::SetProperty( ToolProperty_t *pToolProperty )
+{
+ bool bHandled = m_PropertyStates.SetProperty( pToolProperty );
+
+ // have to mimic what the COM layer used to do which is to configure itself based on the type of application its building
+ // VPC enforces a strict order, configuration blocks must come before any tool block to allow this to be rational
+ if ( bHandled && !V_stricmp( pToolProperty->m_ParseString, "$ConfigurationType" ) )
+ {
+ PropertyState_t *pPropertyState = m_PropertyStates.GetProperty( pToolProperty->m_nPropertyId );
+ if ( pPropertyState &&
+ ( ( V_stristr( pPropertyState->m_OrdinalString.Get(), "static library" ) || !V_stricmp( pPropertyState->m_OrdinalString.Get(), "LIB" ) ) ) )
+ {
+ // static library does not get these tools
+ delete m_pResourcesTool;
+ m_pResourcesTool = NULL;
+
+ delete m_pManifestTool;
+ m_pManifestTool = NULL;
+
+ delete m_pLinkerTool;
+ m_pLinkerTool = NULL;
+
+ delete m_pXboxImageTool;
+ m_pXboxImageTool = NULL;
+
+ delete m_pXboxDeploymentTool;
+ m_pXboxDeploymentTool = NULL;
+ }
+ else
+ {
+ // exe/dlls do not get the librarian
+ delete m_pLibrarianTool;
+ m_pLibrarianTool = NULL;
+ }
+ }
+
+ return bHandled;
+}
+
+bool CProjectTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ return m_PropertyStates.SetProperty( pToolProperty, pRootTool );
+}
+
+//-----------------------------------------------------------------------------
+
+bool CCompilerTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ if ( m_bIsFileConfig )
+ {
+ CProjectConfiguration *pConfig;
+ if ( !GetGenerator()->GetRootConfiguration( m_ConfigName.Get(), &pConfig ) )
+ return false;
+
+ return CProjectTool::SetProperty( pToolProperty, pConfig->GetCompilerTool() );
+ }
+ return CProjectTool::SetProperty( pToolProperty );
+}
+
+
+//-----------------------------------------------------------------------------
+
+bool CCustomBuildTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
+{
+ if ( m_bIsFileConfig )
+ {
+ CProjectConfiguration *pConfig;
+ if ( !GetGenerator()->GetRootConfiguration( m_ConfigName.Get(), &pConfig ) )
+ return false;
+
+ return CProjectTool::SetProperty( pToolProperty, pConfig->GetCustomBuildTool() );
+ }
+ return CProjectTool::SetProperty( pToolProperty );
+}
+
+// These are the only properties we care about for makefiles.
+static const char *g_pRelevantSchemaProperties[] =
+{
+ g_pOption_AdditionalIncludeDirectories,
+ g_pOption_PreprocessorDefinitions,
+ g_pOption_AdditionalProjectDependencies,
+};
+
+
+CRelevantPropertyNames g_RelevantSchemaPropertyNames =
+{
+ g_pRelevantSchemaProperties,
+ V_ARRAYSIZE( g_pRelevantSchemaProperties )
+};
+
+
+CVCProjGenerator::CVCProjGenerator() :
+ BaseClass( &g_RelevantSchemaPropertyNames )
+{
+ m_pGeneratorDefinition = NULL;
+ m_pRootFolder = NULL;
+ m_FileDictionary.SetLessFunc( FilesSortLessFunc );
+
+ Clear();
+}
+
+void CVCProjGenerator::Clear()
+{
+ m_nActivePropertySection = KEYWORD_UNKNOWN;
+
+ m_pProjectFile = NULL;
+ m_pConfig = NULL;
+ m_pFileConfig = NULL;
+
+ m_pDebuggingTool = NULL;
+ m_pCompilerTool = NULL;
+ m_pLibrarianTool = NULL;
+ m_pLinkerTool = NULL;
+ m_pManifestTool = NULL;
+ m_pXMLDocGenTool = NULL;
+ m_pBrowseInfoTool = NULL;
+ m_pResourcesTool = NULL;
+ m_pPreBuildEventTool = NULL;
+ m_pPreLinkEventTool = NULL;
+ m_pPostBuildEventTool = NULL;
+ m_pCustomBuildTool = NULL;
+ m_pXboxImageTool = NULL;
+ m_pXboxDeploymentTool = NULL;
+
+ m_spFolderStack.Purge();
+ m_spCompilerStack.Purge();
+ m_spCustomBuildToolStack.Purge();
+
+ // undefined until set
+ m_VSIType = PS3_VSI_TYPE_UNDEFINED;
+
+ m_FileDictionary.Purge();
+
+ // setup expected root folder
+ delete m_pRootFolder;
+ m_pRootFolder = new CProjectFolder( this, "???" );
+
+ // setup the root configurations
+ m_RootConfigurations.PurgeAndDeleteElements();
+
+ CProjectConfiguration *pDebugConfig = new CProjectConfiguration( this, "Debug", NULL );
+ m_RootConfigurations.AddToTail( pDebugConfig );
+
+ CProjectConfiguration *pReleaseConfig = new CProjectConfiguration( this, "Release", NULL );
+ m_RootConfigurations.AddToTail( pReleaseConfig );
+}
+
+void CVCProjGenerator::SetupGeneratorDefinition( IVCProjWriter *pVCProjWriter, const char *pDefinitionName, PropertyName_t *pPropertyNames )
+{
+ m_pVCProjWriter = pVCProjWriter;
+
+ delete m_pGeneratorDefinition;
+ m_pGeneratorDefinition = new CGeneratorDefinition();
+ m_pGeneratorDefinition->LoadDefinition( pDefinitionName, pPropertyNames );
+}
+
+const char* CVCProjGenerator::GetProjectFileExtension()
+{
+ if ( g_pVPC->Is2010() )
+ {
+ return "vcxproj";
+ }
+ return "vcproj";
+}
+
+void CVCProjGenerator::StartProject()
+{
+ if ( !m_pGeneratorDefinition )
+ {
+ g_pVPC->VPCError( "Missing a properly configured generator definition" );
+ }
+
+ BaseClass::StartProject();
+
+ // create the default project
+ // must have a root project for most operations
+ m_ProjectName = "UNNAMED";
+ m_OutputFilename = g_pVPC->GetOutputFilename();
+
+ SetGUID( m_OutputFilename.Get() );
+}
+
+void CVCProjGenerator::EndProject()
+{
+ BaseClass::EndProject();
+
+ // push generator definition scripts into CRC check
+ CRC32_t scriptCRC = 0;
+ const char *pScriptName = m_pGeneratorDefinition->GetScriptName( &scriptCRC );
+ char scriptPath[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( CFmtStr( "$SRCDIR\\%s", pScriptName ), scriptPath, sizeof( scriptPath ) );
+ g_pVPC->AddScriptToCRCCheck( scriptPath, scriptCRC );
+
+ // done once, right before save
+ ApplyInternalPreprocessorDefinitions();
+
+ VPC_FakeKeyword_SchemaFolder( this );
+
+#ifdef STEAM
+#error( "NEEDS TO BE FIXED" )
+ // add the perforce integration magic
+ bstr = "Perforce Project";
+ g_spProject->put_SccProjectName( bstr );
+ bstr = "..";
+ g_spProject->put_SccLocalPath( bstr );
+ bstr = "MSSCCI:Perforce SCM";
+ g_spProject->put_SccProvider( bstr );
+#endif
+
+ g_pVPC->VPCStatus( true, "Saving... Project: '%s' File: '%s'", GetProjectName().String(), g_pVPC->GetOutputFilename() );
+
+ if ( m_ProjectName.IsEmpty() )
+ {
+ g_pVPC->VPCError( "Invalid Empty Project Name" );
+ }
+
+ if ( m_OutputFilename.IsEmpty() )
+ {
+ g_pVPC->VPCError( "Invalid Empty Output Filename" );
+ }
+
+ if ( m_GUIDString.IsEmpty() )
+ {
+ g_pVPC->VPCError( "Invalid Empty GUID String" );
+ }
+
+ // Save the .vcproj file.
+ bool bValid = m_pVCProjWriter->Save( m_OutputFilename.Get() );
+ if ( !bValid )
+ {
+ g_pVPC->VPCError( "Cannot save the specified project '%s' to '%s'", GetProjectName().Get(), m_OutputFilename.Get() );
+ }
+
+ // Expected to not be inside a property section.
+ Assert( m_nActivePropertySection == KEYWORD_UNKNOWN );
+
+ Clear();
+}
+
+void CVCProjGenerator::SetGUID( const char *pOutputFilename )
+{
+ char szBasename[MAX_PATH];
+ V_FileBase( pOutputFilename, szBasename, sizeof( szBasename ) );
+
+ // set the GUID
+ MD5Context_t ctx;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ V_memset( &ctx, 0, sizeof( ctx ) );
+ V_memset( digest, 0, sizeof( digest ) );
+ MD5Init( &ctx );
+ MD5Update( &ctx, (unsigned char *)szBasename, strlen( szBasename ) );
+ MD5Final( digest, &ctx );
+
+ char szMD5[64];
+ V_binarytohex( digest, MD5_DIGEST_LENGTH, szMD5, sizeof( szMD5 ) );
+ V_strupr( szMD5 );
+
+ char szGUID[MAX_PATH];
+ V_snprintf( szGUID, sizeof( szGUID ), "{%8.8s-%4.4s-%4.4s-%4.4s-%12.12s}", szMD5, &szMD5[8], &szMD5[12], &szMD5[16], &szMD5[20] );
+ m_GUIDString = szGUID;
+}
+
+CUtlString CVCProjGenerator::GetProjectName()
+{
+ return m_ProjectName;
+}
+
+void CVCProjGenerator::SetProjectName( const char *pProjectName )
+{
+ m_ProjectName = pProjectName;
+}
+
+void CVCProjGenerator::StartFolder( const char *pFolderName )
+{
+ BaseClass::StartFolder( pFolderName );
+
+ bool bValid;
+ CProjectFolder *pFolder = NULL;
+
+ if ( m_spFolderStack.Count() == 0 )
+ {
+ // add to root
+ bValid = AddFolder( pFolderName, NULL, &pFolder );
+ }
+ else
+ {
+ // add as subfolder
+ bValid = AddFolder( pFolderName, m_spFolderStack.Top(), &pFolder );
+ }
+
+ if ( !bValid )
+ {
+ // resolve failure
+ // folder already exists, not an error
+ // find the matching object
+ pFolder = NULL;
+ if ( m_spFolderStack.Count() == 0 )
+ {
+ // at root
+ GetFolder( pFolderName, NULL, &pFolder );
+ }
+ else
+ {
+ // at subfolder
+ GetFolder( pFolderName, m_spFolderStack.Top(), &pFolder );
+ }
+ if ( !pFolder )
+ {
+ g_pVPC->VPCError( "Cannot find expected folder %s", pFolderName );
+ }
+ }
+
+ m_spFolderStack.Push( pFolder );
+}
+
+void CVCProjGenerator::EndFolder()
+{
+ BaseClass::EndFolder();
+
+ if ( m_spFolderStack.Count() == 0 )
+ {
+ g_pVPC->VPCError( "EndFolder called and no folder has been started." );
+ }
+
+ m_spFolderStack.Pop();
+}
+
+bool CVCProjGenerator::StartFile( const char *pFilename, bool bWarnIfAlreadyExists )
+{
+ // normalize filename, filenames need to compare correctly
+ char cleanFilename[MAX_PATH];
+ V_strncpy( cleanFilename, pFilename, sizeof( cleanFilename ) );
+ V_RemoveDotSlashes( cleanFilename, CORRECT_PATH_SEPARATOR );
+
+ // some vpc scripts decided to unecessarily double quote their filenames
+ // remove any incoming surrounding quotes, this only causes string handling problems (i.e. extension comparison, etc)
+ // all files get serialized to xml output with mandatory surrounding quotes
+ if ( cleanFilename[0] == '\"' )
+ {
+ int len = strlen( cleanFilename );
+ if ( len > 1 && cleanFilename[len-1] == '\"' )
+ {
+ memcpy( cleanFilename, cleanFilename+1, len - 2 );
+ cleanFilename[len-2] = '\0';
+ }
+ }
+
+ pFilename = cleanFilename;
+
+ BaseClass::StartFile( pFilename, bWarnIfAlreadyExists );
+
+ CProjectFile *pFile = NULL;
+
+ if ( m_spFolderStack.Count() == 0 )
+ {
+ // add at root
+ AddFileToFolder( pFilename, NULL, bWarnIfAlreadyExists, &pFile );
+ }
+ else
+ {
+ // add at subfolder
+ AddFileToFolder( pFilename, m_spFolderStack.Top(), bWarnIfAlreadyExists, &pFile );
+ }
+
+ m_pProjectFile = pFile;
+ return ( pFile != NULL );
+}
+
+void CVCProjGenerator::EndFile()
+{
+ BaseClass::EndFile();
+}
+
+bool CVCProjGenerator::RemoveFile( const char *pFilename )
+{
+ // normalize filename, filenames need to compare correctly
+ char cleanFilename[MAX_PATH];
+ V_strncpy( cleanFilename, pFilename, sizeof( cleanFilename ) );
+ V_RemoveDotSlashes( cleanFilename, CORRECT_PATH_SEPARATOR );
+ pFilename = cleanFilename;
+
+ BaseClass::RemoveFile( pFilename );
+
+ bool bValid;
+ if ( m_spFolderStack.Count() == 0 )
+ {
+ // remove from root
+ bValid = RemoveFileFromFolder( pFilename, NULL );
+ }
+ else
+ {
+ // remove at subfolder
+ bValid = RemoveFileFromFolder( pFilename, m_spFolderStack.Top() );
+ }
+
+ return bValid;
+}
+
+bool CVCProjGenerator::Config_GetConfigurations( const char *pszConfigName )
+{
+ CProjectConfiguration *pConfig = NULL;
+ bool bValid = GetRootConfiguration( pszConfigName, &pConfig );
+ if ( !bValid )
+ {
+ g_pVPC->VPCError( "Could not get configuration '%s'", pszConfigName );
+ }
+ m_pConfig = pConfig;
+
+ return true;
+}
+
+void CVCProjGenerator::StartConfigurationBlock( const char *pConfigName, bool bFileSpecific )
+{
+ BaseClass::StartConfigurationBlock( pConfigName, bFileSpecific );
+
+ if ( bFileSpecific )
+ {
+ CProjectConfiguration *pFileConfig = NULL;
+ bool bValid = m_pProjectFile->GetConfiguration( pConfigName, &pFileConfig );
+ if ( !bValid )
+ {
+ // not found, must be valid config
+ // must match predefined configurations, prevents misspellings
+ if ( !IsConfigurationNameValid( pConfigName ) )
+ {
+ g_pVPC->VPCError( "File %s, Unknown configuration '%s'", m_pProjectFile->m_Name.Get(), pConfigName );
+ }
+
+ bValid = m_pProjectFile->AddConfiguration( pConfigName, &pFileConfig );
+ if ( !bValid )
+ {
+ g_pVPC->VPCError( "File %s, Could not get file configuration '%s'", m_pProjectFile->m_Name.Get(), pConfigName );
+ }
+ }
+ m_pFileConfig = pFileConfig;
+ }
+ else
+ {
+ Config_GetConfigurations( pConfigName );
+ }
+}
+
+void CVCProjGenerator::EndConfigurationBlock()
+{
+ BaseClass::EndConfigurationBlock();
+
+ if ( m_pFileConfig && m_pFileConfig->IsEmpty() )
+ {
+ // any file configuration (after parsing) that has no property state gets purged
+ m_pProjectFile->RemoveConfiguration( m_pFileConfig );
+ }
+
+ m_pFileConfig = NULL;
+}
+
+void CVCProjGenerator::FileExcludedFromBuild( bool bExcluded )
+{
+ if ( !m_pFileConfig )
+ {
+ g_pVPC->VPCSyntaxError( "Cannot set $ExcludedFromBuild unless in a $File configuration context" );
+ }
+
+ BaseClass::FileExcludedFromBuild( bExcluded );
+
+ ToolProperty_t* pToolProperty = m_pGeneratorDefinition->GetProperty( KEYWORD_GENERAL, "$ExcludedFromBuild" );
+ if ( !pToolProperty )
+ {
+ g_pVPC->VPCError( "Missing proper declaration for $ExcludedFromBuild" );
+ }
+
+ m_pFileConfig->m_PropertyStates.SetBoolProperty( pToolProperty, bExcluded );
+}
+
+bool CVCProjGenerator::StartPropertySection( configKeyword_e eKeyword, bool *pbShouldSkip )
+{
+ BaseClass::StartPropertySection( eKeyword );
+
+ *pbShouldSkip = false;
+ m_nActivePropertySection = KEYWORD_UNKNOWN;
+ bool bHandled = false;
+
+ switch ( eKeyword )
+ {
+ case KEYWORD_GENERAL:
+ bHandled = true;
+ break;
+
+ case KEYWORD_DEBUGGING:
+ m_pDebuggingTool = m_pConfig->GetDebuggingTool();
+ if ( !m_pDebuggingTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
+ if ( eKeyword == KEYWORD_UNKNOWN )
+ {
+ // skip this section
+ break;
+ }
+
+ m_spCompilerStack.Push( m_pCompilerTool );
+ if ( m_pFileConfig )
+ {
+ m_pCompilerTool = m_pFileConfig->GetCompilerTool();
+ }
+ else
+ {
+ m_pCompilerTool = m_pConfig->GetCompilerTool();
+ }
+ if ( !m_pCompilerTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_LIBRARIAN:
+ m_pLibrarianTool = m_pConfig->GetLibrarianTool();
+ if ( !m_pLibrarianTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_LINKER:
+ case KEYWORD_PS3_SNCLINKER:
+ case KEYWORD_PS3_GCCLINKER:
+ eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
+ if ( eKeyword == KEYWORD_UNKNOWN )
+ {
+ // skip this section
+ break;
+ }
+
+ m_pLinkerTool = m_pConfig->GetLinkerTool();
+ if ( !m_pLinkerTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_MANIFEST:
+ if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
+ {
+ // windows specific
+ break;
+ }
+
+ m_pManifestTool = m_pConfig->GetManifestTool();
+ if ( !m_pManifestTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_XMLDOCGEN:
+ if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
+ {
+ // windows specific
+ break;
+ }
+
+ m_pXMLDocGenTool = m_pConfig->GetXMLDocGenTool();
+ if ( !m_pXMLDocGenTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_BROWSEINFO:
+ if ( g_pVPC->IsPlatformDefined( "PS3" ) )
+ {
+ // not for ps3
+ break;
+ }
+
+ m_pBrowseInfoTool = m_pConfig->GetBrowseInfoTool();
+ if ( !m_pBrowseInfoTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_RESOURCES:
+ if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
+ {
+ // windows specific
+ break;
+ }
+
+ m_pResourcesTool = m_pConfig->GetResourcesTool();
+ if ( !m_pResourcesTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_PREBUILDEVENT:
+ m_pPreBuildEventTool = m_pConfig->GetPreBuildEventTool();
+ if ( !m_pPreBuildEventTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_PRELINKEVENT:
+ m_pPreLinkEventTool = m_pConfig->GetPreLinkEventTool();
+ if ( !m_pPreLinkEventTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_POSTBUILDEVENT:
+ m_pPostBuildEventTool = m_pConfig->GetPostBuildEventTool();
+ if ( !m_pPostBuildEventTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_CUSTOMBUILDSTEP:
+ m_spCustomBuildToolStack.Push( m_pCustomBuildTool );
+ if ( m_pFileConfig )
+ {
+ m_pCustomBuildTool = m_pFileConfig->GetCustomBuildTool();
+ }
+ else
+ {
+ m_pCustomBuildTool = m_pConfig->GetCustomBuildTool();
+ }
+ if ( !m_pCustomBuildTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_XBOXIMAGE:
+ if ( !g_pVPC->IsPlatformDefined( "X360" ) )
+ {
+ // xbox generator specific
+ break;
+ }
+
+ m_pXboxImageTool = m_pConfig->GetXboxImageTool();
+ if ( !m_pXboxImageTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ case KEYWORD_XBOXDEPLOYMENT:
+ if ( !g_pVPC->IsPlatformDefined( "X360" ) )
+ {
+ // xbox generator specific
+ break;
+ }
+
+ m_pXboxDeploymentTool = m_pConfig->GetXboxDeploymentTool();
+ if ( !m_pXboxDeploymentTool )
+ {
+ g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
+ }
+ bHandled = true;
+ break;
+
+ default:
+ // unknown
+ return false;
+ }
+
+ if ( bHandled )
+ {
+ // handled
+ m_nActivePropertySection = eKeyword;
+ }
+ else
+ {
+ // allow other platform specifc sections to just be quietly ignored
+ *pbShouldSkip = true;
+ }
+
+ return true;
+}
+
+void CVCProjGenerator::EndPropertySection( configKeyword_e eKeyword )
+{
+ BaseClass::EndPropertySection( eKeyword );
+
+ switch( eKeyword )
+ {
+ case KEYWORD_CUSTOMBUILDSTEP:
+ m_spCustomBuildToolStack.Pop( m_pCustomBuildTool );
+ break;
+
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
+ m_spCompilerStack.Pop( m_pCompilerTool );
+ break;
+ }
+
+ m_nActivePropertySection = KEYWORD_UNKNOWN;
+}
+
+void CVCProjGenerator::HandleProperty( const char *pPropertyName, const char *pCustomScriptData )
+{
+ // don't allow the baseclass to alter the script state
+ g_pVPC->GetScript().PushCurrentScript();
+ BaseClass::HandleProperty( pPropertyName, pCustomScriptData );
+ g_pVPC->GetScript().PopScript();
+
+ if ( pCustomScriptData )
+ {
+ g_pVPC->GetScript().PushScript( "HandleProperty custom data", pCustomScriptData );
+ }
+
+ ToolProperty_t *pToolProperty = m_pGeneratorDefinition->GetProperty( m_nActivePropertySection, pPropertyName );
+ if ( !pToolProperty )
+ {
+ // unknown property
+ g_pVPC->VPCSyntaxError( "Unknown property %s", pPropertyName );
+ }
+
+ const char *pToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ // quietly ignoring any property without a value
+ // not an error
+ if ( pCustomScriptData )
+ {
+ g_pVPC->GetScript().PopScript();
+ }
+ return;
+ }
+
+ CProjectConfiguration *pConfig = NULL;
+ CProjectTool *pTool = NULL;
+ switch ( m_nActivePropertySection )
+ {
+ case KEYWORD_GENERAL:
+ pConfig = m_pConfig;
+ break;
+
+ case KEYWORD_DEBUGGING:
+ pTool = m_pDebuggingTool;
+ break;
+
+ case KEYWORD_COMPILER:
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_GCCCOMPILER:
+ pTool = m_pCompilerTool;
+ break;
+
+ case KEYWORD_LIBRARIAN:
+ pTool = m_pLibrarianTool;
+ break;
+
+ case KEYWORD_LINKER:
+ case KEYWORD_PS3_SNCLINKER:
+ case KEYWORD_PS3_GCCLINKER:
+ pTool = m_pLinkerTool;
+ break;
+
+ case KEYWORD_MANIFEST:
+ pTool = m_pManifestTool;
+ break;
+
+ case KEYWORD_XMLDOCGEN:
+ pTool = m_pXMLDocGenTool;
+ break;
+
+ case KEYWORD_BROWSEINFO:
+ pTool = m_pBrowseInfoTool;
+ break;
+
+ case KEYWORD_RESOURCES:
+ pTool = m_pResourcesTool;
+ break;
+
+ case KEYWORD_PREBUILDEVENT:
+ pTool = m_pPreBuildEventTool;
+ break;
+
+ case KEYWORD_PRELINKEVENT:
+ pTool = m_pPreLinkEventTool;
+ break;
+
+ case KEYWORD_POSTBUILDEVENT:
+ pTool = m_pPostBuildEventTool;
+ break;
+
+ case KEYWORD_CUSTOMBUILDSTEP:
+ pTool = m_pCustomBuildTool;
+ break;
+
+ case KEYWORD_XBOXIMAGE:
+ pTool = m_pXboxImageTool;
+ break;
+
+ case KEYWORD_XBOXDEPLOYMENT:
+ pTool = m_pXboxDeploymentTool;
+ break;
+
+ default:
+ g_pVPC->VPCError( "HandleProperty: No support for Tool:%s Property:%s - requires implementation", g_pVPC->KeywordToName( m_nActivePropertySection ), pPropertyName );
+ }
+
+ bool bHandled = false;
+ if ( pTool )
+ {
+ bHandled = pTool->SetProperty( pToolProperty );
+ }
+ else if ( pConfig )
+ {
+ bHandled = pConfig->SetProperty( pToolProperty );
+ }
+
+ if ( !bHandled )
+ {
+ g_pVPC->VPCError( "HandleProperty: Failed to set %s", pPropertyName );
+ }
+
+ if ( pCustomScriptData )
+ {
+ g_pVPC->GetScript().PopScript();
+ }
+}
+
+bool CVCProjGenerator::GetFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **ppOutFolder )
+{
+ bool bValid;
+ if ( !pParentFolder )
+ {
+ bValid = m_pRootFolder->GetFolder( pFolderName, ppOutFolder );
+ }
+ else
+ {
+ bValid = pParentFolder->GetFolder( pFolderName, ppOutFolder );
+ }
+ return bValid;
+}
+
+bool CVCProjGenerator::AddFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **ppOutFolder )
+{
+ bool bValid;
+ if ( !pParentFolder )
+ {
+ bValid = m_pRootFolder->AddFolder( pFolderName, ppOutFolder );
+ }
+ else
+ {
+ bValid = pParentFolder->AddFolder( pFolderName, ppOutFolder );
+ }
+ return bValid;
+}
+
+bool CVCProjGenerator::FindFile( const char *pFilename, CProjectFile **ppFile )
+{
+ CProjectFile findProjectFile( this, pFilename );
+
+ int iIndex = m_FileDictionary.Find( &findProjectFile );
+ if ( iIndex != m_FileDictionary.InvalidIndex() )
+ {
+ // found
+ if ( ppFile )
+ {
+ *ppFile = m_FileDictionary[iIndex];
+ }
+ return true;
+ }
+
+ // not found
+ if ( ppFile )
+ {
+ *ppFile = NULL;
+ }
+
+ return false;
+}
+
+void CVCProjGenerator::AddFileToFolder( const char *pFilename, CProjectFolder *pFolder, bool bWarnIfAlreadyExists, CProjectFile **ppFile )
+{
+ if ( FindFile( pFilename, ppFile ) )
+ {
+ // already present
+ if ( bWarnIfAlreadyExists )
+ {
+ g_pVPC->VPCWarning( "File %s already exists in project", pFilename );
+ }
+ return;
+ }
+
+ CProjectFile *pFile;
+ if ( !pFolder )
+ {
+ // add at root
+ m_pRootFolder->AddFile( pFilename, &pFile );
+ }
+ else
+ {
+ // add at folder
+ pFolder->AddFile( pFilename, &pFile );
+ }
+
+ // add to dictionary
+ m_FileDictionary.Insert( pFile );
+ if ( ppFile )
+ {
+ *ppFile = pFile;
+ }
+}
+
+bool CVCProjGenerator::RemoveFileFromFolder( const char *pFilename, CProjectFolder *pFolder )
+{
+ bool bFound = false;
+ CProjectFile findProjectFile( this, pFilename );
+
+ int iIndex = m_FileDictionary.Find( &findProjectFile );
+ if ( iIndex != m_FileDictionary.InvalidIndex() )
+ {
+ bFound = true;
+ m_FileDictionary.RemoveAt( iIndex );
+ }
+
+ if ( !bFound )
+ return false;
+
+ if ( !pFolder )
+ {
+ m_pRootFolder->RemoveFile( pFilename );
+ }
+ else
+ {
+ pFolder->RemoveFile( pFilename );
+ }
+
+ return bFound;
+}
+
+void CVCProjGenerator::GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames )
+{
+ configurationNames.Purge();
+ for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
+ {
+ configurationNames.AddToTail( m_RootConfigurations[i]->m_Name.Get() );
+ }
+}
+
+bool CVCProjGenerator::GetRootConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
+{
+ if ( !pConfigName || !pConfigName[0] )
+ {
+ g_pVPC->VPCError( "Empty or bad configuration name." );
+ }
+
+ if ( ppConfig )
+ {
+ // assume not found
+ *ppConfig = NULL;
+ }
+
+ for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
+ {
+ if ( !V_stricmp( m_RootConfigurations[i]->m_Name.Get(), pConfigName ) )
+ {
+ // found
+ if ( ppConfig )
+ {
+ *ppConfig = m_RootConfigurations[i];
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CVCProjGenerator::IsConfigurationNameValid( const char *pConfigName )
+{
+ return GetRootConfiguration( pConfigName, NULL );
+}
+
+configKeyword_e CVCProjGenerator::SetPS3VisualStudioIntegrationType( configKeyword_e eKeyword )
+{
+ PS3VSIType_e vsiType = PS3_VSI_TYPE_UNDEFINED;
+
+ switch ( eKeyword )
+ {
+ case KEYWORD_COMPILER:
+ case KEYWORD_LINKER:
+ if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
+ {
+ return eKeyword;
+ }
+
+ if ( m_VSIType == PS3_VSI_TYPE_UNDEFINED )
+ {
+ // PS3 defaults to SNC, unless explictly specified
+ vsiType = PS3_VSI_TYPE_SNC;
+ }
+ else
+ {
+ // already set
+ vsiType = m_VSIType;
+ }
+ break;
+
+ case KEYWORD_PS3_SNCCOMPILER:
+ case KEYWORD_PS3_SNCLINKER:
+ if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
+ {
+ // ps3 generator specific
+ // not available for other platforms
+ return KEYWORD_UNKNOWN;
+ }
+ vsiType = PS3_VSI_TYPE_SNC;
+ break;
+
+ case KEYWORD_PS3_GCCCOMPILER:
+ case KEYWORD_PS3_GCCLINKER:
+ if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
+ {
+ // ps3 generator specific
+ // not available for other platforms
+ return KEYWORD_UNKNOWN;
+ }
+ vsiType = PS3_VSI_TYPE_GCC;
+ break;
+
+ default:
+ g_pVPC->VPCError( "Unknown PS3 compiler/linker type" );
+ break;
+ }
+
+ if ( m_VSIType == PS3_VSI_TYPE_UNDEFINED )
+ {
+ // once set, compiler/linker choice (snc or gcc) cannot be changed
+ m_VSIType = vsiType;
+ }
+ else if ( m_VSIType != vsiType )
+ {
+ // cannot intermix tool properties, they must be exclusive
+ g_pVPC->VPCSyntaxError( "PS3 compiler/linker (GCC or SNC) already set, cannot be changed" );
+ }
+
+ // remap ambiguous compiler/linker tool to explicit SNC/GCC tool flavor
+ if ( eKeyword == KEYWORD_COMPILER )
+ {
+ eKeyword = ( m_VSIType == PS3_VSI_TYPE_SNC ) ? KEYWORD_PS3_SNCCOMPILER : KEYWORD_PS3_GCCCOMPILER;
+ }
+ else if ( eKeyword == KEYWORD_LINKER )
+ {
+ eKeyword = ( m_VSIType == PS3_VSI_TYPE_SNC ) ? KEYWORD_PS3_SNCLINKER : KEYWORD_PS3_GCCLINKER;
+ }
+
+ return eKeyword;
+}
+
+void CVCProjGenerator::ApplyInternalPreprocessorDefinitions()
+{
+ // prep to add in vpc generated compiler defines
+ CUtlVector< macro_t* > macroDefines;
+ g_pVPC->GetMacrosMarkedForCompilerDefines( macroDefines );
+
+ if ( !macroDefines.Count() )
+ {
+ // nothing to fixup
+ return;
+ }
+
+ // get all the vpc macros that have been marked for auto adding as compiler define
+ CUtlString extraDefineString;
+ for ( int i = 0; i < macroDefines.Count(); i++ )
+ {
+ macro_t *pMacro = macroDefines[i];
+
+ CUtlString tempString;
+ tempString.Format( ";%s=%s", pMacro->name.String(), pMacro->value.String() );
+ extraDefineString += tempString;
+ }
+
+ // fixup root configurations
+ for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
+ {
+ CCompilerTool *pCompilerTool = m_RootConfigurations[i]->GetCompilerTool();
+ if ( pCompilerTool )
+ {
+ PropertyState_t *pPropertyState = pCompilerTool->m_PropertyStates.GetProperty( "$PreprocessorDefinitions" );
+ if ( pPropertyState )
+ {
+ pPropertyState->m_StringValue += extraDefineString;
+ }
+ }
+ }
+
+ // fixup any file confiuration overrides
+ for ( int iIndex = m_FileDictionary.FirstInorder(); iIndex != m_FileDictionary.InvalidIndex(); iIndex = m_FileDictionary.NextInorder( iIndex ) )
+ {
+ CProjectFile *pProjectFile = m_FileDictionary[iIndex];
+ for ( int i = 0; i < pProjectFile->m_Configs.Count(); i++ )
+ {
+ CCompilerTool *pCompilerTool = pProjectFile->m_Configs[i]->GetCompilerTool();
+ if ( pCompilerTool )
+ {
+ PropertyState_t *pPropertyState = pCompilerTool->m_PropertyStates.GetProperty( "$PreprocessorDefinitions" );
+ if ( pPropertyState )
+ {
+ pPropertyState->m_StringValue += extraDefineString;
+ }
+ }
+ }
+ }
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_vcproj.h b/external/vpc/utils/vpc/projectgenerator_vcproj.h
new file mode 100644
index 0000000..3ccf208
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_vcproj.h
@@ -0,0 +1,379 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef VCPROJGENERATOR_H
+#define VCPROJGENERATOR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+class CProjectConfiguration;
+class CVCProjGenerator;
+class CProjectTool;
+
+struct PropertyState_t
+{
+ ToolProperty_t *m_pToolProperty;
+ CUtlString m_OrdinalString;
+ CUtlString m_StringValue;
+};
+
+// ps3 visual studio integration
+enum PS3VSIType_e
+{
+ PS3_VSI_TYPE_UNDEFINED = -1,
+ PS3_VSI_TYPE_SNC = 0,
+ PS3_VSI_TYPE_GCC = 1,
+};
+
+class CProjectFile
+{
+public:
+ CProjectFile( CVCProjGenerator *pGenerator, const char *pFilename );
+ ~CProjectFile();
+
+ bool GetConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig );
+ bool AddConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig );
+ bool RemoveConfiguration( CProjectConfiguration *pConfig );
+
+ CUtlString m_Name;
+ CVCProjGenerator *m_pGenerator;
+ CUtlVector< CProjectConfiguration* > m_Configs;
+};
+
+class CProjectFolder
+{
+public:
+ CProjectFolder( CVCProjGenerator *pGenerator, const char *pFolderName );
+ ~CProjectFolder();
+
+ bool GetFolder( const char *pFolderName, CProjectFolder **pFolder );
+ bool AddFolder( const char *pFolderName, CProjectFolder **pFolder );
+ void AddFile( const char *pFilename, CProjectFile **ppFile );
+ bool FindFile( const char *pFilename );
+ bool RemoveFile( const char *pFilename );
+
+ CUtlString m_Name;
+ CVCProjGenerator *m_pGenerator;
+ CUtlLinkedList< CProjectFolder* > m_Folders;
+ CUtlLinkedList< CProjectFile* > m_Files;
+};
+
+class CPropertyStateLessFunc
+{
+public:
+ bool Less( const int& lhs, const int& rhs, void *pContext );
+};
+
+class CPropertyStates
+{
+public:
+ CPropertyStates();
+
+ bool SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+ bool SetBoolProperty( ToolProperty_t *pToolProperty, bool bEnabled );
+
+ PropertyState_t *GetProperty( int nPropertyId );
+ PropertyState_t *GetProperty( const char *pPropertyName );
+
+ CUtlVector< PropertyState_t > m_Properties;
+ CUtlSortVector< int, CPropertyStateLessFunc > m_PropertiesInOutputOrder;
+
+private:
+ bool SetStringProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+ bool SetListProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+ bool SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+ bool SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool, bool bEnabled );
+ bool SetIntegerProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+};
+
+class CProjectTool
+{
+public:
+ CProjectTool( CVCProjGenerator *pGenerator )
+ {
+ m_pGenerator = pGenerator;
+ }
+
+ CVCProjGenerator *GetGenerator() { return m_pGenerator; }
+
+ // when the property belongs to the root tool (i.e. linker), no root tool is passed in
+ // when the property is for the file's specific configuration tool, (i.e. compiler/debug), the root tool must be supplied
+ virtual bool SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+
+ CPropertyStates m_PropertyStates;
+
+private:
+ CVCProjGenerator *m_pGenerator;
+};
+
+class CDebuggingTool : public CProjectTool
+{
+public:
+ CDebuggingTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CCompilerTool : public CProjectTool
+{
+public:
+ CCompilerTool( CVCProjGenerator *pGenerator, const char *pConfigName, bool bIsFileConfig ) : CProjectTool( pGenerator )
+ {
+ m_ConfigName = pConfigName;
+ m_bIsFileConfig = bIsFileConfig;
+ }
+
+ bool SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+
+private:
+ CUtlString m_ConfigName;
+ bool m_bIsFileConfig;
+};
+
+class CLibrarianTool : public CProjectTool
+{
+public:
+ CLibrarianTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CLinkerTool : public CProjectTool
+{
+public:
+ CLinkerTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CManifestTool : public CProjectTool
+{
+public:
+ CManifestTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CXMLDocGenTool : public CProjectTool
+{
+public:
+ CXMLDocGenTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CBrowseInfoTool : public CProjectTool
+{
+public:
+ CBrowseInfoTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CResourcesTool : public CProjectTool
+{
+public:
+ CResourcesTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CPreBuildEventTool : public CProjectTool
+{
+public:
+ CPreBuildEventTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CPreLinkEventTool : public CProjectTool
+{
+public:
+ CPreLinkEventTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CPostBuildEventTool : public CProjectTool
+{
+public:
+ CPostBuildEventTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CCustomBuildTool : public CProjectTool
+{
+public:
+ CCustomBuildTool( CVCProjGenerator *pGenerator, const char *pConfigName, bool bIsFileConfig ) : CProjectTool( pGenerator )
+ {
+ m_ConfigName = pConfigName;
+ m_bIsFileConfig = bIsFileConfig;
+ }
+
+ bool SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool = NULL );
+
+private:
+ CUtlString m_ConfigName;
+ bool m_bIsFileConfig;
+};
+
+class CXboxImageTool : public CProjectTool
+{
+public:
+ CXboxImageTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CXboxDeploymentTool : public CProjectTool
+{
+public:
+ CXboxDeploymentTool( CVCProjGenerator *pGenerator ) : CProjectTool( pGenerator ) {}
+};
+
+class CProjectConfiguration
+{
+public:
+ CProjectConfiguration( CVCProjGenerator *pGenerator, const char *pConfigName, const char *pFilename );
+ ~CProjectConfiguration();
+
+ CDebuggingTool *GetDebuggingTool() { return m_pDebuggingTool; }
+ CCompilerTool *GetCompilerTool() { return m_pCompilerTool; }
+ CLibrarianTool *GetLibrarianTool() { return m_pLibrarianTool; }
+ CLinkerTool *GetLinkerTool() { return m_pLinkerTool; }
+ CManifestTool *GetManifestTool() { return m_pManifestTool; }
+ CXMLDocGenTool *GetXMLDocGenTool() { return m_pXMLDocGenTool; }
+ CBrowseInfoTool *GetBrowseInfoTool() { return m_pBrowseInfoTool; }
+ CResourcesTool *GetResourcesTool() { return m_pResourcesTool; }
+ CPreBuildEventTool *GetPreBuildEventTool() { return m_pPreBuildEventTool; }
+ CPreLinkEventTool *GetPreLinkEventTool() { return m_pPreLinkEventTool; }
+ CPostBuildEventTool *GetPostBuildEventTool() { return m_pPostBuildEventTool; }
+ CCustomBuildTool *GetCustomBuildTool() { return m_pCustomBuildTool; }
+ CXboxImageTool *GetXboxImageTool() { return m_pXboxImageTool; }
+ CXboxDeploymentTool *GetXboxDeploymentTool() { return m_pXboxDeploymentTool; }
+
+ bool IsEmpty();
+
+ bool SetProperty( ToolProperty_t *pToolProperty );
+
+ CVCProjGenerator *m_pGenerator;
+
+ // type of config, and config's properties
+ bool m_bIsFileConfig;
+ CUtlString m_Name;
+
+ CPropertyStates m_PropertyStates;
+
+private:
+ // the config's tools
+ CDebuggingTool *m_pDebuggingTool;
+ CCompilerTool *m_pCompilerTool;
+ CLibrarianTool *m_pLibrarianTool;
+ CLinkerTool *m_pLinkerTool;
+ CManifestTool *m_pManifestTool;
+ CXMLDocGenTool *m_pXMLDocGenTool;
+ CBrowseInfoTool *m_pBrowseInfoTool;
+ CResourcesTool *m_pResourcesTool;
+ CPreBuildEventTool *m_pPreBuildEventTool;
+ CPreLinkEventTool *m_pPreLinkEventTool;
+ CPostBuildEventTool *m_pPostBuildEventTool;
+ CCustomBuildTool *m_pCustomBuildTool;
+ CXboxImageTool *m_pXboxImageTool;
+ CXboxDeploymentTool *m_pXboxDeploymentTool;
+};
+
+class IVCProjWriter
+{
+public:
+ virtual bool Save( const char *pOutputFilename ) = 0;
+};
+
+class CVCProjGenerator : public CBaseProjectDataCollector
+{
+public:
+ typedef CBaseProjectDataCollector BaseClass;
+ CVCProjGenerator();
+
+ virtual const char *GetProjectFileExtension();
+ virtual void StartProject();
+ virtual void EndProject();
+ virtual CUtlString GetProjectName();
+ virtual void SetProjectName( const char *pProjectName );
+ virtual void GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames );
+ virtual void StartConfigurationBlock( const char *pConfigName, bool bFileSpecific );
+ virtual void EndConfigurationBlock();
+ virtual bool StartPropertySection( configKeyword_e keyword, bool *pbShouldSkip );
+ virtual void HandleProperty( const char *pProperty, const char *pCustomScriptData );
+ virtual void EndPropertySection( configKeyword_e keyword );
+ virtual void StartFolder( const char *pFolderName );
+ virtual void EndFolder();
+ virtual bool StartFile( const char *pFilename, bool bWarnIfAlreadyExists );
+ virtual void EndFile();
+ virtual void FileExcludedFromBuild( bool bExcluded );
+ virtual bool RemoveFile( const char *pFilename );
+
+ CGeneratorDefinition *GetGeneratorDefinition() { return m_pGeneratorDefinition; }
+ void SetupGeneratorDefinition( IVCProjWriter *pVCProjWriter, const char *pDefinitionName, PropertyName_t *pPropertyNames );
+
+ PS3VSIType_e GetVSIType() { return m_VSIType; }
+
+ CUtlString GetGUIDString() { return m_GUIDString; }
+
+ bool GetRootConfiguration( const char *pConfigName, CProjectConfiguration **pConfig );
+
+ CProjectFolder *GetRootFolder() { return m_pRootFolder; }
+
+private:
+ void Clear();
+ bool Config_GetConfigurations( const char *pszConfigName );
+
+ // returns true if found, false otherwise
+ bool GetFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **pOutFolder );
+ // returns true if added, false otherwise (duplicate)
+ bool AddFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **pOutFolder );
+
+ // returns true if found, false otherwise
+ bool FindFile( const char *pFilename, CProjectFile **pFile );
+ void AddFileToFolder( const char *pFilename, CProjectFolder *pFolder, bool bWarnIfExists, CProjectFile **pFile );
+
+ // returns true if removed, false otherwise (not found)
+ bool RemoveFileFromFolder( const char *pFilename, CProjectFolder *pFolder );
+
+ bool IsConfigurationNameValid( const char *pConfigName );
+
+ void SetGUID( const char *pOutputFilename );
+
+ configKeyword_e SetPS3VisualStudioIntegrationType( configKeyword_e eKeyword );
+
+ void ApplyInternalPreprocessorDefinitions();
+
+private:
+ configKeyword_e m_nActivePropertySection;
+ CGeneratorDefinition *m_pGeneratorDefinition;
+
+ CDebuggingTool *m_pDebuggingTool;
+ CCompilerTool *m_pCompilerTool;
+ CLibrarianTool *m_pLibrarianTool;
+ CLinkerTool *m_pLinkerTool;
+ CManifestTool *m_pManifestTool;
+ CXMLDocGenTool *m_pXMLDocGenTool;
+ CBrowseInfoTool *m_pBrowseInfoTool;
+ CResourcesTool *m_pResourcesTool;
+ CPreBuildEventTool *m_pPreBuildEventTool;
+ CPreLinkEventTool *m_pPreLinkEventTool;
+ CPostBuildEventTool *m_pPostBuildEventTool;
+ CCustomBuildTool *m_pCustomBuildTool;
+ CXboxImageTool *m_pXboxImageTool;
+ CXboxDeploymentTool *m_pXboxDeploymentTool;
+
+ CProjectConfiguration *m_pConfig;
+ CProjectConfiguration *m_pFileConfig;
+ CProjectFile *m_pProjectFile;
+
+ CSimplePointerStack< CProjectFolder*, CProjectFolder*, 128 > m_spFolderStack;
+ CSimplePointerStack< CCompilerTool*, CCompilerTool*, 128 > m_spCompilerStack;
+ CSimplePointerStack< CCustomBuildTool*, CCustomBuildTool*, 128 > m_spCustomBuildToolStack;
+
+ CUtlString m_ProjectName;
+ CUtlString m_OutputFilename;
+
+ CProjectFolder *m_pRootFolder;
+
+ CUtlVector< CProjectConfiguration* > m_RootConfigurations;
+
+ // primary file dictionary
+ CUtlRBTree< CProjectFile*, int > m_FileDictionary;
+
+ CUtlString m_GUIDString;
+
+ IVCProjWriter *m_pVCProjWriter;
+
+ // ps3 visual studio integration
+ PS3VSIType_e m_VSIType;
+};
+
+#endif // VCPROJGENERATOR_H
+
diff --git a/external/vpc/utils/vpc/projectgenerator_win32.cpp b/external/vpc/utils/vpc/projectgenerator_win32.cpp
new file mode 100644
index 0000000..a4ba522
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32.cpp
@@ -0,0 +1,349 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#undef PROPERTYNAME
+#define PROPERTYNAME( X, Y ) { X##_##Y, #X, #Y },
+static PropertyName_t s_Win32PropertyNames[] =
+{
+ #include "projectgenerator_win32.inc"
+ { -1, NULL, NULL }
+};
+
+IBaseProjectGenerator* GetWin32ProjectGenerator()
+{
+ static CProjectGenerator_Win32 *s_pProjectGenerator = NULL;
+ if ( !s_pProjectGenerator )
+ {
+ s_pProjectGenerator = new CProjectGenerator_Win32();
+ }
+
+ return s_pProjectGenerator->GetProjectGenerator();
+}
+
+CProjectGenerator_Win32::CProjectGenerator_Win32()
+{
+ m_pVCProjGenerator = new CVCProjGenerator();
+ m_pVCProjGenerator->SetupGeneratorDefinition( this, "win32_2005.def", s_Win32PropertyNames );
+}
+
+bool CProjectGenerator_Win32::WriteFile( CProjectFile *pFile )
+{
+ m_XMLWriter.PushNode( "File" );
+ m_XMLWriter.Write( CFmtStrMax( "RelativePath=\"%s\"", pFile->m_Name.Get() ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int i = 0; i < pFile->m_Configs.Count(); i++ )
+ {
+ if ( !WriteConfiguration( pFile->m_Configs[i] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::WriteFolder( CProjectFolder *pFolder )
+{
+ m_XMLWriter.PushNode( "Filter" );
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_XMLWriter.FixupXMLString( pFolder->m_Name.Get() ) ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::WriteConfiguration( CProjectConfiguration *pConfig )
+{
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ if ( pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( "FileConfiguration" );
+ }
+ else
+ {
+ m_XMLWriter.PushNode( "Configuration" );
+ }
+
+ const char *pOutputName = "???";
+ if ( !V_stricmp( pConfig->m_Name.Get(), "debug" ) )
+ {
+ pOutputName = "Debug";
+ }
+ else if ( !V_stricmp( pConfig->m_Name.Get(), "release" ) )
+ {
+ pOutputName = "Release";
+ }
+ else
+ {
+ return false;
+ }
+
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s|%s\"", pOutputName, pTargetPlatformName ) );
+
+ // write configuration properties
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex] );
+ }
+
+ m_XMLWriter.Write( ">" );
+
+ if ( !WriteTool( "VCPreBuildEventTool", pConfig->GetPreBuildEventTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCCustomBuildTool", pConfig->GetCustomBuildTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCXMLDataGeneratorTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCWebServiceProxyGeneratorTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCMIDLTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCCLCompilerTool", pConfig->GetCompilerTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCManagedResourceCompilerTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCResourceCompilerTool", pConfig->GetResourcesTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCPreLinkEventTool", pConfig->GetPreLinkEventTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCLinkerTool", pConfig->GetLinkerTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCLibrarianTool", pConfig->GetLibrarianTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCALinkTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCManifestTool", pConfig->GetManifestTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCXDCMakeTool", pConfig->GetXMLDocGenTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCBscMakeTool", pConfig->GetBrowseInfoTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCFxCopTool", pConfig ) )
+ return false;
+
+ if ( !pConfig->GetLibrarianTool() )
+ {
+ if ( !WriteNULLTool( "VCAppVerifierTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCWebDeploymentTool", pConfig ) )
+ return false;
+ }
+
+ if ( !WriteTool( "VCPostBuildEventTool", pConfig->GetPostBuildEventTool() ) )
+ return false;
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::WriteToXML()
+{
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ m_XMLWriter.PushNode( "VisualStudioProject" );
+ m_XMLWriter.Write( "ProjectType=\"Visual C++\"" );
+
+ if ( g_pVPC->BUse2008() )
+ m_XMLWriter.Write( "Version=\"9.00\"" );
+ else
+ m_XMLWriter.Write( "Version=\"8.00\"" );
+
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_pVCProjGenerator->GetProjectName().Get() ) );
+ m_XMLWriter.Write( CFmtStrMax( "ProjectGUID=\"%s\"", m_pVCProjGenerator->GetGUIDString().Get() ) );
+ if ( g_pVPC->BUseP4SCC() )
+ m_XMLWriter.Write( "SccProjectName=\"Perforce Project\"\nSccLocalPath=\"..\"\nSccProvider=\"MSSCCI:Perforce SCM\"\n" );
+ m_XMLWriter.Write( ">" );
+
+ m_XMLWriter.PushNode( "Platforms" );
+ m_XMLWriter.PushNode( "Platform" );
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", pTargetPlatformName) );
+ m_XMLWriter.PopNode( false );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "ToolFiles" );
+ m_XMLWriter.PopNode( true );
+
+ CUtlVector< CUtlString > configurationNames;
+ m_pVCProjGenerator->GetAllConfigurationNames( configurationNames );
+
+ // write the root configurations
+ m_XMLWriter.PushNode( "Configurations" );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteConfiguration( pConfiguration ) )
+ return false;
+ }
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "References" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "Files" );
+
+ CProjectFolder *pRootFolder = m_pVCProjGenerator->GetRootFolder();
+
+ for ( int iIndex = pRootFolder->m_Folders.Head(); iIndex != pRootFolder->m_Folders.InvalidIndex(); iIndex = pRootFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pRootFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pRootFolder->m_Files.Head(); iIndex != pRootFolder->m_Files.InvalidIndex(); iIndex = pRootFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pRootFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::Save( const char *pOutputFilename )
+{
+ if ( !m_XMLWriter.Open( pOutputFilename ) )
+ return false;
+
+ bool bValid = WriteToXML();
+
+ m_XMLWriter.Close();
+
+ return bValid;
+}
+
+bool CProjectGenerator_Win32::WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig )
+{
+ if ( pConfig->m_bIsFileConfig )
+ return true;
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( CFmtStr( "Name=\"%s\"", pToolName ) );
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::WriteTool( const char *pToolName, const CProjectTool *pProjectTool )
+{
+ if ( !pProjectTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( CFmtStr( "Name=\"%s\"", pToolName ) );
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex] );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32::WriteProperty( const PropertyState_t *pPropertyState, const char *pOutputName, const char *pOutputValue )
+{
+ if ( !pPropertyState )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, pOutputValue ) );
+ return true;
+ }
+
+ if ( !pOutputName )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_OutputString.Get();
+ if ( !pOutputName[0] )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_ParseString.Get();
+ if ( pOutputName[0] == '$' )
+ {
+ pOutputName++;
+ }
+ }
+ }
+
+ if ( pPropertyState )
+ {
+ switch ( pPropertyState->m_pToolProperty->m_nType )
+ {
+ case PT_BOOLEAN:
+ {
+ bool bEnabled = Sys_StringToBool( pPropertyState->m_StringValue.Get() );
+ if ( pPropertyState->m_pToolProperty->m_bInvertOutput )
+ {
+ bEnabled ^= 1;
+ }
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, bEnabled ? "true" : "false" ) );
+ }
+ break;
+
+ case PT_STRING:
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, m_XMLWriter.FixupXMLString( pPropertyState->m_StringValue.Get() ) ) );
+ break;
+
+ case PT_LIST:
+ case PT_INTEGER:
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, pPropertyState->m_StringValue.Get() ) );
+ break;
+
+ case PT_IGNORE:
+ break;
+
+ default:
+ g_pVPC->VPCError( "CProjectGenerator_Win32: WriteProperty, %s - not implemented", pOutputName );
+ }
+ }
+
+ return true;
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_win32.h b/external/vpc/utils/vpc/projectgenerator_win32.h
new file mode 100644
index 0000000..01048bf
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32.h
@@ -0,0 +1,41 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_WIN32_H
+#define PROJECTGENERATOR_WIN32_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define PROPERTYNAME( X, Y ) X##_##Y,
+enum Win32Properties_e
+{
+ #include "projectgenerator_win32.inc"
+};
+
+class CProjectGenerator_Win32 : public IVCProjWriter
+{
+public:
+ CProjectGenerator_Win32();
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pVCProjGenerator; }
+
+ virtual bool Save( const char *pOutputFilename );
+
+private:
+ bool WriteToXML();
+
+ bool WriteFolder( CProjectFolder *pFolder );
+ bool WriteFile( CProjectFile *pFile );
+ bool WriteConfiguration( CProjectConfiguration *pConfig );
+ bool WriteProperty( const PropertyState_t *pPropertyState, const char *pOutputName = NULL, const char *pValue = NULL );
+ bool WriteTool( const char *pToolName, const CProjectTool *pProjectTool );
+ bool WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig );
+
+ CXMLWriter m_XMLWriter;
+ CVCProjGenerator *m_pVCProjGenerator;
+};
+
+#endif // PROJECTGENERATOR_WIN32_H
diff --git a/external/vpc/utils/vpc/projectgenerator_win32.inc b/external/vpc/utils/vpc/projectgenerator_win32.inc
new file mode 100644
index 0000000..65d2929
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32.inc
@@ -0,0 +1,252 @@
+
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Property Enumerations
+//
+//=====================================================================================//
+
+// Config
+PROPERTYNAME( WIN32_GENERAL, ExcludedFromBuild )
+PROPERTYNAME( WIN32_GENERAL, OutputDirectory )
+PROPERTYNAME( WIN32_GENERAL, IntermediateDirectory )
+PROPERTYNAME( WIN32_GENERAL, ConfigurationType )
+PROPERTYNAME( WIN32_GENERAL, CharacterSet )
+PROPERTYNAME( WIN32_GENERAL, WholeProgramOptimization )
+PROPERTYNAME( WIN32_GENERAL, ExtensionsToDeleteOnClean )
+PROPERTYNAME( WIN32_GENERAL, BuildLogFile )
+PROPERTYNAME( WIN32_GENERAL, InheritedProjectPropertySheets )
+PROPERTYNAME( WIN32_GENERAL, UseOfMFC )
+PROPERTYNAME( WIN32_GENERAL, UseOfATL )
+PROPERTYNAME( WIN32_GENERAL, MinimizeCRTUseInATL )
+
+// Debugging
+PROPERTYNAME( WIN32_DEBUGGING, Command )
+PROPERTYNAME( WIN32_DEBUGGING, CommandArguments )
+PROPERTYNAME( WIN32_DEBUGGING, RemoteMachine )
+PROPERTYNAME( WIN32_DEBUGGING, WorkingDirectory )
+PROPERTYNAME( WIN32_DEBUGGING, Attach )
+PROPERTYNAME( WIN32_DEBUGGING, DebuggerType )
+PROPERTYNAME( WIN32_DEBUGGING, Environment )
+PROPERTYNAME( WIN32_DEBUGGING, MergeEnvironment )
+PROPERTYNAME( WIN32_DEBUGGING, SQLDebugging )
+
+// Compiler
+PROPERTYNAME( WIN32_COMPILER, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_COMPILER, AdditionalOptions )
+PROPERTYNAME( WIN32_COMPILER, Optimization )
+PROPERTYNAME( WIN32_COMPILER, InlineFunctionExpansion )
+PROPERTYNAME( WIN32_COMPILER, EnableIntrinsicFunctions )
+PROPERTYNAME( WIN32_COMPILER, FavorSizeOrSpeed )
+PROPERTYNAME( WIN32_COMPILER, EnableFiberSafeOptimizations )
+PROPERTYNAME( WIN32_COMPILER, WholeProgramOptimization )
+PROPERTYNAME( WIN32_COMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( WIN32_COMPILER, PreprocessorDefinitions )
+PROPERTYNAME( WIN32_COMPILER, IgnoreStandardIncludePath )
+PROPERTYNAME( WIN32_COMPILER, GeneratePreprocessedFile )
+PROPERTYNAME( WIN32_COMPILER, KeepComments )
+PROPERTYNAME( WIN32_COMPILER, EnableStringPooling )
+PROPERTYNAME( WIN32_COMPILER, EnableMinimalRebuild )
+PROPERTYNAME( WIN32_COMPILER, EnableCPPExceptions )
+PROPERTYNAME( WIN32_COMPILER, BasicRuntimeChecks )
+PROPERTYNAME( WIN32_COMPILER, SmallerTypeCheck )
+PROPERTYNAME( WIN32_COMPILER, RuntimeLibrary )
+PROPERTYNAME( WIN32_COMPILER, StructMemberAlignment )
+PROPERTYNAME( WIN32_COMPILER, BufferSecurityCheck )
+PROPERTYNAME( WIN32_COMPILER, EnableFunctionLevelLinking )
+PROPERTYNAME( WIN32_COMPILER, EnableEnhancedInstructionSet )
+PROPERTYNAME( WIN32_COMPILER, FloatingPointModel )
+PROPERTYNAME( WIN32_COMPILER, EnableFloatingPointExceptions )
+PROPERTYNAME( WIN32_COMPILER, DisableLanguageExtensions )
+PROPERTYNAME( WIN32_COMPILER, DefaultCharUnsigned )
+PROPERTYNAME( WIN32_COMPILER, TreatWCHAR_TAsBuiltInType )
+PROPERTYNAME( WIN32_COMPILER, ForceConformanceInForLoopScope )
+PROPERTYNAME( WIN32_COMPILER, EnableRunTimeTypeInfo )
+PROPERTYNAME( WIN32_COMPILER, OpenMPSupport )
+PROPERTYNAME( WIN32_COMPILER, CreateUsePrecompiledHeader )
+PROPERTYNAME( WIN32_COMPILER, CreateUsePCHThroughFile )
+PROPERTYNAME( WIN32_COMPILER, PrecompiledHeaderFile )
+PROPERTYNAME( WIN32_COMPILER, ExpandAttributedSource )
+PROPERTYNAME( WIN32_COMPILER, AssemblerOutput )
+PROPERTYNAME( WIN32_COMPILER, ASMListLocation )
+PROPERTYNAME( WIN32_COMPILER, ObjectFileName )
+PROPERTYNAME( WIN32_COMPILER, ProgramDatabaseFileName )
+PROPERTYNAME( WIN32_COMPILER, GenerateXMLDocumentationFiles )
+PROPERTYNAME( WIN32_COMPILER, EnableBrowseInformation )
+PROPERTYNAME( WIN32_COMPILER, BrowseFile )
+PROPERTYNAME( WIN32_COMPILER, WarningLevel )
+PROPERTYNAME( WIN32_COMPILER, TreatWarningsAsErrors )
+PROPERTYNAME( WIN32_COMPILER, Detect64bitPortabilityIssues )
+PROPERTYNAME( WIN32_COMPILER, SuppressStartupBanner )
+PROPERTYNAME( WIN32_COMPILER, DebugInformationFormat )
+PROPERTYNAME( WIN32_COMPILER, CompileAs )
+PROPERTYNAME( WIN32_COMPILER, ForceIncludes )
+PROPERTYNAME( WIN32_COMPILER, ShowIncludes )
+PROPERTYNAME( WIN32_COMPILER, UndefineAllPreprocessorDefinitions )
+PROPERTYNAME( WIN32_COMPILER, UndefinePreprocessorDefinitions )
+PROPERTYNAME( WIN32_COMPILER, UseFullPaths )
+PROPERTYNAME( WIN32_COMPILER, OmitDefaultLibraryNames )
+PROPERTYNAME( WIN32_COMPILER, TrapIntegerDividesOptimization )
+PROPERTYNAME( WIN32_COMPILER, PreschedulingOptimization )
+PROPERTYNAME( WIN32_COMPILER, InlineAssemblyOptimization )
+PROPERTYNAME( WIN32_COMPILER, RegisterReservation )
+PROPERTYNAME( WIN32_COMPILER, Stalls )
+PROPERTYNAME( WIN32_COMPILER, CallAttributedProfiling )
+PROPERTYNAME( WIN32_COMPILER, XMLDocumentationFileName )
+PROPERTYNAME( WIN32_COMPILER, DisableSpecificWarnings )
+PROPERTYNAME( WIN32_COMPILER, ResolveUsingReferences )
+PROPERTYNAME( WIN32_COMPILER, OmitFramePointers )
+PROPERTYNAME( WIN32_COMPILER, CallingConvention )
+PROPERTYNAME( WIN32_COMPILER, ForceUsing )
+PROPERTYNAME( WIN32_COMPILER, ErrorReporting )
+
+// Librarian
+PROPERTYNAME( WIN32_LIBRARIAN, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_LIBRARIAN, AdditionalDependencies )
+PROPERTYNAME( WIN32_LIBRARIAN, OutputFile )
+PROPERTYNAME( WIN32_LIBRARIAN, AdditionalLibraryDirectories )
+PROPERTYNAME( WIN32_LIBRARIAN, SuppressStartupBanner )
+PROPERTYNAME( WIN32_LIBRARIAN, ModuleDefinitionFileName )
+PROPERTYNAME( WIN32_LIBRARIAN, IgnoreAllDefaultLibraries )
+PROPERTYNAME( WIN32_LIBRARIAN, IgnoreSpecificLibrary )
+PROPERTYNAME( WIN32_LIBRARIAN, ExportNamedFunctions )
+PROPERTYNAME( WIN32_LIBRARIAN, ForceSymbolReferences )
+PROPERTYNAME( WIN32_LIBRARIAN, LinkLibraryDependencies )
+PROPERTYNAME( WIN32_LIBRARIAN, AdditionalOptions )
+
+// Linker
+PROPERTYNAME( WIN32_LINKER, IgnoreImportLibrary )
+PROPERTYNAME( WIN32_LINKER, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_LINKER, AdditionalOptions )
+PROPERTYNAME( WIN32_LINKER, AdditionalDependencies )
+PROPERTYNAME( WIN32_LINKER, ShowProgress )
+PROPERTYNAME( WIN32_LINKER, OutputFile )
+PROPERTYNAME( WIN32_LINKER, Version )
+PROPERTYNAME( WIN32_LINKER, EnableIncrementalLinking )
+PROPERTYNAME( WIN32_LINKER, SuppressStartupBanner )
+PROPERTYNAME( WIN32_LINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( WIN32_LINKER, GenerateManifest )
+PROPERTYNAME( WIN32_LINKER, IgnoreAllDefaultLibraries )
+PROPERTYNAME( WIN32_LINKER, IgnoreSpecificLibrary )
+PROPERTYNAME( WIN32_LINKER, ModuleDefinitionFile )
+PROPERTYNAME( WIN32_LINKER, GenerateDebugInfo )
+PROPERTYNAME( WIN32_LINKER, DebuggableAssembly )
+PROPERTYNAME( WIN32_LINKER, GenerateProgramDatabaseFile )
+PROPERTYNAME( WIN32_LINKER, GenerateMapFile )
+PROPERTYNAME( WIN32_LINKER, MapFileName )
+PROPERTYNAME( WIN32_LINKER, SubSystem )
+PROPERTYNAME( WIN32_LINKER, EnableLargeAddresses )
+PROPERTYNAME( WIN32_LINKER, MapExports )
+PROPERTYNAME( WIN32_LINKER, StackReserveSize )
+PROPERTYNAME( WIN32_LINKER, StackCommitSize )
+PROPERTYNAME( WIN32_LINKER, References )
+PROPERTYNAME( WIN32_LINKER, EnableCOMDATFolding )
+PROPERTYNAME( WIN32_LINKER, LinkTimeCodeGeneration )
+PROPERTYNAME( WIN32_LINKER, EntryPoint )
+PROPERTYNAME( WIN32_LINKER, NoEntryPoint )
+PROPERTYNAME( WIN32_LINKER, SetChecksum )
+PROPERTYNAME( WIN32_LINKER, BaseAddress )
+PROPERTYNAME( WIN32_LINKER, ImportLibrary )
+PROPERTYNAME( WIN32_LINKER, TargetMachine )
+PROPERTYNAME( WIN32_LINKER, FixedBaseAddress )
+PROPERTYNAME( WIN32_LINKER, ErrorReporting )
+PROPERTYNAME( WIN32_LINKER, FunctionOrder )
+PROPERTYNAME( WIN32_LINKER, LinkLibraryDependencies )
+PROPERTYNAME( WIN32_LINKER, UseLibraryDependencyInputs )
+PROPERTYNAME( WIN32_LINKER, ForceSymbolReferences )
+PROPERTYNAME( WIN32_LINKER, StripPrivateSymbols )
+PROPERTYNAME( WIN32_LINKER, ProfileGuidedDatabase )
+PROPERTYNAME( WIN32_LINKER, MergeSections )
+PROPERTYNAME( WIN32_LINKER, RegisterOutput )
+PROPERTYNAME( WIN32_LINKER, AddModuleToAssembly )
+PROPERTYNAME( WIN32_LINKER, EmbedManagedResourceFile )
+PROPERTYNAME( WIN32_LINKER, DelayLoadedDLLs )
+PROPERTYNAME( WIN32_LINKER, AssemblyLinkResource )
+PROPERTYNAME( WIN32_LINKER, ManifestFile )
+PROPERTYNAME( WIN32_LINKER, AdditionalManifestDependencies )
+PROPERTYNAME( WIN32_LINKER, AllowIsolation )
+PROPERTYNAME( WIN32_LINKER, HeapReserveSize )
+PROPERTYNAME( WIN32_LINKER, HeapCommitSize )
+PROPERTYNAME( WIN32_LINKER, TerminalServer )
+PROPERTYNAME( WIN32_LINKER, SwapRunFromCD )
+PROPERTYNAME( WIN32_LINKER, SwapRunFromNetwork )
+PROPERTYNAME( WIN32_LINKER, Driver )
+PROPERTYNAME( WIN32_LINKER, OptimizeForWindows98 )
+PROPERTYNAME( WIN32_LINKER, MIDLCommands )
+PROPERTYNAME( WIN32_LINKER, IgnoreEmbeddedIDL )
+PROPERTYNAME( WIN32_LINKER, MergeIDLBaseFileName )
+PROPERTYNAME( WIN32_LINKER, TypeLibrary )
+PROPERTYNAME( WIN32_LINKER, TypeLibResourceID )
+PROPERTYNAME( WIN32_LINKER, TurnOffAssemblyGeneration )
+PROPERTYNAME( WIN32_LINKER, DelayLoadedDLL )
+PROPERTYNAME( WIN32_LINKER, Profile )
+PROPERTYNAME( WIN32_LINKER, CLRThreadAttribute )
+PROPERTYNAME( WIN32_LINKER, CLRImageType )
+PROPERTYNAME( WIN32_LINKER, KeyFile )
+PROPERTYNAME( WIN32_LINKER, KeyContainer )
+PROPERTYNAME( WIN32_LINKER, DelaySign )
+PROPERTYNAME( WIN32_LINKER, CLRUnmanagedCodeCheck )
+
+// Manifest
+PROPERTYNAME( WIN32_MANIFESTTOOL, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_MANIFESTTOOL, SuppressStartupBanner )
+PROPERTYNAME( WIN32_MANIFESTTOOL, VerboseOutput )
+PROPERTYNAME( WIN32_MANIFESTTOOL, AssemblyIdentity )
+PROPERTYNAME( WIN32_MANIFESTTOOL, UseFAT32WorkAround )
+PROPERTYNAME( WIN32_MANIFESTTOOL, AdditionalManifestFiles )
+PROPERTYNAME( WIN32_MANIFESTTOOL, InputResourceManifests )
+PROPERTYNAME( WIN32_MANIFESTTOOL, EmbedManifest )
+PROPERTYNAME( WIN32_MANIFESTTOOL, OutputManifestFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, ManifestResourceFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, GenerateCatalogFiles )
+PROPERTYNAME( WIN32_MANIFESTTOOL, DependencyInformationFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, TypeLibraryFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, RegistrarScriptFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, ComponentFileName )
+PROPERTYNAME( WIN32_MANIFESTTOOL, ReplacementsFile )
+PROPERTYNAME( WIN32_MANIFESTTOOL, UpdateFileHashes )
+PROPERTYNAME( WIN32_MANIFESTTOOL, UpdateFileHashesSearchPath )
+PROPERTYNAME( WIN32_MANIFESTTOOL, AdditionalOptions )
+
+// XML Document Generator
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, SuppressStartupBanner )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, ValidateIntelliSense )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, AdditionalDocumentFiles )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, OutputDocumentFile )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, DocumentLibraryDependencies )
+PROPERTYNAME( WIN32_XMLDOCUMENTGENERATOR, AdditionalOptions )
+
+// Browse Information
+PROPERTYNAME( WIN32_BROWSEINFORMATION, SuppressStartupBanner )
+PROPERTYNAME( WIN32_BROWSEINFORMATION, OutputFile )
+PROPERTYNAME( WIN32_BROWSEINFORMATION, AdditionalOptions )
+
+// Resources
+PROPERTYNAME( WIN32_RESOURCES, PreprocessorDefinitions )
+PROPERTYNAME( WIN32_RESOURCES, Culture )
+PROPERTYNAME( WIN32_RESOURCES, AdditionalIncludeDirectories )
+PROPERTYNAME( WIN32_RESOURCES, IgnoreStandardIncludePath )
+PROPERTYNAME( WIN32_RESOURCES, ShowProgress )
+PROPERTYNAME( WIN32_RESOURCES, ResourceFileName )
+PROPERTYNAME( WIN32_RESOURCES, AdditionalOptions )
+
+// Pre Build
+PROPERTYNAME( WIN32_PREBUILDEVENT, Description )
+PROPERTYNAME( WIN32_PREBUILDEVENT, CommandLine )
+PROPERTYNAME( WIN32_PREBUILDEVENT, ExcludedFromBuild )
+
+// Pre Link
+PROPERTYNAME( WIN32_PRELINKEVENT, Description )
+PROPERTYNAME( WIN32_PRELINKEVENT, CommandLine )
+PROPERTYNAME( WIN32_PRELINKEVENT, ExcludedFromBuild )
+
+// Post Build
+PROPERTYNAME( WIN32_POSTBUILDEVENT, Description )
+PROPERTYNAME( WIN32_POSTBUILDEVENT, CommandLine )
+PROPERTYNAME( WIN32_POSTBUILDEVENT, ExcludedFromBuild )
+
+// Custom Build
+PROPERTYNAME( WIN32_CUSTOMBUILDSTEP, Description )
+PROPERTYNAME( WIN32_CUSTOMBUILDSTEP, CommandLine )
+PROPERTYNAME( WIN32_CUSTOMBUILDSTEP, AdditionalDependencies )
+PROPERTYNAME( WIN32_CUSTOMBUILDSTEP, Outputs )
diff --git a/external/vpc/utils/vpc/projectgenerator_win32_2010.cpp b/external/vpc/utils/vpc/projectgenerator_win32_2010.cpp
new file mode 100644
index 0000000..62a9eed
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32_2010.cpp
@@ -0,0 +1,625 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#undef PROPERTYNAME
+#define PROPERTYNAME( X, Y ) { X##_##Y, #X, #Y },
+static PropertyName_t s_Win32PropertyNames_2010[] =
+{
+ #include "projectgenerator_win32_2010.inc"
+ { -1, NULL, NULL }
+};
+
+IBaseProjectGenerator* GetWin32ProjectGenerator_2010()
+{
+ static CProjectGenerator_Win32_2010 *s_pProjectGenerator = NULL;
+ if ( !s_pProjectGenerator )
+ {
+ s_pProjectGenerator = new CProjectGenerator_Win32_2010();
+ }
+
+ return s_pProjectGenerator->GetProjectGenerator();
+}
+
+CProjectGenerator_Win32_2010::CProjectGenerator_Win32_2010()
+{
+ m_pVCProjGenerator = new CVCProjGenerator();
+ m_pVCProjGenerator->SetupGeneratorDefinition( this, "win32_2010.def", s_Win32PropertyNames_2010 );
+}
+
+enum TypeKeyNames_e
+{
+ TKN_LIBRARY = 0,
+ TKN_INCLUDE,
+ TKN_COMPILE,
+ TKN_RESOURCECOMPILE,
+ TKN_CUSTOMBUILD,
+ TKN_NONE,
+ TKN_MAX_COUNT,
+};
+
+static const char *s_TypeKeyNames[] =
+{
+ "Library",
+ "ClInclude",
+ "ClCompile",
+ "ResourceCompile",
+ "CustomBuild",
+ "None"
+};
+
+const char *CProjectGenerator_Win32_2010::GetKeyNameForFile( CProjectFile *pFile )
+{
+ COMPILE_TIME_ASSERT( ARRAYSIZE( s_TypeKeyNames ) == TKN_MAX_COUNT );
+
+ const char *pExtension = V_GetFileExtension( pFile->m_Name.Get() );
+
+ const char *pKeyName = s_TypeKeyNames[TKN_NONE];
+ if ( pExtension )
+ {
+ if ( pFile->m_Configs.Count() && pFile->m_Configs[0]->GetCustomBuildTool() )
+ {
+ pKeyName = s_TypeKeyNames[TKN_CUSTOMBUILD];
+ }
+ else if ( IsCFileExtension( pExtension ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_COMPILE];
+ }
+ else if ( IsHFileExtension( pExtension ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_INCLUDE];
+ }
+ else if ( !V_stricmp( pExtension, "lib" ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_LIBRARY];
+ }
+ else if ( !V_stricmp( pExtension, "rc" ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_RESOURCECOMPILE];
+ }
+ }
+
+ return pKeyName;
+}
+
+bool CProjectGenerator_Win32_2010::WritePropertyGroupTool( CProjectTool *pProjectTool, CProjectConfiguration *pConfiguration )
+{
+ if ( !pProjectTool )
+ return true;
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !pProjectTool->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex], true, pConfiguration->m_Name.Get() ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteFile( CProjectFile *pFile, const char *pFileTypeName )
+{
+ const char *pKeyName = GetKeyNameForFile( pFile );
+ if ( V_stricmp( pFileTypeName, pKeyName ) )
+ {
+ // skip it
+ return true;
+ }
+
+ if ( !pFile->m_Configs.Count() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "<%s Include=\"%s\" />", pKeyName, pFile->m_Name.Get() ) );
+ }
+ else
+ {
+ m_XMLWriter.PushNode( pKeyName, CFmtStr( "Include=\"%s\"", pFile->m_Name.Get() ) );
+
+ for ( int i = 0; i < pFile->m_Configs.Count(); i++ )
+ {
+ if ( !WriteConfiguration( pFile->m_Configs[i] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteFolder( CProjectFolder *pFolder, const char *pFileTypeName, int nDepth )
+{
+ if ( !nDepth )
+ {
+ m_XMLWriter.PushNode( "ItemGroup" );
+ }
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pFolder->m_Files[iIndex], pFileTypeName ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pFolder->m_Folders[iIndex], pFileTypeName, nDepth+1 ) )
+ return false;
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteConfiguration( CProjectConfiguration *pConfig )
+{
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ m_XMLWriter.PushNode( "PropertyGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\" Label=\"Configuration\"", pConfig->m_Name.Get(), pTargetPlatformName ) );
+
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( pConfig->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+ }
+ else
+ {
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex], true, pConfig->m_Name.Get() ) )
+ return false;
+ }
+
+ if ( !WriteTool( "ClCompile", pConfig->GetCompilerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "CustomBuildStep", pConfig->GetCustomBuildTool(), pConfig ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteTools( CProjectConfiguration *pConfig )
+{
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ m_XMLWriter.PushNode( "ItemDefinitionGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\"", pConfig->m_Name.Get(), pTargetPlatformName ) );
+
+ if ( !WriteTool( "PreBuildEvent", pConfig->GetPreBuildEventTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "ClCompile", pConfig->GetCompilerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "ResourceCompile", pConfig->GetResourcesTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "PreLinkEvent", pConfig->GetPreLinkEventTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Link", pConfig->GetLinkerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Lib", pConfig->GetLibrarianTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Manifest", pConfig->GetManifestTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Xdcmake", pConfig->GetXMLDocGenTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Bscmake", pConfig->GetBrowseInfoTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "PostBuildEvent", pConfig->GetPostBuildEventTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "CustomBuildStep", pConfig->GetCustomBuildTool(), pConfig ) )
+ return false;
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WritePrimaryXML( const char *pOutputFilename )
+{
+ if ( !m_XMLWriter.Open( pOutputFilename, true ) )
+ return false;
+
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ m_XMLWriter.PushNode( "Project", "DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"" );
+
+ m_XMLWriter.PushNode( "ItemGroup", "Label=\"ProjectConfigurations\"" );
+ CUtlVector< CUtlString > configurationNames;
+ m_pVCProjGenerator->GetAllConfigurationNames( configurationNames );
+ const char *pPlatformString = "Win32";
+ if ( g_pVPC->IsPlatformDefined( "WIN64" ) )
+ pPlatformString = "x64";
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ m_XMLWriter.PushNode( "ProjectConfiguration", CFmtStr( "Include=\"%s|%s\"", configurationNames[i].Get(), pTargetPlatformName ) );
+ m_XMLWriter.WriteLineNode( "Configuration", "", configurationNames[i].Get() );
+ m_XMLWriter.WriteLineNode( "Platform", "", CFmtStr( "%s", pTargetPlatformName ) );
+ m_XMLWriter.PopNode( true );
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "PropertyGroup", "Label=\"Globals\"" );
+ m_XMLWriter.WriteLineNode( "ProjectName", "", m_pVCProjGenerator->GetProjectName().Get() );
+ m_XMLWriter.WriteLineNode( "ProjectGuid", "", m_pVCProjGenerator->GetGUIDString().Get() );
+ if ( g_pVPC->BUseP4SCC() )
+ {
+ m_XMLWriter.WriteLineNode( "SccProjectName", "", "Perforce Project" );
+ // it looks like 2k10 (at least) doesn't hook files in the project but not under
+ // the project root into source control, so make all the projects local paths
+ // the solution dir
+ char szCurrentDirectory[MAX_PATH];
+ V_GetCurrentDirectory( szCurrentDirectory, V_ARRAYSIZE( szCurrentDirectory ) );
+ char szRelativeFilename[MAX_PATH];
+ if ( !V_MakeRelativePath( g_pVPC->GetStartDirectory(), szCurrentDirectory, szRelativeFilename, sizeof( szRelativeFilename ) ) )
+ V_strncpy( szRelativeFilename, ".", V_ARRAYSIZE( szRelativeFilename ) );
+ m_XMLWriter.WriteLineNode( "SccLocalPath", "", szRelativeFilename );
+ m_XMLWriter.WriteLineNode( "SccProvider", "", "MSSCCI:Perforce SCM" );
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />" );
+
+ // When building 64 bit, use 64 bit toolchain (there is no 64 bit toolchain for 32 bit projects).
+ // This property is written early/specially to ensure it is written prior to Microsoft.Cpp.props
+ if ( g_pVPC->IsPlatformDefined( "win64" ) && !g_pVPC->BUse32BitTools() )
+ {
+ m_XMLWriter.PushNode( "PropertyGroup" );
+ m_XMLWriter.WriteLineNode( "PreferredToolArchitecture", NULL, "x64" );
+ m_XMLWriter.PopNode( true );
+ }
+
+ // write the root configurations
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteConfiguration( pConfiguration ) )
+ return false;
+ }
+ }
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />" );
+ m_XMLWriter.PushNode( "ImportGroup", "Label=\"ExtensionSettings\"" );
+ m_XMLWriter.PopNode( true );
+
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ m_XMLWriter.PushNode( "ImportGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\" Label=\"PropertySheets\"", configurationNames[i].Get(), pTargetPlatformName ) );
+ m_XMLWriter.Write( "<Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />" );
+ m_XMLWriter.PopNode( true );
+ }
+
+ m_XMLWriter.Write( "<PropertyGroup Label=\"UserMacros\" />" );
+
+ m_XMLWriter.PushNode( "PropertyGroup" );
+ m_XMLWriter.WriteLineNode( "_ProjectFileVersion", "", "10.0.30319.1" );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ for ( int j = 0; j < pConfiguration->m_PropertyStates.m_PropertiesInOutputOrder.Count(); j++ )
+ {
+ int sortedIndex = pConfiguration->m_PropertyStates.m_PropertiesInOutputOrder[j];
+ if ( !pConfiguration->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pConfiguration->m_PropertyStates.m_Properties[sortedIndex], true, pConfiguration->m_Name.Get() ) )
+ return false;
+ }
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPreBuildEventTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPreLinkEventTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetLinkerTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetLibrarianTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPostBuildEventTool(), pConfiguration ) )
+ return false;
+ }
+ }
+ m_XMLWriter.PopNode( true );
+
+ // write the tool configurations
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteTools( pConfiguration ) )
+ return false;
+ }
+ }
+
+ // write root folders
+ for ( int i = 0; i < TKN_MAX_COUNT; i++ )
+ {
+ if ( !WriteFolder( m_pVCProjGenerator->GetRootFolder(), s_TypeKeyNames[i], 0 ) )
+ return false;
+ }
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />" );
+ m_XMLWriter.PushNode( "ImportGroup", "Label=\"ExtensionTargets\"" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.Close();
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteFolderToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath )
+{
+ CUtlString parentPath = CFmtStr( "%s%s%s", pParentPath, pParentPath[0] ? "\\" : "", pFolder->m_Name.Get() );
+
+ MD5Context_t ctx;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ V_memset( &ctx, 0, sizeof( ctx ) );
+ V_memset( digest, 0, sizeof( digest ) );
+ MD5Init( &ctx );
+ MD5Update( &ctx, (unsigned char *)parentPath.Get(), strlen( parentPath.Get() ) );
+ MD5Final( digest, &ctx );
+
+ char szMD5[64];
+ V_binarytohex( digest, MD5_DIGEST_LENGTH, szMD5, sizeof( szMD5 ) );
+ V_strupr( szMD5 );
+
+ char szGUID[MAX_PATH];
+ V_snprintf( szGUID, sizeof( szGUID ), "{%8.8s-%4.4s-%4.4s-%4.4s-%12.12s}", szMD5, &szMD5[8], &szMD5[12], &szMD5[16], &szMD5[20] );
+
+ m_XMLFilterWriter.PushNode( "Filter", CFmtStr( "Include=\"%s\"", parentPath.Get() ) );
+ m_XMLFilterWriter.WriteLineNode( "UniqueIdentifier", "", szGUID );
+ m_XMLFilterWriter.PopNode( true );
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderToSecondaryXML( pFolder->m_Folders[iIndex], parentPath.Get() ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteFileToSecondaryXML( CProjectFile *pFile, const char *pParentPath, const char *pFileTypeName )
+{
+ const char *pKeyName = GetKeyNameForFile( pFile );
+ if ( V_stricmp( pFileTypeName, pKeyName ) )
+ {
+ // skip it
+ return true;
+ }
+
+ if ( pParentPath )
+ {
+ m_XMLFilterWriter.PushNode( pKeyName, CFmtStr( "Include=\"%s\"", pFile->m_Name.Get() ) );
+ m_XMLFilterWriter.WriteLineNode( "Filter", "", pParentPath );
+ m_XMLFilterWriter.PopNode( true );
+ }
+ else
+ {
+ m_XMLFilterWriter.Write( CFmtStr( "<%s Include=\"%s\" />", pKeyName, pFile->m_Name.Get() ) );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteFolderContentsToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath, const char *pFileTypeName, int nDepth )
+{
+ CUtlString parentPath;
+ if ( pParentPath )
+ {
+ parentPath = CFmtStr( "%s%s%s", pParentPath, pParentPath[0] ? "\\" : "", pFolder->m_Name.Get() );
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLFilterWriter.PushNode( "ItemGroup", NULL );
+ }
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFileToSecondaryXML( pFolder->m_Files[iIndex], parentPath.Get(), pFileTypeName ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderContentsToSecondaryXML( pFolder->m_Folders[iIndex], parentPath.Get(), pFileTypeName, nDepth+1 ) )
+ return false;
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLFilterWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteSecondaryXML( const char *pOutputFilename )
+{
+ if ( !m_XMLFilterWriter.Open( pOutputFilename, true ) )
+ return false;
+
+ m_XMLFilterWriter.PushNode( "Project", "ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"" );
+
+ // write the root folders
+ m_XMLFilterWriter.PushNode( "ItemGroup", NULL );
+ CProjectFolder *pRootFolder = m_pVCProjGenerator->GetRootFolder();
+ for ( int iIndex = pRootFolder->m_Folders.Head(); iIndex != pRootFolder->m_Folders.InvalidIndex(); iIndex = pRootFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderToSecondaryXML( pRootFolder->m_Folders[iIndex], "" ) )
+ return false;
+ }
+ m_XMLFilterWriter.PopNode( true );
+
+ // write folder contents
+ for ( int i = 0; i < TKN_MAX_COUNT; i++ )
+ {
+ if ( !WriteFolderContentsToSecondaryXML( pRootFolder, NULL, s_TypeKeyNames[i], 0 ) )
+ return false;
+ }
+
+ m_XMLFilterWriter.PopNode( true );
+
+ m_XMLFilterWriter.Close();
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteTool( const char *pToolName, const CProjectTool *pProjectTool, CProjectConfiguration *pConfig )
+{
+ if ( !pProjectTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( pToolName, NULL );
+ }
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ if ( pProjectTool->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex] ) )
+ return false;
+ }
+ else
+ {
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex], true, pConfig->m_Name.Get() ) )
+ return false;
+ }
+ }
+
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::WriteProperty( const PropertyState_t *pPropertyState, bool bEmitConfiguration, const char *pConfigName, const char *pOutputName, const char *pOutputValue )
+{
+ if ( !pPropertyState )
+ {
+ m_XMLWriter.WriteLineNode( pOutputName, "", pOutputValue );
+ return true;
+ }
+
+ if ( !pOutputName )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_OutputString.Get();
+ if ( !pOutputName[0] )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_ParseString.Get();
+ if ( pOutputName[0] == '$' )
+ {
+ pOutputName++;
+ }
+ }
+ }
+
+ const char *pCondition = "";
+ CUtlString conditionString;
+ if ( bEmitConfiguration )
+ {
+ const char *pTargetPlatformName = g_pVPC->IsPlatformDefined( "win64" ) ? "x64" : "Win32";
+
+ conditionString = CFmtStr( " Condition=\"'$(Configuration)|$(Platform)'=='%s|%s'\"", pConfigName, pTargetPlatformName );
+ pCondition = conditionString.Get();
+ }
+
+ if ( pPropertyState )
+ {
+ switch ( pPropertyState->m_pToolProperty->m_nType )
+ {
+ case PT_BOOLEAN:
+ {
+ bool bEnabled = Sys_StringToBool( pPropertyState->m_StringValue.Get() );
+ if ( pPropertyState->m_pToolProperty->m_bInvertOutput )
+ {
+ bEnabled ^= 1;
+ }
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, bEnabled ? "true" : "false" );
+ }
+ break;
+
+ case PT_STRING:
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, m_XMLWriter.FixupXMLString( pPropertyState->m_StringValue.Get() ) );
+ break;
+
+ case PT_LIST:
+ case PT_INTEGER:
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, pPropertyState->m_StringValue.Get() );
+ break;
+
+ case PT_IGNORE:
+ break;
+
+ default:
+ g_pVPC->VPCError( "CProjectGenerator_Win32_2010: WriteProperty, %s - not implemented", pOutputName );
+ }
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Win32_2010::Save( const char *pOutputFilename )
+{
+ bool bValid = WritePrimaryXML( pOutputFilename );
+ if ( bValid )
+ {
+ bValid = WriteSecondaryXML( CFmtStr( "%s.filters", pOutputFilename ) );
+ if ( !bValid )
+ {
+ g_pVPC->VPCError( "Cannot save to the specified project '%s'", pOutputFilename );
+ }
+ }
+
+ return bValid;
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_win32_2010.h b/external/vpc/utils/vpc/projectgenerator_win32_2010.h
new file mode 100644
index 0000000..ac5f44f
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32_2010.h
@@ -0,0 +1,54 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_WIN32_2010_H
+#define PROJECTGENERATOR_WIN32_2010_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define PROPERTYNAME( X, Y ) X##_##Y,
+enum Win32_2010_Properties_e
+{
+ #include "projectgenerator_win32_2010.inc"
+};
+
+class CProjectGenerator_Win32_2010 : public IVCProjWriter
+{
+public:
+ CProjectGenerator_Win32_2010();
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pVCProjGenerator; }
+
+ virtual bool Save( const char *pOutputFilename );
+
+private:
+ // primary XML - foo.vcxproj
+ bool WritePrimaryXML( const char *pOutputFilename );
+ bool WriteFolder( CProjectFolder *pFolder, const char *pFileTypeName, int nDepth );
+ bool WriteFile( CProjectFile *pFile, const char *pFileTypeName );
+ bool WriteConfiguration( CProjectConfiguration *pConfig );
+ bool WriteTools( CProjectConfiguration *pConfig );
+ bool WriteProperty( const PropertyState_t *pPropertyState, bool bEmitConfiguration = false, const char *pConfigurationName = NULL, const char *pOutputName = NULL, const char *pValue = NULL );
+ bool WriteTool( const char *pToolName, const CProjectTool *pProjectTool, CProjectConfiguration *pConfig );
+ bool WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig );
+ bool WritePropertyGroupTool( CProjectTool *pProjectTool, CProjectConfiguration *pConfiguration );
+ bool WritePropertyGroup();
+
+ // secondary XML - foo.vcxproj.filters
+ bool WriteSecondaryXML( const char *pOutputFilename );
+ bool WriteFolderToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath );
+ bool WriteFolderContentsToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath, const char *pFileTypeName, int nDepth );
+ bool WriteFileToSecondaryXML( CProjectFile *pFile, const char *pParentPath, const char *pFileTypeName );
+
+ const char *GetKeyNameForFile( CProjectFile *pFile );
+
+ CXMLWriter m_XMLWriter;
+ CXMLWriter m_XMLFilterWriter;
+
+ CVCProjGenerator *m_pVCProjGenerator;
+};
+
+#endif // PROJECTGENERATOR_WIN32_2010_H
diff --git a/external/vpc/utils/vpc/projectgenerator_win32_2010.inc b/external/vpc/utils/vpc/projectgenerator_win32_2010.inc
new file mode 100644
index 0000000..dcf1143
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_win32_2010.inc
@@ -0,0 +1,299 @@
+
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Property Enumerations
+//
+//=====================================================================================//
+
+// Config
+PROPERTYNAME( WIN32_2010_GENERAL, ExcludedFromBuild )
+PROPERTYNAME( WIN32_2010_GENERAL, OutputDirectory )
+PROPERTYNAME( WIN32_2010_GENERAL, IntermediateDirectory )
+PROPERTYNAME( WIN32_2010_GENERAL, ConfigurationType )
+PROPERTYNAME( WIN32_2010_GENERAL, CharacterSet )
+PROPERTYNAME( WIN32_2010_GENERAL, WholeProgramOptimization )
+PROPERTYNAME( WIN32_2010_GENERAL, ExtensionsToDeleteOnClean )
+PROPERTYNAME( WIN32_2010_GENERAL, BuildLogFile )
+PROPERTYNAME( WIN32_2010_GENERAL, InheritedProjectPropertySheets )
+PROPERTYNAME( WIN32_2010_GENERAL, UseOfMFC )
+PROPERTYNAME( WIN32_2010_GENERAL, UseOfATL )
+PROPERTYNAME( WIN32_2010_GENERAL, MinimizeCRTUseInATL )
+PROPERTYNAME( WIN32_2010_GENERAL, TargetName )
+PROPERTYNAME( WIN32_2010_GENERAL, TargetExtension )
+PROPERTYNAME( WIN32_2010_GENERAL, PlatformToolset )
+PROPERTYNAME( WIN32_2010_GENERAL, ExecutableDirectories )
+
+// Debugging
+PROPERTYNAME( WIN32_2010_DEBUGGING, Command )
+PROPERTYNAME( WIN32_2010_DEBUGGING, CommandArguments )
+PROPERTYNAME( WIN32_2010_DEBUGGING, RemoteMachine )
+PROPERTYNAME( WIN32_2010_DEBUGGING, WorkingDirectory )
+PROPERTYNAME( WIN32_2010_DEBUGGING, Attach )
+PROPERTYNAME( WIN32_2010_DEBUGGING, DebuggerType )
+PROPERTYNAME( WIN32_2010_DEBUGGING, Environment )
+PROPERTYNAME( WIN32_2010_DEBUGGING, MergeEnvironment )
+PROPERTYNAME( WIN32_2010_DEBUGGING, SQLDebugging )
+
+// Compiler
+PROPERTYNAME( WIN32_2010_COMPILER, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_2010_COMPILER, AdditionalOptions )
+PROPERTYNAME( WIN32_2010_COMPILER, Optimization )
+PROPERTYNAME( WIN32_2010_COMPILER, InlineFunctionExpansion )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableIntrinsicFunctions )
+PROPERTYNAME( WIN32_2010_COMPILER, FavorSizeOrSpeed )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableFiberSafeOptimizations )
+PROPERTYNAME( WIN32_2010_COMPILER, WholeProgramOptimization )
+PROPERTYNAME( WIN32_2010_COMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( WIN32_2010_COMPILER, PreprocessorDefinitions )
+PROPERTYNAME( WIN32_2010_COMPILER, IgnoreStandardIncludePath )
+PROPERTYNAME( WIN32_2010_COMPILER, GeneratePreprocessedFile )
+PROPERTYNAME( WIN32_2010_COMPILER, KeepComments )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableStringPooling )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableMinimalRebuild )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableCPPExceptions )
+PROPERTYNAME( WIN32_2010_COMPILER, BasicRuntimeChecks )
+PROPERTYNAME( WIN32_2010_COMPILER, SmallerTypeCheck )
+PROPERTYNAME( WIN32_2010_COMPILER, RuntimeLibrary )
+PROPERTYNAME( WIN32_2010_COMPILER, StructMemberAlignment )
+PROPERTYNAME( WIN32_2010_COMPILER, BufferSecurityCheck )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableFunctionLevelLinking )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableEnhancedInstructionSet )
+PROPERTYNAME( WIN32_2010_COMPILER, FloatingPointModel )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableFloatingPointExceptions )
+PROPERTYNAME( WIN32_2010_COMPILER, DisableLanguageExtensions )
+PROPERTYNAME( WIN32_2010_COMPILER, DefaultCharUnsigned )
+PROPERTYNAME( WIN32_2010_COMPILER, TreatWCHAR_TAsBuiltInType )
+PROPERTYNAME( WIN32_2010_COMPILER, ForceConformanceInForLoopScope )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableRunTimeTypeInfo )
+PROPERTYNAME( WIN32_2010_COMPILER, OpenMPSupport )
+PROPERTYNAME( WIN32_2010_COMPILER, PrecompiledHeader )
+PROPERTYNAME( WIN32_2010_COMPILER, PrecompiledHeaderFile )
+PROPERTYNAME( WIN32_2010_COMPILER, PrecompiledHeaderOutputFile )
+PROPERTYNAME( WIN32_2010_COMPILER, ExpandAttributedSource )
+PROPERTYNAME( WIN32_2010_COMPILER, AssemblerOutput )
+PROPERTYNAME( WIN32_2010_COMPILER, ASMListLocation )
+PROPERTYNAME( WIN32_2010_COMPILER, ObjectFileName )
+PROPERTYNAME( WIN32_2010_COMPILER, ProgramDatabaseFileName )
+PROPERTYNAME( WIN32_2010_COMPILER, GenerateXMLDocumentationFiles )
+PROPERTYNAME( WIN32_2010_COMPILER, EnableBrowseInformation )
+PROPERTYNAME( WIN32_2010_COMPILER, BrowseFile )
+PROPERTYNAME( WIN32_2010_COMPILER, WarningLevel )
+PROPERTYNAME( WIN32_2010_COMPILER, TreatWarningsAsErrors )
+PROPERTYNAME( WIN32_2010_COMPILER, Detect64bitPortabilityIssues )
+PROPERTYNAME( WIN32_2010_COMPILER, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_COMPILER, DebugInformationFormat )
+PROPERTYNAME( WIN32_2010_COMPILER, CompileAs )
+PROPERTYNAME( WIN32_2010_COMPILER, ForceIncludes )
+PROPERTYNAME( WIN32_2010_COMPILER, ShowIncludes )
+PROPERTYNAME( WIN32_2010_COMPILER, UndefineAllPreprocessorDefinitions )
+PROPERTYNAME( WIN32_2010_COMPILER, UndefinePreprocessorDefinitions )
+PROPERTYNAME( WIN32_2010_COMPILER, UseFullPaths )
+PROPERTYNAME( WIN32_2010_COMPILER, OmitDefaultLibraryNames )
+PROPERTYNAME( WIN32_2010_COMPILER, TrapIntegerDividesOptimization )
+PROPERTYNAME( WIN32_2010_COMPILER, PreschedulingOptimization )
+PROPERTYNAME( WIN32_2010_COMPILER, InlineAssemblyOptimization )
+PROPERTYNAME( WIN32_2010_COMPILER, RegisterReservation )
+PROPERTYNAME( WIN32_2010_COMPILER, Stalls )
+PROPERTYNAME( WIN32_2010_COMPILER, CallAttributedProfiling )
+PROPERTYNAME( WIN32_2010_COMPILER, XMLDocumentationFileName )
+PROPERTYNAME( WIN32_2010_COMPILER, DisableSpecificWarnings )
+PROPERTYNAME( WIN32_2010_COMPILER, ResolveUsingReferences )
+PROPERTYNAME( WIN32_2010_COMPILER, OmitFramePointers )
+PROPERTYNAME( WIN32_2010_COMPILER, CallingConvention )
+PROPERTYNAME( WIN32_2010_COMPILER, ForceUsing )
+PROPERTYNAME( WIN32_2010_COMPILER, ErrorReporting )
+PROPERTYNAME( WIN32_2010_COMPILER, CommonLanguageRuntimeSupport )
+PROPERTYNAME( WIN32_2010_COMPILER, MultiProcessorCompilation )
+PROPERTYNAME( WIN32_2010_COMPILER, UseUnicodeForAssemblerListing )
+PROPERTYNAME( WIN32_2010_COMPILER, IgnoreStandardIncludePaths )
+PROPERTYNAME( WIN32_2010_COMPILER, PreprocessToAFile )
+PROPERTYNAME( WIN32_2010_COMPILER, PreprocessSuppressLineNumbers )
+PROPERTYNAME( WIN32_2010_COMPILER, CreateHotpatchableImage )
+PROPERTYNAME( WIN32_2010_COMPILER, BrowseInformationFile )
+PROPERTYNAME( WIN32_2010_COMPILER, ForcedIncludeFile )
+PROPERTYNAME( WIN32_2010_COMPILER, ForcedUsingFile )
+PROPERTYNAME( WIN32_2010_COMPILER, OmitDefaultLibName )
+PROPERTYNAME( WIN32_2010_COMPILER, InternalCompilerErrorReporting )
+PROPERTYNAME( WIN32_2010_COMPILER, TreatSpecificWarningsAsErrors )
+
+// Librarian
+PROPERTYNAME( WIN32_2010_LIBRARIAN, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, AdditionalDependencies )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, OutputFile )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, AdditionalLibraryDirectories )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, ModuleDefinitionFileName )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, IgnoreAllDefaultLibraries )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, IgnoreSpecificLibrary )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, ExportNamedFunctions )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, ForceSymbolReferences )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, LinkLibraryDependencies )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, TargetMachine )
+PROPERTYNAME( WIN32_2010_LIBRARIAN, AdditionalOptions )
+
+// Linker
+PROPERTYNAME( WIN32_2010_LINKER, IgnoreImportLibrary )
+PROPERTYNAME( WIN32_2010_LINKER, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_2010_LINKER, AdditionalOptions )
+PROPERTYNAME( WIN32_2010_LINKER, AdditionalDependencies )
+PROPERTYNAME( WIN32_2010_LINKER, ShowProgress )
+PROPERTYNAME( WIN32_2010_LINKER, OutputFile )
+PROPERTYNAME( WIN32_2010_LINKER, Version )
+PROPERTYNAME( WIN32_2010_LINKER, EnableIncrementalLinking )
+PROPERTYNAME( WIN32_2010_LINKER, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_LINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( WIN32_2010_LINKER, IgnoreSpecificDefaultLibraries )
+PROPERTYNAME( WIN32_2010_LINKER, GenerateManifest )
+PROPERTYNAME( WIN32_2010_LINKER, IgnoreAllDefaultLibraries )
+PROPERTYNAME( WIN32_2010_LINKER, IgnoreSpecificLibrary )
+PROPERTYNAME( WIN32_2010_LINKER, ModuleDefinitionFile )
+PROPERTYNAME( WIN32_2010_LINKER, GenerateDebugInfo )
+PROPERTYNAME( WIN32_2010_LINKER, DebuggableAssembly )
+PROPERTYNAME( WIN32_2010_LINKER, GenerateProgramDatabaseFile )
+PROPERTYNAME( WIN32_2010_LINKER, GenerateMapFile )
+PROPERTYNAME( WIN32_2010_LINKER, MapFileName )
+PROPERTYNAME( WIN32_2010_LINKER, SubSystem )
+PROPERTYNAME( WIN32_2010_LINKER, EnableLargeAddresses )
+PROPERTYNAME( WIN32_2010_LINKER, MapExports )
+PROPERTYNAME( WIN32_2010_LINKER, StackReserveSize )
+PROPERTYNAME( WIN32_2010_LINKER, StackCommitSize )
+PROPERTYNAME( WIN32_2010_LINKER, References )
+PROPERTYNAME( WIN32_2010_LINKER, EnableCOMDATFolding )
+PROPERTYNAME( WIN32_2010_LINKER, LinkTimeCodeGeneration )
+PROPERTYNAME( WIN32_2010_LINKER, EntryPoint )
+PROPERTYNAME( WIN32_2010_LINKER, NoEntryPoint )
+PROPERTYNAME( WIN32_2010_LINKER, SetChecksum )
+PROPERTYNAME( WIN32_2010_LINKER, BaseAddress )
+PROPERTYNAME( WIN32_2010_LINKER, ImportLibrary )
+PROPERTYNAME( WIN32_2010_LINKER, TargetMachine )
+PROPERTYNAME( WIN32_2010_LINKER, FixedBaseAddress )
+PROPERTYNAME( WIN32_2010_LINKER, ErrorReporting )
+PROPERTYNAME( WIN32_2010_LINKER, FunctionOrder )
+PROPERTYNAME( WIN32_2010_LINKER, LinkLibraryDependencies )
+PROPERTYNAME( WIN32_2010_LINKER, UseLibraryDependencyInputs )
+PROPERTYNAME( WIN32_2010_LINKER, ForceSymbolReferences )
+PROPERTYNAME( WIN32_2010_LINKER, StripPrivateSymbols )
+PROPERTYNAME( WIN32_2010_LINKER, ProfileGuidedDatabase )
+PROPERTYNAME( WIN32_2010_LINKER, MergeSections )
+PROPERTYNAME( WIN32_2010_LINKER, RegisterOutput )
+PROPERTYNAME( WIN32_2010_LINKER, AddModuleToAssembly )
+PROPERTYNAME( WIN32_2010_LINKER, EmbedManagedResourceFile )
+PROPERTYNAME( WIN32_2010_LINKER, DelayLoadedDLLs )
+PROPERTYNAME( WIN32_2010_LINKER, AssemblyLinkResource )
+PROPERTYNAME( WIN32_2010_LINKER, ManifestFile )
+PROPERTYNAME( WIN32_2010_LINKER, AdditionalManifestDependencies )
+PROPERTYNAME( WIN32_2010_LINKER, AllowIsolation )
+PROPERTYNAME( WIN32_2010_LINKER, HeapReserveSize )
+PROPERTYNAME( WIN32_2010_LINKER, HeapCommitSize )
+PROPERTYNAME( WIN32_2010_LINKER, TerminalServer )
+PROPERTYNAME( WIN32_2010_LINKER, SwapRunFromCD )
+PROPERTYNAME( WIN32_2010_LINKER, SwapRunFromNetwork )
+PROPERTYNAME( WIN32_2010_LINKER, Driver )
+PROPERTYNAME( WIN32_2010_LINKER, OptimizeForWindows98 )
+PROPERTYNAME( WIN32_2010_LINKER, MIDLCommands )
+PROPERTYNAME( WIN32_2010_LINKER, IgnoreEmbeddedIDL )
+PROPERTYNAME( WIN32_2010_LINKER, MergeIDLBaseFileName )
+PROPERTYNAME( WIN32_2010_LINKER, TypeLibrary )
+PROPERTYNAME( WIN32_2010_LINKER, TypeLibResourceID )
+PROPERTYNAME( WIN32_2010_LINKER, TurnOffAssemblyGeneration )
+PROPERTYNAME( WIN32_2010_LINKER, DelayLoadedDLL )
+PROPERTYNAME( WIN32_2010_LINKER, Profile )
+PROPERTYNAME( WIN32_2010_LINKER, CLRThreadAttribute )
+PROPERTYNAME( WIN32_2010_LINKER, CLRImageType )
+PROPERTYNAME( WIN32_2010_LINKER, KeyFile )
+PROPERTYNAME( WIN32_2010_LINKER, KeyContainer )
+PROPERTYNAME( WIN32_2010_LINKER, DelaySign )
+PROPERTYNAME( WIN32_2010_LINKER, CLRUnmanagedCodeCheck )
+PROPERTYNAME( WIN32_2010_LINKER, PerUserRedirection )
+PROPERTYNAME( WIN32_2010_LINKER, LinkStatus )
+PROPERTYNAME( WIN32_2010_LINKER, PreventDllBinding )
+PROPERTYNAME( WIN32_2010_LINKER, TreatLinkerWarningsAsErrors )
+PROPERTYNAME( WIN32_2010_LINKER, ForceFileOutput )
+PROPERTYNAME( WIN32_2010_LINKER, CreateHotpatchableImage )
+PROPERTYNAME( WIN32_2010_LINKER, SpecifySectionAttributes )
+PROPERTYNAME( WIN32_2010_LINKER, EnableUserAccountControl )
+PROPERTYNAME( WIN32_2010_LINKER, UACExecutionLevel )
+PROPERTYNAME( WIN32_2010_LINKER, UACBypassUIProtection )
+PROPERTYNAME( WIN32_2010_LINKER, MinimumRequiredVersion )
+PROPERTYNAME( WIN32_2010_LINKER, RandomizedBaseAddress )
+PROPERTYNAME( WIN32_2010_LINKER, DataExecutionPrevention )
+PROPERTYNAME( WIN32_2010_LINKER, UnloaddelayloadedDLL )
+PROPERTYNAME( WIN32_2010_LINKER, NobinddelayloadedDLL )
+PROPERTYNAME( WIN32_2010_LINKER, SectionAlignment )
+PROPERTYNAME( WIN32_2010_LINKER, PreserveLastErrorCodeforPInvokeCalls )
+PROPERTYNAME( WIN32_2010_LINKER, ImageHasSafeExceptionHandlers )
+
+// Manifest
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, VerboseOutput )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, AssemblyIdentity )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, UseFAT32WorkAround )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, AdditionalManifestFiles )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, InputResourceManifests )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, EmbedManifest )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, OutputManifestFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, ManifestResourceFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, GenerateCatalogFiles )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, DependencyInformationFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, TypeLibraryFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, RegistrarScriptFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, ComponentFileName )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, ReplacementsFile )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, UpdateFileHashes )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, UpdateFileHashesSearchPath )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, AdditionalOptions )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, GenerateManifestFromManagedAssembly )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, SuppressDependencyElement )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, GenerateCategoryTags )
+PROPERTYNAME( WIN32_2010_MANIFESTTOOL, EnableDPIAwareness )
+
+// XML Document Generator
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, UseUNICODEResponseFiles )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, ValidateIntelliSense )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, AdditionalDocumentFiles )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, OutputDocumentFile )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, DocumentLibraryDependencies )
+PROPERTYNAME( WIN32_2010_XMLDOCUMENTGENERATOR, AdditionalOptions )
+
+// Browse Information
+PROPERTYNAME( WIN32_2010_BROWSEINFORMATION, SuppressStartupBanner )
+PROPERTYNAME( WIN32_2010_BROWSEINFORMATION, OutputFile )
+PROPERTYNAME( WIN32_2010_BROWSEINFORMATION, AdditionalOptions )
+PROPERTYNAME( WIN32_2010_BROWSEINFORMATION, PreserveSBRFiles )
+
+// Resources
+PROPERTYNAME( WIN32_2010_RESOURCES, PreprocessorDefinitions )
+PROPERTYNAME( WIN32_2010_RESOURCES, Culture )
+PROPERTYNAME( WIN32_2010_RESOURCES, AdditionalIncludeDirectories )
+PROPERTYNAME( WIN32_2010_RESOURCES, IgnoreStandardIncludePath )
+PROPERTYNAME( WIN32_2010_RESOURCES, ShowProgress )
+PROPERTYNAME( WIN32_2010_RESOURCES, ResourceFileName )
+PROPERTYNAME( WIN32_2010_RESOURCES, AdditionalOptions )
+
+// Pre Build
+PROPERTYNAME( WIN32_2010_PREBUILDEVENT, Description )
+PROPERTYNAME( WIN32_2010_PREBUILDEVENT, CommandLine )
+PROPERTYNAME( WIN32_2010_PREBUILDEVENT, ExcludedFromBuild )
+PROPERTYNAME( WIN32_2010_PREBUILDEVENT, UseInBuild )
+
+// Pre Link
+PROPERTYNAME( WIN32_2010_PRELINKEVENT, Description )
+PROPERTYNAME( WIN32_2010_PRELINKEVENT, CommandLine )
+PROPERTYNAME( WIN32_2010_PRELINKEVENT, ExcludedFromBuild )
+PROPERTYNAME( WIN32_2010_PRELINKEVENT, UseInBuild )
+
+// Post Build
+PROPERTYNAME( WIN32_2010_POSTBUILDEVENT, Description )
+PROPERTYNAME( WIN32_2010_POSTBUILDEVENT, CommandLine )
+PROPERTYNAME( WIN32_2010_POSTBUILDEVENT, ExcludedFromBuild )
+PROPERTYNAME( WIN32_2010_POSTBUILDEVENT, UseInBuild )
+
+// Custom Build
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, Description )
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, CommandLine )
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, AdditionalDependencies )
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, Outputs )
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, ExecuteAfter )
+PROPERTYNAME( WIN32_2010_CUSTOMBUILDSTEP, ExecuteBefore )
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360.cpp b/external/vpc/utils/vpc/projectgenerator_xbox360.cpp
new file mode 100644
index 0000000..96998f9
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360.cpp
@@ -0,0 +1,343 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#undef PROPERTYNAME
+#define PROPERTYNAME( X, Y ) { X##_##Y, #X, #Y },
+static PropertyName_t s_Xbox360PropertyNames[] =
+{
+ #include "projectgenerator_xbox360.inc"
+ { -1, NULL, NULL }
+};
+
+IBaseProjectGenerator* GetXbox360ProjectGenerator()
+{
+ static CProjectGenerator_Xbox360 *s_pProjectGenerator = NULL;
+ if ( !s_pProjectGenerator )
+ {
+ s_pProjectGenerator = new CProjectGenerator_Xbox360();
+ }
+
+ return s_pProjectGenerator->GetProjectGenerator();
+}
+
+CProjectGenerator_Xbox360::CProjectGenerator_Xbox360()
+{
+ m_pVCProjGenerator = new CVCProjGenerator();
+ m_pVCProjGenerator->SetupGeneratorDefinition( this, "xbox360.def", s_Xbox360PropertyNames );
+}
+
+bool CProjectGenerator_Xbox360::WriteFile( CProjectFile *pFile )
+{
+ m_XMLWriter.PushNode( "File" );
+ m_XMLWriter.Write( CFmtStrMax( "RelativePath=\"%s\"", pFile->m_Name.Get() ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int i = 0; i < pFile->m_Configs.Count(); i++ )
+ {
+ if ( !WriteConfiguration( pFile->m_Configs[i] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::WriteFolder( CProjectFolder *pFolder )
+{
+ m_XMLWriter.PushNode( "Filter" );
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_XMLWriter.FixupXMLString( pFolder->m_Name.Get() ) ) );
+ m_XMLWriter.Write( ">" );
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::WriteConfiguration( CProjectConfiguration *pConfig )
+{
+ if ( pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( "FileConfiguration" );
+ }
+ else
+ {
+ m_XMLWriter.PushNode( "Configuration" );
+ }
+
+ const char *pOutputName = "???";
+ if ( !V_stricmp( pConfig->m_Name.Get(), "debug" ) )
+ {
+ pOutputName = "Debug|Xbox 360";
+ }
+ else if ( !V_stricmp( pConfig->m_Name.Get(), "release" ) )
+ {
+ pOutputName = "Release|Xbox 360";
+ }
+ else
+ {
+ return false;
+ }
+
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", pOutputName ) );
+
+ // write configuration properties
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex] );
+ }
+
+ if ( !pConfig->m_bIsFileConfig && pConfig->m_PropertyStates.m_Properties.Count() )
+ {
+ WriteProperty( NULL, "UseOfMFC", "-1" );
+ WriteProperty( NULL, "UseOfATL", "0" );
+ }
+
+ m_XMLWriter.Write( ">" );
+
+ if ( !WriteTool( "VCPreBuildEventTool", pConfig->GetPreBuildEventTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCCustomBuildTool", pConfig->GetCustomBuildTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCXMLDataGeneratorTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCWebServiceProxyGeneratorTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCMIDLTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCCLX360CompilerTool", pConfig->GetCompilerTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCManagedResourceCompilerTool", pConfig ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCResourceCompilerTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCPreLinkEventTool", pConfig->GetPreLinkEventTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCX360LinkerTool", pConfig->GetLinkerTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCLibrarianTool", pConfig->GetLibrarianTool() ) )
+ return false;
+
+ if ( !WriteNULLTool( "VCALinkTool", pConfig ) )
+ return false;
+
+ if ( !WriteTool( "VCX360ImageTool", pConfig->GetXboxImageTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCBscMakeTool", pConfig->GetBrowseInfoTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCX360DeploymentTool", pConfig->GetXboxDeploymentTool() ) )
+ return false;
+
+ if ( !WriteTool( "VCPostBuildEventTool", pConfig->GetPostBuildEventTool() ) )
+ return false;
+
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( "DebuggerTool" );
+ m_XMLWriter.PopNode( false );
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::WriteToXML()
+{
+ m_XMLWriter.PushNode( "VisualStudioProject" );
+ m_XMLWriter.Write( "ProjectType=\"Visual C++\"" );
+
+ if ( g_pVPC->BUse2008() )
+ m_XMLWriter.Write( "Version=\"9.00\"" );
+ else
+ m_XMLWriter.Write( "Version=\"8.00\"" );
+
+ m_XMLWriter.Write( CFmtStrMax( "Name=\"%s\"", m_pVCProjGenerator->GetProjectName().Get() ) );
+ m_XMLWriter.Write( CFmtStrMax( "ProjectGUID=\"%s\"", m_pVCProjGenerator->GetGUIDString().Get() ) );
+ m_XMLWriter.Write( ">" );
+
+ m_XMLWriter.PushNode( "Platforms" );
+ m_XMLWriter.PushNode( "Platform" );
+ m_XMLWriter.Write( "Name=\"Xbox 360\"" );
+ m_XMLWriter.PopNode( false );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "ToolFiles" );
+ m_XMLWriter.PopNode( true );
+
+ CUtlVector< CUtlString > configurationNames;
+ m_pVCProjGenerator->GetAllConfigurationNames( configurationNames );
+
+ // write the root configurations
+ m_XMLWriter.PushNode( "Configurations" );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteConfiguration( pConfiguration ) )
+ return false;
+ }
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "References" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "Files" );
+
+ CProjectFolder *pRootFolder = m_pVCProjGenerator->GetRootFolder();
+
+ for ( int iIndex = pRootFolder->m_Folders.Head(); iIndex != pRootFolder->m_Folders.InvalidIndex(); iIndex = pRootFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pRootFolder->m_Folders[iIndex] ) )
+ return false;
+ }
+
+ for ( int iIndex = pRootFolder->m_Files.Head(); iIndex != pRootFolder->m_Files.InvalidIndex(); iIndex = pRootFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pRootFolder->m_Files[iIndex] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::Save( const char *pOutputFilename )
+{
+ if ( !m_XMLWriter.Open( pOutputFilename ) )
+ return false;
+
+ bool bValid = WriteToXML();
+
+ m_XMLWriter.Close();
+
+ return bValid;
+}
+
+bool CProjectGenerator_Xbox360::WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig )
+{
+ if ( pConfig->m_bIsFileConfig )
+ return true;
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( CFmtStr( "Name=\"%s\"", pToolName ) );
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::WriteTool( const char *pToolName, const CProjectTool *pProjectTool )
+{
+ if ( !pProjectTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ m_XMLWriter.PushNode( "Tool" );
+
+ m_XMLWriter.Write( CFmtStr( "Name=\"%s\"", pToolName ) );
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex] );
+ }
+
+ m_XMLWriter.PopNode( false );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360::WriteProperty( const PropertyState_t *pPropertyState, const char *pOutputName, const char *pOutputValue )
+{
+ if ( !pPropertyState )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, pOutputValue ) );
+ return true;
+ }
+
+ if ( !pOutputName )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_OutputString.Get();
+ if ( !pOutputName[0] )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_ParseString.Get();
+ if ( pOutputName[0] == '$' )
+ {
+ pOutputName++;
+ }
+ }
+ }
+
+ if ( pPropertyState )
+ {
+ switch ( pPropertyState->m_pToolProperty->m_nType )
+ {
+ case PT_BOOLEAN:
+ {
+ bool bEnabled = Sys_StringToBool( pPropertyState->m_StringValue.Get() );
+ if ( pPropertyState->m_pToolProperty->m_bInvertOutput )
+ {
+ bEnabled ^= 1;
+ }
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, bEnabled ? "true" : "false" ) );
+ }
+ break;
+
+ case PT_STRING:
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, m_XMLWriter.FixupXMLString( pPropertyState->m_StringValue.Get() ) ) );
+ break;
+
+ case PT_LIST:
+ case PT_INTEGER:
+ m_XMLWriter.Write( CFmtStrMax( "%s=\"%s\"", pOutputName, pPropertyState->m_StringValue.Get() ) );
+ break;
+
+ case PT_IGNORE:
+ break;
+
+ default:
+ g_pVPC->VPCError( "CProjectGenerator_Xbox360: WriteProperty, %s - not implemented", pOutputName );
+ }
+ }
+
+ return true;
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360.h b/external/vpc/utils/vpc/projectgenerator_xbox360.h
new file mode 100644
index 0000000..78f4ece
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360.h
@@ -0,0 +1,41 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_XBOX360_H
+#define PROJECTGENERATOR_XBOX360_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define PROPERTYNAME( X, Y ) X##_##Y,
+enum Xbox360Properties_e
+{
+ #include "projectgenerator_xbox360.inc"
+};
+
+class CProjectGenerator_Xbox360 : public IVCProjWriter
+{
+public:
+ CProjectGenerator_Xbox360();
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pVCProjGenerator; }
+
+ virtual bool Save( const char *pOutputFilename );
+
+private:
+ bool WriteToXML();
+
+ bool WriteFolder( CProjectFolder *pFolder );
+ bool WriteFile( CProjectFile *pFile );
+ bool WriteConfiguration( CProjectConfiguration *pConfig );
+ bool WriteProperty( const PropertyState_t *pPropertyState, const char *pOutputName = NULL, const char *pValue = NULL );
+ bool WriteTool( const char *pToolName, const CProjectTool *pProjectTool );
+ bool WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig );
+
+ CXMLWriter m_XMLWriter;
+ CVCProjGenerator *m_pVCProjGenerator;
+};
+
+#endif // PROJECTGENERATOR_XBOX360_H
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360.inc b/external/vpc/utils/vpc/projectgenerator_xbox360.inc
new file mode 100644
index 0000000..4a18aca
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360.inc
@@ -0,0 +1,192 @@
+
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Property Enumerations
+//
+//=====================================================================================//
+
+// Config
+PROPERTYNAME( XBOX360_GENERAL, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_GENERAL, OutputDirectory )
+PROPERTYNAME( XBOX360_GENERAL, IntermediateDirectory )
+PROPERTYNAME( XBOX360_GENERAL, ConfigurationType )
+PROPERTYNAME( XBOX360_GENERAL, CharacterSet )
+PROPERTYNAME( XBOX360_GENERAL, WholeProgramOptimization )
+PROPERTYNAME( XBOX360_GENERAL, ExtensionsToDeleteOnClean )
+PROPERTYNAME( XBOX360_GENERAL, BuildLogFile )
+PROPERTYNAME( XBOX360_GENERAL, InheritedProjectPropertySheets )
+
+// Debugging
+PROPERTYNAME( XBOX360_DEBUGGING, Command )
+PROPERTYNAME( XBOX360_DEBUGGING, CommandArguments )
+PROPERTYNAME( XBOX360_DEBUGGING, RemoteMachine )
+
+// Compiler
+PROPERTYNAME( XBOX360_COMPILER, AdditionalOptions )
+PROPERTYNAME( XBOX360_COMPILER, Optimization )
+PROPERTYNAME( XBOX360_COMPILER, InlineFunctionExpansion )
+PROPERTYNAME( XBOX360_COMPILER, EnableIntrinsicFunctions )
+PROPERTYNAME( XBOX360_COMPILER, FavorSizeOrSpeed )
+PROPERTYNAME( XBOX360_COMPILER, EnableFiberSafeOptimizations )
+PROPERTYNAME( XBOX360_COMPILER, WholeProgramOptimization )
+PROPERTYNAME( XBOX360_COMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( XBOX360_COMPILER, PreprocessorDefinitions )
+PROPERTYNAME( XBOX360_COMPILER, IgnoreStandardIncludePath )
+PROPERTYNAME( XBOX360_COMPILER, GeneratePreprocessedFile )
+PROPERTYNAME( XBOX360_COMPILER, KeepComments )
+PROPERTYNAME( XBOX360_COMPILER, EnableStringPooling )
+PROPERTYNAME( XBOX360_COMPILER, EnableMinimalRebuild )
+PROPERTYNAME( XBOX360_COMPILER, EnableCPPExceptions )
+PROPERTYNAME( XBOX360_COMPILER, BasicRuntimeChecks )
+PROPERTYNAME( XBOX360_COMPILER, SmallerTypeCheck )
+PROPERTYNAME( XBOX360_COMPILER, RuntimeLibrary )
+PROPERTYNAME( XBOX360_COMPILER, StructMemberAlignment )
+PROPERTYNAME( XBOX360_COMPILER, BufferSecurityCheck )
+PROPERTYNAME( XBOX360_COMPILER, EnableFunctionLevelLinking )
+PROPERTYNAME( XBOX360_COMPILER, FloatingPointModel )
+PROPERTYNAME( XBOX360_COMPILER, EnableFloatingPointExceptions )
+PROPERTYNAME( XBOX360_COMPILER, DisableLanguageExtensions )
+PROPERTYNAME( XBOX360_COMPILER, DefaultCharUnsigned )
+PROPERTYNAME( XBOX360_COMPILER, TreatWCHAR_TAsBuiltInType )
+PROPERTYNAME( XBOX360_COMPILER, ForceConformanceInForLoopScope )
+PROPERTYNAME( XBOX360_COMPILER, EnableRunTimeTypeInfo )
+PROPERTYNAME( XBOX360_COMPILER, OpenMPSupport )
+PROPERTYNAME( XBOX360_COMPILER, CreateUsePrecompiledHeader )
+PROPERTYNAME( XBOX360_COMPILER, CreateUsePCHThroughFile )
+PROPERTYNAME( XBOX360_COMPILER, PrecompiledHeaderFile )
+PROPERTYNAME( XBOX360_COMPILER, ExpandAttributedSource )
+PROPERTYNAME( XBOX360_COMPILER, AssemblerOutput )
+PROPERTYNAME( XBOX360_COMPILER, ASMListLocation )
+PROPERTYNAME( XBOX360_COMPILER, ObjectFileName )
+PROPERTYNAME( XBOX360_COMPILER, ProgramDatabaseFileName )
+PROPERTYNAME( XBOX360_COMPILER, EnableBrowseInformation )
+PROPERTYNAME( XBOX360_COMPILER, BrowseFile )
+PROPERTYNAME( XBOX360_COMPILER, WarningLevel )
+PROPERTYNAME( XBOX360_COMPILER, TreatWarningsAsErrors )
+PROPERTYNAME( XBOX360_COMPILER, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_COMPILER, DebugInformationFormat )
+PROPERTYNAME( XBOX360_COMPILER, CompileAs )
+PROPERTYNAME( XBOX360_COMPILER, ForceIncludes )
+PROPERTYNAME( XBOX360_COMPILER, ShowIncludes )
+PROPERTYNAME( XBOX360_COMPILER, UndefineAllPreprocessorDefinitions )
+PROPERTYNAME( XBOX360_COMPILER, UndefinePreprocessorDefinitions )
+PROPERTYNAME( XBOX360_COMPILER, UseFullPaths )
+PROPERTYNAME( XBOX360_COMPILER, OmitDefaultLibraryNames )
+PROPERTYNAME( XBOX360_COMPILER, TrapIntegerDividesOptimization )
+PROPERTYNAME( XBOX360_COMPILER, PreschedulingOptimization )
+PROPERTYNAME( XBOX360_COMPILER, InlineAssemblyOptimization )
+PROPERTYNAME( XBOX360_COMPILER, RegisterReservation )
+PROPERTYNAME( XBOX360_COMPILER, Stalls )
+PROPERTYNAME( XBOX360_COMPILER, CallAttributedProfiling )
+PROPERTYNAME( XBOX360_COMPILER, UseUNICODEResponseFiles )
+PROPERTYNAME( XBOX360_COMPILER, GenerateXMLDocumentationFiles )
+PROPERTYNAME( XBOX360_COMPILER, XMLDocumentationFileName )
+PROPERTYNAME( XBOX360_COMPILER, DisableSpecificWarnings )
+
+// Librarian
+PROPERTYNAME( XBOX360_LIBRARIAN, OutputFile )
+PROPERTYNAME( XBOX360_LIBRARIAN, AdditionalDependencies )
+PROPERTYNAME( XBOX360_LIBRARIAN, AdditionalLibraryDirectories )
+PROPERTYNAME( XBOX360_LIBRARIAN, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_LIBRARIAN, ModuleDefinitionFileName )
+PROPERTYNAME( XBOX360_LIBRARIAN, IgnoreAllDefaultLibraries )
+PROPERTYNAME( XBOX360_LIBRARIAN, IgnoreSpecificLibrary )
+PROPERTYNAME( XBOX360_LIBRARIAN, ExportNamedFunctions )
+PROPERTYNAME( XBOX360_LIBRARIAN, ForceSymbolReferences )
+PROPERTYNAME( XBOX360_LIBRARIAN, UseUNICODEResponseFiles )
+PROPERTYNAME( XBOX360_LIBRARIAN, LinkLibraryDependencies )
+PROPERTYNAME( XBOX360_LIBRARIAN, AdditionalOptions )
+
+// Linker
+PROPERTYNAME( XBOX360_LINKER, IgnoreImportLibrary )
+PROPERTYNAME( XBOX360_LINKER, AdditionalOptions )
+PROPERTYNAME( XBOX360_LINKER, AdditionalDependencies )
+PROPERTYNAME( XBOX360_LINKER, ShowProgress )
+PROPERTYNAME( XBOX360_LINKER, OutputFile )
+PROPERTYNAME( XBOX360_LINKER, EnableIncrementalLinking )
+PROPERTYNAME( XBOX360_LINKER, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_LINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( XBOX360_LINKER, IgnoreAllDefaultLibraries )
+PROPERTYNAME( XBOX360_LINKER, IgnoreSpecificLibrary )
+PROPERTYNAME( XBOX360_LINKER, ModuleDefinitionFile )
+PROPERTYNAME( XBOX360_LINKER, GenerateDebugInfo )
+PROPERTYNAME( XBOX360_LINKER, GenerateProgramDatabaseFile )
+PROPERTYNAME( XBOX360_LINKER, GenerateMapFile )
+PROPERTYNAME( XBOX360_LINKER, MapFileName )
+PROPERTYNAME( XBOX360_LINKER, MapExports )
+PROPERTYNAME( XBOX360_LINKER, StackReserveSize )
+PROPERTYNAME( XBOX360_LINKER, StackCommitSize )
+PROPERTYNAME( XBOX360_LINKER, References )
+PROPERTYNAME( XBOX360_LINKER, EnableCOMDATFolding )
+PROPERTYNAME( XBOX360_LINKER, LinkTimeCodeGeneration )
+PROPERTYNAME( XBOX360_LINKER, EntryPoint )
+PROPERTYNAME( XBOX360_LINKER, NoEntryPoint )
+PROPERTYNAME( XBOX360_LINKER, SetChecksum )
+PROPERTYNAME( XBOX360_LINKER, BaseAddress )
+PROPERTYNAME( XBOX360_LINKER, ImportLibrary )
+PROPERTYNAME( XBOX360_LINKER, FixedBaseAddress )
+PROPERTYNAME( XBOX360_LINKER, ErrorReporting )
+PROPERTYNAME( XBOX360_LINKER, FunctionOrder )
+PROPERTYNAME( XBOX360_LINKER, Version )
+PROPERTYNAME( XBOX360_LINKER, LinkLibraryDependencies )
+PROPERTYNAME( XBOX360_LINKER, UseLibraryDependencyInputs )
+PROPERTYNAME( XBOX360_LINKER, UseUNICODEResponseFiles )
+PROPERTYNAME( XBOX360_LINKER, ForceSymbolReferences )
+PROPERTYNAME( XBOX360_LINKER, StripPrivateSymbols )
+PROPERTYNAME( XBOX360_LINKER, ProfileGuidedDatabase )
+PROPERTYNAME( XBOX360_LINKER, MergeSections )
+
+// Browse Information
+PROPERTYNAME( XBOX360_BROWSEINFORMATION, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_BROWSEINFORMATION, OutputFile )
+PROPERTYNAME( XBOX360_BROWSEINFORMATION, AdditionalOptions )
+
+// Pre Build
+PROPERTYNAME( XBOX360_PREBUILDEVENT, Description )
+PROPERTYNAME( XBOX360_PREBUILDEVENT, CommandLine )
+PROPERTYNAME( XBOX360_PREBUILDEVENT, ExcludedFromBuild )
+
+// Pre Link
+PROPERTYNAME( XBOX360_PRELINKEVENT, Description )
+PROPERTYNAME( XBOX360_PRELINKEVENT, CommandLine )
+PROPERTYNAME( XBOX360_PRELINKEVENT, ExcludedFromBuild )
+
+// Post Build
+PROPERTYNAME( XBOX360_POSTBUILDEVENT, Description )
+PROPERTYNAME( XBOX360_POSTBUILDEVENT, CommandLine )
+PROPERTYNAME( XBOX360_POSTBUILDEVENT, ExcludedFromBuild )
+
+// Custom Build
+PROPERTYNAME( XBOX360_CUSTOMBUILDSTEP, Description )
+PROPERTYNAME( XBOX360_CUSTOMBUILDSTEP, CommandLine )
+PROPERTYNAME( XBOX360_CUSTOMBUILDSTEP, Outputs )
+PROPERTYNAME( XBOX360_CUSTOMBUILDSTEP, AdditionalDependencies )
+
+// Image Conversion
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, OutputFile )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, ProjectDefaults )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, WorkspaceSize )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, ExportByName )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, OpticalDiscDriveMapping )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, PAL50Incompatible )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, TitleID )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, LANKey )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, BaseAddress )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, HeapSize )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, AdditionalSections )
+PROPERTYNAME( XBOX360_XBOX360IMAGECONVERSION, AdditionalOptions )
+
+// Console Deployment
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, DeploymentRoot )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, DeploymentFiles )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, Progress )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, ForceCopy )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, DeploymentType )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, EmulationType )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, Layout )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, LayoutRoot )
+PROPERTYNAME( XBOX360_CONSOLEDEPLOYMENT, AdditionalOptions )
+
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360_2010.cpp b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.cpp
new file mode 100644
index 0000000..285285c
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.cpp
@@ -0,0 +1,596 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#undef PROPERTYNAME
+#define PROPERTYNAME( X, Y ) { X##_##Y, #X, #Y },
+static PropertyName_t s_Xbox360PropertyNames_2010[] =
+{
+ #include "projectgenerator_xbox360_2010.inc"
+ { -1, NULL, NULL }
+};
+
+IBaseProjectGenerator* GetXbox360ProjectGenerator_2010()
+{
+ static CProjectGenerator_Xbox360_2010 *s_pProjectGenerator = NULL;
+ if ( !s_pProjectGenerator )
+ {
+ s_pProjectGenerator = new CProjectGenerator_Xbox360_2010();
+ }
+
+ return s_pProjectGenerator->GetProjectGenerator();
+}
+
+CProjectGenerator_Xbox360_2010::CProjectGenerator_Xbox360_2010()
+{
+ m_pVCProjGenerator = new CVCProjGenerator();
+ m_pVCProjGenerator->SetupGeneratorDefinition( this, "xbox360_2010.def", s_Xbox360PropertyNames_2010 );
+}
+
+enum TypeKeyNames_e
+{
+ TKN_LIBRARY = 0,
+ TKN_INCLUDE,
+ TKN_COMPILE,
+ TKN_RESOURCECOMPILE,
+ TKN_CUSTOMBUILD,
+ TKN_NONE,
+ TKN_MAX_COUNT,
+};
+
+static const char *s_TypeKeyNames[] =
+{
+ "Library",
+ "ClInclude",
+ "ClCompile",
+ "ResourceCompile",
+ "CustomBuild",
+ "None"
+};
+
+const char *CProjectGenerator_Xbox360_2010::GetKeyNameForFile( CProjectFile *pFile )
+{
+ COMPILE_TIME_ASSERT( ARRAYSIZE( s_TypeKeyNames ) == TKN_MAX_COUNT );
+
+ const char *pExtension = V_GetFileExtension( pFile->m_Name.Get() );
+
+ const char *pKeyName = s_TypeKeyNames[TKN_NONE];
+ if ( pExtension )
+ {
+ if ( pFile->m_Configs.Count() && pFile->m_Configs[0]->GetCustomBuildTool() )
+ {
+ pKeyName = s_TypeKeyNames[TKN_CUSTOMBUILD];
+ }
+ else if ( IsCFileExtension( pExtension ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_COMPILE];
+ }
+ else if ( IsHFileExtension( pExtension ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_INCLUDE];
+ }
+ else if ( !V_stricmp( pExtension, "lib" ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_LIBRARY];
+ }
+ else if ( !V_stricmp( pExtension, "rc" ) )
+ {
+ pKeyName = s_TypeKeyNames[TKN_RESOURCECOMPILE];
+ }
+ }
+
+ return pKeyName;
+}
+
+bool CProjectGenerator_Xbox360_2010::WritePropertyGroupTool( CProjectTool *pProjectTool, CProjectConfiguration *pConfiguration )
+{
+ if ( !pProjectTool )
+ return true;
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !pProjectTool->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex], true, pConfiguration->m_Name.Get() ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteFile( CProjectFile *pFile, const char *pFileTypeName )
+{
+ const char *pKeyName = GetKeyNameForFile( pFile );
+ if ( V_stricmp( pFileTypeName, pKeyName ) )
+ {
+ // skip it
+ return true;
+ }
+
+ if ( !pFile->m_Configs.Count() )
+ {
+ m_XMLWriter.Write( CFmtStrMax( "<%s Include=\"%s\" />", pKeyName, pFile->m_Name.Get() ) );
+ }
+ else
+ {
+ m_XMLWriter.PushNode( pKeyName, CFmtStr( "Include=\"%s\"", pFile->m_Name.Get() ) );
+
+ for ( int i = 0; i < pFile->m_Configs.Count(); i++ )
+ {
+ if ( !WriteConfiguration( pFile->m_Configs[i] ) )
+ return false;
+ }
+
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteFolder( CProjectFolder *pFolder, const char *pFileTypeName, int nDepth )
+{
+ if ( !nDepth )
+ {
+ m_XMLWriter.PushNode( "ItemGroup" );
+ }
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFile( pFolder->m_Files[iIndex], pFileTypeName ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolder( pFolder->m_Folders[iIndex], pFileTypeName, nDepth+1 ) )
+ return false;
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteConfiguration( CProjectConfiguration *pConfig )
+{
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( "PropertyGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|Xbox 360'\" Label=\"Configuration\"", pConfig->m_Name.Get() ) );
+
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( pConfig->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex] ) )
+ return false;
+ }
+
+ WriteProperty( NULL, false, NULL, "UseOfAtl", "false" );
+
+ m_XMLWriter.PopNode( true );
+ }
+ else
+ {
+ for ( int i = 0; i < pConfig->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pConfig->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !WriteProperty( &pConfig->m_PropertyStates.m_Properties[sortedIndex], true, pConfig->m_Name.Get() ) )
+ return false;
+ }
+
+ if ( !WriteTool( "ClCompile", pConfig->GetCompilerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "CustomBuildStep", pConfig->GetCustomBuildTool(), pConfig ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteTools( CProjectConfiguration *pConfig )
+{
+ m_XMLWriter.PushNode( "ItemDefinitionGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|Xbox 360'\"", pConfig->m_Name.Get() ) );
+
+ if ( !WriteTool( "PreBuildEvent", pConfig->GetPreBuildEventTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "CustomBuildStep", pConfig->GetCustomBuildTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "ClCompile", pConfig->GetCompilerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "PreLinkEvent", pConfig->GetPreLinkEventTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Link", pConfig->GetLinkerTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Lib", pConfig->GetLibrarianTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "ImageXex", pConfig->GetXboxImageTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Bscmake", pConfig->GetBrowseInfoTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "Deploy", pConfig->GetXboxDeploymentTool(), pConfig ) )
+ return false;
+
+ if ( !WriteTool( "PostBuildEvent", pConfig->GetPostBuildEventTool(), pConfig ) )
+ return false;
+
+ m_XMLWriter.PopNode( true );
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WritePrimaryXML( const char *pOutputFilename )
+{
+ if ( !m_XMLWriter.Open( pOutputFilename, true ) )
+ return false;
+
+ m_XMLWriter.PushNode( "Project", "DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"" );
+
+ m_XMLWriter.PushNode( "ItemGroup", "Label=\"ProjectConfigurations\"" );
+ CUtlVector< CUtlString > configurationNames;
+ m_pVCProjGenerator->GetAllConfigurationNames( configurationNames );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ m_XMLWriter.PushNode( "ProjectConfiguration", CFmtStr( "Include=\"%s|Xbox 360\"", configurationNames[i].Get() ) );
+ m_XMLWriter.WriteLineNode( "Configuration", "", configurationNames[i].Get() );
+ m_XMLWriter.WriteLineNode( "Platform", "", "Xbox 360" );
+ m_XMLWriter.PopNode( true );
+ }
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PushNode( "PropertyGroup", "Label=\"Globals\"" );
+ m_XMLWriter.WriteLineNode( "ProjectName", "", m_pVCProjGenerator->GetProjectName().Get() );
+ m_XMLWriter.WriteLineNode( "ProjectGuid", "", m_pVCProjGenerator->GetGUIDString().Get() );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />" );
+
+ // write the root configurations
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteConfiguration( pConfiguration ) )
+ return false;
+ }
+ }
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />" );
+ m_XMLWriter.PushNode( "ImportGroup", "Label=\"ExtensionSettings\"" );
+ m_XMLWriter.PopNode( true );
+
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ m_XMLWriter.PushNode( "ImportGroup", CFmtStr( "Condition=\"'$(Configuration)|$(Platform)'=='%s|Xbox 360'\" Label=\"PropertySheets\"", configurationNames[i].Get() ) );
+ m_XMLWriter.Write( "<Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />" );
+ m_XMLWriter.PopNode( true );
+ }
+
+ m_XMLWriter.Write( "<PropertyGroup Label=\"UserMacros\" />" );
+
+ m_XMLWriter.PushNode( "PropertyGroup" );
+ m_XMLWriter.WriteLineNode( "_ProjectFileVersion", "", "10.0.30319.1" );
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ for ( int j = 0; j < pConfiguration->m_PropertyStates.m_PropertiesInOutputOrder.Count(); j++ )
+ {
+ int sortedIndex = pConfiguration->m_PropertyStates.m_PropertiesInOutputOrder[j];
+ if ( !pConfiguration->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pConfiguration->m_PropertyStates.m_Properties[sortedIndex], true, pConfiguration->m_Name.Get() ) )
+ return false;
+ }
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPreBuildEventTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPreLinkEventTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetLinkerTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetLibrarianTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetPostBuildEventTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetXboxImageTool(), pConfiguration ) )
+ return false;
+
+ if ( !WritePropertyGroupTool( pConfiguration->GetXboxDeploymentTool(), pConfiguration ) )
+ return false;
+ }
+ }
+ m_XMLWriter.PopNode( true );
+
+ // write the tool configurations
+ for ( int i = 0; i < configurationNames.Count(); i++ )
+ {
+ CProjectConfiguration *pConfiguration = NULL;
+ if ( m_pVCProjGenerator->GetRootConfiguration( configurationNames[i].Get(), &pConfiguration ) )
+ {
+ if ( !WriteTools( pConfiguration ) )
+ return false;
+ }
+ }
+
+ // write root folders
+ for ( int i = 0; i < TKN_MAX_COUNT; i++ )
+ {
+ if ( !WriteFolder( m_pVCProjGenerator->GetRootFolder(), s_TypeKeyNames[i], 0 ) )
+ return false;
+ }
+
+ m_XMLWriter.Write( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />" );
+ m_XMLWriter.PushNode( "ImportGroup", "Label=\"ExtensionTargets\"" );
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.PopNode( true );
+
+ m_XMLWriter.Close();
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteFolderToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath )
+{
+ CUtlString parentPath = CFmtStr( "%s%s%s", pParentPath, pParentPath[0] ? "\\" : "", pFolder->m_Name.Get() );
+
+ MD5Context_t ctx;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ V_memset( &ctx, 0, sizeof( ctx ) );
+ V_memset( digest, 0, sizeof( digest ) );
+ MD5Init( &ctx );
+ MD5Update( &ctx, (unsigned char *)parentPath.Get(), strlen( parentPath.Get() ) );
+ MD5Final( digest, &ctx );
+
+ char szMD5[64];
+ V_binarytohex( digest, MD5_DIGEST_LENGTH, szMD5, sizeof( szMD5 ) );
+ V_strupr( szMD5 );
+
+ char szGUID[MAX_PATH];
+ V_snprintf( szGUID, sizeof( szGUID ), "{%8.8s-%4.4s-%4.4s-%4.4s-%12.12s}", szMD5, &szMD5[8], &szMD5[12], &szMD5[16], &szMD5[20] );
+
+ m_XMLFilterWriter.PushNode( "Filter", CFmtStr( "Include=\"%s\"", parentPath.Get() ) );
+ m_XMLFilterWriter.WriteLineNode( "UniqueIdentifier", "", szGUID );
+ m_XMLFilterWriter.PopNode( true );
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderToSecondaryXML( pFolder->m_Folders[iIndex], parentPath.Get() ) )
+ return false;
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteFileToSecondaryXML( CProjectFile *pFile, const char *pParentPath, const char *pFileTypeName )
+{
+ const char *pKeyName = GetKeyNameForFile( pFile );
+ if ( V_stricmp( pFileTypeName, pKeyName ) )
+ {
+ // skip it
+ return true;
+ }
+
+ if ( pParentPath )
+ {
+ m_XMLFilterWriter.PushNode( pKeyName, CFmtStr( "Include=\"%s\"", pFile->m_Name.Get() ) );
+ m_XMLFilterWriter.WriteLineNode( "Filter", "", pParentPath );
+ m_XMLFilterWriter.PopNode( true );
+ }
+ else
+ {
+ m_XMLFilterWriter.Write( CFmtStr( "<%s Include=\"%s\" />", pKeyName, pFile->m_Name.Get() ) );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteFolderContentsToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath, const char *pFileTypeName, int nDepth )
+{
+ CUtlString parentPath;
+ if ( pParentPath )
+ {
+ parentPath = CFmtStr( "%s%s%s", pParentPath, pParentPath[0] ? "\\" : "", pFolder->m_Name.Get() );
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLFilterWriter.PushNode( "ItemGroup", NULL );
+ }
+
+ for ( int iIndex = pFolder->m_Files.Head(); iIndex != pFolder->m_Files.InvalidIndex(); iIndex = pFolder->m_Files.Next( iIndex ) )
+ {
+ if ( !WriteFileToSecondaryXML( pFolder->m_Files[iIndex], parentPath.Get(), pFileTypeName ) )
+ return false;
+ }
+
+ for ( int iIndex = pFolder->m_Folders.Head(); iIndex != pFolder->m_Folders.InvalidIndex(); iIndex = pFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderContentsToSecondaryXML( pFolder->m_Folders[iIndex], parentPath.Get(), pFileTypeName, nDepth+1 ) )
+ return false;
+ }
+
+ if ( !nDepth )
+ {
+ m_XMLFilterWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteSecondaryXML( const char *pOutputFilename )
+{
+ if ( !m_XMLFilterWriter.Open( pOutputFilename, true ) )
+ return false;
+
+ m_XMLFilterWriter.PushNode( "Project", "ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"" );
+
+ // write the root folders
+ m_XMLFilterWriter.PushNode( "ItemGroup", NULL );
+ CProjectFolder *pRootFolder = m_pVCProjGenerator->GetRootFolder();
+ for ( int iIndex = pRootFolder->m_Folders.Head(); iIndex != pRootFolder->m_Folders.InvalidIndex(); iIndex = pRootFolder->m_Folders.Next( iIndex ) )
+ {
+ if ( !WriteFolderToSecondaryXML( pRootFolder->m_Folders[iIndex], "" ) )
+ return false;
+ }
+ m_XMLFilterWriter.PopNode( true );
+
+ // write folder contents
+ for ( int i = 0; i < TKN_MAX_COUNT; i++ )
+ {
+ if ( !WriteFolderContentsToSecondaryXML( pRootFolder, NULL, s_TypeKeyNames[i], 0 ) )
+ return false;
+ }
+
+ m_XMLFilterWriter.PopNode( true );
+
+ m_XMLFilterWriter.Close();
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteTool( const char *pToolName, const CProjectTool *pProjectTool, CProjectConfiguration *pConfig )
+{
+ if ( !pProjectTool )
+ {
+ // not an error, some tools n/a for a config
+ return true;
+ }
+
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PushNode( pToolName, NULL );
+ }
+
+ for ( int i = 0; i < pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder.Count(); i++ )
+ {
+ int sortedIndex = pProjectTool->m_PropertyStates.m_PropertiesInOutputOrder[i];
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ if ( pProjectTool->m_PropertyStates.m_Properties[sortedIndex].m_pToolProperty->m_bEmitAsGlobalProperty )
+ continue;
+
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex] ) )
+ return false;
+ }
+ else
+ {
+ if ( !WriteProperty( &pProjectTool->m_PropertyStates.m_Properties[sortedIndex], true, pConfig->m_Name.Get() ) )
+ return false;
+ }
+ }
+
+ if ( !pConfig->m_bIsFileConfig )
+ {
+ m_XMLWriter.PopNode( true );
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::WriteProperty( const PropertyState_t *pPropertyState, bool bEmitConfiguration, const char *pConfigName, const char *pOutputName, const char *pOutputValue )
+{
+ if ( !pPropertyState )
+ {
+ m_XMLWriter.WriteLineNode( pOutputName, "", pOutputValue );
+ return true;
+ }
+
+ if ( !pOutputName )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_OutputString.Get();
+ if ( !pOutputName[0] )
+ {
+ pOutputName = pPropertyState->m_pToolProperty->m_ParseString.Get();
+ if ( pOutputName[0] == '$' )
+ {
+ pOutputName++;
+ }
+ }
+ }
+
+ const char *pCondition = "";
+ CUtlString conditionString;
+ if ( bEmitConfiguration )
+ {
+ conditionString = CFmtStr( " Condition=\"'$(Configuration)|$(Platform)'=='%s|Xbox 360'\"", pConfigName );
+ pCondition = conditionString.Get();
+ }
+
+ if ( pPropertyState )
+ {
+ switch ( pPropertyState->m_pToolProperty->m_nType )
+ {
+ case PT_BOOLEAN:
+ {
+ bool bEnabled = Sys_StringToBool( pPropertyState->m_StringValue.Get() );
+ if ( pPropertyState->m_pToolProperty->m_bInvertOutput )
+ {
+ bEnabled ^= 1;
+ }
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, bEnabled ? "true" : "false" );
+ }
+ break;
+
+ case PT_STRING:
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, m_XMLWriter.FixupXMLString( pPropertyState->m_StringValue.Get() ) );
+ break;
+
+ case PT_LIST:
+ case PT_INTEGER:
+ m_XMLWriter.WriteLineNode( pOutputName, pCondition, pPropertyState->m_StringValue.Get() );
+ break;
+
+ case PT_IGNORE:
+ break;
+
+ default:
+ g_pVPC->VPCError( "CProjectGenerator_Xbox360_2010: WriteProperty, %s - not implemented", pOutputName );
+ }
+ }
+
+ return true;
+}
+
+bool CProjectGenerator_Xbox360_2010::Save( const char *pOutputFilename )
+{
+ bool bValid = WritePrimaryXML( pOutputFilename );
+ if ( bValid )
+ {
+ bValid = WriteSecondaryXML( CFmtStr( "%s.filters", pOutputFilename ) );
+ if ( !bValid )
+ {
+ g_pVPC->VPCError( "Cannot save to the specified project '%s'", pOutputFilename );
+ }
+ }
+
+ return bValid;
+}
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360_2010.h b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.h
new file mode 100644
index 0000000..ce88157
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.h
@@ -0,0 +1,54 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef PROJECTGENERATOR_XBOX360_2010_H
+#define PROJECTGENERATOR_XBOX360_2010_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define PROPERTYNAME( X, Y ) X##_##Y,
+enum Xbox360_2010_Properties_e
+{
+ #include "projectgenerator_xbox360_2010.inc"
+};
+
+class CProjectGenerator_Xbox360_2010 : public IVCProjWriter
+{
+public:
+ CProjectGenerator_Xbox360_2010();
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pVCProjGenerator; }
+
+ virtual bool Save( const char *pOutputFilename );
+
+private:
+ // primary XML - foo.vcxproj
+ bool WritePrimaryXML( const char *pOutputFilename );
+ bool WriteFolder( CProjectFolder *pFolder, const char *pFileTypeName, int nDepth );
+ bool WriteFile( CProjectFile *pFile, const char *pFileTypeName );
+ bool WriteConfiguration( CProjectConfiguration *pConfig );
+ bool WriteTools( CProjectConfiguration *pConfig );
+ bool WriteProperty( const PropertyState_t *pPropertyState, bool bEmitConfiguration = false, const char *pConfigurationName = NULL, const char *pOutputName = NULL, const char *pValue = NULL );
+ bool WriteTool( const char *pToolName, const CProjectTool *pProjectTool, CProjectConfiguration *pConfig );
+ bool WriteNULLTool( const char *pToolName, const CProjectConfiguration *pConfig );
+ bool WritePropertyGroupTool( CProjectTool *pProjectTool, CProjectConfiguration *pConfiguration );
+ bool WritePropertyGroup();
+
+ // secondary XML - foo.vcxproj.filters
+ bool WriteSecondaryXML( const char *pOutputFilename );
+ bool WriteFolderToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath );
+ bool WriteFolderContentsToSecondaryXML( CProjectFolder *pFolder, const char *pParentPath, const char *pFileTypeName, int nDepth );
+ bool WriteFileToSecondaryXML( CProjectFile *pFile, const char *pParentPath, const char *pFileTypeName );
+
+ const char *GetKeyNameForFile( CProjectFile *pFile );
+
+ CXMLWriter m_XMLWriter;
+ CXMLWriter m_XMLFilterWriter;
+
+ CVCProjGenerator *m_pVCProjGenerator;
+};
+
+#endif // PROJECTGENERATOR_XBOX360_2010_H
diff --git a/external/vpc/utils/vpc/projectgenerator_xbox360_2010.inc b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.inc
new file mode 100644
index 0000000..78525b8
--- /dev/null
+++ b/external/vpc/utils/vpc/projectgenerator_xbox360_2010.inc
@@ -0,0 +1,210 @@
+
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Property Enumerations
+//
+//=====================================================================================//
+
+// Config
+PROPERTYNAME( XBOX360_2010_GENERAL, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_2010_GENERAL, OutputDirectory )
+PROPERTYNAME( XBOX360_2010_GENERAL, IntermediateDirectory )
+PROPERTYNAME( XBOX360_2010_GENERAL, ConfigurationType )
+PROPERTYNAME( XBOX360_2010_GENERAL, CharacterSet )
+PROPERTYNAME( XBOX360_2010_GENERAL, WholeProgramOptimization )
+PROPERTYNAME( XBOX360_2010_GENERAL, ExtensionsToDeleteOnClean )
+PROPERTYNAME( XBOX360_2010_GENERAL, BuildLogFile )
+PROPERTYNAME( XBOX360_2010_GENERAL, PlatformToolset )
+
+// Debugging
+PROPERTYNAME( XBOX360_2010_DEBUGGING, Command )
+PROPERTYNAME( XBOX360_2010_DEBUGGING, CommandArguments )
+PROPERTYNAME( XBOX360_2010_DEBUGGING, RemoteMachine )
+PROPERTYNAME( XBOX360_2010_DEBUGGING, MapDVDDrive )
+PROPERTYNAME( XBOX360_2010_DEBUGGING, CheckUpToDate )
+
+// Compiler
+PROPERTYNAME( XBOX360_2010_COMPILER, AdditionalOptions )
+PROPERTYNAME( XBOX360_2010_COMPILER, Optimization )
+PROPERTYNAME( XBOX360_2010_COMPILER, InlineFunctionExpansion )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableIntrinsicFunctions )
+PROPERTYNAME( XBOX360_2010_COMPILER, FavorSizeOrSpeed )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableFiberSafeOptimizations )
+PROPERTYNAME( XBOX360_2010_COMPILER, WholeProgramOptimization )
+PROPERTYNAME( XBOX360_2010_COMPILER, AdditionalIncludeDirectories )
+PROPERTYNAME( XBOX360_2010_COMPILER, PreprocessorDefinitions )
+PROPERTYNAME( XBOX360_2010_COMPILER, IgnoreStandardIncludePaths )
+PROPERTYNAME( XBOX360_2010_COMPILER, PreprocessToAFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, PreprocessSuppressLineNumbers )
+PROPERTYNAME( XBOX360_2010_COMPILER, KeepComments )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableStringPooling )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableMinimalRebuild )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableCPPExceptions )
+PROPERTYNAME( XBOX360_2010_COMPILER, BasicRuntimeChecks )
+PROPERTYNAME( XBOX360_2010_COMPILER, RuntimeLibrary )
+PROPERTYNAME( XBOX360_2010_COMPILER, StructMemberAlignment )
+PROPERTYNAME( XBOX360_2010_COMPILER, BufferSecurityCheck )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableFunctionLevelLinking )
+PROPERTYNAME( XBOX360_2010_COMPILER, FloatingPointModel )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableFloatingPointExceptions )
+PROPERTYNAME( XBOX360_2010_COMPILER, DisableLanguageExtensions )
+PROPERTYNAME( XBOX360_2010_COMPILER, TreatWCHAR_TAsBuiltInType )
+PROPERTYNAME( XBOX360_2010_COMPILER, ForceConformanceInForLoopScope )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableRunTimeTypeInfo )
+PROPERTYNAME( XBOX360_2010_COMPILER, OpenMPSupport )
+PROPERTYNAME( XBOX360_2010_COMPILER, PrecompiledHeader )
+PROPERTYNAME( XBOX360_2010_COMPILER, PrecompiledHeaderFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, PrecompiledHeaderOutputFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, ExpandAttributedSource )
+PROPERTYNAME( XBOX360_2010_COMPILER, AssemblerOutput )
+PROPERTYNAME( XBOX360_2010_COMPILER, ASMListLocation )
+PROPERTYNAME( XBOX360_2010_COMPILER, ObjectFileName )
+PROPERTYNAME( XBOX360_2010_COMPILER, ProgramDatabaseFileName )
+PROPERTYNAME( XBOX360_2010_COMPILER, EnableBrowseInformation )
+PROPERTYNAME( XBOX360_2010_COMPILER, BrowseInformationFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, WarningLevel )
+PROPERTYNAME( XBOX360_2010_COMPILER, TreatWarningsAsErrors )
+PROPERTYNAME( XBOX360_2010_COMPILER, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_COMPILER, DebugInformationFormat )
+PROPERTYNAME( XBOX360_2010_COMPILER, CompileAs )
+PROPERTYNAME( XBOX360_2010_COMPILER, ForcedIncludeFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, ShowIncludes )
+PROPERTYNAME( XBOX360_2010_COMPILER, UndefineAllPreprocessorDefinitions )
+PROPERTYNAME( XBOX360_2010_COMPILER, UndefinePreprocessorDefinitions )
+PROPERTYNAME( XBOX360_2010_COMPILER, UseFullPaths )
+PROPERTYNAME( XBOX360_2010_COMPILER, OmitDefaultLibraryName )
+PROPERTYNAME( XBOX360_2010_COMPILER, TrapIntegerDividesOptimization )
+PROPERTYNAME( XBOX360_2010_COMPILER, PreschedulingOptimization )
+PROPERTYNAME( XBOX360_2010_COMPILER, InlineAssemblyOptimization )
+PROPERTYNAME( XBOX360_2010_COMPILER, RegisterReservation )
+PROPERTYNAME( XBOX360_2010_COMPILER, AnalyzeStalls )
+PROPERTYNAME( XBOX360_2010_COMPILER, CallAttributedProfiling )
+PROPERTYNAME( XBOX360_2010_COMPILER, SmallerTypeCheck )
+PROPERTYNAME( XBOX360_2010_COMPILER, DisableSpecificWarnings )
+PROPERTYNAME( XBOX360_2010_COMPILER, MultiProcessorCompilation )
+PROPERTYNAME( XBOX360_2010_COMPILER, UseUnicodeForAssemblerListing )
+PROPERTYNAME( XBOX360_2010_COMPILER, ForcedUsingFile )
+PROPERTYNAME( XBOX360_2010_COMPILER, DeduceVariableType )
+PROPERTYNAME( XBOX360_2010_COMPILER, CodeAnalysisForCCPP )
+PROPERTYNAME( XBOX360_2010_COMPILER, DisabledWarningDirectories )
+
+// Librarian
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, UseUNICODEResponseFiles )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, AdditionalDependencies )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, OutputFile )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, AdditionalLibraryDirectories )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, ModuleDefinitionFileName )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, IgnoreAllDefaultLibraries )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, IgnoreSpecificDefaultLibraries )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, ExportNamedFunctions )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, ForceSymbolReferences )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, LinkLibraryDependencies )
+PROPERTYNAME( XBOX360_2010_LIBRARIAN, AdditionalOptions )
+
+// Linker
+PROPERTYNAME( XBOX360_2010_LINKER, IgnoreImportLibrary )
+PROPERTYNAME( XBOX360_2010_LINKER, AdditionalOptions )
+PROPERTYNAME( XBOX360_2010_LINKER, AdditionalDependencies )
+PROPERTYNAME( XBOX360_2010_LINKER, ShowProgress )
+PROPERTYNAME( XBOX360_2010_LINKER, OutputFile )
+PROPERTYNAME( XBOX360_2010_LINKER, Version )
+PROPERTYNAME( XBOX360_2010_LINKER, EnableIncrementalLinking )
+PROPERTYNAME( XBOX360_2010_LINKER, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_LINKER, AdditionalLibraryDirectories )
+PROPERTYNAME( XBOX360_2010_LINKER, IgnoreAllDefaultLibraries )
+PROPERTYNAME( XBOX360_2010_LINKER, IgnoreSpecificDefaultLibraries )
+PROPERTYNAME( XBOX360_2010_LINKER, ModuleDefinitionFile )
+PROPERTYNAME( XBOX360_2010_LINKER, GenerateDebugInfo )
+PROPERTYNAME( XBOX360_2010_LINKER, GenerateProgramDatabaseFile )
+PROPERTYNAME( XBOX360_2010_LINKER, GenerateMapFile )
+PROPERTYNAME( XBOX360_2010_LINKER, MapFileName )
+PROPERTYNAME( XBOX360_2010_LINKER, MapExports )
+PROPERTYNAME( XBOX360_2010_LINKER, StackCommitSize )
+PROPERTYNAME( XBOX360_2010_LINKER, References )
+PROPERTYNAME( XBOX360_2010_LINKER, EnableCOMDATFolding )
+PROPERTYNAME( XBOX360_2010_LINKER, LinkTimeCodeGeneration )
+PROPERTYNAME( XBOX360_2010_LINKER, EntryPoint )
+PROPERTYNAME( XBOX360_2010_LINKER, NoEntryPoint )
+PROPERTYNAME( XBOX360_2010_LINKER, SetChecksum )
+PROPERTYNAME( XBOX360_2010_LINKER, BaseAddress )
+PROPERTYNAME( XBOX360_2010_LINKER, ImportLibrary )
+PROPERTYNAME( XBOX360_2010_LINKER, FixedBaseAddress )
+PROPERTYNAME( XBOX360_2010_LINKER, ErrorReporting )
+PROPERTYNAME( XBOX360_2010_LINKER, FunctionOrder )
+PROPERTYNAME( XBOX360_2010_LINKER, LinkLibraryDependencies )
+PROPERTYNAME( XBOX360_2010_LINKER, UseLibraryDependencyInputs )
+PROPERTYNAME( XBOX360_2010_LINKER, ForceSymbolReferences )
+PROPERTYNAME( XBOX360_2010_LINKER, StripPrivateSymbols )
+PROPERTYNAME( XBOX360_2010_LINKER, ProfileGuidedDatabase )
+PROPERTYNAME( XBOX360_2010_LINKER, MergeSections )
+PROPERTYNAME( XBOX360_2010_LINKER, AutomaticModuleDefinitionFile )
+
+// Browse Information
+PROPERTYNAME( XBOX360_2010_BROWSEINFORMATION, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_BROWSEINFORMATION, OutputFile )
+PROPERTYNAME( XBOX360_2010_BROWSEINFORMATION, AdditionalOptions )
+PROPERTYNAME( XBOX360_2010_BROWSEINFORMATION, PreserveSBRFiles )
+
+// Pre Build
+PROPERTYNAME( XBOX360_2010_PREBUILDEVENT, Description )
+PROPERTYNAME( XBOX360_2010_PREBUILDEVENT, CommandLine )
+PROPERTYNAME( XBOX360_2010_PREBUILDEVENT, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_2010_PREBUILDEVENT, UseInBuild )
+
+// Pre Link
+PROPERTYNAME( XBOX360_2010_PRELINKEVENT, Description )
+PROPERTYNAME( XBOX360_2010_PRELINKEVENT, CommandLine )
+PROPERTYNAME( XBOX360_2010_PRELINKEVENT, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_2010_PRELINKEVENT, UseInBuild )
+
+// Post Build
+PROPERTYNAME( XBOX360_2010_POSTBUILDEVENT, Description )
+PROPERTYNAME( XBOX360_2010_POSTBUILDEVENT, CommandLine )
+PROPERTYNAME( XBOX360_2010_POSTBUILDEVENT, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_2010_POSTBUILDEVENT, UseInBuild )
+
+// Custom Build
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, Description )
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, CommandLine )
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, AdditionalDependencies )
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, Outputs )
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, ExecuteAfter )
+PROPERTYNAME( XBOX360_2010_CUSTOMBUILDSTEP, ExecuteBefore )
+
+// Image Conversion
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, ConfigurationFile )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, OutputFile )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, TitleID )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, LANKey )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, BaseAddress )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, HeapSize )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, WorkspaceSize )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, AdditionalSections )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, ExportByName )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, OpticalDiscDriveMapping )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, PAL50Incompatible )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, MultidiscTitle )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, PreferBigButtonInput )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, CrossPlatformSystemLink )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, AllowAvatarGetMetadataByXUID )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, AllowControllerSwapping )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, RequireFullExperience )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, GameVoiceRequiredUI )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, KinectElevationControl )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, SkeletalTrackingRequirement )
+PROPERTYNAME( XBOX360_2010_XBOX360IMAGECONVERSION, AdditionalOptions )
+
+// Console Deployment
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, ExcludedFromBuild )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, SuppressStartupBanner )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, DeploymentFiles )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, Progress )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, ForceCopy )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, DeploymentType )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, DeploymentRoot )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, EmulationType )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, LayoutFile )
+PROPERTYNAME( XBOX360_2010_CONSOLEDEPLOYMENT, AdditionalOptions )
+
diff --git a/external/vpc/utils/vpc/projectscript.cpp b/external/vpc/utils/vpc/projectscript.cpp
new file mode 100644
index 0000000..a6402d2
--- /dev/null
+++ b/external/vpc/utils/vpc/projectscript.cpp
@@ -0,0 +1,2484 @@
+//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+#include "tier1/utldict.h"
+#include "tier1/keyvalues.h"
+#include "baseprojectdatacollector.h"
+
+#ifndef STEAM
+ bool V_StrSubstInPlace( char *pchInOut, int cchInOut, const char *pMatch, const char *pReplaceWith, bool bCaseSensitive )
+{
+ bool bRet = false;
+ char *pchT = (char *)malloc( cchInOut );
+ if ( V_StrSubst( pchInOut, pMatch, pReplaceWith, pchT, cchInOut, bCaseSensitive ) )
+ {
+ V_strncpy( pchInOut, pchT, cchInOut );
+ bRet = true;
+ }
+ free( pchT );
+ return bRet;
+}
+#endif
+
+void VPC_ParseFileSection( bool *pbHadConfigSection = NULL )
+{
+ if ( pbHadConfigSection )
+ *pbHadConfigSection = false;
+
+ while ( 1 )
+ {
+ const char *pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ if ( !V_stricmp( pToken, "$configuration" ) )
+ {
+ VPC_Keyword_FileConfiguration( );
+ if ( pbHadConfigSection )
+ *pbHadConfigSection = true;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_TrackSchemaFile
+//
+//-----------------------------------------------------------------------------
+
+void VPC_TrackSchemaFile( const char *pName, bool bRemove, const char *pFileFlag )
+{
+#ifdef STEAM
+ return;
+#else
+ if ( !bRemove && (!pFileFlag || !V_stristr( pFileFlag, "schema" )) )
+ {
+ // adding something that's not schema - ignore
+ return;
+ }
+
+ for ( int i = 0; i < g_pVPC->m_SchemaFiles.Count(); i++ )
+ {
+ if ( !g_pVPC->m_SchemaFiles[i].String() )
+ continue;
+
+ if ( !V_stricmp( pName, g_pVPC->m_SchemaFiles[i].String() ) )
+ {
+ if ( bRemove )
+ {
+ g_pVPC->m_SchemaFiles.Remove( i );
+ }
+ return;
+ }
+ }
+
+ if ( bRemove )
+ {
+ // not found, nothing to do
+ return;
+ }
+
+ g_pVPC->m_SchemaFiles.AddToTail( pName );
+
+ // suppress building of schematized cpp files
+ // (they get #included by an auto-generated cpp that is built instead)
+ const char *pExt = V_GetFileExtension(pName);
+ if ( pExt && !V_stricmp( pExt, "cpp" ) )
+ {
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+ g_pVPC->GetProjectGenerator()->FileIsSchema( true );
+ g_pVPC->GetProjectGenerator()->FileExcludedFromBuild( true );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ }
+
+#endif
+}
+
+static char *ResolveCandidate( const char *pszFile, const char *pszPlatform )
+{
+ char szPath[MAX_PATH];
+ char szPathExpanded[MAX_PATH];
+
+ V_ComposeFileName( g_pVPC->GetProjectPath(), pszFile, szPath, sizeof(szPath) );
+ Sys_ReplaceString( szPath, "$os", pszPlatform, szPathExpanded, sizeof(szPathExpanded) );
+ V_FixSlashes( szPathExpanded );
+ V_RemoveDotSlashes( szPathExpanded );
+ V_FixDoubleSlashes( szPathExpanded );
+
+ if ( Sys_Exists( szPathExpanded ) )
+ {
+ char *pszResolvedFilename = (char*)malloc( MAX_PATH );
+ Sys_ReplaceString( pszFile, "$os", pszPlatform, pszResolvedFilename, MAX_PATH );
+ return pszResolvedFilename;
+ }
+
+ return NULL;
+}
+
+// No particular order, but must not change without changing the arrPlatformChains matrix
+const char *g_szArrPlatforms[] =
+{
+ "win32", // 0
+ "win64", // 1
+ "osx32", // 2
+ "osx64", // 3
+ "linux32", // 4
+ "linux64", // 5
+ "cygwin", // 6
+ "ps3", // 7
+ "x360", // 8
+ "win", // 9
+ "osx", // 10
+ "linux", // 11
+ "posix", // 12
+ "any", // 13
+ NULL
+};
+
+//-----------------------------------------------------------------------------
+// ResolveFilename
+// Utility to expand $OS if present
+// Returns expanded filename to a file that exists on disk, or NULL otherwise
+// vecBonusFiles will contain a list of valid OS files that are on disk but did not
+// match the current target platform.
+//-----------------------------------------------------------------------------
+static char *ResolveFilename( const char *pszFile, CUtlVector<CUtlString> &vecBonusFiles )
+{
+ static const int k_lastRealPlatform = 8; // index, not count
+ static const int k_AnyPlatform = 13; // index
+
+ static const int arrPlatformChains[][9] =
+ {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, // the raw platforms
+ { 9, 9, 10, 10, 11, 11, 12, 12, 9 }, // first fallback
+ { 13, 13, 12, 12, 12, 12, 13, 13, 13 }, // 2nd fallback
+ { 13, 13, 13, 13, 13, 13, 13, 13, 13 }, // 3rd fallback
+ };
+
+ // Don't want the actual backing store to be const since we aren't compile-time init'ing,
+ // but it is single-instance initialized, so make a const ref to it that everyone except
+ // the init codes uses to make sure it doesn't get mucked with.
+ static bool bInited = false;
+ static char _szPlatformStore[128];
+ static const char (&szPlatform)[128] = _szPlatformStore;
+
+ if ( !bInited )
+ {
+ bInited = true;
+ const char *pszPlatform = g_pVPC->GetTargetPlatformName();
+ V_strncpy( _szPlatformStore, pszPlatform, sizeof( szPlatform ) );
+ V_strlower( _szPlatformStore );
+ }
+
+ vecBonusFiles.RemoveAll();
+
+ int nPlatformColumn = -1;
+ for ( int i = 0; i <= k_lastRealPlatform; i++ )
+ {
+ if ( V_strcmp( szPlatform, g_szArrPlatforms[i] ) == 0 )
+ {
+ nPlatformColumn = i;
+ break;
+ }
+ }
+
+ if ( nPlatformColumn < 0 )
+ {
+ g_pVPC->VPCWarning( "Internal Error: Target Platform: '%s' unrecognized while expanding $os!", szPlatform );
+ return NULL;
+ }
+
+ // Now walk the chain of potential platform matches from strongest to weakest
+ char *pszResolved = NULL;
+ int nPlatformToCheck = -1;
+ int nCurrentPlatformRow = -1;
+ do
+ {
+ nCurrentPlatformRow++;
+ nPlatformToCheck = arrPlatformChains[nCurrentPlatformRow][nPlatformColumn];
+ pszResolved = ResolveCandidate( pszFile, g_szArrPlatforms[ nPlatformToCheck ] );
+ if ( pszResolved )
+ break;
+ }
+ while ( arrPlatformChains[nCurrentPlatformRow][nPlatformColumn] != k_AnyPlatform );
+
+ // Now go pickup the any files that exist, but were non-matches
+ for ( int i = 0; g_szArrPlatforms[i] != NULL; i++ )
+ {
+ // Don't pick up the actual found platform
+ if ( i != nPlatformToCheck )
+ {
+ CUtlString file( ResolveCandidate( pszFile, g_szArrPlatforms[ i ] ) );
+ if ( !file.IsEmpty() )
+ vecBonusFiles.AddToTail( file );
+ }
+ }
+ return pszResolved;
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_AddFile
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_AddFilesByPattern()
+{
+ CUtlVector<CUtlString> files;
+
+ while ( 1 )
+ {
+ const char *pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ // Is this a conditional expression?
+ if ( pToken[0] == '[' )
+ {
+ if ( files.Count() == 0 )
+ {
+ g_pVPC->VPCSyntaxError( "Conditional specified on a $FilePattern without any pattern preceding it." );
+ }
+
+ if ( !g_pVPC->EvaluateConditionalExpression( pToken ) )
+ {
+ // we did all that work for no reason, time to bail out
+ return;
+ }
+ }
+
+ char szFilename[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( pToken, szFilename, sizeof( szFilename ) );
+
+ V_FixSlashes( szFilename );
+
+ CUtlVector< CUtlString > vecResults;
+ Sys_ExpandFilePattern( szFilename, vecResults );
+
+ for ( int i=0; i < vecResults.Count(); i++ )
+ {
+ g_pVPC->VPCStatus( false, "glob: adding '%s' to project", vecResults[i].String() );
+ g_pVPC->GetProjectGenerator()->StartFile( vecResults[i].String(), true );
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+ }
+
+}
+
+// forward decl we need in the add file code
+void VPC_Keyword_Folder( bool bUnity, const folderConfig_t *pInheritedFolderConfig = NULL );
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_AddFile
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_AddFile( const char *pFileFlag = NULL, const folderConfig_t *pFolderConfig = NULL )
+{
+ bool bAllowNextLine = false;
+ CUtlVector<CUtlString> files;
+ CUtlVector<CUtlString> unbuiltFiles;
+
+ bool bHasConditional = false;
+ while ( 1 )
+ {
+ const char *pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ // Is this a conditional expression?
+ if ( pToken[0] == '[' )
+ {
+ if ( files.Count() == 0 )
+ {
+ g_pVPC->VPCSyntaxError( "Conditional specified on a $File without any file preceding it." );
+ }
+
+ if ( !g_pVPC->EvaluateConditionalExpression( pToken ) )
+ {
+ // DO NOT INTEGRATE OR TAKE THIS TO STEAM
+ // Steam VPC differs in conditional handling inside grouped files
+ unbuiltFiles.AddToTail( files[files.Count() - 1] );
+ files.Remove( files.Count() - 1 );
+ //unbuiltFiles.AddMultipleToTail( files.Count(), files.Base() );
+ //files.RemoveAll();
+ }
+
+ bHasConditional = true;
+ continue;
+ }
+
+ char szFilename[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( pToken, szFilename, sizeof( szFilename ) );
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ V_FixSlashes( szFilename );
+
+ CUtlString string = szFilename;
+ files.AddToTail( string );
+
+ // check for another optional file
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+ }
+
+ // check for optional section
+ bool bHasSection = false;
+ const char *pToken = g_pVPC->GetScript().PeekNextToken( true );
+ if ( pToken && pToken[0] && !V_stricmp( pToken, "{" ) )
+ {
+ bHasSection = true;
+ }
+
+ // dynamic files need to opt out of strict file presence check
+ bool bDynamicFile = pFileFlag && V_stristr( pFileFlag, "dynamic" );
+
+ // need to check files early to handle possible rejected section
+ if ( g_pVPC->IsCheckFiles() && !bDynamicFile )
+ {
+ for ( int i=0; i<files.Count(); i++ )
+ {
+ const char *pFilename = files[i].String();
+ if ( !Sys_Exists( pFilename ) && !V_stristr( pFilename, "$os" ) )
+ {
+#if defined( POSIX )
+ // We have a _lot_ of vpc files that contain header files with the incorrect casing.
+ // So try to lowercase the filename here and if it exists, replace it and carry on.
+ //
+ CUtlString FileNameLower = files[ i ];
+
+ V_strlower( FileNameLower.Get() );
+ if( Sys_Exists( FileNameLower ) )
+ {
+ files[ i ] = FileNameLower;
+ continue;
+ }
+#endif
+
+ // Hack around all the libraries which are listed as $File instead of $Lib
+ const char* extension = strrchr( pFilename, '.' );
+ if ( !extension || stricmp( extension, ".lib" ) )
+ {
+ g_pVPC->VPCWarning( "File '%s' does not exist. Not adding to project.", pFilename );
+ g_pVPC->IncrementFileMissing();
+ files.Remove( i );
+ }
+ else
+ {
+ // don't complain about libs that contain $(Configuration) in their path
+ if ( !V_stristr( pFilename, "$(Configuration)" ) )
+ g_pVPC->VPCWarning( "Library '%s' does not exist. Adding to project anyway.", pFilename );
+ }
+ }
+ }
+ }
+
+ if ( g_pVPC->IsShowCaseIssues() && !bDynamicFile )
+ {
+ for ( int i = 0; i < files.Count(); i++ )
+ {
+ const char *pFilename = files[i].String();
+ char actualFilename[MAX_PATH];
+ if ( !Sys_IsFilenameCaseConsistent( pFilename, actualFilename, sizeof( actualFilename ) ) )
+ {
+ g_pVPC->VPCWarning( "Case Consistency Issue! File '%s' specified in '%s' is inconsistent with OS version '%s'.", pFilename, g_pVPC->GetProjectName(), actualFilename );
+
+ // need script stack to assist in tracking down missing file
+ g_pVPC->GetScript().SpewScriptStack();
+ }
+ }
+ }
+
+ if ( !files.Count() && bHasSection )
+ {
+ // optional section has been conditionally removed
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+
+ for ( int i=0; i < unbuiltFiles.Count(); i++ )
+ {
+ const char *pExcludedFilename = unbuiltFiles[i].String();
+
+ g_pVPC->GetProjectGenerator()->StartFile( pExcludedFilename, true );
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+ g_pVPC->GetProjectGenerator()->FileExcludedFromBuild( true );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+
+ if ( bHasSection )
+ {
+ // found optional section, parse opening brace
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+ }
+
+ // Handle $OS expansion
+ // save parser state
+ CScriptSource startingScriptSource = g_pVPC->GetScript().GetCurrentScript();
+
+ for ( int i=0; i<files.Count(); i++ )
+ {
+ const char *pFilename = files[i].String();
+
+ CUtlString filename;
+ if ( !g_pVPC->m_bInMkSlnPass && V_stristr( pFilename, "$os" ) )
+ {
+ CUtlVector< CUtlString > vecExcludedFiles;
+ filename = ResolveFilename( pFilename, vecExcludedFiles );
+ char rgchRejectList[4096]; rgchRejectList[0]='\0';
+ if ( vecExcludedFiles.Count() )
+ {
+ for ( int i=0; i<files.Count(); i++ )
+ {
+ V_strncat( rgchRejectList, files[i].String(), V_ARRAYSIZE( rgchRejectList ) );
+ V_strncat( rgchRejectList, ",", V_ARRAYSIZE( rgchRejectList ) );
+ }
+ }
+ g_pVPC->VPCStatus( false, "$OS: Resolved %s -> %s, rejected %s", pFilename, filename.String(), rgchRejectList );
+
+ if ( filename.IsEmpty() )
+ {
+ g_pVPC->VPCWarning( "$File %s did not resolve to an existing file, skipping!", pFilename );
+ continue;
+ }
+
+ for ( i=0; i < vecExcludedFiles.Count(); i++ )
+ {
+ const char *pExcludedFilename = vecExcludedFiles[i].String();
+ const char *pExcludedExtension = V_GetFileExtension( pExcludedFilename );
+ if ( !pExcludedExtension )
+ {
+ pExcludedExtension = "";
+ }
+ if ( pExcludedExtension && !V_stricmp( pExcludedExtension, "cpp" ) )
+ {
+ g_pVPC->VPCStatus( false, "excluding '%s' from build", pExcludedFilename );
+ g_pVPC->GetProjectGenerator()->StartFile( pExcludedFilename, true );
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+ g_pVPC->GetProjectGenerator()->FileExcludedFromBuild( true );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+ }
+
+ pFilename = filename.String();
+ }
+
+ bool bAdded = g_pVPC->GetProjectGenerator()->StartFile( pFilename, true );
+
+ if ( bDynamicFile )
+ {
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+ g_pVPC->GetProjectGenerator()->FileIsDynamic( true );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ }
+
+ // Lookup extension for a custom build script
+ const char *pExtension = V_GetFileExtension( pFilename );
+ if ( !pExtension )
+ {
+ pExtension = "";
+ }
+
+ if ( !g_pVPC->m_sUnityCurrent.IsEmpty() && !V_stricmp( pExtension, "cpp" ) && !bHasSection && !bHasConditional )
+ {
+ bool bEmitUnityFiles = ( !g_pVPC->m_bInMkSlnPass && ( g_pVPC->IsForceGenerate() || !g_pVPC->IsProjectCurrent( g_pVPC->GetOutputFilename(), false ) ) );
+ if ( bEmitUnityFiles )
+ {
+ // append to the unity file
+ g_pVPC->VPCStatus( false, "Unity: adding '%s' to unity file '%s'", pFilename, g_pVPC->m_sUnityCurrent.String() );
+ FILE *fp = fopen( g_pVPC->m_sUnityCurrent.String(), "at" );
+ if ( !fp )
+ {
+ g_pVPC->VPCError( "Cannot open %s for appending", g_pVPC->m_sUnityCurrent.String() );
+ }
+ else
+ {
+ char pFixedFilename[MAX_PATH];
+ V_strncpy( pFixedFilename, pFilename, sizeof(pFixedFilename) );
+ V_FixSlashes( pFixedFilename, '/' );
+ fprintf( fp, "#include \"%s\"\n", pFixedFilename );
+ fclose( fp );
+ }
+ }
+
+ g_pVPC->VPCStatus( false, "Unity: excluding '%s' from build", pFilename );
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), true );
+ g_pVPC->GetProjectGenerator()->FileExcludedFromBuild( true );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ }
+ else
+ {
+ bool bHadConfigSection = false;
+
+ int index = g_pVPC->m_CustomBuildSteps.Find( pExtension );
+ if ( g_pVPC->m_CustomBuildSteps.IsValidIndex( index ) )
+ {
+ CUtlString buildsteps = g_pVPC->m_CustomBuildSteps[index];
+ const char *pBuffer = buildsteps.Get();
+
+ CUtlString scriptName;
+ scriptName = pExtension;
+ scriptName += " custom build step";
+
+ // save parser state
+ g_pVPC->GetScript().PushScript( g_pVPC->GetScript().GetName(), pBuffer );
+
+ // parse injected buildstep
+ VPC_ParseFileSection( &bHadConfigSection );
+
+ // restore parser state
+ g_pVPC->GetScript().PopScript();
+ g_pVPC->GetScript().RestoreScript( startingScriptSource );
+ }
+
+ // apply optional section to each file
+ if ( bHasSection && bAdded )
+ {
+ // restore parser state
+ g_pVPC->GetScript().RestoreScript( startingScriptSource );
+ VPC_ParseFileSection( &bHadConfigSection );
+ }
+
+ // if this file doesn't have a file-specific config, but the folder we're in has a config
+ // apply that folder config to the file here
+ if ( !bHadConfigSection && pFolderConfig )
+ VPC_ApplyFolderConfigurationToFile( *pFolderConfig );
+
+ }
+
+ VPC_TrackSchemaFile( pFilename, false, pFileFlag );
+
+ if ( bAdded )
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+}
+
+// parse a list of filenames from the current token, handling conditionals, macro expansion, \\, fixslashes, etc
+static void VPC_ParseFileList( CUtlStringList &files )
+{
+ bool bAllowNextLine = false;
+
+ while ( 1 )
+ {
+ const char *pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ const char *pNextToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( !pNextToken || !pNextToken[0] )
+ {
+ // current token is last token
+ // last token can be optional conditional, need to identify
+ // backup and reparse up to last token
+ if ( pToken && pToken[0] == '[' )
+ {
+ if ( files.Count() == 0 )
+ {
+ g_pVPC->VPCSyntaxError( "Conditional specified on a file list without any file preceding it." );
+ }
+ // last token is an optional conditional
+ bool bResult = g_pVPC->EvaluateConditionalExpression( pToken );
+ if ( !bResult ) // was conditional false?
+ {
+ files.PurgeAndDeleteElements();
+ }
+ return;
+ }
+ }
+
+ char szFilename[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( pToken, szFilename, sizeof( szFilename ) );
+ V_FixSlashes( szFilename );
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ files.CopyAndAddToTail( szFilename );
+
+ // check for another optional file
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+ }
+}
+
+// add or remove .lib or dll import files, automatically adding prefixes and suffices to the name
+static void VPC_HandleLibraryExpansion( char const *pDefaultPath, char const *pFileNamePrefix, char const *pSuffix, bool bRemove )
+{
+ if ( !pFileNamePrefix )
+ {
+ pFileNamePrefix = "";
+ }
+ char szResolvedFilePrefix[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( pFileNamePrefix, szResolvedFilePrefix, sizeof(szResolvedFilePrefix) );
+
+ CUtlStringList impFiles;
+ VPC_ParseFileList( impFiles );
+ for( int i = 0; i < impFiles.Count(); i++ )
+ {
+ char szFilename[MAX_PATH];
+ char const *pPathPrefixToUse = pDefaultPath;
+
+ // do not add the path prefix if the filename contains path information already, or if null was passed.
+ char impFile[MAX_PATH];
+ V_strncpy( impFile, impFiles[i], sizeof( impFile ) );
+ V_RemoveDotSlashes( impFile );
+
+ char *pLastSlash = (char*)MAX( strrchr( impFile, '\\' ), strrchr( impFile, '/' ) );
+ if ( pLastSlash )
+ {
+ *pLastSlash = 0;
+ const char *pFilenamePart = pLastSlash + 1;
+ // don't prepend the prefix if the filename already starts with it
+ bool bAddPrefix = true;
+ if ( V_strlen(szResolvedFilePrefix) && !V_strnicmp( pFilenamePart, szResolvedFilePrefix, V_strlen(szResolvedFilePrefix) ) )
+ bAddPrefix = false;
+ sprintf( szFilename, "%s/%s%s%s", impFile, bAddPrefix ? pFileNamePrefix : "", pFilenamePart, pSuffix );
+ }
+ else
+ {
+ bool bAddPrefix = true;
+ if ( V_strlen(szResolvedFilePrefix) && !V_strnicmp( impFiles[i], szResolvedFilePrefix, V_strlen(szResolvedFilePrefix) ) )
+ bAddPrefix = false;
+ sprintf( szFilename, "%s%s%s%s", pPathPrefixToUse, bAddPrefix ? pFileNamePrefix : "", impFiles[i], pSuffix );
+ }
+
+ char szFilename1[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( szFilename, szFilename1, sizeof( szFilename1 ) );
+
+ // Replace forward slashes with backslashes regardless of target platform
+ V_FixSlashes( szFilename1 );
+ V_RemoveDotSlashes( szFilename1 );
+
+ if ( bRemove )
+ {
+ bool bSucc = g_pVPC->GetProjectGenerator()->RemoveFile( szFilename1 );
+ if ( !bSucc )
+ {
+ g_pVPC->VPCError( "Broken $implib command. Failed to remove file %s from project.", szFilename1 );
+ }
+ }
+ else
+ {
+ bool bAdded = g_pVPC->GetProjectGenerator()->StartFile( szFilename1, true );
+ if ( !bAdded )
+ {
+ g_pVPC->VPCError( "couldn't add %s", szFilename1 );
+ }
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+ }
+}
+
+enum EVPCKeywordFlag
+{
+ k_eVPCKeywordFlag_Remove = 0x00000001,
+ k_eVPCKeywordFlag_External = 0x00000002,
+};
+
+static void VPC_Keyword_ImportLibrary( uint32 Flags )
+{
+ char const *pSuffix = "$_IMPLIB_EXT";
+ bool bRemove = !!(Flags & k_eVPCKeywordFlag_Remove );
+
+ if( ( Flags & k_eVPCKeywordFlag_External ) &&
+ g_pVPC->FindOrCreateMacro( "_EXTERNAL_IMPLIB_EXT", false, NULL ) )
+ {
+ pSuffix = "$_EXTERNAL_IMPLIB_EXT";
+ }
+
+ VPC_HandleLibraryExpansion( "$LIBPUBLIC\\", "$_IMPLIB_PREFIX", pSuffix, bRemove );
+}
+
+static void VPC_Keyword_LinkerLibrary( uint32 Flags )
+{
+ char const *pSuffix = "$_STATICLIB_EXT";
+ bool bRemove = !!(Flags & k_eVPCKeywordFlag_Remove );
+
+ if( ( Flags & k_eVPCKeywordFlag_External ) &&
+ g_pVPC->FindOrCreateMacro( "_EXTERNAL_STATICLIB_EXT", false, NULL ) )
+ {
+ pSuffix = "$_EXTERNAL_STATICLIB_EXT";
+ }
+
+ VPC_HandleLibraryExpansion( "$LIBPUBLIC\\", "$_STATICLIB_PREFIX", pSuffix, bRemove );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_RemoveFile
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_RemoveFile()
+{
+ CUtlStringList filesToRemove;
+ VPC_ParseFileList( filesToRemove );
+ for ( int i = 0; i < filesToRemove.Count(); i++ )
+ {
+ bool bSucc = g_pVPC->GetProjectGenerator()->RemoveFile( filesToRemove[i] );
+ if ( !bSucc )
+ {
+ g_pVPC->VPCWarning( "Failed to remove file %s from project", filesToRemove[i] );
+ }
+
+ VPC_TrackSchemaFile( filesToRemove[i], true, NULL );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Folder
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_Folder( bool bUnity, const folderConfig_t *pInheritedFolderConfig /* = NULL */ )
+{
+ const char *pToken;
+ char folderName[MAX_PATH];
+ folderConfig_t folderConfig;
+
+ // by default, our active config is any config that we inherited from the parent.
+ const folderConfig_t *pActiveFolderConfig = pInheritedFolderConfig;
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, folderName, sizeof( folderName ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+
+ g_pVPC->GetProjectGenerator()->StartFolder( folderName );
+
+ bool bEmitUnityFiles = ( !g_pVPC->m_bInMkSlnPass && ( g_pVPC->IsForceGenerate() || !g_pVPC->IsProjectCurrent( g_pVPC->GetOutputFilename(), false ) ) );
+ if ( bUnity )
+ {
+ // generate a .cpp file from the folderName
+ char unityName[MAX_PATH];
+ V_snprintf( unityName, sizeof(unityName), "%s_%s_unity.cpp", folderName, g_pVPC->GetProjectName() );
+ V_StrSubstInPlace( unityName, sizeof(unityName), " ", "_", false );
+
+ // make sure we have a unique file name, we don't want to tread on another projects unity
+ g_pVPC->m_sUnityCurrent = unityName;
+ int cAttempt = 1;
+ while ( g_pVPC->m_UnityFilesSeen.Find( g_pVPC->m_sUnityCurrent ) != g_pVPC->m_UnityFilesSeen.InvalidIndex() )
+ {
+ V_snprintf( unityName, sizeof(unityName), "%s_%s_unity_%d.cpp", folderName, g_pVPC->GetProjectName(), ++cAttempt );
+ V_StrSubstInPlace( unityName, sizeof(unityName), " ", "_", false );
+ g_pVPC->m_sUnityCurrent = unityName;
+ }
+
+ g_pVPC->m_UnityStack.Push( g_pVPC->m_sUnityCurrent );
+
+ if ( bEmitUnityFiles )
+ {
+ g_pVPC->VPCStatus( false, "Unity: emitting '%s' in project: '%s'", unityName, g_pVPC->GetProjectName() );
+
+ // always add the stdafx.h at the top (if we're using a precompiled header, what if we're not?)
+ FILE *fp = fopen( g_pVPC->m_sUnityCurrent.String(), "wt" );
+ if ( !fp )
+ {
+ g_pVPC->VPCError( "Cannot open %s for writing", g_pVPC->m_sUnityCurrent.String() );
+ }
+ else
+ {
+ const char *pStdAfx = g_pVPC->GetMacroValue( "STDAFX" );
+ if ( pStdAfx && *pStdAfx )
+ {
+ fprintf( fp, "#include \"%s\"\n", pStdAfx );
+ }
+ fclose( fp );
+ }
+ }
+
+ g_pVPC->m_UnityFilesSeen.Insert( g_pVPC->m_sUnityCurrent );
+
+ // Msg( "pushing unity file %s\n", g_sUnityCurrent );
+ g_pVPC->GetProjectGenerator()->StartFile( g_pVPC->m_sUnityCurrent, true );
+ g_pVPC->GetProjectGenerator()->EndFile();
+ }
+
+ // Now parse all the files and subfolders..
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // pop
+ break;
+ }
+ else if ( !V_stricmp( pToken, "$file" ) || !V_stricmp( pToken, "$schemafile" ) || !V_stricmp( pToken, "$entschemafile" ) )
+ {
+ // add file
+ VPC_Keyword_AddFile( NULL, pActiveFolderConfig );
+ }
+ else if ( !V_stricmp( pToken, "$DynamicFile" ) )
+ {
+ // add file
+ VPC_Keyword_AddFile( "dynamic", pActiveFolderConfig );
+ }
+ else if ( !V_stricmp( pToken, "$FilePattern" ) )
+ {
+ // glob the given pattern, add all files
+ VPC_Keyword_AddFilesByPattern();
+ }
+// THIS IS A LEGACY INCORRECT IMPLEMENTATION
+// else if ( !V_stricmp( pToken, "$schemafile" ) )
+// {
+// // add file
+// VPC_Keyword_AddFile( "schema" );
+// }
+ else if ( !V_stricmp( pToken, "$implib" ) ||
+ !V_stricmp( pToken, "$implibexternal" ) ||
+ !V_stricmp( pToken, "-$implib" ) ||
+ !V_stricmp( pToken, "-$implibexternal" ) )
+ {
+ uint32 KeywordFlags = ( pToken[ 0 ] == '-' ) ? k_eVPCKeywordFlag_Remove : 0;
+
+ if( V_stristr( pToken, "external" ) )
+ KeywordFlags |= k_eVPCKeywordFlag_External;
+
+ VPC_Keyword_ImportLibrary( KeywordFlags );
+ }
+ else if ( !V_stricmp( pToken, "$lib" ) ||
+ !V_stricmp( pToken, "$libexternal" ) ||
+ !V_stricmp( pToken, "-$lib" ) ||
+ !V_stricmp( pToken, "-$libexternal" ) )
+ {
+ uint32 KeywordFlags = ( pToken[ 0 ] == '-' ) ? k_eVPCKeywordFlag_Remove : 0;
+
+ if( V_stristr( pToken, "external" ) )
+ KeywordFlags |= k_eVPCKeywordFlag_External;
+
+ VPC_Keyword_LinkerLibrary( KeywordFlags );
+ }
+ else if ( !V_stricmp( pToken, "-$file" ) )
+ {
+ // remove file
+ VPC_Keyword_RemoveFile();
+ }
+ else if ( !V_stricmp( pToken, "$folder" ) )
+ {
+ // descend into subdirectory
+ VPC_Keyword_Folder( false, pActiveFolderConfig );
+ }
+ else if ( !V_stricmp( pToken, "$unity" ) )
+ {
+ VPC_Keyword_Folder( g_pVPC->IsUnity(), pActiveFolderConfig );
+ }
+ else if ( !V_stricmp( pToken, "$configuration" ) )
+ {
+ // read the folder-specific configuration.
+ VPC_Keyword_FolderConfiguration( &folderConfig );
+
+ // if we found a new config section, make it active and apply it to subsequent files
+ if ( folderConfig.BHasConfig() )
+ pActiveFolderConfig = &folderConfig;
+ else
+ pActiveFolderConfig = NULL;
+ }
+ else
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+
+ if ( bUnity )
+ {
+ // Msg( "popping unity file %s\n", g_sUnityCurrent );
+ g_pVPC->m_UnityStack.Pop();
+
+ if ( g_pVPC->m_UnityStack.Count() == 0 )
+ g_pVPC->m_sUnityCurrent = NULL;
+ else
+ g_pVPC->m_sUnityCurrent = g_pVPC->m_UnityStack.Top();
+ }
+ g_pVPC->GetProjectGenerator()->EndFolder();
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Shaders
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_Shaders( int depth )
+{
+ const char *pToken;
+ char shadersName[MAX_PATH];
+ CUtlBuffer vpcBuffer;
+ CUtlVector< CUtlString > fxcList;
+ CUtlVector< CUtlString > vshList;
+ CUtlVector< CUtlString > pshList;
+ CUtlVector< CUtlString > vfxList;
+ CUtlVector< CUtlString > otherList;
+ int i;
+ bool bIgnoreRedundancyWarning;
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, shadersName, sizeof( shadersName ) ) )
+ {
+ return;
+ }
+
+ g_pVPC->VPCStatus( false, "Parsing: %s", shadersName );
+ g_pVPC->GetScript().PushScript( shadersName );
+
+ // parse the shader list file into types (fxc,vsh,psh)
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ // end of file
+ break;
+ }
+
+ if ( V_stristr( pToken, ".fxc" ) )
+ {
+ fxcList.AddToTail( pToken );
+ }
+ else if ( V_stristr( pToken, ".vsh" ) )
+ {
+ vshList.AddToTail( pToken );
+ }
+ else if ( V_stristr( pToken, ".psh" ) )
+ {
+ pshList.AddToTail( pToken );
+ }
+ else if ( V_stristr( pToken, ".vfx" ) )
+ {
+ vfxList.AddToTail( pToken );
+ }
+ else
+ {
+ otherList.AddToTail( pToken );
+ }
+ }
+
+ g_pVPC->GetScript().PopScript();
+
+ if ( !fxcList.Count() &&
+ !vshList.Count() &&
+ !pshList.Count() &&
+ !vfxList.Count() &&
+ !otherList.Count() )
+ {
+ g_pVPC->VPCWarning( "No shaders found in %s", shadersName );
+ return;
+ }
+
+ // generate a vpc compatible file to generate the shader file hierarchy
+ vpcBuffer.SetBufferType( true, true );
+ vpcBuffer.Printf( "$Folder \"Shader Source\" \n" );
+ vpcBuffer.Printf( "{\n" );
+
+ // add the shader file as a convienence
+ vpcBuffer.Printf( "$file \"%s\"\n", shadersName );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+
+ // fxc files
+ if ( fxcList.Count() )
+ {
+ vpcBuffer.Printf( "$Folder \"fxc\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ for ( i=0; i<fxcList.Count(); i++ )
+ {
+ vpcBuffer.Printf( "$file \"%s\"\n", fxcList[i].String() );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+ }
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ // vsh files
+ if ( vshList.Count() )
+ {
+ vpcBuffer.Printf( "$Folder \"vsh\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ for ( i=0; i<vshList.Count(); i++ )
+ {
+ vpcBuffer.Printf( "$file \"%s\"\n", vshList[i].String() );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+ }
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ // psh files
+ if ( pshList.Count() )
+ {
+ vpcBuffer.Printf( "$Folder \"psh\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ for ( i=0; i<pshList.Count(); i++ )
+ {
+ vpcBuffer.Printf( "$file \"%s\"\n", pshList[i].String() );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+ }
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ // vfx files
+ if ( vfxList.Count() )
+ {
+ vpcBuffer.Printf( "$Folder \"vfx\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ for ( i=0; i<vfxList.Count(); i++ )
+ {
+ vpcBuffer.Printf( "$file \"%s\"\n", vfxList[i].String() );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+ }
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ // other files
+ if ( otherList.Count() )
+ {
+ // psh files
+ vpcBuffer.Printf( "$Folder \"other\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ for ( i=0; i<otherList.Count(); i++ )
+ {
+ vpcBuffer.Printf( "$file \"%s\"\n", otherList[i].String() );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$Configuration\n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf( "$ExcludedFromBuild \"Yes\"\n" );
+ vpcBuffer.Printf( "}\n" );
+ vpcBuffer.Printf( "}\n" );
+ }
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ // end of shader folder
+ vpcBuffer.Printf( "}\n" );
+
+ // save parser
+ bIgnoreRedundancyWarning = g_pVPC->IsIgnoreRedundancyWarning();
+ g_pVPC->SetIgnoreRedundancyWarning( true );
+
+ g_pVPC->GetScript().PushScript( "Internal List", (char*)vpcBuffer.Base() );
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( pToken && pToken[0] && !V_stricmp( pToken, "$folder" ) )
+ {
+ VPC_Keyword_Folder( false );
+ }
+
+ // restore parser
+ g_pVPC->GetScript().PopScript();
+ g_pVPC->SetIgnoreRedundancyWarning( bIgnoreRedundancyWarning );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Macro
+//
+//-----------------------------------------------------------------------------
+enum MacroType_t { VPC_MACRO_VALUE, VPC_MACRO_EMPTY_STRING };
+void VPC_Keyword_Macro( MacroType_t eMacroType )
+{
+ const char *pToken;
+ char macro[MAX_SYSTOKENCHARS];
+ char value[MAX_SYSTOKENCHARS];
+
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+ strcpy( macro, pToken );
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, value, sizeof( value ) ) )
+ {
+ return;
+ }
+
+ char environmentValue[MAX_SYSTOKENCHARS];
+ if ( Sys_EvaluateEnvironmentExpression( value, "", environmentValue, sizeof( environmentValue ) ) )
+ {
+ V_strncpy( value, environmentValue, sizeof( value ) );
+ }
+
+ g_pVPC->FindOrCreateMacro( macro, true, ( eMacroType == VPC_MACRO_VALUE ) ? value : "" );
+}
+
+//-----------------------------------------------------------------------------
+// $MacroRequired <Macro> [DefaultValue] [Condition]
+// $MacroRequiredAllowEmpty <Macro> [DefaultValue] [Condition]
+//
+// Forces a script to error if a macro that it depends on was not set.
+// The Default will be used if the macro was not defined, otherwise error.
+// This is to allow a required macro in a base script to have a concept
+// of a default initialization value.
+//-----------------------------------------------------------------------------
+enum MacroRequiredType_t { VPC_MACRO_REQUIRED_NOT_EMPTY, VPC_MACRO_REQUIRED_ALLOW_EMPTY };
+void VPC_Keyword_MacroRequired( MacroRequiredType_t eMacroRequiredType )
+{
+ char macroName[MAX_SYSTOKENCHARS];
+ char macroDefaultValue[MAX_SYSTOKENCHARS];
+ const char *pToken;
+
+ macroDefaultValue[0] = '\0';
+
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ strcpy( macroName, pToken );
+
+ // optional default macro value or conditional
+ pToken = g_pVPC->GetScript().PeekNextToken( false );
+ if ( pToken && pToken[0] )
+ {
+ if ( pToken[0] == '[' )
+ {
+ // evaulate argument as conditional
+ if ( !g_pVPC->EvaluateConditionalExpression( pToken ) )
+ {
+ return;
+ }
+ }
+ else
+ {
+ // argument is a default macro value
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, macroDefaultValue, sizeof( macroDefaultValue ) ) )
+ {
+ return;
+ }
+ }
+ }
+
+ // find macro, needs to be present and non-empty
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( macroName, false, NULL );
+ if ( !pMacro || ( eMacroRequiredType == VPC_MACRO_REQUIRED_NOT_EMPTY && !strlen( pMacro->value.String() ) ) )
+ {
+ if ( macroDefaultValue[0] || ( eMacroRequiredType == VPC_MACRO_REQUIRED_ALLOW_EMPTY ) )
+ {
+ g_pVPC->FindOrCreateMacro( macroName, true, macroDefaultValue );
+ }
+ else
+ {
+ // In case we're in mksln showing a pacifier of dots. Make sure to show the error on a new line.
+ g_pVPC->VPCSyntaxError( "\n\nRequired Macro '%s', not defined or empty", macroName );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_LoadAddressMacro
+//
+// $LoadAddressMacro <MacroName>
+// {
+// <ProjectName> <BaseAddress>
+// }
+//
+// Specialized instruction to populate the load address macro based on a project
+// name.
+//-----------------------------------------------------------------------------
+void VPC_Keyword_LoadAddressMacro( void )
+{
+ char szProjectName[MAX_SYSTOKENCHARS];
+ char szMacroName[MAX_SYSTOKENCHARS];
+ char szBaseAddress[MAX_SYSTOKENCHARS];
+ const char *pToken;
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, szMacroName, sizeof( szMacroName ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ break;
+ }
+ strcpy( szProjectName, pToken );
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ break;
+ }
+ else
+ {
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, szBaseAddress, sizeof( szBaseAddress ) ) )
+ {
+ continue;
+ }
+
+ if ( !V_stricmp( szProjectName, g_pVPC->GetLoadAddressName() ) )
+ {
+ // set Macro
+ g_pVPC->FindOrCreateMacro( szMacroName, true, szBaseAddress );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_LoadAddressMacroAlias
+//
+// $LoadAddressMacroAlias <Alias>
+// {
+// <ProjectName>
+// }
+//
+// When evaluating $LoadAddressMacro/$LoadAddressMacroAuto, substitute all listed <ProjectName> entries with <Alias>
+//-----------------------------------------------------------------------------
+void VPC_Keyword_LoadAddressMacroAlias( void )
+{
+ char szProjectName[MAX_SYSTOKENCHARS];
+ char szAlias[MAX_SYSTOKENCHARS];
+ const char *pToken;
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, szAlias, sizeof( szAlias ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ break;
+ }
+ strcpy( szProjectName, pToken );
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ break;
+ }
+ else
+ {
+ if ( !V_stricmp( szProjectName, g_pVPC->GetProjectName() ) )
+ {
+ // set Macro and alias
+ g_pVPC->FindOrCreateMacro( "LOADADDRESSNAME", true, szAlias );
+ g_pVPC->SetLoadAddressName( szAlias );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Internal_LoadAddressMacroAuto
+//
+// bPad - Differentiate between $LoadAddressMacroAuto and $LoadAddressMacroAuto_Padded
+// implementations
+//
+// Specialized instruction to populate the load address macro based on a project
+// name.
+//-----------------------------------------------------------------------------
+void Internal_LoadAddressMacroAuto( bool bPad )
+{
+ char szProjectName[MAX_SYSTOKENCHARS];
+ char szMacroName[MAX_SYSTOKENCHARS];
+ char szBaseAddress[MAX_SYSTOKENCHARS];
+ char szLength[MAX_SYSTOKENCHARS];
+ const char *pToken;
+
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ strcpy( szMacroName, pToken );
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, szBaseAddress, sizeof( szBaseAddress ) ) )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+ unsigned int baseAddress = 0;
+ sscanf( szBaseAddress, "%x", &baseAddress );
+ unsigned int iInitialBaseAddress = baseAddress;
+
+ macro_t *pMacro = NULL;
+ int iSetEntryNum = 0;
+ int iSetBaseAddress = 0;
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ int iEntryNum = 0;
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ break;
+ }
+ strcpy( szProjectName, pToken );
+
+ if ( !V_stricmp( szProjectName, g_pVPC->GetLoadAddressName() ) )
+ {
+ // set Macro
+ char szMacroValue[MAX_SYSTOKENCHARS];
+ sprintf( szMacroValue, "0x%8.8x", baseAddress );
+
+ iSetEntryNum = iEntryNum;
+ iSetBaseAddress = baseAddress;
+ pMacro = g_pVPC->FindOrCreateMacro( szMacroName, true, szMacroValue );
+ }
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ break;
+ }
+ else
+ {
+ unsigned int dllLength = 0;
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, szLength, sizeof( szLength ) ) )
+ {
+ continue;
+ }
+ if ( strstr( szLength, "." ) )
+ {
+ // assume float format
+ float fLength = 0;
+ sscanf( szLength, "%f", &fLength );
+ dllLength = fLength * 1024.0f * 1024.0f;
+ }
+ else
+ {
+ sscanf( szLength, "%d", &dllLength );
+ }
+
+ if ( !bPad )
+ {
+ dllLength = AlignValue( dllLength, 64 * 1024 ); //will align later when we actually set the darn thing
+ }
+
+ if ( dllLength == 0 )
+ {
+ g_pVPC->VPCSyntaxError( "$LoadAddressMacroAuto no longer supports 0 size dlls. Use $LoadAddressMacroAlias to have two orthogonal projects load in the same space" );
+ }
+
+ baseAddress += dllLength;
+ }
+
+ ++iEntryNum;
+ }
+
+ if ( bPad && pMacro )
+ {
+ unsigned int iEndAddress;
+ if ( (iInitialBaseAddress >= 0x82000000) && (iInitialBaseAddress < 0x8C000000) )
+ {
+ iEndAddress = 0x8BFFFFFF;
+ }
+ else
+ {
+ iEndAddress = 0x9BFFFFFF;
+ }
+
+ // compute leftover unused address space
+ unsigned int iRemainingSpace = iEndAddress - baseAddress;
+
+ int iPadPerEntry = iRemainingSpace / iEntryNum;
+ //iPadPerEntry = iPadPerEntry & ~(64 * 1024); //align DOWN to 64k
+ if ( iPadPerEntry > 0 )
+ {
+ // set the base address again with padding added
+ iSetBaseAddress += iPadPerEntry * iSetEntryNum;
+ iSetBaseAddress = AlignValue( iSetBaseAddress, 64 * 1024 );
+
+ char szMacroValue[MAX_SYSTOKENCHARS];
+ sprintf( szMacroValue, "0x%8.8x", iSetBaseAddress );
+
+ pMacro->value = szMacroValue;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_LoadAddressMacroAuto
+//
+// $LoadAddressMacroAuto <MacroName> <BaseAddress>
+// {
+// <ProjectName> <Length>
+// }
+//
+// Specialized instruction to populate the load address macro based on a project
+// name.
+//-----------------------------------------------------------------------------
+void VPC_Keyword_LoadAddressMacroAuto( void )
+{
+ Internal_LoadAddressMacroAuto( false );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_LoadAddressMacroAuto_Padded
+//
+// $LoadAddressMacroAuto_Padded <MacroName> <BaseAddress>
+// {
+// <ProjectName> <Length>
+// }
+//
+// Specialized instruction to populate the load address macro based on a project
+// name. Assumes the contained list is minimally packed and has free reign of
+// space up to the limit. Finds unused space spreads it out evenly between
+// each project
+//-----------------------------------------------------------------------------
+void VPC_Keyword_LoadAddressMacroAuto_Padded( void )
+{
+ Internal_LoadAddressMacroAuto( true );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_SharedKeyword_Conditional
+// $Conditional "CONDITIONNAME" "VALUE"
+//
+// Sets a conditional that can be used later in the script to affect later keywords.
+// This works in both project and group scripts.
+//-----------------------------------------------------------------------------
+void VPC_SharedKeyword_Conditional()
+{
+ const char *pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ char name[MAX_SYSTOKENCHARS];
+ if ( pToken[0] == '$' )
+ {
+ // being nice to users, quietly remove the unwanted conditional prefix '$'
+ pToken++;
+ }
+ strcpy( name, pToken );
+
+ char value[MAX_SYSTOKENCHARS];
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, value, sizeof( value ) ) )
+ {
+ return;
+ }
+
+ conditional_t *pConditional = g_pVPC->FindOrCreateConditional( name, true, CONDITIONAL_CUSTOM );
+ if ( pConditional->type != CONDITIONAL_CUSTOM )
+ {
+ // scripts cannot change any platform or game conditionals
+ g_pVPC->VPCSyntaxError( "$Conditional cannot be used on the reserved '$%s'", pConditional->upperCaseName.Get() );
+ }
+
+ char environmentValue[MAX_SYSTOKENCHARS];
+ if ( Sys_EvaluateEnvironmentExpression( value, "0", environmentValue, sizeof( environmentValue ) ) )
+ {
+ V_strncpy( value, environmentValue, sizeof( value ) );
+ }
+
+ g_pVPC->SetConditional( name, Sys_StringToBool( value ) );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_IgnoreRedundancyWarning
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_IgnoreRedundancyWarning( void )
+{
+ char value[MAX_SYSTOKENCHARS];
+
+ if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, value, sizeof( value ) ) )
+ {
+ return;
+ }
+
+ bool bVal = Sys_StringToBool( value );
+ g_pVPC->SetIgnoreRedundancyWarning( bVal );
+}
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Linux
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_Linux( void )
+{
+ // always ignore everything in this block
+ // parsed and processed by a different tool
+ g_pVPC->GetScript().SkipBracedSection();
+}
+
+void VPC_PrepareToReadScript( const char *pInputScriptName, int depth, bool bQuiet, char* &pScriptBuffer, char szScriptName[MAX_PATH] )
+{
+ if ( !depth )
+ {
+ // startup initialization
+ g_pVPC->GetProjectGenerator()->StartProject();
+ }
+
+ V_strncpy( szScriptName, pInputScriptName, MAX_PATH );
+ V_FixSlashes( szScriptName );
+
+ // always spew the root script
+ if ( !bQuiet )
+ {
+ bool bSpew = ( depth == 0 );
+ g_pVPC->VPCStatus( bSpew, "Parsing: %s", szScriptName );
+ }
+
+ // parse the text script
+ if ( !Sys_Exists( szScriptName ) )
+ {
+ g_pVPC->VPCError( "Cannot open %s", szScriptName );
+ }
+
+ // load it with the file expansions to compute it's CRC, so we notice if new matching files appear on disk
+ // and regenerate the project correctly.
+ int scriptLen = Sys_LoadTextFileWithIncludes( szScriptName, &pScriptBuffer, true );
+ if ( scriptLen < 0 )
+ {
+ // unexpected due to existence check
+ g_pVPC->VPCError( "Cannot open %s", szScriptName );
+ }
+
+ g_pVPC->AddScriptToCRCCheck( szScriptName, CRC32_ProcessSingleBuffer( pScriptBuffer, scriptLen ) );
+
+ delete pScriptBuffer;
+ Sys_LoadTextFileWithIncludes( szScriptName, &pScriptBuffer, false );
+
+ g_pVPC->GetScript().PushScript( szScriptName, pScriptBuffer );
+}
+
+//-----------------------------------------------------------------------------
+// Adds the current VPC file to the 'VPC Script' file, setting all the
+// custom builds steps needed to verify the .vcproj is up to date
+//-----------------------------------------------------------------------------
+void VPC_AddCurrentVPCScriptToProjectFolder( bool bDoCRCCheck )
+{
+ // skip including VPC scripts if NOVPC is defined
+ if( g_pVPC->EvaluateConditionalExpression( "$NOVPC" ) )
+ return;
+
+ g_pVPC->GetProjectGenerator()->StartFolder( "VPC Scripts" );
+ g_pVPC->GetProjectGenerator()->StartFile( g_pVPC->GetScript().GetName(), false );
+
+ // only emit the extra information on windows, and only for the project vpc
+ if ( bDoCRCCheck && g_pVPC->EvaluateConditionalExpression( "$WINDOWS" ) )
+ {
+ CUtlString sSentinel = CFmtStr( "$PROJECTDIR\\%s.sentinel", g_pVPC->GetScript().GetName() ).Access();
+ bool bShouldSkip;
+
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ char rgchCRCCheckExpanded[2048]; rgchCRCCheckExpanded[0] = '\0';
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i], true );
+ g_pVPC->GetProjectGenerator()->StartPropertySection( KEYWORD_CUSTOMBUILDSTEP, &bShouldSkip );
+ // this will write a sentinel file so we have a clear build target so we can know the last time we checked
+ g_pVPC->GetProjectGenerator()->HandleProperty( "$Description", CFmtStr("\"Running VPC CRC Check - %s\"", g_pVPC->GetScript().GetName() ) );
+ g_pVPC->GetProjectGenerator()->HandleProperty( "$CommandLine", CFmtStr( "\"rem IncrediBuild_AllowOverlap\n%s\necho crc_complete > %s\"", g_pVPC->GetMacroValue( "CRCCHECK" ), sSentinel.Get() ) );
+ g_pVPC->GetProjectGenerator()->HandleProperty( "$Outputs", sSentinel );
+ g_pVPC->GetProjectGenerator()->EndPropertySection( KEYWORD_CUSTOMBUILDSTEP );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+ }
+
+ g_pVPC->GetProjectGenerator()->EndFile();
+ g_pVPC->GetProjectGenerator()->EndFolder();
+}
+
+void VPC_HandleIncludeStatement( int depth, bool bQuiet, void (*CallbackFn)( const char *pScriptName, int depth, bool bQuiet ) )
+{
+ char szBigBuffer[MAX_SYSTOKENCHARS];
+ if ( g_pVPC->GetScript().ParsePropertyValue( NULL, szBigBuffer, sizeof( szBigBuffer ) ) )
+ {
+ // recurse into and run
+ char *pScriptBuffer;
+ char szFixedScriptName[MAX_PATH];
+ VPC_PrepareToReadScript( szBigBuffer, depth+1, bQuiet, pScriptBuffer, szFixedScriptName );
+
+ VPC_AddCurrentVPCScriptToProjectFolder( false );
+
+ CallbackFn( szBigBuffer, depth+1, bQuiet );
+ free( pScriptBuffer );
+
+ // restore state
+ g_pVPC->GetScript().PopScript();
+ }
+}
+
+void VPC_HandleProjectCommands( const char *pUnusedScriptName, int depth, bool bQuiet )
+{
+ const char *pToken;
+
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ break;
+ }
+ else if ( !V_stricmp( pToken, "$include" ) )
+ {
+ VPC_HandleIncludeStatement( depth, bQuiet, VPC_HandleProjectCommands );
+ }
+ else if ( !V_stricmp( pToken, "$Folder" ) )
+ {
+ // root level folder
+ VPC_Keyword_Folder( false );
+ }
+ else if ( !V_stricmp( pToken, "$Unity" ) )
+ {
+ // root level folder
+ VPC_Keyword_Folder( g_pVPC->IsUnity() );
+ }
+ else if ( !V_stricmp( pToken, "$File" ) )
+ {
+ // add root level file
+ VPC_Keyword_AddFile();
+ }
+ else if ( !V_stricmp( pToken, "$SchemaFile" ) )
+ {
+ // add root level file
+ VPC_Keyword_AddFile( "schema" );
+ }
+ else if ( !V_stricmp( pToken, "-$File" ) )
+ {
+ // remove root level file
+ VPC_Keyword_RemoveFile();
+ }
+ else if ( !V_stricmp( pToken, "$Shaders" ) )
+ {
+ // add root level shaders folder
+ VPC_Keyword_Shaders( 0 );
+ }
+ else if ( !V_stricmp( pToken, "$macro" ) )
+ {
+ VPC_Keyword_Macro( VPC_MACRO_VALUE );
+ }
+ else
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+}
+
+
+void WriteCRCCheckFile( const char *pVCProjFilename )
+{
+ char szFilename[MAX_PATH];
+ V_snprintf( szFilename, sizeof( szFilename ), "%s." VPCCRCCHECK_FILE_EXTENSION, pVCProjFilename );
+
+ FILE *fp = fopen( szFilename, "wt" );
+ if ( !fp )
+ {
+ g_pVPC->VPCError( "Unable to open %s to write CRCs into.", szFilename );
+ }
+
+ fprintf( fp, "%s\n", VPCCRCCHECK_FILE_VERSION_STRING );
+ // add the executable crc
+ char vpcExeAbsPath[MAX_PATH]; vpcExeAbsPath[0] = '\0';
+ CRC32_t nCRCFromFileContents = 0;
+ if ( Sys_GetExecutablePath( vpcExeAbsPath, sizeof( vpcExeAbsPath ) ) )
+ {
+ char *pBuffer;
+ int cbVPCExe = Sys_LoadFile( vpcExeAbsPath, (void**)&pBuffer );
+
+ // Calculate the CRC from the contents of the file.
+ nCRCFromFileContents = CRC32_ProcessSingleBuffer( pBuffer, cbVPCExe );
+ delete [] pBuffer;
+ }
+
+ const char *vpcExePath = vpcExeAbsPath;
+
+ char vpcExeRelPath[MAX_PATH]; vpcExeRelPath[0] = '\0';
+ if ( V_MakeRelativePath( vpcExeAbsPath, g_pVPC->GetProjectPath(), vpcExeRelPath, sizeof( vpcExeRelPath ) ) )
+ {
+ vpcExePath = vpcExeRelPath;
+ }
+
+ fprintf( fp, "%8.8x %s\n", ( unsigned int ) nCRCFromFileContents, vpcExePath );
+
+ // add the supplemental string crc
+ fprintf( fp, "%s\n", g_pVPC->GetCRCString() );
+
+ CUtlDict<int, int> filenameDict( k_eDictCompareTypeFilenames );
+ for ( int i=0; i < g_pVPC->m_ScriptList.Count(); i++ )
+ {
+ scriptList_t *pScript = &g_pVPC->m_ScriptList[i];
+
+ // Use the dictionary to prevent duplicate file CRCs being written in here.
+ if ( filenameDict.Find( pScript->m_scriptName.String() ) == filenameDict.InvalidIndex() )
+ {
+ filenameDict.Insert( pScript->m_scriptName.String(), 1 );
+
+ // [crc] [filename]
+ fprintf( fp, "%8.8x %s\n", ( unsigned int ) pScript->m_crc, pScript->m_scriptName.Get() );
+ }
+ }
+
+ fclose( fp );
+}
+
+
+//
+// This is called when it's done parsing a project. If there were any $SchemaFile
+// entries in the project, then we will make this project depend on schemacompiler
+// (via $AdditionalProjectDependencies).
+//
+// This fixes full rebuild problems where it's building a project that uses schemacompiler
+// at the same time as it's building schemacompiler. This usually screws up when
+// it tries to copy the new schemacompiler.exe to game\bin but it's in use.
+//
+void VPC_ForceAdditionalSchemaDependencies( const char *pProjectName )
+{
+ if ( g_pVPC->m_SchemaFiles.Count() == 0 )
+ return;
+
+ // Add "$BASE;SchemaCompiler" to $AdditionalProjectDependencies.
+ CUtlVector< CUtlString > configurationNames;
+ g_pVPC->GetProjectGenerator()->GetAllConfigurationNames( configurationNames );
+ for ( int i=0; i < configurationNames.Count(); i++ )
+ {
+ g_pVPC->GetProjectGenerator()->StartConfigurationBlock( configurationNames[i].String(), false );
+ g_pVPC->GetProjectGenerator()->StartPropertySection( KEYWORD_GENERAL, NULL );
+
+ g_pVPC->GetProjectGenerator()->HandleProperty( g_pOption_AdditionalProjectDependencies, "$BASE;SchemaCompiler" );
+
+ g_pVPC->GetProjectGenerator()->EndPropertySection( KEYWORD_GENERAL );
+ g_pVPC->GetProjectGenerator()->EndConfigurationBlock();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// VPC_Keyword_Project
+//
+//-----------------------------------------------------------------------------
+void VPC_Keyword_Project( int depth, bool bQuiet )
+{
+ char szProjectName[MAX_PATH];
+
+ // check for optional project name
+ const char *pToken = g_pVPC->GetScript().PeekNextToken( false );
+
+ if ( pToken && pToken[0] && V_stricmp( pToken, "{" ) )
+ {
+ // get optional project name
+ pToken = g_pVPC->GetScript().GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+
+ g_pVPC->ResolveMacrosInString( pToken, szProjectName, sizeof( szProjectName ) );
+
+ if ( g_pVPC->IsDecorateProject() )
+ {
+ g_pVPC->DecorateProjectName( szProjectName );
+ }
+ }
+ else
+ {
+ CUtlString strName = g_pVPC->GetProjectGenerator()->GetProjectName();
+ V_strncpy( szProjectName, strName.String(), sizeof( szProjectName ) );
+ }
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_stricmp( pToken, "{" ) )
+ g_pVPC->VPCSyntaxError();
+
+ VPC_HandleProjectCommands( NULL, depth, bQuiet );
+
+ // the unnamed project does not get written, once it is named it will be written on closing scope
+ if ( V_stricmp( szProjectName, "UNNAMED" ) )
+ {
+ VPC_ForceAdditionalSchemaDependencies( szProjectName );
+
+ // change name
+ g_pVPC->GetProjectGenerator()->SetProjectName( szProjectName );
+
+ // need to do this at the end of parsing the project, so we have all the macros needed
+ VPC_AddCurrentVPCScriptToProjectFolder( true );
+
+ g_pVPC->GetProjectGenerator()->EndProject();
+ g_pVPC->m_bGeneratedProject = true;
+ }
+}
+
+static const char* fileTypes[] =
+{
+ "c", "cpp", "cxx", "cc",
+ "h", "hh", "hxx", "hpp", ""
+};
+bool VPC_IsBuiltInFileType( const char *extension )
+{
+ for (int i = 0; i < V_ARRAYSIZE(fileTypes); i++)
+ {
+ if ( !V_stricmp( fileTypes[i], extension ) )
+ return true;
+ }
+
+ return false;
+}
+
+void VPC_Keyword_CustomBuildStep( void )
+{
+ bool bAllowNextLine = false;
+ CUtlVector<CUtlString> extensions;
+
+ const char *pToken = NULL;
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ // Is this a conditional expression?
+ if ( pToken[0] == '[' )
+ {
+ if ( extensions.Count() == 0 )
+ {
+ g_pVPC->VPCSyntaxError( "Conditional specified on a $CustomBuildStep without any extensions preceding it." );
+ }
+
+ if ( !g_pVPC->EvaluateConditionalExpression( pToken ) )
+ {
+ extensions.Remove( extensions.Count() - 1 );
+ }
+
+ continue;
+ }
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ if ( VPC_IsBuiltInFileType( pToken ) )
+ {
+ g_pVPC->VPCSyntaxError( "Cannot define custom build steps for built in file type: %s", pToken);
+ }
+
+ CUtlString string = pToken;
+ extensions.AddToTail( string );
+
+ // check for another optional file
+ pToken = g_pVPC->GetScript().PeekNextToken( bAllowNextLine );
+ if ( !pToken || !pToken[0] )
+ break;
+ }
+
+
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] || V_strcmp( pToken, "{" ) )
+ {
+ g_pVPC->VPCSyntaxError( "Missing section for CustomBuildStep" );
+ }
+ else if ( extensions.Count() == 0 )
+ {
+ g_pVPC->GetScript().SkipBracedSection();
+ return;
+ }
+ else
+ {
+ const char *pScriptSave = g_pVPC->GetScript().GetData();
+ while ( 1 )
+ {
+ pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !V_stricmp( pToken, "}" ) )
+ {
+ // end of section
+ break;
+ }
+ }
+
+ CUtlString buildsteps;
+ if ( g_pVPC->GetScript().GetData() > pScriptSave )
+ {
+ CUtlString tempString;
+ tempString.SetDirect( pScriptSave, int( g_pVPC->GetScript().GetData() - pScriptSave - 1 ) );
+ buildsteps += "$Configuration\n{\n$CustomBuildStep\n{";
+ buildsteps += tempString + "}\n}\n";
+ }
+
+ if ( !buildsteps.IsEmpty() )
+ {
+ FOR_EACH_VEC( extensions, i )
+ {
+ g_pVPC->m_CustomBuildSteps.Insert( extensions[i], buildsteps );
+ }
+ }
+ }
+}
+
+void VPC_ParseProjectScriptParameters( const char *szScriptName, int depth, bool bQuiet )
+{
+ while ( 1 )
+ {
+ const char *pToken = g_pVPC->GetScript().GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ // end of file
+ break;
+ }
+
+ if ( !V_stricmp( pToken, "$include" ) )
+ {
+ VPC_HandleIncludeStatement( depth, bQuiet, VPC_ParseProjectScriptParameters );
+ }
+ else if ( !V_stricmp( pToken, "$configuration" ) )
+ {
+ VPC_Keyword_Configuration();
+ }
+ else if ( !V_stricmp( pToken, "$project" ) )
+ {
+ VPC_Keyword_Project( depth, bQuiet );
+ }
+ else if ( !V_stricmp( pToken, "$macro" ) )
+ {
+ VPC_Keyword_Macro( VPC_MACRO_VALUE );
+ }
+ else if ( !V_stricmp( pToken, "$MacroEmptyString" ) )
+ {
+ VPC_Keyword_Macro( VPC_MACRO_EMPTY_STRING );
+ }
+ else if ( !V_stricmp( pToken, "$MacroRequired" ) )
+ {
+ VPC_Keyword_MacroRequired( VPC_MACRO_REQUIRED_NOT_EMPTY );
+ }
+ else if ( !V_stricmp( pToken, "$MacroRequiredAllowEmpty" ) )
+ {
+ VPC_Keyword_MacroRequired( VPC_MACRO_REQUIRED_ALLOW_EMPTY );
+ }
+ else if ( !V_stricmp( pToken, "$LoadAddressMacro" ) )
+ {
+ VPC_Keyword_LoadAddressMacro();
+ }
+ else if ( !V_stricmp( pToken, "$LoadAddressMacroAlias" ) )
+ {
+ VPC_Keyword_LoadAddressMacroAlias();
+ }
+ else if ( !V_stricmp( pToken, "$LoadAddressMacroAuto" ) )
+ {
+ VPC_Keyword_LoadAddressMacroAuto();
+ }
+ else if ( !V_stricmp( pToken, "$LoadAddressMacroAuto_Padded" ) )
+ {
+ VPC_Keyword_LoadAddressMacroAuto_Padded();
+ }
+ else if ( !V_stricmp( pToken, "$IgnoreRedundancyWarning" ) )
+ {
+ VPC_Keyword_IgnoreRedundancyWarning();
+ }
+ else if ( !V_stricmp( pToken, "$Linux" ) )
+ {
+ VPC_Keyword_Linux();
+ }
+ else if ( !V_stricmp( pToken, "$CustomBuildStep" ) )
+ {
+ VPC_Keyword_CustomBuildStep();
+ }
+ else if ( !V_stricmp( pToken, "$Conditional" ) )
+ {
+ VPC_SharedKeyword_Conditional();
+ }
+ else
+ {
+ g_pVPC->VPCSyntaxError();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CVPC::ParseProjectScript( const char *pScriptName, int depth, bool bQuiet, bool bWriteCRCCheckFile )
+{
+ char *pScriptBuffer;
+ char szScriptName[MAX_PATH];
+
+ VPC_PrepareToReadScript( pScriptName, depth, bQuiet, pScriptBuffer, szScriptName );
+
+ int cMissingFilesPreParse = g_pVPC->GetMissingFilesCount();
+
+ if ( !depth )
+ {
+ // create reserved $ROOTSCRIPT - tracks the root script
+ FindOrCreateMacro( "ROOTSCRIPT", true, szScriptName );
+
+ // create reserved $PROJECTNAME - tracks the undecorated pure project name
+ // $(ProjectName) can be auto-decorated, making it unuseable by scripts expecting a pure project name
+ FindOrCreateMacro( "PROJECTNAME", true, g_pVPC->GetProjectName() );
+
+ // create reserved $LOADADDRESSNAME - defaults to project name but can be aliased with $LoadAddressMacroAlias
+ FindOrCreateMacro( "LOADADDRESSNAME", true, g_pVPC->GetLoadAddressName() );
+
+ // create reserved $CRCCHECK
+ // The CRCs themselves are dumped into theproject.vcproj.vpc_crc (in VPC_WriteCRCCheckFile), so all this does
+ // is point vpccrccheck.exe at it with "vpccrccheck.exe -crc2 theproject.vcproj"
+ // scripts add the terminal /n if they append, after referencing $CRCCHECK
+ // needs to be quoted to work with /dp which puts " (platform) " in project names,
+
+ CUtlString crcCheckString;
+ crcCheckString = "if exist $QUOTE$SRCDIR\\devtools\\bin\\" VPCCRCCHECK_EXE_FILENAME "$QUOTE $QUOTE$SRCDIR\\devtools\\bin\\" VPCCRCCHECK_EXE_FILENAME "$QUOTE -crc2 $QUOTE";
+ crcCheckString += g_pVPC->GetOutputFilename();
+ crcCheckString += "$QUOTE\nif ERRORLEVEL 1 exit /b 1";
+ g_pVPC->FindOrCreateMacro( "CRCCHECK", true, crcCheckString.Get() );
+
+ // create reserved $PROJECTDIR
+ char szProjectRootPath[MAX_PATH];
+ V_snprintf( szProjectRootPath, sizeof( szProjectRootPath ), "%s", g_pVPC->GetProjectPath() );
+ V_RemoveDotSlashes( szProjectRootPath );
+ SetMacro( "PROJECTDIR", szProjectRootPath, true );
+
+ // reset
+ g_pVPC->m_SchemaFiles.Purge();
+
+ // reset unity file tracking (it's per project)
+ g_pVPC->m_UnityFilesSeen.RemoveAll();
+ g_pVPC->m_UnityStack.Clear();
+ g_pVPC->m_sUnityCurrent = NULL;
+ }
+
+ VPC_ParseProjectScriptParameters( szScriptName, depth, bQuiet );
+
+ free( pScriptBuffer );
+
+ // for safety, force callers to restore to proper state
+ g_pVPC->GetScript().PopScript();
+
+ if ( !depth )
+ {
+ // at end of all processing, don't write crc checks if we're missing files
+ if ( bWriteCRCCheckFile && g_pVPC->GetMissingFilesCount() == cMissingFilesPreParse )
+ {
+ // Finally write out the file with all the CRCs in it. This is referenced by the $CRCCHECK macro in the prebuild steps.
+ WriteCRCCheckFile( g_pVPC->GetOutputFilename() );
+ }
+
+ g_pVPC->m_ScriptList.Purge();
+ g_pVPC->RemoveScriptCreatedMacros(); // Remove any macros that came from the script file.
+ }
+
+ return true;
+}
+
+void CVPC::AddScriptToCRCCheck( const char *pScriptName, CRC32_t crc )
+{
+ for ( int i = 0; i < m_ScriptList.Count(); i++ )
+ {
+ if ( !V_stricmp( m_ScriptList[i].m_scriptName, pScriptName ) )
+ {
+ // update
+ g_pVPC->m_ScriptList[i].m_crc = crc;
+ return;
+ }
+ }
+
+ int index = g_pVPC->m_ScriptList.AddToTail();
+ g_pVPC->m_ScriptList[index].m_scriptName = pScriptName;
+ g_pVPC->m_ScriptList[index].m_crc = crc;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+// Schema Script Generation
+//
+// Temporary - Once the schema workflow settles down, this schema-specific code should be
+// at minimum moved into its own file, and ideally generalized so that VPC
+// has a minimum of embedded schema-specific logic.
+//
+//
+//
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+KeyValues *ConfigPreprocessorSettingsAsKV( CSpecificConfig *pConfig );
+struct SchemaFileInfo_t
+{
+ bool bIsCppFile;
+ char szFile[MAX_PATH];
+ char szGeneratedFile[MAX_PATH];
+};
+
+void VPC_FakeKeyword_SchemaFolder( CBaseProjectDataCollector *pDataCollector )
+{
+ if ( g_pVPC->m_SchemaFiles.Count() == 0 )
+ return;
+
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( "NOSCHEMACOMPILER", false, NULL );
+ if ( pMacro && atoi( pMacro->value.Get() ) )
+ return;
+
+ CUtlString platformName = g_pVPC->GetTargetPlatformName();
+ V_strlower( platformName.Get() );
+ const char *pPlatformName = platformName.String();
+
+ CUtlVector<SchemaFileInfo_t> schemaFileInfos;
+ schemaFileInfos.AddMultipleToTail( g_pVPC->m_SchemaFiles.Count() );
+
+ char schemaCompilerPath[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( "$SRCDIR/devtools/bin/schemacompiler.dll", schemaCompilerPath, sizeof( schemaCompilerPath ) );
+
+ CUtlString schemaInputs;
+ CUtlString schemaOutputs;
+ char szExt[MAX_PATH];
+
+ schemaInputs += schemaCompilerPath;
+
+ for ( int i = 0; i < g_pVPC->m_SchemaFiles.Count(); i++ )
+ {
+ if ( !g_pVPC->m_SchemaFiles[i].String() )
+ continue;
+
+ schemaInputs += ";";
+ schemaInputs += g_pVPC->m_SchemaFiles[i];
+
+ V_ExtractFileExtension( g_pVPC->m_SchemaFiles[i], szExt, sizeof(szExt) );
+ SchemaFileInfo_t &fileInfo = schemaFileInfos[i];
+
+ V_strncpy( fileInfo.szFile, g_pVPC->m_SchemaFiles[i], sizeof(fileInfo.szFile) );
+ V_FixSlashes( fileInfo.szFile, '/' );
+
+ char szNoExt[MAX_PATH];
+ V_StripExtension( fileInfo.szFile, szNoExt, sizeof(szNoExt) );
+ char szBase[MAX_PATH];
+ V_FileBase( fileInfo.szFile, szBase, sizeof(szBase) );
+ char szPath[MAX_PATH];
+ V_ExtractFilePath( fileInfo.szFile, szPath, sizeof(szPath) );
+
+ char szGenRelPath[MAX_PATH];
+
+ if ( IsCFileExtension( szExt ) )
+ {
+ fileInfo.bIsCppFile = true;
+ V_snprintf( szGenRelPath, sizeof(szGenRelPath),
+ "generated_code_%s_%s/%s_schema_cpp_gen.cpp", g_pVPC->GetProjectName(), pPlatformName, szBase );
+ }
+ else
+ {
+ fileInfo.bIsCppFile = false;
+ V_snprintf( szGenRelPath, sizeof(szGenRelPath),
+ "generated_code_%s_%s/%s_schema_gen.cpp", g_pVPC->GetProjectName(), pPlatformName, szBase );
+ }
+
+ V_strncpy( fileInfo.szGeneratedFile, szGenRelPath, sizeof(fileInfo.szGeneratedFile) );
+ V_FixSlashes( fileInfo.szGeneratedFile, '/' );
+
+ schemaOutputs += fileInfo.szGeneratedFile;
+ schemaOutputs += ";";
+ }
+
+ char szSchemaOutAnchorPath[MAX_PATH];
+ V_snprintf( szSchemaOutAnchorPath, sizeof( szSchemaOutAnchorPath ),
+ "generated_code_%s_%s/%s_schema_anchor.cpp", g_pVPC->GetProjectName(), pPlatformName, g_pVPC->GetProjectName() );
+ V_FixSlashes( szSchemaOutAnchorPath, '/' );
+ schemaOutputs += szSchemaOutAnchorPath;
+ schemaOutputs += ";";
+
+ char szSchemaPath[MAX_PATH];
+ V_snprintf( szSchemaPath, sizeof( szSchemaPath ), "%s_%s.schproj", g_pVPC->GetProjectName(), pPlatformName );
+
+ //////////////////////////////////////////////////////////////////////////
+
+ CUtlBuffer vpcBuffer;
+
+ char schemaCompilerExePath[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( "$SRCDIR/devtools/bin/schemacompiler.exe", schemaCompilerExePath, sizeof( schemaCompilerExePath ) );
+ V_FixSlashes( schemaCompilerExePath );
+
+ vpcBuffer.SetBufferType( true, true );
+ vpcBuffer.Printf( "$Folder \"Autogenerated Schema Files\" \n" );
+ vpcBuffer.Printf( "{\n" );
+ vpcBuffer.Printf(
+ "$File \"%s\"\n"
+ "{\n"
+ " $Configuration\n"
+ " {\n"
+ " $CustomBuildStep\n"
+ " {\n"
+ " $CommandLine \"%s -schproj $(InputPath) -config $(ConfigurationName)\"\n"
+ " $Description \"Schema Compiler for [$(ConfigurationName)] $(InputName)\"\n"
+ " $Outputs \"%s\"\n"
+ " $AdditionalDependencies \"%s\"\n"
+ " }\n"
+ " }\n"
+ "}\n", szSchemaPath, schemaCompilerExePath, schemaOutputs.Get(), schemaInputs.Get() );
+
+ static const char *schemaConfiguration =
+ "{\n"
+ " $Configuration\n"
+ " {\n"
+ " $Compiler\n"
+ " {\n"
+ //" $PreprocessorDefinitions \"NO_MEMOVERRIDE_NEW_DELETE\"\n"
+ " $Create/UsePrecompiledHeader \"Not Using Precompiled Headers\"\n"
+ " }\n"
+ " }\n"
+ "}\n";
+
+ vpcBuffer.Printf( "$Folder \"Cpp Schema Wrappers\" \n" );
+ {
+ vpcBuffer.Printf( "{\n" );
+
+ for ( int i = 0; i < schemaFileInfos.Count(); ++i )
+ {
+ if ( schemaFileInfos[i].bIsCppFile )
+ {
+ vpcBuffer.Printf( "$File \"%s\"\n", schemaFileInfos[i].szGeneratedFile );
+ vpcBuffer.Printf( schemaConfiguration );
+ }
+ }
+
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ vpcBuffer.Printf( "$Folder \"Header-Generated Files\" \n" );
+ {
+ vpcBuffer.Printf( "{\n" );
+
+ for ( int i = 0; i < schemaFileInfos.Count(); ++i )
+ {
+ if ( !schemaFileInfos[i].bIsCppFile )
+ {
+ vpcBuffer.Printf( "$File \"%s\"\n", schemaFileInfos[i].szGeneratedFile );
+ vpcBuffer.Printf( schemaConfiguration );
+ }
+ }
+
+ vpcBuffer.Printf( "}\n" );
+ }
+
+ vpcBuffer.Printf( "$File \"%s\"\n", szSchemaOutAnchorPath );
+ vpcBuffer.Printf( schemaConfiguration );
+ vpcBuffer.Printf( "}\n" );
+
+ // save parser
+ bool bIgnoreRedundancyWarning = g_pVPC->IsIgnoreRedundancyWarning();
+ g_pVPC->SetIgnoreRedundancyWarning( true );
+ g_pVPC->GetScript().PushScript( "Internal List [Schema]", (char*)vpcBuffer.Base() );
+
+ const char *pToken = g_pVPC->GetScript().GetToken( true );
+ if ( pToken && pToken[0] && !V_stricmp( pToken, "$folder" ) )
+ {
+ VPC_Keyword_Folder( false );
+ }
+
+ // restore parser
+ g_pVPC->GetScript().PopScript();
+ g_pVPC->SetIgnoreRedundancyWarning( bIgnoreRedundancyWarning );
+
+ //////////////////////////////////////////////////////////////////////////
+
+ KeyValues *pOutKeyValues = new KeyValues("schproj");
+ pOutKeyValues->SetString( "project_name", g_pVPC->GetProjectName() );
+ pOutKeyValues->SetString( "platform_name", pPlatformName );
+ pOutKeyValues->SetString( "anchor_path", szSchemaOutAnchorPath );
+ char dmeTargetFolder[MAX_PATH];
+ g_pVPC->ResolveMacrosInString( "$SRCDIR\\public", dmeTargetFolder, sizeof( dmeTargetFolder ) );
+ pOutKeyValues->SetString( "dme_target_folder", dmeTargetFolder );
+
+ KeyValues *pOutAllConfigs = new KeyValues( "configs" );
+ pOutKeyValues->AddSubKey( pOutAllConfigs );
+
+ for ( int i = pDataCollector->m_BaseConfigData.m_Configurations.First();
+ i != pDataCollector->m_BaseConfigData.m_Configurations.InvalidIndex();
+ i = pDataCollector->m_BaseConfigData.m_Configurations.Next( i ) )
+ {
+ CSpecificConfig *pConfig = pDataCollector->m_BaseConfigData.m_Configurations[i];
+ pOutAllConfigs->AddSubKey( ConfigPreprocessorSettingsAsKV( pConfig ) );
+ }
+
+ char szNum[64];
+ {
+ KeyValues *pOutInputs = new KeyValues( "inputs" );
+ int nInput = 0;
+ pOutKeyValues->AddSubKey( pOutInputs );
+ for ( int i = 0; i < schemaFileInfos.Count(); i++ )
+ {
+ V_snprintf( szNum, sizeof(szNum), "%03d", nInput++ );
+
+ SchemaFileInfo_t &fileInfo = schemaFileInfos[i];
+
+ KeyValues *pOutFile = new KeyValues( szNum );
+ pOutInputs->AddSubKey( pOutFile );
+
+ pOutFile->SetString( "generation_target", fileInfo.szGeneratedFile );
+ pOutFile->SetBool( "is_cpp", fileInfo.bIsCppFile );
+ pOutFile->SetString( "input", fileInfo.szFile );
+ }
+ }
+ CUtlBuffer tmpBuf;
+ tmpBuf.SetBufferType( true, true );
+ pOutKeyValues->RecursiveSaveToFile( tmpBuf, 0 );
+ pOutKeyValues->deleteThis();
+
+ FILE *fp = fopen( szSchemaPath, "wt" );
+ if ( !fp )
+ {
+ g_pVPC->VPCStatus( true, "Error Saving File: '%s'", szSchemaPath );
+ }
+ else
+ {
+ fwrite( tmpBuf.Base(), sizeof(char), tmpBuf.TellMaxPut(), fp );
+ fclose( fp );
+ }
+}
+
+KeyValues *ConfigPreprocessorSettingsAsKV( CSpecificConfig * pConfig )
+{
+ KeyValues *pOutConfig = new KeyValues( pConfig->GetConfigName() );
+
+ char szNum[64];
+ KeyValues *pInConfigKV = pConfig->m_pKV;
+
+ //////////////////////////////////////////////////////////////////////////
+ // write defines
+
+ {
+ KeyValues *pOutDefines = new KeyValues( "defines" );
+ pOutConfig->AddSubKey( pOutDefines );
+
+ CSplitString outStrings( pInConfigKV->GetString( g_pOption_PreprocessorDefinitions ),
+ (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+
+ int nDefine = 0;
+
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ V_snprintf( szNum, sizeof(szNum), "%03d", nDefine++ );
+ pOutDefines->SetString( szNum, outStrings[i] );
+ }
+
+ // change #1001922 from source2 did the pBuf...
+ char pBuf[512];
+ for ( int i=0; i < g_pVPC->m_Macros.Count(); i++ )
+ {
+ macro_t *pMacro = &g_pVPC->m_Macros[i];
+
+ if ( pMacro->m_bSetupDefineInProjectFile )
+ {
+ V_snprintf( szNum, sizeof(szNum), "%03d", nDefine++ );
+ V_snprintf( pBuf, sizeof(pBuf), "%s=%s", pMacro->name.Get(), pMacro->value.Get() );
+ pOutDefines->SetString( szNum, pBuf );
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // write includes
+
+ KeyValues *pOutIncludes = new KeyValues( "includes" );
+ pOutConfig->AddSubKey( pOutIncludes );
+
+ int nInclude = 0;
+
+ CSplitString outStrings( pInConfigKV->GetString( g_pOption_AdditionalIncludeDirectories ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ V_snprintf( szNum, sizeof(szNum), "%03d", nInclude++ );
+
+ char sDir[MAX_PATH];
+ V_StrSubst( outStrings[i], "$(IntDir)", "$(OBJ_DIR)", sDir, sizeof( sDir ) );
+ V_FixSlashes( sDir, '/' );
+ pOutIncludes->SetString( szNum, sDir );
+ }
+
+ return pOutConfig;
+}
diff --git a/external/vpc/utils/vpc/scriptsource.cpp b/external/vpc/utils/vpc/scriptsource.cpp
new file mode 100644
index 0000000..82583e0
--- /dev/null
+++ b/external/vpc/utils/vpc/scriptsource.cpp
@@ -0,0 +1,565 @@
+//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
+//
+//
+//
+//==================================================================================================
+
+#include "vpc.h"
+
+#define MAX_SCRIPT_STACK_SIZE 32
+
+CScript::CScript()
+{
+ m_ScriptName = "(empty)";
+ m_nScriptLine = 0;
+ m_pScriptData = NULL;
+ m_pScriptLine = &m_nScriptLine;
+
+ m_Token[0] = '\0';
+ m_PeekToken[0] = '\0';
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const char *CScript::SkipWhitespace( const char *data, bool *pHasNewLines, int* pNumLines )
+{
+ int c;
+
+ while ( ( c = *data ) <= ' ' )
+ {
+ if ( c == '\n' )
+ {
+ if ( pNumLines )
+ {
+ (*pNumLines)++;
+ }
+
+ if ( pHasNewLines )
+ {
+ *pHasNewLines = true;
+ }
+ }
+ else if ( !c )
+ {
+ return ( NULL );
+ }
+
+ data++;
+ }
+
+ return data;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const char *CScript::SkipToValidToken( const char *data, bool *pHasNewLines, int* pNumLines )
+{
+ int c;
+
+ for ( ;; )
+ {
+ data = SkipWhitespace( data, pHasNewLines, pNumLines );
+
+ c = *data;
+ if ( !c )
+ {
+ break;
+ }
+
+ if ( c == '/' && data[1] == '/' )
+ {
+ // skip double slash comments
+ data += 2;
+ while ( *data && *data != '\n' )
+ {
+ data++;
+ }
+ if ( *data && *data == '\n' )
+ {
+ data++;
+ if ( pNumLines )
+ {
+ (*pNumLines)++;
+ }
+ if ( pHasNewLines )
+ {
+ *pHasNewLines = true;
+ }
+ }
+ }
+ else if ( c == '/' && data[1] == '*' )
+ {
+ // skip /* */ comments
+ data += 2;
+ while ( *data && ( *data != '*' || data[1] != '/' ) )
+ {
+ if ( *data == '\n' )
+ {
+ if ( pNumLines )
+ {
+ (*pNumLines)++;
+ }
+ if ( pHasNewLines )
+ {
+ *pHasNewLines = true;
+ }
+ }
+ data++;
+ }
+
+ if ( *data )
+ {
+ data += 2;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return data;
+}
+
+//-----------------------------------------------------------------------------
+// The next token should be an open brace.
+// Skips until a matching close brace is found.
+// Internal brace depths are properly skipped.
+//-----------------------------------------------------------------------------
+void CScript::SkipBracedSection( const char** dataptr, int* numlines )
+{
+ const char* token;
+ int depth;
+
+ depth = 0;
+ do
+ {
+ token = GetToken( dataptr, true, numlines );
+ if ( token[1] == '\0' )
+ {
+ if ( token[0] == '{' )
+ depth++;
+ else if ( token[0] == '}' )
+ depth--;
+ }
+ }
+ while( depth && *dataptr );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CScript::SkipRestOfLine( const char** dataptr, int* numlines )
+{
+ const char* p;
+ int c;
+
+ p = *dataptr;
+ while ( ( c = *p++ ) != '\0' )
+ {
+ if ( c == '\n' )
+ {
+ if ( numlines )
+ ( *numlines )++;
+ break;
+ }
+ }
+ *dataptr = p;
+}
+
+//-----------------------------------------------------------------------------
+// Does not corrupt results obtained with GetToken().
+//-----------------------------------------------------------------------------
+const char* CScript::PeekNextToken( const char *dataptr, bool bAllowLineBreaks )
+{
+ // save the primary token, about to be corrupted
+ char savedToken[MAX_SYSTOKENCHARS];
+ V_strncpy( savedToken, m_Token, MAX_SYSTOKENCHARS );
+
+ const char *pSaved = dataptr;
+ const char *pToken = GetToken( &pSaved, bAllowLineBreaks, NULL );
+
+ // restore
+ V_strncpy( m_PeekToken, pToken, MAX_SYSTOKENCHARS );
+ V_strncpy( m_Token, savedToken, MAX_SYSTOKENCHARS );
+
+ return m_PeekToken;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+const char *CScript::GetToken( const char **dataptr, bool allowLineBreaks, int *pNumLines )
+{
+ char c;
+ char endSymbol;
+ int len;
+ bool hasNewLines;
+ const char* data;
+
+ c = 0;
+ data = *dataptr;
+ len = 0;
+ m_Token[0] = 0;
+ hasNewLines = false;
+
+ // make sure incoming data is valid
+ if ( !data )
+ {
+ *dataptr = NULL;
+ return m_Token;
+ }
+
+ for ( ;; )
+ {
+ // skip whitespace
+ data = SkipWhitespace( data, &hasNewLines, pNumLines );
+ if ( !data )
+ {
+ *dataptr = NULL;
+ return m_Token;
+ }
+
+ if ( hasNewLines && !allowLineBreaks )
+ {
+ *dataptr = data;
+ return m_Token;
+ }
+
+ c = *data;
+
+ if ( c == '/' && data[1] == '/' )
+ {
+ // skip double slash comments
+ data += 2;
+ while ( *data && *data != '\n' )
+ {
+ data++;
+ }
+ if ( *data && *data == '\n' )
+ {
+ if ( !allowLineBreaks )
+ continue;
+
+ data++;
+ if ( pNumLines )
+ {
+ (*pNumLines)++;
+ }
+ }
+ }
+ else if ( c =='/' && data[1] == '*' )
+ {
+ // skip /* */ comments
+ data += 2;
+ while ( *data && ( *data != '*' || data[1] != '/' ) )
+ {
+ if ( *data == '\n' && pNumLines )
+ {
+ (*pNumLines)++;
+ }
+ data++;
+ }
+
+ if ( *data )
+ {
+ data += 2;
+ }
+ }
+ else
+ break;
+ }
+
+ // handle scoped strings "???" <???> [???]
+ if ( c == '\"' || c == '<' || c == '[')
+ {
+ bool bConditionalExpression = false;
+ endSymbol = '\0';
+ switch ( c )
+ {
+ case '\"':
+ endSymbol = '\"';
+ break;
+ case '<':
+ endSymbol = '>';
+ break;
+ case '[':
+ bConditionalExpression = true;
+ endSymbol = ']';
+ break;
+ }
+
+ // want to preserve entire conditional expession [blah...blah...blah]
+ // maintain a conditional's open/close scope characters
+ if ( !bConditionalExpression )
+ {
+ // skip past scope character
+ data++;
+ }
+
+ for ( ;; )
+ {
+ c = *data++;
+
+ if ( c == endSymbol || !c )
+ {
+ if ( c == endSymbol && bConditionalExpression )
+ {
+ // keep end symbol
+ m_Token[len++] = c;
+ }
+
+ m_Token[len] = 0;
+ *dataptr = (char*)data;
+ return m_Token;
+ }
+
+ if ( len < MAX_SYSTOKENCHARS-1 )
+ {
+ m_Token[len++] = c;
+ }
+ }
+ }
+
+ // parse a regular word
+ do
+ {
+ if ( len < MAX_SYSTOKENCHARS )
+ {
+ m_Token[len++] = c;
+ }
+
+ data++;
+ c = *data;
+ }
+ while ( c > ' ' );
+
+ if ( len >= MAX_SYSTOKENCHARS )
+ {
+ len = 0;
+ }
+
+ m_Token[len] = '\0';
+ *dataptr = (char*)data;
+
+ return m_Token;
+}
+
+void CScript::PushScript( const char *pFilename )
+{
+ // parse the text script
+ if ( !Sys_Exists( pFilename ) )
+ {
+ g_pVPC->VPCError( "Cannot open %s", pFilename );
+ }
+
+ char *pScriptBuffer;
+ Sys_LoadTextFileWithIncludes( pFilename, &pScriptBuffer, false );
+
+ PushScript( pFilename, pScriptBuffer, 1, true );
+}
+
+void CScript::PushScript( const char *pScriptName, const char *pScriptData, int nScriptLine, bool bFreeScriptAtPop )
+{
+ if ( m_ScriptStack.Count() > MAX_SCRIPT_STACK_SIZE )
+ {
+ g_pVPC->VPCError( "PushScript( scriptname=%s ) - stack overflow\n", pScriptName );
+ }
+
+ // Push the current state onto the stack.
+ m_ScriptStack.Push( GetCurrentScript() );
+
+ // Set their state as the current state.
+ m_ScriptName = pScriptName;
+ m_pScriptData = pScriptData;
+ m_nScriptLine = nScriptLine;
+ m_bFreeScriptAtPop = bFreeScriptAtPop;
+}
+
+void CScript::PushCurrentScript()
+{
+ PushScript( m_ScriptName.Get(), m_pScriptData, m_nScriptLine, m_bFreeScriptAtPop );
+}
+
+CScriptSource CScript::GetCurrentScript()
+{
+ return CScriptSource( m_ScriptName.Get(), m_pScriptData, m_nScriptLine, m_bFreeScriptAtPop );
+}
+
+void CScript::RestoreScript( const CScriptSource &scriptSource )
+{
+ m_ScriptName = scriptSource.GetName();
+ m_pScriptData = scriptSource.GetData();
+ m_nScriptLine = scriptSource.GetLine();
+ m_bFreeScriptAtPop = scriptSource.IsFreeScriptAtPop();
+}
+
+void CScript::PopScript()
+{
+ if ( m_ScriptStack.Count() == 0 )
+ {
+ g_pVPC->VPCError( "PopScript(): stack is empty" );
+ }
+
+ if ( m_bFreeScriptAtPop && m_pScriptData )
+ {
+ free( (void *)m_pScriptData );
+ }
+
+ // Restore the top entry on the stack and pop it off.
+ const CScriptSource &state = m_ScriptStack.Top();
+ m_ScriptName = state.GetName();
+ m_pScriptData = state.GetData();
+ m_nScriptLine = state.GetLine();
+ m_bFreeScriptAtPop = state.IsFreeScriptAtPop();
+
+ m_ScriptStack.Pop();
+}
+
+void CScript::EnsureScriptStackEmpty()
+{
+ if ( m_ScriptStack.Count() != 0 )
+ {
+ g_pVPC->VPCError( "EnsureScriptStackEmpty(): script stack is not empty!" );
+ }
+}
+
+void CScript::SpewScriptStack()
+{
+ if ( m_ScriptStack.Count() )
+ {
+ CUtlString str;
+
+ // emit stack with current at top
+ str += "Script Stack:\n";
+ str += CFmtStr( " %s Line:%d\n", m_ScriptName.String(), m_nScriptLine );
+ for ( int i = m_ScriptStack.Count() - 1; i >= 0; i-- )
+ {
+ if ( i == 0 && !m_ScriptStack[i].GetData() && m_ScriptStack[i].GetLine() <= 0 )
+ {
+ // ignore empty bottom of stack
+ break;
+ }
+
+ str += CFmtStr( " %s Line:%d\n", m_ScriptStack[i].GetName(), m_ScriptStack[i].GetLine() );
+ }
+ str += "\n";
+
+ Log_Msg( LOG_VPC, "%s", str.String() );
+ }
+}
+
+const char *CScript::GetToken( bool bAllowLineBreaks )
+{
+ return GetToken( &m_pScriptData, bAllowLineBreaks, m_pScriptLine );
+}
+
+const char *CScript::PeekNextToken( bool bAllowLineBreaks )
+{
+ return PeekNextToken( m_pScriptData, bAllowLineBreaks );
+}
+
+void CScript::SkipRestOfLine()
+{
+ SkipRestOfLine( &m_pScriptData, m_pScriptLine );
+}
+
+void CScript::SkipBracedSection()
+{
+ SkipBracedSection( &m_pScriptData, m_pScriptLine );
+}
+
+void CScript::SkipToValidToken()
+{
+ m_pScriptData = SkipToValidToken( m_pScriptData, NULL, m_pScriptLine );
+}
+
+//-----------------------------------------------------------------------------
+// Handles expressions of the form <$BASE> <xxx> ... <xxx> [condition]
+// Output is a concatenated string.
+//
+// Returns true if expression should be used, false if it should be ignored due
+// to an optional condition that evaluated false.
+//-----------------------------------------------------------------------------
+bool CScript::ParsePropertyValue( const char *pBaseString, char *pOutBuff, int outBuffSize )
+{
+ const char **pScriptData = &m_pScriptData;
+ int *pScriptLine = m_pScriptLine;
+
+ const char *pToken;
+ const char *pNextToken;
+ char *pOut = pOutBuff;
+ int remaining = outBuffSize-1;
+ int len;
+ bool bAllowNextLine = false;
+ char buffer1[MAX_SYSTOKENCHARS];
+ char buffer2[MAX_SYSTOKENCHARS];
+ bool bResult = true;
+
+ while ( 1 )
+ {
+ pToken = GetToken( pScriptData, bAllowNextLine, pScriptLine );
+ if ( !pToken || !pToken[0] )
+ g_pVPC->VPCSyntaxError();
+
+ pNextToken = PeekNextToken( *pScriptData, false );
+ if ( !pNextToken || !pNextToken[0] )
+ {
+ // current token is last token
+ // last token can be optional conditional, need to identify
+ // backup and reparse up to last token
+ if ( pToken && pToken[0] == '[' )
+ {
+ // last token is an optional conditional
+ bResult = g_pVPC->EvaluateConditionalExpression( pToken );
+ break;
+ }
+ }
+
+ if ( !V_stricmp( pToken, "\\" ) )
+ {
+ bAllowNextLine = true;
+ continue;
+ }
+ else
+ {
+ bAllowNextLine = false;
+ }
+
+ if ( !V_stricmp( pToken, "\\n" ) )
+ {
+ pToken = "\n";
+ }
+
+ if ( pToken[0] )
+ {
+ // handle reserved macro
+ if ( !pBaseString )
+ pBaseString = "";
+ strcpy( buffer1, pToken );
+ Sys_ReplaceString( buffer1, "$base", pBaseString, buffer2, sizeof( buffer2 ) );
+
+ g_pVPC->ResolveMacrosInString( buffer2, buffer1, sizeof( buffer1 ) );
+
+ len = strlen( buffer1 );
+ if ( remaining < len )
+ len = remaining;
+
+ if ( len > 0 )
+ {
+ memcpy( pOut, buffer1, len );
+ pOut += len;
+ remaining -= len;
+ }
+ }
+
+ pToken = PeekNextToken( *pScriptData, false );
+ if ( !pToken || !pToken[0] || !V_stricmp( pNextToken, "}" ) )
+ break;
+ }
+
+ *pOut++ = '\0';
+
+ if ( !pOutBuff[0] )
+ g_pVPC->VPCSyntaxError();
+
+ return bResult;
+} \ No newline at end of file
diff --git a/external/vpc/utils/vpc/scriptsource.h b/external/vpc/utils/vpc/scriptsource.h
new file mode 100644
index 0000000..4564eb1
--- /dev/null
+++ b/external/vpc/utils/vpc/scriptsource.h
@@ -0,0 +1,95 @@
+//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
+//
+// This module manages a stack of "script sources".
+//
+//==================================================================================================
+
+#ifndef SCRIPTSOURCE_H
+#define SCRIPTSOURCE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define MAX_SYSPRINTMSG 4096
+#define MAX_SYSTOKENCHARS 4096
+
+class CScriptSource
+{
+public:
+ CScriptSource()
+ {
+ Set( "", NULL, 0, false );
+ }
+
+ CScriptSource( const char *pScriptName, const char *pScriptData, int nScriptLine, bool bFreeScriptAtPop )
+ {
+ Set( pScriptName, pScriptData, nScriptLine, bFreeScriptAtPop );
+ }
+
+ void Set( const char *pScriptName, const char *pScriptData, int nScriptLine, bool bFreeScriptAtPop )
+ {
+ m_ScriptName = pScriptName;
+ m_pScriptData = pScriptData;
+ m_nScriptLine = nScriptLine;
+ m_bFreeScriptAtPop = bFreeScriptAtPop;
+ }
+
+ const char *GetName() const { return m_ScriptName.Get(); }
+ const char *GetData() const { return m_pScriptData; }
+ int GetLine() const { return m_nScriptLine; }
+ bool IsFreeScriptAtPop() const { return m_bFreeScriptAtPop; }
+
+private:
+ CUtlString m_ScriptName;
+ const char *m_pScriptData;
+ int m_nScriptLine;
+ bool m_bFreeScriptAtPop;
+};
+
+class CScript
+{
+public:
+ CScript();
+
+ void PushScript( const char *pFilename );
+ void PushScript( const char *pScriptName, const char *ppScriptData, int nScriptLine = 1, bool bFreeScriptAtPop = false );
+ void PushCurrentScript();
+ void PopScript();
+ CScriptSource GetCurrentScript();
+ void RestoreScript( const CScriptSource &scriptSource );
+ void EnsureScriptStackEmpty();
+ void SpewScriptStack();
+
+ const char *GetName() const { return m_ScriptName.Get(); }
+ const char *GetData() const { return m_pScriptData; }
+ int GetLine() const { return m_nScriptLine; }
+
+ const char *GetToken( bool bAllowLineBreaks );
+ const char *PeekNextToken( bool bAllowLineBreaks );
+ void SkipRestOfLine();
+ void SkipBracedSection();
+ void SkipToValidToken();
+
+ bool ParsePropertyValue( const char *pBaseString, char *pOutBuff, int outBuffSize );
+
+private:
+ const char *SkipWhitespace( const char *data, bool *pHasNewLines, int *pNumLines );
+ const char *SkipToValidToken( const char *data, bool *pHasNewLines, int *pNumLines );
+ void SkipBracedSection( const char **dataptr, int *numlines );
+ void SkipRestOfLine( const char **dataptr, int *numlines );
+ const char *PeekNextToken( const char *dataptr, bool bAllowLineBreaks );
+ const char *GetToken( const char **dataptr, bool allowLineBreaks, int *pNumLines );
+
+ CUtlStack< CScriptSource > m_ScriptStack;
+
+ int m_nScriptLine;
+ int *m_pScriptLine;
+ const char *m_pScriptData;
+ CUtlString m_ScriptName;
+ bool m_bFreeScriptAtPop;
+
+ char m_Token[MAX_SYSTOKENCHARS];
+ char m_PeekToken[MAX_SYSTOKENCHARS];
+};
+
+#endif // SCRIPTSOURCE_H
diff --git a/external/vpc/utils/vpc/solutiongenerator_codelite.cpp b/external/vpc/utils/vpc/solutiongenerator_codelite.cpp
new file mode 100644
index 0000000..604d861
--- /dev/null
+++ b/external/vpc/utils/vpc/solutiongenerator_codelite.cpp
@@ -0,0 +1,285 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "dependencies.h"
+#include "utlgraph.h"
+
+class CSolutionGenerator_CodeLite : public IBaseSolutionGenerator {
+public:
+ CSolutionGenerator_CodeLite() {
+ m_nIndent = 0;
+ m_fp = NULL;
+ }
+
+ virtual void GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects ) {
+ char szSolutionName[MAX_PATH];
+ V_FileBase( pSolutionFilename, szSolutionName, MAX_PATH );
+
+ char szSolutionFileBaseName[MAX_PATH];
+
+ // Default extension.
+ char szTmpSolutionFilename[MAX_PATH];
+ if ( !V_GetFileExtension( pSolutionFilename ) ) {
+ V_strncpy( szSolutionFileBaseName, pSolutionFilename, sizeof( szSolutionFileBaseName ) );
+ V_snprintf( szTmpSolutionFilename, sizeof( szTmpSolutionFilename ), "%s.workspace", pSolutionFilename );
+ pSolutionFilename = szTmpSolutionFilename;
+ } else {
+ V_StripExtension( pSolutionFilename, szSolutionFileBaseName, sizeof( szSolutionFileBaseName ) );
+ }
+
+ Msg( "\nWriting CodeLite workspace %s.\n\n", pSolutionFilename );
+
+ // Write the file.
+ m_fp = fopen( pSolutionFilename, "wt" );
+ if ( !m_fp )
+ g_pVPC->VPCError( "Can't open %s for writing.", pSolutionFilename );
+
+ Write( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
+ Write( "<CodeLite_Workspace Name=\"%s\" Database=\"%s.tags\">\n", szSolutionName, szSolutionFileBaseName );
+
+ ++m_nIndent;
+ Write( "<Project Name=\"all\" Path=\"%s.project\" Active=\"Yes\"/>\n", szSolutionFileBaseName);
+ for ( int i=0; i < projects.Count(); i++ ) {
+ CDependency_Project *pCurProject = projects[i];
+ project_t *pProjectT = &g_pVPC->m_Projects[ pCurProject->m_iProjectIndex ];
+
+ char szProjectFileBaseName[MAX_PATH];
+ V_StripExtension( pCurProject->m_ProjectFilename.String(), szProjectFileBaseName, sizeof( szProjectFileBaseName ) );
+
+ Write( "<Project Name=\"%s\" Path=\"%s.project\"/>\n", pProjectT->name.String(), szProjectFileBaseName );
+ }
+
+ Write( "<BuildMatrix>\n" );
+ ++m_nIndent;
+ Write( "<WorkspaceConfiguration Name=\"Debug\" Selected=\"no\">\n" );
+ ++m_nIndent;
+ Write( "<Project Name=\"all\" ConfigName=\"Debug\"/>\n" );
+ for ( int i=0; i < projects.Count(); i++ ) {
+ CDependency_Project *pCurProject = projects[i];
+ project_t *pProjectT = &g_pVPC->m_Projects[ pCurProject->m_iProjectIndex ];
+
+ Write( "<Project Name=\"%s\" ConfigName=\"Debug\"/>\n", pProjectT->name.String() );
+ }
+ --m_nIndent;
+ Write( "</WorkspaceConfiguration>\n" );
+
+ Write( "<WorkspaceConfiguration Name=\"Release\" Selected=\"yes\">\n" );
+ ++m_nIndent;
+ Write( "<Project Name=\"all\" ConfigName=\"Release\"/>\n" );
+ for ( int i=0; i < projects.Count(); i++ ) {
+ CDependency_Project *pCurProject = projects[i];
+ project_t *pProjectT = &g_pVPC->m_Projects[ pCurProject->m_iProjectIndex ];
+
+ Write( "<Project Name=\"%s\" ConfigName=\"Release\"/>\n", pProjectT->name.String() );
+ }
+ --m_nIndent;
+ Write( "</WorkspaceConfiguration>\n" );
+ --m_nIndent;
+ Write( "</BuildMatrix>\n" );
+ --m_nIndent;
+ Write( "</CodeLite_Workspace>\n" );
+
+ fclose( m_fp );
+
+ WriteBuildOrderProject( szSolutionFileBaseName, projects );
+ }
+
+ void WriteBuildOrderProject( const char *pszSolutionFileBaseName, CUtlVector<CDependency_Project*> &projects ) {
+ // write out a project with no files to encode the build order (dependencies)
+ char szProjectFileName[MAX_PATH];
+ V_snprintf( szProjectFileName, sizeof( szProjectFileName ), "%s.project", pszSolutionFileBaseName );
+
+ m_nIndent = 0;
+ m_fp = fopen( szProjectFileName, "wt" );
+ if ( !m_fp )
+ g_pVPC->VPCError( "Can't open %s for writing.", szProjectFileName );
+
+ Write( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
+ Write( "<CodeLite_Project Name=\"all\" InternalType=\"\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<Description/>\n" );
+ Write( "<Dependencies/>\n" );
+ Write( "<Settings Type=\"Static Library\">\n" );
+ {
+ ++m_nIndent;
+ Write( "<GlobalSettings>\n" );
+ ++m_nIndent;
+ Write( "<Compiler Options=\"\" C_Options=\"\">\n" );
+ ++m_nIndent;
+ Write( "<IncludePath Value=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</Compiler>\n" );
+ Write( "<Linker Options=\"\">\n" );
+ ++m_nIndent;
+ Write( "<LibraryPath Value=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</Linker>\n" );
+ Write( "<ResourceCompiler Options=\"\"/>\n" );
+ --m_nIndent;
+ Write( "</GlobalSettings>\n" );
+
+ Write( "<Configuration Name=\"Debug\" CompilerType=\"gnu g++\" DebuggerType=\"GNU gdb debugger\" Type=\"Executable\" BuildCmpWithGlobalSettings=\"append\" BuildLnkWithGlobalSettings=\"append\" BuildResWithGlobalSettings=\"append\">\n" );
+#if 0
+ ++m_nIndent;
+ Write( "<Compiler Options=\"-g\" C_Options="" Required="yes" PreCompiledHeader="">\n" );
+ ++m_nIndent;
+ Write( "<IncludePath Value=\"\"/>" );
+ --m_nIndent;
+ --m_nIndent;
+#endif
+ Write( "</Configuration>\n" );
+
+ Write( "<Configuration Name=\"Release\" CompilerType=\"gnu g++\" DebuggerType=\"GNU gdb debugger\" Type=\"Executable\" BuildCmpWithGlobalSettings=\"append\" BuildLnkWithGlobalSettings=\"append\" BuildResWithGlobalSettings=\"append\">\n" );
+#if 0
+ ++m_nIndent;
+ Write( "<Compiler Options=\"-g\" C_Options="" Required="yes" PreCompiledHeader="">\n" );
+ ++m_nIndent;
+ Write( "<IncludePath Value=\"\"/>" );
+ --m_nIndent;
+ --m_nIndent;
+#endif
+ Write( "</Configuration>\n" );
+
+ --m_nIndent;
+ }
+ Write( "</Settings>\n" );
+
+ --m_nIndent;
+
+ CUtlGraph<int, int> dependencyGraph;
+
+ // walk the project list building a dependency graph
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+
+ CDependency_Project *pCurProject = projects[i];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ //project_t *pProjectT = &g_projects[ pCurProject->m_iProjectIndex ];
+ //printf( "%s depends on\n", pProjectT->name.String() );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ ) {
+ if ( i == iTestProject )
+ continue;
+
+ // do I depend on anyone?
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() ) {
+ // add an edge from this project to the one it depends on
+ dependencyGraph.AddEdge( i, iTestProject, 1 );
+ //printf( " %s -> %s\n", projects[ i ]->m_ProjectName.String(),
+ // projects[ iTestProject ]->m_ProjectName.String() );
+
+ }
+ }
+ }
+
+ Write( "<Dependencies Name=\"Debug\">\n" );
+ ++m_nIndent;
+
+ CUtlVector<int> visitedList;
+ for( int i = 0; i < projects.Count(); i++ ) {
+ TraverseFrom( projects, dependencyGraph, visitedList, i );
+ }
+ --m_nIndent;
+ Write( "</Dependencies>\n" );
+
+ Write( "<Dependencies Name=\"Release\">\n" );
+ ++m_nIndent;
+ visitedList.Purge();
+ for( int i = 0; i < projects.Count(); i++ ) {
+ TraverseFrom( projects, dependencyGraph, visitedList, i );
+ }
+ --m_nIndent;
+ Write( "</Dependencies>\n" );
+
+ }
+ Write( "</CodeLite_Project>\n" );
+ fclose( m_fp );
+ }
+
+ void TraverseFrom( CUtlVector<CDependency_Project*> &projects, CUtlGraph<int, int> &dependencyGraph, CUtlVector<int> &visitedList, int root ) {
+ CUtlGraphVisitor<int> visitor( dependencyGraph );
+
+ if ( visitedList.Find( root ) != visitedList.InvalidIndex() )
+ return;
+
+ // this project has no dependencies, just emit it
+ if ( !visitor.Begin( root ) )
+ {
+ Write( "<Project Name=\"%s\"/>\n", projects[ root ]->m_ProjectName.String() );
+ visitedList.AddToTail( root );
+ return;
+ }
+
+ // printf( "considering %i (%s)\n", root, projects[ root ]->m_ProjectName.String() );
+
+ while ( visitor.Advance() ) {
+ // printf( "%i (%s) depends on %i (%s)\n", root, projects[ root ]->m_ProjectName.String(), visitor.CurrentNode(), projects[ visitor.CurrentNode() ]->m_ProjectName.String() );
+ TraverseFrom( projects, dependencyGraph, visitedList, visitor.CurrentNode() );
+ }
+
+ Write( "<Project Name=\"%s\"/>\n", projects[ root ]->m_ProjectName.String() );
+ visitedList.AddToTail( root );
+ // printf( "emitting %i (%s)\n", root, projects[ root ]->m_ProjectName.String() );
+ }
+
+ void ResolveAdditionalProjectDependencies(
+ CDependency_Project *pCurProject,
+ CUtlVector<CDependency_Project*> &projects,
+ CUtlVector<CDependency_Project*> &additionalProjectDependencies ) {
+ for ( int i=0; i < pCurProject->m_AdditionalProjectDependencies.Count(); i++ ) {
+ const char *pLookingFor = pCurProject->m_AdditionalProjectDependencies[i].String();
+
+ int j;
+ for ( j=0; j < projects.Count(); j++ ) {
+ if ( V_stricmp( projects[j]->m_ProjectName.String(), pLookingFor ) == 0 )
+ break;
+ }
+
+ if ( j == projects.Count() )
+ g_pVPC->VPCError( "Project %s lists '%s' in its $AdditionalProjectDependencies, but there is no project by that name in the selected projects.", pCurProject->GetName(), pLookingFor );
+
+ additionalProjectDependencies.AddToTail( projects[j] );
+ }
+ }
+
+ const char* FindInFile( const char *pFilename, const char *pFileData, const char *pSearchFor ) {
+ const char *pPos = V_stristr( pFileData, pSearchFor );
+ if ( !pPos )
+ g_pVPC->VPCError( "Can't find ProjectGUID in %s.", pFilename );
+
+ return pPos + V_strlen( pSearchFor );
+ }
+
+ void 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, " " );
+
+ fprintf( m_fp, "%s", sOut );
+ }
+
+ FILE *m_fp;
+ int m_nIndent;
+};
+
+
+static CSolutionGenerator_CodeLite g_SolutionGenerator_CodeLite;
+IBaseSolutionGenerator* GetSolutionGenerator_CodeLite() {
+ return &g_SolutionGenerator_CodeLite;
+}
diff --git a/external/vpc/utils/vpc/solutiongenerator_makefile.cpp b/external/vpc/utils/vpc/solutiongenerator_makefile.cpp
new file mode 100644
index 0000000..827d930
--- /dev/null
+++ b/external/vpc/utils/vpc/solutiongenerator_makefile.cpp
@@ -0,0 +1,341 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "dependencies.h"
+
+
+extern void V_MakeAbsoluteCygwinPath( char *pOut, int outLen, const char *pRelativePath );
+
+extern void MakeFriendlyProjectName( char *pchProject )
+{
+ int strLen = V_strlen( pchProject );
+ for ( int j = 0; j < strLen; j++ )
+ {
+ if ( pchProject[j] == ' ' )
+ pchProject[j] = '_';
+ if ( pchProject[j] == '(' || pchProject[j] == ')' )
+ {
+ V_memmove( pchProject+j, pchProject+j+1, strLen - j );
+ strLen--;
+ }
+ }
+}
+
+
+class CSolutionGenerator_Makefile : public IBaseSolutionGenerator
+{
+private:
+ void GenerateProjectNames( CUtlVector<CUtlString> &projNames, CUtlVector<CDependency_Project*> &projects )
+ {
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pCurProject = projects[i];
+ char szFriendlyName[256];
+ V_strncpy( szFriendlyName, pCurProject->m_ProjectName.String(), sizeof(szFriendlyName) );
+ MakeFriendlyProjectName( szFriendlyName );
+ projNames[ projNames.AddToTail() ] = szFriendlyName;
+ }
+ }
+
+public:
+ virtual void GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects )
+ {
+ // Default extension.
+ char szTmpSolutionFilename[MAX_PATH];
+ if ( !V_GetFileExtension( pSolutionFilename ) )
+ {
+ V_snprintf( szTmpSolutionFilename, sizeof( szTmpSolutionFilename ), "%s.mak", pSolutionFilename );
+ pSolutionFilename = szTmpSolutionFilename;
+ }
+
+ const char *pTargetPlatformName;
+ // forestw: if PLATFORM macro exists we should use its value, this accommodates overrides of PLATFORM in .vpc files
+ macro_t *pMacro = g_pVPC->FindOrCreateMacro( "PLATFORM", false, NULL );
+ if ( pMacro )
+ pTargetPlatformName = pMacro->value.String();
+ else
+ pTargetPlatformName = g_pVPC->GetTargetPlatformName();
+
+ Msg( "\nWriting master makefile %s.\n\n", pSolutionFilename );
+
+ // Write the file.
+ FILE *fp = fopen( pSolutionFilename, "wt" );
+ if ( !fp )
+ g_pVPC->VPCError( "Can't open %s for writing.", pSolutionFilename );
+
+ fprintf( fp, "# VPC MASTER MAKEFILE\n\n" );
+
+ fprintf( fp, "# Disable built-in rules/variables. We don't depend on them, and they slow down make processing.\n" );
+ fprintf( fp, "MAKEFLAGS += --no-builtin-rules --no-builtin-variables\n" );
+ fprintf( fp, "ifeq ($(MAKE_VERBOSE),)\n" );
+ fprintf( fp, "MAKEFLAGS += --no-print-directory\n" );
+ fprintf( fp, "endif\n\n" );
+
+ fprintf( fp, "ifneq \"$(LINUX_TOOLS_PATH)\" \"\"\n" );
+ fprintf( fp, " TOOL_PATH = $(LINUX_TOOLS_PATH)/\n" );
+ fprintf( fp, " SHELL := $(TOOL_PATH)bash\n" );
+ fprintf( fp, "else\n" );
+ fprintf( fp, " SHELL := /bin/bash\n" );
+ fprintf( fp, "endif\n" );
+
+ fprintf( fp, "ifndef NO_CHROOT\n" );
+ if ( V_stristr( pTargetPlatformName, "64" ) )
+ {
+ fprintf( fp, " export CHROOT_NAME ?= $(subst /,_,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))amd64\n");
+ fprintf( fp, " RUNTIME_NAME ?= steamrt_scout_amd64\n");
+ fprintf( fp, " CHROOT_PERSONALITY ?= linux\n");
+ }
+ else if ( V_stristr( pTargetPlatformName, "32" ) )
+ {
+ fprintf( fp, " export CHROOT_NAME ?= $(subst /,_,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))\n");
+ fprintf( fp, " RUNTIME_NAME ?= steamrt_scout_i386\n");
+ fprintf( fp, " CHROOT_PERSONALITY ?= linux32\n");
+ }
+ else
+ {
+ g_pVPC->VPCError( "TargetPlatform (%s) doesn't seem to be 32 or 64 bit, can't configure chroot parameters", pTargetPlatformName );
+ }
+ fprintf( fp, " CHROOT_CONF := /etc/schroot/chroot.d/$(CHROOT_NAME).conf\n");
+ fprintf( fp, " CHROOT_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/tools/runtime/linux)\n\n");
+
+ fprintf( fp, " export MAKE_CHROOT = 1\n" );
+ fprintf( fp, " ifneq (\"$(SCHROOT_CHROOT_NAME)\", \"$(CHROOT_NAME)\")\n");
+ fprintf( fp, " SHELL := schroot --chroot $(CHROOT_NAME) -- /bin/bash\n");
+ fprintf( fp, " endif\n");
+ fprintf( fp, "endif\n\n" ); // NO_CHROOT
+
+ fprintf( fp, "ECHO = $(TOOL_PATH)echo\n" );
+ fprintf( fp, "ETAGS = $(TOOL_PATH)etags\n" );
+ fprintf( fp, "FIND = $(TOOL_PATH)find\n" );
+ fprintf( fp, "UNAME = $(TOOL_PATH)uname\n" );
+ fprintf( fp, "XARGS = $(TOOL_PATH)xargs\n" );
+ fprintf( fp, "\n");
+
+ fprintf( fp, "# to control parallelism, set the MAKE_JOBS environment variable\n" );
+ fprintf( fp, "ifeq ($(strip $(MAKE_JOBS)),)\n");
+ fprintf( fp, " ifeq ($(shell $(UNAME)),Darwin)\n" );
+ fprintf( fp, " CPUS := $(shell /usr/sbin/sysctl -n hw.ncpu)\n" );
+ fprintf( fp, " endif\n");
+ fprintf( fp, " ifeq ($(shell $(UNAME)),Linux)\n" );
+ fprintf( fp, " CPUS := $(shell $(TOOL_PATH)grep processor /proc/cpuinfo | $(TOOL_PATH)wc -l)\n" );
+ fprintf( fp, " endif\n");
+ fprintf( fp, " MAKE_JOBS := $(CPUS)\n" );
+ fprintf( fp, "endif\n\n" );
+
+ fprintf( fp, "ifeq ($(strip $(MAKE_JOBS)),)\n");
+ fprintf( fp, " MAKE_JOBS := 8\n" );
+ fprintf( fp, "endif\n\n" );
+ // Handle VALVE_NO_PROJECT_DEPS
+ fprintf( fp, "# make VALVE_NO_PROJECT_DEPS 1 or empty (so VALVE_NO_PROJECT_DEPS=0 works as expected)\n");
+ fprintf( fp, "ifeq ($(strip $(VALVE_NO_PROJECT_DEPS)),1)\n");
+ fprintf( fp, "\tVALVE_NO_PROJECT_DEPS := 1\n");
+ fprintf( fp, "else\n");
+ fprintf( fp, "\tVALVE_NO_PROJECT_DEPS :=\n");
+ fprintf( fp, "endif\n\n");
+
+ // Handle VALVE_NO_PROJECT_DEPS
+ fprintf( fp, "# make VALVE_NO_PROJECT_DEPS 1 or empty (so VALVE_NO_PROJECT_DEPS=0 works as expected)\n");
+ fprintf( fp, "ifeq ($(strip $(VALVE_NO_PROJECT_DEPS)),1)\n");
+ fprintf( fp, "\tVALVE_NO_PROJECT_DEPS := 1\n");
+ fprintf( fp, "else\n");
+ fprintf( fp, "\tVALVE_NO_PROJECT_DEPS :=\n");
+ fprintf( fp, "endif\n\n");
+
+ // First, make a target with all the project names.
+ fprintf( fp, "# All projects (default target)\n" );
+ fprintf( fp, "all: $(CHROOT_CONF)\n" );
+ fprintf( fp, "\t$(MAKE) -f $(lastword $(MAKEFILE_LIST)) -j$(MAKE_JOBS) all-targets\n\n" );
+
+ fprintf( fp, "all-targets : " );
+
+ CUtlVector<CUtlString> projNames;
+ GenerateProjectNames( projNames, projects );
+
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ fprintf( fp, "%s ", projNames[i].String() );
+ }
+
+ fprintf( fp, "\n\n\n# Individual projects + dependencies\n\n" );
+
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pCurProject = projects[i];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ fprintf( fp, "%s : $(if $(VALVE_NO_PROJECT_DEPS),,$(CHROOT_CONF) ", projNames[i].String() );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( i == iTestProject )
+ continue;
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ fprintf( fp, "%s ", projNames[iTestProject].String() );
+ }
+ }
+
+ fprintf( fp, ")" ); // Closing $(if) above
+
+ // Now add the code to build this thing.
+ char sDirTemp[MAX_PATH], sDir[MAX_PATH];
+ V_strncpy( sDirTemp, pCurProject->m_ProjectFilename.String(), sizeof( sDirTemp ) );
+ V_StripFilename( sDirTemp );
+ V_MakeAbsoluteCygwinPath( sDir, sizeof( sDir ), sDirTemp );
+
+ const char *pFilename = V_UnqualifiedFileName( pCurProject->m_ProjectFilename.String() );
+
+ fprintf( fp, "\n\t@echo \"Building: %s\"", projNames[i].String());
+ fprintf( fp, "\n\t@+cd %s && $(MAKE) -f %s $(SUBMAKE_PARAMS) $(CLEANPARAM)", sDir, pFilename );
+
+ fprintf( fp, "\n\n" );
+ }
+
+ fprintf( fp, "# this is a bit over-inclusive, but the alternative (actually adding each referenced c/cpp/h file to\n" );
+ fprintf( fp, "# the tags file) seems like more work than it's worth. feel free to fix that up if it bugs you. \n" );
+ fprintf( fp, "TAGS:\n" );
+ fprintf( fp, "\t@rm -f TAGS\n" );
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pCurProject = projects[i];
+ char sDirTemp[MAX_PATH], sDir[MAX_PATH];
+ V_strncpy( sDirTemp, pCurProject->m_ProjectFilename.String(), sizeof( sDirTemp ) );
+ V_StripFilename( sDirTemp );
+ V_MakeAbsoluteCygwinPath( sDir, sizeof( sDir ), sDirTemp );
+ fprintf( fp, "\t@$(FIND) %s -name \'*.cpp\' -print0 | $(XARGS) -0 $(ETAGS) --declarations --ignore-indentation --append\n", sDir );
+ fprintf( fp, "\t@$(FIND) %s -name \'*.h\' -print0 | $(XARGS) -0 $(ETAGS) --language=c++ --declarations --ignore-indentation --append\n", sDir );
+ fprintf( fp, "\t@$(FIND) %s -name \'*.c\' -print0 | $(XARGS) -0 $(ETAGS) --declarations --ignore-indentation --append\n", sDir );
+ }
+ fprintf( fp, "\n\n" );
+
+ fprintf( fp, "\n# Mark all the projects as phony or else make will see the directories by the same name and think certain targets \n\n" );
+ fprintf( fp, ".PHONY: TAGS showtargets regen showregen clean cleantargets cleanandremove relink " );
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ fprintf( fp, "%s ", projNames[i].String() );
+ }
+ fprintf( fp, "\n\n\n" );
+
+ fprintf( fp, "\n# The standard clean command to clean it all out.\n" );
+ fprintf( fp, "\nclean: \n" );
+ fprintf( fp, "\t@$(MAKE) -f $(lastword $(MAKEFILE_LIST)) -j$(MAKE_JOBS) all-targets CLEANPARAM=clean\n\n\n" );
+
+ fprintf( fp, "\n# clean targets, so we re-link next time.\n" );
+ fprintf( fp, "\ncleantargets: \n" );
+ fprintf( fp, "\t@$(MAKE) -f $(lastword $(MAKEFILE_LIST)) -j$(MAKE_JOBS) all-targets CLEANPARAM=cleantargets\n\n\n" );
+
+ fprintf( fp, "\n# p4 edit and remove targets, so we get an entirely clean build.\n" );
+ fprintf( fp, "\ncleanandremove: \n" );
+ fprintf( fp, "\t@$(MAKE) -f $(lastword $(MAKEFILE_LIST)) -j$(MAKE_JOBS) all-targets CLEANPARAM=cleanandremove\n\n\n" );
+
+ fprintf( fp, "\n#relink\n" );
+ fprintf( fp, "\nrelink: cleantargets \n" );
+ fprintf( fp, "\t@$(MAKE) -f $(lastword $(MAKEFILE_LIST)) -j$(MAKE_JOBS) all-targets\n\n\n" );
+
+
+
+ // Create the showtargets target.
+ fprintf( fp, "\n# Here's a command to list out all the targets\n\n" );
+ fprintf( fp, "\nshowtargets: \n" );
+ fprintf( fp, "\t@$(ECHO) '-------------------' && \\\n" );
+ fprintf( fp, "\t$(ECHO) '----- TARGETS -----' && \\\n" );
+ fprintf( fp, "\t$(ECHO) '-------------------' && \\\n" );
+ fprintf( fp, "\t$(ECHO) 'clean' && \\\n" );
+ fprintf( fp, "\t$(ECHO) 'regen' && \\\n" );
+ fprintf( fp, "\t$(ECHO) 'showregen' && \\\n" );
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ fprintf( fp, "\t$(ECHO) '%s'", projNames[i].String() );
+ if ( i != projects.Count()-1 )
+ fprintf( fp, " && \\" );
+ fprintf( fp, "\n" );
+ }
+ fprintf( fp, "\n\n" );
+
+
+ // Create the regen target.
+ fprintf( fp, "\n# Here's a command to regenerate this makefile\n\n" );
+ fprintf( fp, "\nregen: \n" );
+ fprintf( fp, "\t" );
+ ICommandLine *pCommandLine = CommandLine();
+ for ( int i=0; i < pCommandLine->ParmCount(); i++ )
+ {
+ fprintf( fp, "%s ", pCommandLine->GetParm( i ) );
+ }
+ fprintf( fp, "\n\n" );
+
+
+ // Create the showregen target.
+ fprintf( fp, "\n# Here's a command to list out all the targets\n\n" );
+ fprintf( fp, "\nshowregen: \n" );
+ fprintf( fp, "\t@$(ECHO) " );
+ for ( int i=0; i < pCommandLine->ParmCount(); i++ )
+ {
+ fprintf( fp, "%s ", pCommandLine->GetParm( i ) );
+ }
+ fprintf( fp, "\n\n" );
+
+ // Auto-create the chroot if it's not there
+ fprintf( fp, "ifdef CHROOT_CONF\n"
+ "$(CHROOT_CONF): $(CHROOT_DIR)/$(RUNTIME_NAME)/timestamp\n"
+ "$(CHROOT_CONF): SHELL = /bin/bash\n"
+ "$(CHROOT_DIR)/$(RUNTIME_NAME)/timestamp: $(CHROOT_DIR)/$(RUNTIME_NAME).tar.xz\n"
+ "\t@echo \"Configuring schroot at $(CHROOT_DIR) (requires sudo)\"\n"
+ "\tsudo $(CHROOT_DIR)/configure_runtime.sh ${CHROOT_NAME} $(RUNTIME_NAME) $(CHROOT_PERSONALITY)\n"
+ "endif\n");
+
+
+ fclose( fp );
+ }
+
+ void ResolveAdditionalProjectDependencies(
+ CDependency_Project *pCurProject,
+ CUtlVector<CDependency_Project*> &projects,
+ CUtlVector<CDependency_Project*> &additionalProjectDependencies )
+ {
+ for ( int i=0; i < pCurProject->m_AdditionalProjectDependencies.Count(); i++ )
+ {
+ const char *pLookingFor = pCurProject->m_AdditionalProjectDependencies[i].String();
+
+ int j;
+ for ( j=0; j < projects.Count(); j++ )
+ {
+ if ( V_stricmp( projects[j]->m_ProjectName.String(), pLookingFor ) == 0 )
+ break;
+ }
+
+ if ( j == projects.Count() )
+ g_pVPC->VPCError( "Project %s lists '%s' in its $AdditionalProjectDependencies, but there is no project by that name in the selected projects.", pCurProject->GetName(), pLookingFor );
+
+ additionalProjectDependencies.AddToTail( projects[j] );
+ }
+ }
+
+ const char* FindInFile( const char *pFilename, const char *pFileData, const char *pSearchFor )
+ {
+ const char *pPos = V_stristr( pFileData, pSearchFor );
+ if ( !pPos )
+ g_pVPC->VPCError( "Can't find ProjectGUID in %s.", pFilename );
+
+ return pPos + V_strlen( pSearchFor );
+ }
+};
+
+
+static CSolutionGenerator_Makefile g_SolutionGenerator_Makefile;
+IBaseSolutionGenerator* GetMakefileSolutionGenerator()
+{
+ return &g_SolutionGenerator_Makefile;
+}
+
+
+
diff --git a/external/vpc/utils/vpc/solutiongenerator_win32.cpp b/external/vpc/utils/vpc/solutiongenerator_win32.cpp
new file mode 100644
index 0000000..9314795
--- /dev/null
+++ b/external/vpc/utils/vpc/solutiongenerator_win32.cpp
@@ -0,0 +1,370 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "dependencies.h"
+#include "tier1/checksum_md5.h"
+
+class CVCProjInfo
+{
+public:
+ CUtlString m_ProjectName;
+ CUtlString m_ProjectGUID;
+};
+
+
+struct RegStartPoint
+{
+ HKEY baseKey;
+ const char* const baseDir;
+};
+
+class CSolutionGenerator_Win32 : public IBaseSolutionGenerator
+{
+public:
+ void GetVCPROJSolutionGUID( char (&szSolutionGUID)[256] )
+ {
+ HKEY hKey;
+ int firstVer = 8;
+ const int lastVer = 14; // Handle up to VS 14, AKA VS 2015
+ if ( g_pVPC->Is2010() )
+ {
+ firstVer = 10;
+ }
+ else if ( g_pVPC->BUse2008() )
+ {
+ firstVer = 9;
+ }
+ for ( int vsVer = firstVer; vsVer <= lastVer; ++vsVer )
+ {
+ // Handle both VisualStudio and VCExpress (used by some SourceSDK customers)
+ RegStartPoint searchPoints[] =
+ {
+ { HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VisualStudio\\%d.0\\Projects" }, // Visual Studio Professional
+ { HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\%d.0\\Projects" }, // VC Express 2010 and 2012
+ { HKEY_CURRENT_USER, "Software\\Microsoft\\WDExpress\\%d.0_Config\\Projects" }, // WinDev Express -- VS Express starting with VS 2013
+ };
+ for ( int j = 0; j < ARRAYSIZE(searchPoints); ++j )
+ {
+ RegStartPoint& searchPoint = searchPoints[ j ];
+ char pRegKeyName[1000];
+ V_snprintf( pRegKeyName, ARRAYSIZE(pRegKeyName), searchPoint.baseDir, vsVer );
+ LONG ret = RegOpenKeyEx( searchPoint.baseKey, pRegKeyName, 0, KEY_READ, &hKey );
+ //if ( ret != ERROR_SUCCESS )
+ // g_pVPC->VPCError( "Unable to open registry key %s.", pRegKeyName );
+
+ for ( int i=0; i < 200; i++ )
+ {
+ char szKeyName[MAX_PATH];
+ DWORD dwKeyNameSize = sizeof( szKeyName );
+ ret = RegEnumKeyEx( hKey, i, szKeyName, &dwKeyNameSize, NULL, NULL, NULL, NULL );
+ if ( ret == ERROR_NO_MORE_ITEMS )
+ break;
+
+ HKEY hSubKey;
+ LONG ret = RegOpenKeyEx( hKey, szKeyName, 0, KEY_READ, &hSubKey );
+ if ( ret == ERROR_SUCCESS )
+ {
+ DWORD dwType;
+ char ext[MAX_PATH];
+ DWORD dwExtLen = sizeof( ext );
+ ret = RegQueryValueEx( hSubKey, "DefaultProjectExtension", NULL, &dwType, (BYTE*)ext, &dwExtLen );
+ RegCloseKey( hSubKey );
+
+ // VS 2012 and beyond has the DefaultProjectExtension as vcxproj instead of vcproj
+ if ( ret == ERROR_SUCCESS && dwType == REG_SZ && ( V_stricmp( ext, "vcproj" ) == 0 || V_stricmp( ext, "vcxproj" ) == 0 ) )
+ {
+ V_strncpy( szSolutionGUID, szKeyName, ARRAYSIZE(szSolutionGUID) );
+ RegCloseKey( hKey );
+ return;
+ }
+ }
+ }
+
+ RegCloseKey( hKey );
+ }
+ }
+ g_pVPC->VPCError( "Unable to find RegKey for .vcproj or .vcxproj files in solutions." );
+ }
+
+ virtual void GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects )
+ {
+ // Default extension.
+ char szTmpSolutionFilename[MAX_PATH];
+ if ( !V_GetFileExtension( pSolutionFilename ) )
+ {
+ V_snprintf( szTmpSolutionFilename, sizeof( szTmpSolutionFilename ), "%s.sln", pSolutionFilename );
+ pSolutionFilename = szTmpSolutionFilename;
+ }
+
+ Msg( "\nWriting solution file %s.\n\n", pSolutionFilename );
+
+ char szSolutionGUID[256];
+ GetVCPROJSolutionGUID( szSolutionGUID );
+
+ CUtlVector<CVCProjInfo> vcprojInfos;
+ GetProjectInfos( projects, vcprojInfos );
+
+ // Write the file.
+ FILE *fp = fopen( pSolutionFilename, "wt" );
+ if ( !fp )
+ g_pVPC->VPCError( "Can't open %s for writing.", pSolutionFilename );
+
+
+ if ( g_pVPC->Is2015() )
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 12.00\n" ); // still on 12
+ fprintf( fp, "# Visual Studio 2015\n" );
+ }
+ else if ( g_pVPC->Is2013() )
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 12.00\n" ); // Format didn't change from VS 2012 to VS 2013
+ fprintf( fp, "# Visual Studio 2013\n" );
+ }
+ else if ( g_pVPC->Is2012() )
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 12.00\n" );
+ fprintf( fp, "# Visual Studio 2012\n" );
+ }
+ else if ( g_pVPC->Is2010() )
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 11.00\n" );
+ fprintf( fp, "# Visual Studio 2010\n" );
+ }
+ else if ( g_pVPC->BUse2008() )
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 10.00\n" );
+ fprintf( fp, "# Visual Studio 2008\n" );
+ }
+ else
+ {
+ fprintf( fp, "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 9.00\n" );
+ fprintf( fp, "# Visual Studio 2005\n" );
+ }
+ fprintf( fp, "#\n" );
+ fprintf( fp, "# Automatically generated solution:\n" );
+ fprintf( fp, "# devtools\\bin\\vpc " );
+ for ( int k = 1; k < __argc; ++ k )
+ fprintf( fp, "%s ", __argv[k] );
+ fprintf( fp, "\n" );
+ fprintf( fp, "#\n" );
+ fprintf( fp, "#\n" );
+
+ if ( !g_pVPC->Is2010() )
+ {
+ // if /slnItems <filename> is passed on the command line, build a Solution Items project
+ const char *pSolutionItemsFilename = g_pVPC->GetSolutionItemsFilename();
+ if ( pSolutionItemsFilename[0] != '\0' )
+ {
+ fprintf( fp, "Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{AAAAAAAA-8B4A-11D0-8D11-90A07D6D6F7D}\"\n" );
+ fprintf( fp, "\tProjectSection(SolutionItems) = preProject\n" );
+ WriteSolutionItems( fp );
+ fprintf( fp, "\tEndProjectSection\n" );
+ fprintf( fp, "EndProject\n" );
+ }
+ }
+
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pCurProject = projects[i];
+ CVCProjInfo *pProjInfo = &vcprojInfos[i];
+
+ // Get a relative filename for the vcproj file.
+ const char *pFullProjectFilename = pCurProject->m_ProjectFilename.String();
+ char szRelativeFilename[MAX_PATH];
+ if ( !V_MakeRelativePath( pFullProjectFilename, g_pVPC->GetSourcePath(), szRelativeFilename, sizeof( szRelativeFilename ) ) )
+ g_pVPC->VPCError( "Can't make a relative path (to the base source directory) for %s.", pFullProjectFilename );
+
+ fprintf( fp, "Project(\"%s\") = \"%s\", \"%s\", \"{%s}\"\n", szSolutionGUID, pProjInfo->m_ProjectName.String(), szRelativeFilename, pProjInfo->m_ProjectGUID.String() );
+ bool bHasDependencies = false;
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( i == iTestProject )
+ continue;
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ if ( pCurProject->DependsOn( pTestProject, k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagRecurse ) ||
+ pCurProject->DependsOn( pTestProject, k_EDependsOnFlagCheckAdditionalDependencies | k_EDependsOnFlagTraversePastLibs ) )
+ {
+ if ( !bHasDependencies )
+ {
+ fprintf( fp, "\tProjectSection(ProjectDependencies) = postProject\n" );
+ bHasDependencies = true;
+ }
+ fprintf( fp, "\t\t{%s} = {%s}\n", vcprojInfos[iTestProject].m_ProjectGUID.String(), vcprojInfos[iTestProject].m_ProjectGUID.String() );
+ }
+ }
+ if ( bHasDependencies )
+ fprintf( fp, "\tEndProjectSection\n" );
+
+ fprintf( fp, "EndProject\n" );
+ }
+
+ fclose( fp );
+ Sys_CopyToMirror( pSolutionFilename );
+ }
+
+ const char* FindInFile( const char *pFilename, const char *pFileData, const char *pSearchFor )
+ {
+ const char *pPos = V_stristr( pFileData, pSearchFor );
+ if ( !pPos )
+ {
+ g_pVPC->VPCError( "Can't find %s in %s.", pSearchFor, pFilename );
+ }
+
+ return pPos + V_strlen( pSearchFor );
+ }
+
+ void GetProjectInfos( CUtlVector<CDependency_Project*> &projects, CUtlVector<CVCProjInfo> &vcprojInfos )
+ {
+ for ( int i=0; i < projects.Count(); i++ )
+ {
+ CDependency_Project *pCurProject = projects[i];
+ const char *pFilename = pCurProject->m_ProjectFilename.String();
+
+ CVCProjInfo vcprojInfo;
+
+ char *pFileData;
+ int nResult = Sys_LoadFile( pFilename, (void**)&pFileData, false );
+ if ( nResult == -1 )
+ g_pVPC->VPCError( "Can't open %s to get ProjectGUID.", pFilename );
+
+ const char *pSearchFor;
+ if ( g_pVPC->Is2010() )
+ {
+ pSearchFor = "<ProjectGuid>{";
+ }
+ else
+ {
+ pSearchFor = "ProjectGUID=\"{";
+ }
+
+ const char *pPos = FindInFile( pFilename, pFileData, pSearchFor );
+ char szGuid[37];
+ const char *pGuid = pPos;
+ V_strncpy( szGuid, pGuid, sizeof( szGuid ) );
+ vcprojInfo.m_ProjectGUID = szGuid;
+
+ const char *pEnd;
+ if ( g_pVPC->Is2010() )
+ {
+ pPos = FindInFile( pFilename, pFileData, "<ProjectName>" );
+ pEnd = V_stristr( pPos, "<" );
+ }
+ else
+ {
+ pPos = FindInFile( pFilename, pFileData, "Name=\"" );
+ pEnd = V_stristr( pPos, "\"" );
+ }
+
+ if ( !pEnd || (pEnd - pPos) > 1024 || (pEnd - pPos) <= 0 )
+ g_pVPC->VPCError( "Can't find valid 'Name=' in %s.", pFilename );
+
+ char szName[256];
+ V_strncpy( szName, pPos, (pEnd - pPos) + 1 );
+ vcprojInfo.m_ProjectName = szName;
+
+ vcprojInfos.AddToTail( vcprojInfo );
+
+ free( pFileData );
+ }
+ }
+
+ // Parse g_SolutionItemsFilename, reading in filenames (including wildcards),
+ // and add them to the Solution Items project we're already writing.
+ void WriteSolutionItems( FILE *fp )
+ {
+ char szFullSolutionItemsPath[MAX_PATH];
+ if ( V_IsAbsolutePath( g_pVPC->GetSolutionItemsFilename() ) )
+ V_strncpy( szFullSolutionItemsPath, g_pVPC->GetSolutionItemsFilename(), sizeof( szFullSolutionItemsPath ) );
+ else
+ V_ComposeFileName( g_pVPC->GetStartDirectory(), g_pVPC->GetSolutionItemsFilename(), szFullSolutionItemsPath, sizeof( szFullSolutionItemsPath ) );
+
+ g_pVPC->GetScript().PushScript( szFullSolutionItemsPath );
+
+ int numSolutionItems = 0;
+ while ( g_pVPC->GetScript().GetData() )
+ {
+ // read a line
+ const char *pToken = g_pVPC->GetScript().GetToken( false );
+
+ // strip out \r\n chars
+ char *end = V_strstr( pToken, "\n" );
+ if ( end )
+ {
+ *end = '\0';
+ }
+ end = V_strstr( pToken, "\r" );
+ if ( end )
+ {
+ *end = '\0';
+ }
+
+ // bail on strings too small to be paths
+ if ( V_strlen( pToken ) < 3 )
+ continue;
+
+ // compose an absolute path w/o any ../
+ char szFullPath[MAX_PATH];
+ if ( V_IsAbsolutePath( pToken ) )
+ V_strncpy( szFullPath, pToken, sizeof( szFullPath ) );
+ else
+ V_ComposeFileName( g_pVPC->GetStartDirectory(), pToken, szFullPath, sizeof( szFullPath ) );
+
+ if ( !V_RemoveDotSlashes( szFullPath ) )
+ continue;
+
+ if ( V_strstr( szFullPath, "*" ) != NULL )
+ {
+ // wildcard!
+ char szWildcardPath[MAX_PATH];
+ V_strncpy( szWildcardPath, szFullPath, sizeof( szWildcardPath ) );
+ V_StripFilename( szWildcardPath );
+
+ struct _finddata32_t data;
+ intptr_t handle = _findfirst32( szFullPath, &data );
+ if ( handle != -1L )
+ {
+ do
+ {
+ if ( ( data.attrib & _A_SUBDIR ) == 0 )
+ {
+ // not a dir, just a filename - add it
+ V_ComposeFileName( szWildcardPath, data.name, szFullPath, sizeof( szFullPath ) );
+
+ if ( V_RemoveDotSlashes( szFullPath ) )
+ {
+ fprintf( fp, "\t\t%s = %s\n", szFullPath, szFullPath );
+ ++numSolutionItems;
+ }
+ }
+ } while ( _findnext32( handle, &data ) == 0 );
+
+ _findclose( handle );
+ }
+ }
+ else
+ {
+ // just a file - add it
+ fprintf( fp, "\t\t%s = %s\n", szFullPath, szFullPath );
+ ++numSolutionItems;
+ }
+ }
+
+ g_pVPC->GetScript().PopScript();
+
+ Msg( "Found %d solution files in %s\n", numSolutionItems, g_pVPC->GetSolutionItemsFilename() );
+ }
+};
+
+
+static CSolutionGenerator_Win32 g_SolutionGenerator_Win32;
+IBaseSolutionGenerator* GetSolutionGenerator_Win32()
+{
+ return &g_SolutionGenerator_Win32;
+}
+
diff --git a/external/vpc/utils/vpc/solutiongenerator_xcode.cpp b/external/vpc/utils/vpc/solutiongenerator_xcode.cpp
new file mode 100644
index 0000000..f061ed4
--- /dev/null
+++ b/external/vpc/utils/vpc/solutiongenerator_xcode.cpp
@@ -0,0 +1,2806 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "vpc.h"
+#include "dependencies.h"
+#include "baseprojectdatacollector.h"
+#include "utlsortvector.h"
+#include "checksum_md5.h"
+
+#ifdef WIN32
+#include <direct.h>
+#define mkdir(dir, mode) _mkdir(dir)
+#define getcwd _getcwd
+#define snprintf _snprintf
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+#else
+#include <stdint.h>
+#endif
+
+static const int k_nShellScriptPhasesPerAggregateTarget = 8;
+
+#ifndef STEAM
+bool V_StrSubstInPlace( char *pchInOut, int cchInOut, const char *pMatch, const char *pReplaceWith, bool bCaseSensitive );
+#endif
+
+static const char *k_pchProjects = "Projects";
+static const char *k_pchLegacyTarget = "build with make";
+static const char *k_rgchConfigNames[] = { "Debug", "Release" };
+
+static const char *g_pOption_AdditionalDependencies = "$AdditionalDependencies";
+static const char *g_pOption_BufferSecurityCheck = "$BufferSecurityCheck";
+static const char *g_pOption_BuildMultiArch = "$BuildMultiArch";
+static const char *g_pOption_BuildX64Only = "$BuildX64Only";
+static const char *g_pOption_CompileAs = "$CompileAs";
+static const char *g_pOption_PreBuildEventCommandLine = "$PreBuildEvent/$CommandLine";
+static const char *g_pOption_CustomBuildStepCommandLine = "$CustomBuildStep/$CommandLine";
+static const char *g_pOption_PostBuildEventCommandLine = "$PostBuildEvent/$CommandLine";
+static const char *g_pOption_ConfigurationType = "$ConfigurationType";
+static const char *g_pOption_Description = "$Description";
+static const char *g_pOption_ExtraCompilerFlags = "$GCC_ExtraCompilerFlags";
+static const char *g_pOption_ExtraLinkerFlags = "$GCC_ExtraLinkerFlags";
+static const char *g_pOption_ForceInclude = "$ForceIncludes";
+static const char *g_pOption_LinkAsBundle = "$LinkAsBundle";
+static const char *g_pOption_LocalFrameworks = "$LocalFrameworks";
+static const char *g_pOption_LowerCaseFileNames = "$LowerCaseFileNames";
+static const char *g_pOption_OptimizerLevel = "$OptimizerLevel";
+static const char *g_pOption_OutputDirectory = "$OutputDirectory";
+static const char *g_pOption_Outputs = "$Outputs";
+static const char *g_pOption_PostBuildEvent = "$PostBuildEvent";
+static const char *g_pOption_PrecompiledHeader = "$Create/UsePrecompiledHeader";
+static const char *g_pOption_PrecompiledHeaderFile = "$PrecompiledHeaderFile";
+static const char *g_pOption_SymbolVisibility = "$SymbolVisibility";
+static const char *g_pOption_SystemFrameworks = "$SystemFrameworks";
+static const char *g_pOption_SystemLibraries = "$SystemLibraries";
+static const char *g_pOption_UsePCHThroughFile = "$Create/UsePCHThroughFile";
+static const char *g_pOption_AdditionalLibraryDirectories = "$AdditionalLibraryDirectories";
+static const char *g_pOption_TargetCopies = "$TargetCopies";
+static const char *g_pOption_TreatWarningsAsErrors = "$TreatWarningsAsErrors";
+
+// These are the only properties we care about for xcodeprojects.
+static const char *g_pRelevantProperties[] =
+{
+ g_pOption_AdditionalDependencies,
+ g_pOption_AdditionalIncludeDirectories,
+ g_pOption_AdditionalLibraryDirectories,
+ g_pOption_BufferSecurityCheck,
+ g_pOption_CompileAs,
+ g_pOption_OptimizerLevel,
+ g_pOption_OutputFile,
+ g_pOption_GameOutputFile,
+ g_pOption_SymbolVisibility,
+ g_pOption_PreprocessorDefinitions,
+ g_pOption_ConfigurationType,
+ g_pOption_ImportLibrary,
+ g_pOption_LinkAsBundle,
+ g_pOption_PrecompiledHeader,
+ g_pOption_UsePCHThroughFile,
+ g_pOption_PrecompiledHeaderFile,
+ g_pOption_PreBuildEventCommandLine,
+ g_pOption_CustomBuildStepCommandLine,
+ g_pOption_PostBuildEventCommandLine,
+ g_pOption_OutputDirectory,
+ g_pOption_Outputs,
+ g_pOption_Description,
+ g_pOption_SystemLibraries,
+ g_pOption_SystemFrameworks,
+ g_pOption_LocalFrameworks,
+ g_pOption_BuildMultiArch,
+ g_pOption_BuildX64Only,
+ g_pOption_ExtraCompilerFlags,
+ g_pOption_ExtraLinkerFlags,
+ g_pOption_ForceInclude,
+ g_pOption_TargetCopies,
+ g_pOption_TreatWarningsAsErrors,
+};
+
+
+static CRelevantPropertyNames g_RelevantPropertyNames =
+{
+ g_pRelevantProperties,
+ V_ARRAYSIZE( g_pRelevantProperties )
+};
+
+
+static const char *k_rgchXCConfigFiles[] = { "debug.xcconfig", "release.xcconfig", "base.xcconfig" };
+
+static int k_oidBuildConfigList = 0xc0de;
+static int k_rgOidBuildConfigs[] = { 0x1c0de, 0x1c0e0 };
+
+class CProjectGenerator_Xcode : public CBaseProjectDataCollector
+{
+ typedef CBaseProjectDataCollector BaseClass;
+public:
+ CProjectGenerator_Xcode() : BaseClass( &g_RelevantPropertyNames )
+ {
+ m_bIsCurrent = false;
+ m_nShellScriptPhases = 0;
+ m_nCustomBuildRules = 0;
+ m_nPreBuildEvents = 0;
+ }
+
+ virtual void Setup() {}
+
+ virtual const char *GetProjectFileExtension() { return ""; }
+
+ virtual void EndProject()
+ {
+ m_OutputFilename = g_pVPC->GetOutputFilename();
+ // we need the "project file" to exist for crc checking
+ if ( !Sys_Exists( m_OutputFilename ) )
+ Sys_Touch( m_OutputFilename );
+
+ // remember if we needed rebuild according to vpc
+ m_bIsCurrent = g_pVPC->IsProjectCurrent( g_pVPC->GetOutputFilename(), false );
+
+ // and update the mod time on the file if we needed rebuild
+ if ( !m_bIsCurrent )
+ Sys_Touch( m_OutputFilename );
+
+ extern CUtlVector<CBaseProjectDataCollector*> g_vecPGenerators;
+ g_vecPGenerators.AddToTail( this );
+
+ extern IBaseProjectGenerator *g_pGenerator;
+ g_pVPC->SetProjectGenerator( new CProjectGenerator_Xcode() );
+ }
+
+ bool m_bIsCurrent;
+ int m_nShellScriptPhases;
+ int m_nCustomBuildRules;
+ int m_nPreBuildEvents;
+ CUtlString m_OutputFilename;
+};
+
+// we assume (and assert) that the order of this vector is the same as the order of the projects vector
+extern CUtlVector<CBaseProjectDataCollector*> g_vecPGenerators;
+
+class CSolutionGenerator_Xcode : public IBaseSolutionGenerator
+{
+public:
+ virtual void GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects );
+private:
+ void XcodeFileTypeFromFileName( const char *pszFileName, char *pchOutBuf, int cchOutBuf );
+ void XcodeProductTypeFromFileName( const char *pszFileName, char *pchOutBuf, int cchOutBuf );
+ void EmitBuildSettings( const char *pszProjectName, const char *pszProjectDir, CUtlDict<CFileConfig *,int> *pDictFiles, KeyValues *pConfigKV, KeyValues *pReleaseKV, bool bIsDebug );
+ void WriteFilesFolder( uint64_t oid, const char *pFolderName, const char *pExtensions, CBaseProjectDataCollector *pProject );
+
+ void Write( const char *pMsg, ... );
+ FILE *m_fp;
+ int m_nIndent;
+
+};
+
+enum EOIDType
+{
+ EOIDTypeProject = 0x00001d00,
+ EOIDTypeGroup,
+ EOIDTypeFileReference,
+ EOIDTypeBuildFile,
+ EOIDTypeSourcesBuildPhase,
+ EOIDTypeFrameworksBuildPhase,
+ EOIDTypeCopyFilesBuildPhase,
+ EOIDTypeHeadersBuildPhase,
+ EOIDTypePreBuildPhase,
+ EOIDTypeShellScriptBuildPhase,
+ EOIDTypePostBuildPhase,
+ EOIDTypeNativeTarget,
+ EOIDTypeAggregateTarget,
+ EOIDTypeTargetDependency,
+ EOIDTypeContainerItemProxy,
+ EOIDTypeBuildConfiguration,
+ EOIDTypeConfigurationList,
+ EOIDTypeCustomBuildRule,
+};
+
+// Make an OID from raw data. You probably want makeoid/makeoid2 below.
+uint64_t makeoid_raw( const char *pData, int nDataLen, EOIDType type, int16_t ordinal = 0 )
+{
+ static unsigned int unOIDSalt = 0;
+ static bool bOIDSaltSet = false;
+ // Since the string passed to makeoid() doesn't change based on all parameters of the object it
+ // is representing, we need to regenerate them per-run. There isn't currently much value in
+ // perserving OIDs that refer to the same object in terms of xcode functionality. If we wanted
+ // deterministic OIDs, we should be hashing all parameters of the object that they represent,
+ // which is a non-trivial refactor.
+ if ( !bOIDSaltSet )
+ {
+ // Define this to generate xcode projects with deterministic OIDs (based on solution/project
+ // names, see makeoid callers). See above comment for why this is for debugging only.
+#if defined( VPC_DETERMINISTIC_XCODE_OIDS )
+ unOIDSalt = 0;
+ Msg( "DEBUG: Generating deterministic OIDs per project/solution name (salt -> 0).\n" );
+#else
+ // You'd think our random API would be better here, but it doesn't actually have a function
+ // to return a full-range int and uses the below code to seed itself. Except in tools where
+ // it is un-seeded without a warning that that is the case.
+ float flAppTime = Plat_FloatTime();
+ ThreadId_t threadId = ThreadGetCurrentId();
+ COMPILE_TIME_ASSERT( sizeof( flAppTime ) <= sizeof( unOIDSalt ) );
+ memcpy( &unOIDSalt, &flAppTime, sizeof( float ) );
+ unOIDSalt ^= threadId;
+#endif // defined( VPC_DETERMINISTIC_XCODE_OIDS )
+
+#ifdef VPC_DEBUG_XCODE_OIDS
+ Msg( "XCode Solution: Using random salt for OIDs of %u\n", unOIDSalt );
+#endif
+ bOIDSaltSet = true;
+ }
+
+ // Lower 32bits of OID is hash of identifier string + salt, upper 32bits is type and ordinal.
+ MD5Context_t md5Context;
+ unsigned char hash[ MD5_DIGEST_LENGTH ] = { 0 };
+ MD5Init( &md5Context );
+ MD5Update( &md5Context, (const unsigned char *)&unOIDSalt, sizeof( unOIDSalt ) );
+ MD5Update( &md5Context, (const unsigned char *)pData, nDataLen );
+ MD5Final( hash, &md5Context );
+
+ // Take lower 32bits of md5
+ COMPILE_TIME_ASSERT( MD5_DIGEST_LENGTH >= sizeof( uint32_t ) );
+ uint32_t lowerHash = 0;
+ memcpy( &lowerHash, hash, sizeof( lowerHash ) );
+
+ uint64_t oid = (uint64_t)lowerHash + ((uint64_t)type << 32) + ((uint64_t)(ordinal+1) << 52);
+#ifdef VPC_DEBUG_XCODE_OIDS
+ Msg( "XCode Solution: Produced OID 0x%llx for \"%s\" with salt %u\n", oid, pszIdentifier, unOIDSalt );
+#endif
+ return oid;
+}
+
+// Make an oid for a unique string identifier, per type, per ordinal
+uint64_t makeoid( const char *pszIdentifier, EOIDType type, int16_t ordinal = 0 )
+{
+ CFmtStr oidStr( "oid1.%s", pszIdentifier );
+ return makeoid_raw( oidStr.Access(), oidStr.Length(), type, ordinal );
+}
+
+// Make an oid for a unique string tuple, per type, per ordinal
+uint64_t makeoid2( const char *pszIdentifierA, const char *pszIdentifierB, EOIDType type, int16_t ordinal = 0 )
+{
+ CFmtStr oidStr( "oid2.%s.%s", pszIdentifierA, pszIdentifierB );
+ return makeoid_raw( oidStr.Access(), oidStr.Length(), type, ordinal );
+}
+
+// Make an oid for a unique string tuple, per type, per ordinal
+uint64_t makeoid3( const char *pszIdentifierA, const char *pszIdentifierB, const char *pszIdentifierC, EOIDType type, int16_t ordinal = 0 )
+{
+ CFmtStr oidStr( "oid3.%s.%s.%s", pszIdentifierA, pszIdentifierB, pszIdentifierC );
+ return makeoid_raw( oidStr.Access(), oidStr.Length(), type, ordinal );
+}
+
+static bool IsStaticLibrary( const char *pszFileName )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ return false;
+ else if ( ! V_stricmp( pchExtension, "a" ) )
+ return true;
+ return false;
+}
+
+
+static bool IsDynamicLibrary( const char *pszFileName )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ return false;
+ else if ( ! V_stricmp( pchExtension, "dylib" ) )
+ return true;
+ return false;
+}
+
+static const char* EscapeQuotes( const char *pStr )
+{
+ int len = V_strlen( pStr );
+ static char str[4096];
+ int i = 0,j = 0;
+ for ( ;i <= len,j < V_ARRAYSIZE(str); )
+ {
+ if ( pStr[i] == '"' )
+ {
+ str[j++] = '\\';
+ str[j++] = '\\';
+ }
+ str[j++] = pStr[i++];
+ }
+ str[j] = '\0';
+
+ return str;
+}
+
+static void UsePOSIXSlashes( const char *pStr, char *pOut, int nOutSize )
+{
+ int len = V_strlen( pStr ) + 2;
+ char *str = pOut;
+ AssertFatal( len <= nOutSize );
+
+ V_strncpy( str, pStr, len );
+ for ( int i = 0; i < len; i++ )
+ {
+ if ( str[i] == '\\' )
+ {
+ // allow escaping of bash special characters
+ if ( i+1 < len && ( str[i+1] != '"' && str[i+1] != '$' &&
+ str[i+1] != '\'' && str[i+1] != '\\' ) )
+ {
+ str[i] = '/';
+ }
+ }
+ if ( str[i] == '\0' )
+ break;
+ }
+}
+
+// Auto-allocating (not in-place) version. Caller is responsible for free'ing (or leaking) the allocated buffer. Most
+// users leak. Is bad. :-/
+static char* UsePOSIXSlashes( const char *pStr )
+{
+ int len = V_strlen( pStr ) + 2;
+ char *str = (char*)malloc(len*sizeof(char));
+ UsePOSIXSlashes( pStr, str, len*sizeof(char) );
+ return str;
+}
+
+// Finds the file name component of a path, and prepends 'lib' to it if necesssary
+// foo/bar/foo.a -> foo/bar/libfoo.a
+// foo/bar/libfoo.a -> unchanged
+static void EnforceLibPrefix( char *pInOutStr, int nOutSize )
+{
+ char *pFile = V_UnqualifiedFileName( pInOutStr );
+ if ( pFile && V_strncmp( pFile, "lib", 3 ) != 0 )
+ {
+ char szOriginalName[MAX_PATH] = { 0 };
+ V_strncpy( szOriginalName, pFile, sizeof( szOriginalName ) );
+
+ *pFile = '\0';
+ V_strncat( pInOutStr, "lib", nOutSize );
+ V_strncat( pInOutStr, szOriginalName, nOutSize );
+ }
+}
+
+// Get the output file with the output directory prepended
+static CUtlString OutputFileWithDirectoryFromConfig( KeyValues *pConfigKV )
+{
+ char szOutputFile[MAX_PATH] = { 0 };
+ char szOutputDir[MAX_PATH] = { 0 };
+ UsePOSIXSlashes( pConfigKV->GetString( g_pOption_OutputFile, "" ), szOutputFile, sizeof( szOutputFile ) );
+ UsePOSIXSlashes( pConfigKV->GetString( g_pOption_OutputDirectory, "" ), szOutputDir, sizeof( szOutputDir ) );
+
+ // Our output file is relative to BUILT_PRODUCTS_DIR already. This is a workaround for VPC files expecting Makefile
+ // semantics -- you shouldn't be using $() in VPC strings.
+ const char szObjDir[] = "$(OBJ_DIR)";
+ V_StrSubstInPlace( szOutputDir, sizeof( szOutputDir ), szObjDir, ".", true );
+ V_StrSubstInPlace( szOutputFile, sizeof( szOutputFile ), szObjDir, ".", true );
+
+ // VPC files have snuck in hard-coding of random variables expecting the Makefile backend to expand them.
+ if ( V_strstr( szOutputDir, "$" ) || V_strstr( szOutputFile, "$" ) )
+ {
+ g_pVPC->VPCWarning( "$OutputDirectory '%s' or $OutputFile directive '%s' contains what looks like a shell variable reference -- "
+ "this will be treated literally in most circumstances by the Xcode build system and is likely not intended.",
+ szOutputDir, szOutputFile );
+ }
+
+ char szFormat[MAX_PATH] = { 0 };
+ V_ComposeFileName( szOutputDir, szOutputFile, szFormat, sizeof( szFormat ) );
+ V_RemoveDotSlashes( szFormat );
+
+ // For the output files, which are in the build/"Products" directory, Xcode expects static libs to be named
+ // "libfoo.a" so it can generate a "-lfoo" command to link with projects that depend upon them (vs passing just
+ // ./path/to/foo.a to the linker, which it doesn't want to do for static libraries generated as dependencies, but
+ // will do for random external static libs... I don't know either)
+ if ( IsStaticLibrary( szFormat ) )
+ {
+ EnforceLibPrefix( szFormat, sizeof( szFormat ) );
+ }
+
+ // Some VPC files are giving output files that are trying to reference a path outside the build directory -- this is
+ // what GameOutputFile is for. This actually doesn't seem to break xcode, but isn't really proper and might break
+ // later.
+ if ( V_IsAbsolutePath( szFormat ) || V_strncmp( szFormat, "../", 3 ) == 0 )
+ {
+ g_pVPC->VPCWarning( "Final output file '%s' (composited from $OutputDirectory '%s' and $OutputFile '%s') escapes the relative "
+ "BUILT_PRODUCTS_DIR used by Xcode -- this may break things, and should be achieved by using $GameOutputFile "
+ "to copy built output to the proper tree location",
+ szFormat, szOutputDir, szOutputFile );
+ }
+
+ CUtlString ret( szFormat );
+ return ret;
+}
+
+static CUtlString GameOutputFileFromConfig( KeyValues *pConfigKV )
+{
+ char szGameOutputFile[MAX_PATH] = { 0 };
+ UsePOSIXSlashes( pConfigKV->GetString( g_pOption_GameOutputFile, "" ), szGameOutputFile, sizeof( szGameOutputFile ) );
+ V_RemoveDotSlashes( szGameOutputFile );
+
+ // VPC files have snuck in hard-coding of random variables expecting the Makefile backend to expand them.
+ if ( V_strstr( szGameOutputFile, "$" ) )
+ {
+ g_pVPC->VPCWarning( "$GameOutputFile '%s' contains what looks like a shell variable reference -- "
+ "this will be treated literally in most circumstances by the Xcode build system and is likely not intended.",
+ szGameOutputFile );
+ }
+
+ CUtlString ret( szGameOutputFile );
+ return ret;
+}
+
+static const char* SkipLeadingWhitespace( const char *pStr )
+{
+ if ( !pStr )
+ return NULL;
+ while ( *pStr != '\0' && isspace(*pStr) )
+ pStr++;
+ return pStr;
+}
+
+static bool ProjectProducesBinary( const CBaseProjectDataCollector *pProjectDataCollector )
+{
+ return ( pProjectDataCollector->m_BaseConfigData.m_Configurations[0]->GetOption( g_pOption_OutputFile ) ||
+ pProjectDataCollector->m_BaseConfigData.m_Configurations[0]->GetOption( g_pOption_GameOutputFile ) );
+}
+
+
+static bool NeedsBuildFileEntry( const char *pszFileName )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ return false;
+ else if ( ! V_stricmp( pchExtension, "cpp" ) || ! V_stricmp( pchExtension, "cxx" ) || ! V_stricmp( pchExtension, "cc" ) || ! V_stricmp( pchExtension, "c" ) || ! V_stricmp( pchExtension, "m" ) || ! V_stricmp( pchExtension, "mm" ) || ! V_stricmp( pchExtension, "cc" ) )
+ return true;
+ else if ( ! V_stricmp( pchExtension, "a" ) || ! V_stricmp( pchExtension, "dylib" ) )
+ return true;
+ return false;
+}
+
+
+static bool IsSourceFile( const char *pszFileName )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ return false;
+ else if ( ! V_stricmp( pchExtension, "cpp" ) || ! V_stricmp( pchExtension, "cc" ) || ! V_stricmp( pchExtension, "cxx" ) || ! V_stricmp( pchExtension, "c" ) || ! V_stricmp( pchExtension, "m" ) || ! V_stricmp( pchExtension, "mm" ) || ! V_stricmp( pchExtension, "cc" ) )
+ return true;
+ return false;
+}
+
+static bool FileBuildsWithCustomBuildRule( const CBaseProjectDataCollector *pProjectDataCollector, CFileConfig *pFileConfig )
+{
+ if ( !pFileConfig || !pProjectDataCollector )
+ return false;
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( pProjectDataCollector->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ pProjectDataCollector->m_BaseConfigData.m_Configurations[1] );
+ return ( pFileSpecificData->GetOption( g_pOption_CustomBuildStepCommandLine ) != NULL &&
+ pFileSpecificData->GetOption( g_pOption_AdditionalDependencies ) == NULL );
+
+}
+
+static bool AppearsInSourcesBuildPhase( const CBaseProjectDataCollector *pProjectDataCollector, CFileConfig *pFileConfig )
+{
+ if ( !pFileConfig )
+ return false;
+ return ( IsSourceFile( pFileConfig->m_Filename.String() ) ||
+ ( FileBuildsWithCustomBuildRule( pProjectDataCollector, pFileConfig ) && ProjectProducesBinary( pProjectDataCollector ) ) );
+}
+
+static bool IsCreatedByCustomBuildStep( const CBaseProjectDataCollector *pProjectDataCollector, CFileConfig *pDynamicFileConfig )
+{
+ for ( int i=pProjectDataCollector->m_Files.First(); i != pProjectDataCollector->m_Files.InvalidIndex(); i=pProjectDataCollector->m_Files.Next(i) )
+ {
+ CFileConfig *pFileConfig = pProjectDataCollector->m_Files[i];
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( pProjectDataCollector->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ pProjectDataCollector->m_BaseConfigData.m_Configurations[1] );
+
+ if ( !pFileSpecificData->GetOption( g_pOption_Outputs) )
+ continue;
+
+ CUtlString sOutputFiles;
+ sOutputFiles.SetLength( MAX_PATH );
+ CUtlString sInputFile;
+ sInputFile.SetLength( MAX_PATH );
+ V_snprintf( sInputFile.Get(), MAX_PATH, "%s/%s", pProjectDataCollector->m_ProjectName.String(), UsePOSIXSlashes( pDynamicFileConfig->m_Filename.String() ) );
+ V_RemoveDotSlashes( sInputFile.Get() );
+
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( pFileSpecificData->GetOption( g_pOption_Outputs), sInputFile, sOutputFiles.Get(), MAX_PATH );
+ V_StrSubstInPlace( sOutputFiles.Get(), MAX_PATH, "$(OBJ_DIR)", "${OBJECT_FILE_DIR_normal}", false );
+
+ if ( V_stristr( sOutputFiles, V_UnqualifiedFileName( pDynamicFileConfig->GetName() ) ) && !pFileSpecificData->GetOption( g_pOption_AdditionalDependencies ) )
+ {
+ g_pVPC->VPCWarning( "Not adding '%s' to the build sources list in project '%s', it's a dyanmic file and seems to be created by building '%s'\n",
+ pDynamicFileConfig->GetName(),
+ pProjectDataCollector->m_ProjectName.String(),
+ pFileConfig->GetName() );
+ return true;
+ }
+ }
+ return false;
+}
+
+void ResolveAdditionalProjectDependencies( CDependency_Project *pCurProject, CUtlVector<CDependency_Project*> &projects, CUtlVector<CDependency_Project*> &additionalProjectDependencies )
+{
+ for ( int i=0; i < pCurProject->m_AdditionalProjectDependencies.Count(); i++ )
+ {
+ const char *pLookingFor = pCurProject->m_AdditionalProjectDependencies[i].String();
+
+ int j;
+ for ( j=0; j < projects.Count(); j++ )
+ {
+ if ( V_stricmp( projects[j]->m_ProjectName.String(), pLookingFor ) == 0 )
+ break;
+ }
+
+ if ( j == projects.Count() )
+ g_pVPC->VPCError( "Project %s lists '%s' in its $AdditionalProjectDependencies, but there is no project by that name.", pCurProject->GetName(), pLookingFor );
+
+ additionalProjectDependencies.AddToTail( projects[j] );
+ }
+}
+
+
+void CSolutionGenerator_Xcode::WriteFilesFolder( uint64_t oid, const char *pFolderName, const char *pExtensions, CBaseProjectDataCollector *pProject )
+{
+ const CUtlDict<CFileConfig *,int> &files = pProject->m_Files;
+
+ CUtlVector<char*> extensions;
+ V_SplitString( pExtensions, ";", extensions );
+
+ Write( "%024llX /* %s */ = {\n", oid, pFolderName );
+ ++m_nIndent;
+ Write( "isa = PBXGroup;\n" );
+ Write( "children = (\n" );
+ ++m_nIndent;
+
+ for ( int i=files.First(); i != files.InvalidIndex(); i=files.Next( i ) )
+ {
+ const char *pFileName = files[i]->GetName();
+
+ // Check for duplicates -- projects may reference a file twice, and xcode does not enjoy any
+ // oid being a member of a group twice.
+ int idxDupe = files.Find( pFileName );
+ if ( files.IsValidIndex( idxDupe ) && idxDupe != i )
+ {
+ continue;
+ }
+
+ // Make sure this file's extension is one of the extensions they're asking for.
+ bool bValidExt = false;
+ const char *pFileExtension = V_GetFileExtension( V_UnqualifiedFileName( 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 )
+ {
+ Write( "%024llX /* %s in %s */,\n", makeoid2( pProject->GetProjectName(), pFileName, EOIDTypeFileReference ), UsePOSIXSlashes( pFileName ), pProject->GetProjectName().String() );
+ }
+ }
+
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "name = \"%s\";\n", pFolderName );
+ Write( "sourceTree = \"<group>\";\n" );
+ --m_nIndent;
+ Write( "};\n" );
+}
+
+
+void CSolutionGenerator_Xcode::XcodeFileTypeFromFileName( const char *pszFileName, char *pchOutBuf, int cchOutBuf )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ snprintf( pchOutBuf, cchOutBuf, "compiled.mach-o.executable" );
+ else if ( ! V_stricmp( pchExtension, "cpp" ) || ! V_stricmp( pchExtension, "cxx" ) || ! V_stricmp( pchExtension, "cc" ) || ! V_stricmp( pchExtension, "h" ) || ! V_stricmp( pchExtension, "hxx" ) || ! V_stricmp( pchExtension, "cc" ) )
+ snprintf( pchOutBuf, cchOutBuf, "sourcecode.cpp.%s", pchExtension );
+ else if ( ! V_stricmp( pchExtension, "c" ) )
+ snprintf( pchOutBuf, cchOutBuf, "sourcecode.cpp.cpp" );
+ else if ( ! V_stricmp( pchExtension, "m" ) || ! V_stricmp( pchExtension, "mm" ) )
+ snprintf( pchOutBuf, cchOutBuf, "sourcecode.objc.%s", pchExtension );
+ else if ( ! V_stricmp( pchExtension, "a" ) )
+ snprintf( pchOutBuf, cchOutBuf, "archive.ar" );
+ else if ( ! V_stricmp( pchExtension, "dylib" ) )
+ {
+ const char *pszLibName = V_UnqualifiedFileName( pszFileName );
+ if ( pszLibName[0] == 'l' && pszLibName[1] == 'i' && pszLibName[2] == 'b' )
+ snprintf( pchOutBuf, cchOutBuf, "compiled.mach-o.dylib" );
+ else
+ snprintf( pchOutBuf, cchOutBuf, "compiled.mach-o.bundle" );
+ }
+ else if ( ! V_stricmp( pchExtension, "pl" ) )
+ snprintf( pchOutBuf, cchOutBuf, "text.script.perl" );
+ else
+ snprintf( pchOutBuf, cchOutBuf, "text.plain" );
+}
+
+
+void CSolutionGenerator_Xcode::XcodeProductTypeFromFileName( const char *pszFileName, char *pchOutBuf, int cchOutBuf )
+{
+ const char *pchExtension = V_GetFileExtension( V_UnqualifiedFileName( pszFileName ) );
+ if ( !pchExtension )
+ snprintf( pchOutBuf, cchOutBuf, "com.apple.product-type.tool" );
+ else if ( ! V_stricmp( pchExtension, "a" ) )
+ snprintf( pchOutBuf, cchOutBuf, "com.apple.product-type.library.static" );
+ else if ( ! V_stricmp( pchExtension, "dylib" ) )
+ {
+ snprintf( pchOutBuf, cchOutBuf, "com.apple.product-type.library.dynamic" );
+#if 0
+ const char *pszLibName = V_UnqualifiedFileName( pszFileName );
+ if ( pszLibName[0] != 'l' || pszLibName[1] != 'i' || pszLibName[2] != 'b' )
+ snprintf( pchOutBuf, cchOutBuf, "com.apple.product-type.bundle" );
+#endif
+ }
+ else
+ snprintf( pchOutBuf, cchOutBuf, "com.apple.product-type.unknown" );
+}
+
+// GetBool only groks 1/0, we want more flexibility
+bool IsTrue(const char *str)
+{
+ if ( V_strlen(str) && ( !V_stricmp( str, "yes" ) || !V_stricmp( str, "true" ) || !V_stricmp( str, "1" ) ) )
+ return true;
+ return false;
+}
+
+void CSolutionGenerator_Xcode::EmitBuildSettings( const char *pszProjectName, const char *pszProjectDir, CUtlDict<CFileConfig *,int> *pDictFiles, KeyValues *pConfigKV, KeyValues *pFirstConfigKV, bool bIsDebug )
+{
+ if ( !pConfigKV )
+ {
+ Write( "PRODUCT_NAME = \"%s\";\n", pszProjectName );
+ return;
+ }
+
+ // KeyValuesDumpAsDevMsg( pConfigKV, 0, 0 );
+
+ // Write( "CC = \"$(SOURCE_ROOT)/devtools/bin/osx32/xcode_ccache_wrapper\";\n" );
+ // Write( "LDPLUSPLUS = \"$(DT_TOOLCHAIN_DIR)/usr/bin/clang++\";\n" );
+
+ Write( "ARCHS = (\n" );
+ {
+ ++m_nIndent;
+ bool bBuildX64 = IsTrue(pConfigKV->GetString( g_pOption_BuildX64Only, "" )) || IsTrue(pConfigKV->GetString( g_pOption_BuildMultiArch, "" ) );
+ bool bBuildi386 = !IsTrue( pConfigKV->GetString( g_pOption_BuildX64Only, "" ) );
+ if ( bBuildi386 )
+ Write( "i386,\n" );
+ if ( bBuildX64 )
+ {
+ Write( "x86_64,\n" );
+ }
+ --m_nIndent;
+ }
+ Write( ");\n" );
+
+ // We do not handle Output file names changing between configurations, and use the first configuration for such
+ // things all over the generator. I think we would need to duplicate all the targets to be release and debug
+ // targets. Instead, when generating configurations, just warn that this isn't supported.
+ CUtlString sBuildOutputFile = OutputFileWithDirectoryFromConfig( pFirstConfigKV );
+ CUtlString sGameOutputFile = GameOutputFileFromConfig( pFirstConfigKV );
+ for ( int iConfig = 1; iConfig < V_ARRAYSIZE(k_rgchXCConfigFiles); iConfig++ )
+ {
+ CUtlString sConfigOutputFile = OutputFileWithDirectoryFromConfig( pConfigKV );
+ CUtlString sConfigGameOutputFile = GameOutputFileFromConfig( pConfigKV );
+ if ( sConfigOutputFile != sBuildOutputFile || sConfigGameOutputFile != sGameOutputFile )
+ {
+ g_pVPC->VPCWarning( "Config '%s' for project '%s' has effective output files:\n"
+ " $OutputDirectory/$OutputFile: %s\n"
+ " $GameOutputFile: %s\n"
+ " This differs from the first configuration's output files:\n"
+ " $OutputDirectory/$OutputFile: %s\n"
+ " $GameOutputFile: %s\n"
+ " XCode does not support having differing product names per config,\n"
+ " the first configuration's names will be used for all configs.",
+ k_rgchConfigNames[iConfig], pszProjectName,
+ sConfigOutputFile.String(), sConfigGameOutputFile.String(),
+ sBuildOutputFile.String(), sGameOutputFile.String() );
+ }
+ }
+
+ if ( sGameOutputFile.Length() )
+ {
+ Write( "PRODUCT_NAME = \"%s\";\n", pszProjectName );
+ Write( "EXECUTABLE_NAME = \"%s\";\n", sBuildOutputFile.String() );
+
+ if ( V_strlen( pConfigKV->GetString( g_pOption_ExtraLinkerFlags, "" ) ) )
+ Write( "OTHER_LDFLAGS = \"%s\";\n", pConfigKV->GetString( g_pOption_ExtraLinkerFlags ) );
+
+
+ CUtlString sOtherCompilerCFlags = "OTHER_CFLAGS = \"$(OTHER_CFLAGS) ";
+ CUtlString sOtherCompilerCPlusFlags = "OTHER_CPLUSPLUSFLAGS = \"$(OTHER_CPLUSPLUSFLAGS) ";
+
+ // Buffer overflow checks default to on so only change things
+ // if we need to turn them off.
+ bool bBufferSecurityCheck = Sys_StringToBool( pConfigKV->GetString( g_pOption_BufferSecurityCheck, "Yes" ) );
+ if ( !bBufferSecurityCheck )
+ {
+ sOtherCompilerCFlags += "-fno-stack-protector ";
+ sOtherCompilerCPlusFlags += "-fno-stack-protector ";
+ }
+
+ if ( V_strlen( pConfigKV->GetString( g_pOption_ExtraCompilerFlags, "" ) ) )
+ {
+ sOtherCompilerCFlags += pConfigKV->GetString( g_pOption_ExtraCompilerFlags );
+ sOtherCompilerCPlusFlags += pConfigKV->GetString( g_pOption_ExtraCompilerFlags );
+ }
+
+ if ( V_strlen( pConfigKV->GetString( g_pOption_ForceInclude, "" ) ) )
+ {
+
+ CSplitString outStrings( pConfigKV->GetString( g_pOption_ForceInclude ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ if ( V_strlen( outStrings[i] ) > 2 )
+ {
+ //char sIncludeDir[ MAX_PATH ];
+ char szIncludeLine[ MAX_PATH ];
+ /*V_snprintf( sIncludeDir, sizeof( sIncludeDir ), "%s/%s", pszProjectDir, outStrings[i] );
+ V_FixSlashes( sIncludeDir, '/' );
+ V_RemoveDotSlashes( sIncludeDir );
+ #ifdef STEAM
+ V_StripPrecedingAndTrailingWhitespace( sIncludeDir );
+ #endif */
+ V_snprintf( szIncludeLine, sizeof(szIncludeLine), " -include %s", UsePOSIXSlashes( outStrings[i] ) );
+ sOtherCompilerCFlags += szIncludeLine;
+ sOtherCompilerCPlusFlags += szIncludeLine;
+ }
+ }
+ }
+
+ sOtherCompilerCFlags += "\";\n" ;
+ sOtherCompilerCPlusFlags += "\";\n" ;
+
+ Write( sOtherCompilerCFlags );
+ Write( sOtherCompilerCPlusFlags );
+
+ if ( IsDynamicLibrary( sGameOutputFile ) )
+ {
+ char szBaseName[MAX_PATH] = { 0 };
+ V_StripExtension( V_UnqualifiedFileName( sGameOutputFile ), szBaseName, sizeof( szBaseName ) );
+
+ if ( Sys_StringToBool( pConfigKV->GetString( g_pOption_LinkAsBundle, "No" ) ) )
+ {
+ Write( "MACH_O_TYPE = mh_bundle;\n" );
+ // Bundles can't have versions and they're defaulted to 1
+ // so make sure we have our own no-version properties.
+ Write( "DYLIB_COMPATIBILITY_VERSION = \"\";\n" );
+ Write( "DYLIB_CURRENT_VERSION = \"\";\n" );
+ }
+ else if ( szBaseName[0] != 'l' || szBaseName[1] != 'i' || szBaseName[2] == 'b' )
+ {
+ //if ( !pConfigKV->GetString( g_pOption_LocalFrameworks, NULL ) )
+ // Write( "OTHER_LDFLAGS = \"-flat_namespace\";\n" );
+ // Write( "MACH_O_TYPE = mh_bundle;\n" );
+ // Write( "EXECUTABLE_EXTENSION = dylib;\n" );
+ // Write( "OTHER_LDFLAGS = \"-flat_namespace -undefined suppress\";\n" );
+ }
+ else
+ {
+ Write( "MACH_O_TYPE = mh_dylib;\n" );
+ }
+
+ Write( "LD_DYLIB_INSTALL_NAME = \"@loader_path/%s.dylib\";\n", szBaseName );
+ }
+
+ if ( IsStaticLibrary( sGameOutputFile ) )
+ {
+ Write( "DEBUG_INFORMATION_FORMAT = dwarf;\n" );
+ }
+ }
+ else
+ Write( "PRODUCT_NAME = \"%s\";\n", pszProjectName );
+
+ // add our header search paths
+ CSplitString outStrings( pConfigKV->GetString( g_pOption_AdditionalIncludeDirectories ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ if ( outStrings.Count() )
+ {
+ char sIncludeDir[MAX_PATH];
+
+ // start the iquote list with the project directory
+ V_snprintf( sIncludeDir, sizeof( sIncludeDir ), "%s", pszProjectDir );
+ V_FixSlashes( sIncludeDir, '/' );
+ V_RemoveDotSlashes( sIncludeDir );
+#ifdef STEAM
+ V_StripPrecedingAndTrailingWhitespace( sIncludeDir );
+#endif
+
+ Write( "USER_HEADER_SEARCH_PATHS = (\n" );
+ ++m_nIndent;
+#ifdef STEAM
+ Write( "\"%s\",\n", sIncludeDir );
+#endif
+ for ( int i=0; i < outStrings.Count(); i++ )
+ {
+ char sExpandedOutString[MAX_PATH];
+
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( outStrings[i], CFmtStr( "%s/dummy.txt", pszProjectDir ).Access(), sExpandedOutString, sizeof( sExpandedOutString ) );
+ V_StrSubstInPlace( sExpandedOutString, sizeof( sExpandedOutString ), "$(OBJ_DIR)", "\"${OBJECT_FILE_DIR_normal}\"", false );
+ V_StrSubstInPlace( sExpandedOutString, sizeof( sExpandedOutString ), "\"", "\\\"", false );
+
+ if ( V_IsAbsolutePath( sExpandedOutString ) || V_strncmp( sExpandedOutString, "$", 1 ) == 0 )
+ V_snprintf( sIncludeDir, sizeof( sExpandedOutString ), "%s", sExpandedOutString );
+ else
+ {
+ V_snprintf( sIncludeDir, sizeof( sExpandedOutString ), "%s/%s", pszProjectDir, sExpandedOutString );
+ V_RemoveDotSlashes( sIncludeDir );
+ }
+#ifdef STEAM
+ V_StripPrecedingAndTrailingWhitespace( sIncludeDir );
+#endif
+ Write( "\"%s\",\n", sIncludeDir );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ }
+
+
+ // add local frameworks we link against to the compiler framework search paths
+ CSplitString localFrameworks( pConfigKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ if ( localFrameworks.Count() )
+ {
+ Write( "FRAMEWORK_SEARCH_PATHS = (\n" );
+ ++m_nIndent;
+ {
+ Write( "\"$(inherited)\",\n" );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkPath[MAX_PATH];
+ V_snprintf( rgchFrameworkPath, sizeof( rgchFrameworkPath ), "%s/%s", pszProjectDir, localFrameworks[i] );
+ rgchFrameworkPath[ V_strlen( rgchFrameworkPath ) - V_strlen( V_UnqualifiedFileName( localFrameworks[i] ) ) ] = '\0';
+ V_RemoveDotSlashes( rgchFrameworkPath );
+
+ Write( "\"%s\",\n", rgchFrameworkPath );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ }
+
+ // add our needed preprocessor definitions
+ CSplitString preprocessorDefines( pConfigKV->GetString( g_pOption_PreprocessorDefinitions ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ CUtlVector< macro_t* > vpcMacroDefines;
+ g_pVPC->GetMacrosMarkedForCompilerDefines( vpcMacroDefines );
+ if ( preprocessorDefines.Count() || vpcMacroDefines.Count() )
+ {
+ Write( "GCC_PREPROCESSOR_DEFINITIONS = (\n" );
+ ++m_nIndent;
+ {
+ Write( "\"$(GCC_PREPROCESSOR_DEFINITIONS)\",\n" );
+ for ( int i=0; i < preprocessorDefines.Count(); i++ )
+ {
+ Write( "\"%s\",\n", preprocessorDefines[i] );
+ }
+ for ( int i=0; i < vpcMacroDefines.Count(); i++ )
+ {
+ Write( "\"%s=%s\",\n", vpcMacroDefines[i]->name.String(), vpcMacroDefines[i]->value.String() );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ }
+
+ bool bTreatWarningsAsErrors = Sys_StringToBool( pConfigKV->GetString( g_pOption_TreatWarningsAsErrors, "false" ) );
+ Write( "GCC_TREAT_WARNINGS_AS_ERRORS = %s;\n", bTreatWarningsAsErrors ? "YES" : "NO" );
+
+ CUtlMap<const char *, bool> librarySearchPaths( StringLessThan );
+ if ( pDictFiles )
+ {
+ // libraries we consume (specified in our files list)
+ for ( int i=pDictFiles->First(); i != pDictFiles->InvalidIndex(); i=pDictFiles->Next(i) )
+ {
+ const char *pFileName = (*pDictFiles)[i]->m_Filename.String();
+ if ( IsStaticLibrary( pFileName ) || IsDynamicLibrary( pFileName ) )
+ {
+ char rgchLibPath[MAX_PATH];
+ V_snprintf( rgchLibPath, sizeof( rgchLibPath ), "%s/%s", pszProjectDir, pFileName );
+ V_RemoveDotSlashes( rgchLibPath );
+ V_StripFilename( rgchLibPath );
+ int nIndex = librarySearchPaths.Find( rgchLibPath );
+ if ( nIndex == librarySearchPaths.InvalidIndex() )
+ {
+ char *pszLibPath = new char[MAX_PATH];
+ V_strncpy( pszLibPath, rgchLibPath, MAX_PATH );
+ nIndex = librarySearchPaths.Insert( pszLibPath );
+ }
+ }
+ }
+ }
+
+ // add additional library search paths
+ CSplitString additionalLibraryDirectories( pConfigKV->GetString( g_pOption_AdditionalLibraryDirectories ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i = 0; i < additionalLibraryDirectories.Count(); i++ )
+ {
+ int nIndex = librarySearchPaths.Find( additionalLibraryDirectories[i] );
+ if ( nIndex == librarySearchPaths.InvalidIndex() )
+ {
+ // we need to dup the string so the map can free it later
+ char *pszLibPath = new char[MAX_PATH];
+ V_strncpy( pszLibPath, additionalLibraryDirectories[i], MAX_PATH );
+ nIndex = librarySearchPaths.Insert( pszLibPath );
+ }
+ }
+ if ( librarySearchPaths.Count() )
+ {
+ char sIncludeDir[MAX_PATH];
+
+ // add the library path we know we need to reference
+ Write( "LIBRARY_SEARCH_PATHS = (\n" );
+ ++m_nIndent;
+ {
+ Write( "\"$(inherited)\",\n" );
+ FOR_EACH_MAP_FAST( librarySearchPaths, i )
+ {
+ char sExpandedOutString[MAX_PATH];
+ V_strncpy( sExpandedOutString, librarySearchPaths.Key(i), sizeof( sExpandedOutString ) );
+ V_StrSubstInPlace( sExpandedOutString, sizeof( sExpandedOutString ), "\"", "\\\"", false );
+
+ if ( V_IsAbsolutePath( sExpandedOutString ) || V_strncmp( sExpandedOutString, "$", 1 ) == 0 )
+ V_snprintf( sIncludeDir, sizeof( sExpandedOutString ), "%s", sExpandedOutString );
+ else
+ {
+ V_snprintf( sIncludeDir, sizeof( sExpandedOutString ), "%s/%s", pszProjectDir, sExpandedOutString );
+ V_RemoveDotSlashes( sIncludeDir );
+ }
+
+ Write( "\"%s\",\n", sIncludeDir );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ }
+
+ while ( librarySearchPaths.Count() )
+ {
+ const char *key = librarySearchPaths.Key( librarySearchPaths.FirstInorder() );
+ librarySearchPaths.Remove( key );
+ delete [] key;
+ }
+}
+
+class CStringLess
+{
+public:
+ bool Less( const char *lhs, const char *rhs, void *pCtx )
+ {
+ return ( strcmp( lhs, rhs ) < 0 ? true : false );
+ }
+};
+
+void CSolutionGenerator_Xcode::GenerateSolutionFile( const char *pSolutionFilename, CUtlVector<CDependency_Project*> &projects )
+{
+ CFmtStr oidStrSolutionRoot( "solutionroot.%s", pSolutionFilename );
+ CFmtStr oidStrProjectsRoot( "projectsroot.%s", pSolutionFilename );
+
+ Assert( projects.Count() == g_vecPGenerators.Count() );
+
+ char sPbxProjFile[MAX_PATH];
+ sprintf( sPbxProjFile, "%s.xcodeproj", pSolutionFilename );
+ mkdir( sPbxProjFile, 0777 );
+ sprintf( sPbxProjFile, "%s.xcodeproj/project.pbxproj", pSolutionFilename );
+
+ char sProjProjectListFile[MAX_PATH];
+ V_snprintf( sProjProjectListFile, sizeof( sProjProjectListFile ), "%s.projects", sPbxProjFile );
+
+ bool bUpToDate = !g_pVPC->IsForceGenerate() && Sys_Exists( sPbxProjFile );
+ int64 llSize = 0, llModTime = 0, llLastModTime = 0;
+
+ FOR_EACH_VEC( projects, iProject )
+ {
+ AssertFatal( !V_strcmp( projects[iProject]->m_ProjectName, g_vecPGenerators[iProject]->GetProjectName() ) );
+ // the solution is up-to-date only if all the projects in it were up to date
+ // and the solution was built after the mod time on all the project outputs
+ CProjectGenerator_Xcode *pProjGen = dynamic_cast<CProjectGenerator_Xcode*>(g_vecPGenerators[iProject]);
+ bUpToDate &= pProjGen->m_bIsCurrent;
+ if ( bUpToDate && Sys_FileInfo( pProjGen->m_OutputFilename, llSize, llModTime ) && llModTime > llLastModTime )
+ {
+ llLastModTime = llModTime;
+ }
+ }
+
+ // regenerate pbxproj if it is older than the latest of the project output files
+ if ( bUpToDate && ( !Sys_FileInfo( sPbxProjFile, llSize, llModTime ) || llModTime < llLastModTime ) )
+ {
+ bUpToDate = false;
+ }
+
+ // now go see if our project list agrees with the one on disk
+ if ( bUpToDate )
+ {
+ FILE *fp = fopen( sProjProjectListFile, "r+t" );
+ if ( !fp )
+ bUpToDate = false;
+
+ char line[2048];
+ char *pLine;
+ if ( bUpToDate )
+ {
+ pLine = fgets( line, sizeof(line), fp );
+ if (!pLine)
+ bUpToDate = false;
+ if ( stricmp( line, VPCCRCCHECK_FILE_VERSION_STRING "\n" ) )
+ bUpToDate = false;
+ }
+
+ int cProjectsPreviously = 0;
+ while (bUpToDate)
+ {
+ pLine = fgets( line, sizeof(line), fp );
+ if ( !pLine )
+ break;
+
+ ++cProjectsPreviously;
+
+ int len = strlen( line ) - 1;
+ while ( line[len] == '\n' || line[len] == '\r' )
+ {
+ line[len] = '\0';
+ len--;
+ }
+
+ // N^2 sucks, but N is small
+ bool bProjectFound = false;
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iGenerator];
+ if ( stricmp( pGenerator->m_ProjectName.String(), pLine ) == 0 )
+ {
+ bProjectFound = true;
+ break;
+ }
+ }
+ if ( !bProjectFound )
+ {
+ // fprintf( stderr, "%s has vanished from the project, regenerating...\n", pLine );
+ bUpToDate = false;
+ break;
+ }
+ }
+ if ( g_vecPGenerators.Count() != cProjectsPreviously )
+ {
+ // fprintf( stderr, "Project count has changed (%d/%d), regenerating...\n", cProjectsPreviously, g_vecPGenerators.Count() );
+ bUpToDate = false;
+ }
+ fclose(fp);
+ }
+
+ if ( bUpToDate )
+ {
+ g_pVPC->VPCStatus( true, "Xcode Project %s.xcodeproj looks up-to-date, not generating", pSolutionFilename );
+ return;
+ }
+
+ m_fp = fopen( sPbxProjFile, "wt" );
+ m_nIndent = 0;
+
+ Msg( "\nWriting master Xcode project %s.xcodeproj.\n\n", pSolutionFilename );
+
+ /** header **/
+ Write( "// !$*UTF8*$!\n{\n" );
+ ++m_nIndent;
+ {
+ /**
+ **
+ ** preamble
+ **
+ **/
+ Write( "archiveVersion = 1;\n" );
+ Write( "classes = {\n" );
+ Write( "};\n" );
+ Write( "objectVersion = 44;\n" );
+ Write( "objects = {\n" );
+ {
+ /**
+ **
+ ** buildfiles - any file that's involved in, or the output of, a build phase
+ **
+ **/
+ Write( "\n/* Begin PBXBuildFile section */" );
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ // poke into the project we're looking @ in the dependency projects vector to figure out it's location on disk
+ char rgchProjectDir[MAX_PATH]; rgchProjectDir[0] = '\0';
+ V_strncpy( rgchProjectDir, projects[iGenerator]->m_ProjectFilename.String(), sizeof( rgchProjectDir ) );
+ V_StripFilename( rgchProjectDir );
+
+ // the files this project references
+ for ( int i=g_vecPGenerators[iGenerator]->m_Files.First(); i != g_vecPGenerators[iGenerator]->m_Files.InvalidIndex(); i=g_vecPGenerators[iGenerator]->m_Files.Next(i) )
+ {
+ char rgchFilePath[MAX_PATH];
+ V_snprintf( rgchFilePath, sizeof( rgchFilePath ), "%s/%s", rgchProjectDir, g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename.String() );
+ V_RemoveDotSlashes( rgchFilePath );
+
+ CFileConfig *pFileConfig = g_vecPGenerators[iGenerator]->m_Files[i];
+ const char *pFileName = pFileConfig->m_Filename.String();
+
+ bool bExcluded = true;
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ bExcluded &= ( pFileConfig->IsExcludedFrom( k_rgchConfigNames[iConfig] ) );
+ }
+
+ if ( bExcluded )
+ {
+ g_pVPC->VPCStatus( false, "xcode: excluding File %s\n", pFileName );
+ continue;
+ }
+
+
+ // dynamic files - generated as part of the build - may be automatically added to the build set by xcode,
+ // if we add them twice, bad things (duplicate symbols) happen.
+ bool bIsDynamicFile = pFileConfig->IsDynamicFile( k_rgchConfigNames[1] );
+
+ // if we have a custom build step, we need to include this file in the build set
+ if ( ( !bIsDynamicFile || !IsCreatedByCustomBuildStep( g_vecPGenerators[iGenerator], pFileConfig ) ) && AppearsInSourcesBuildPhase( g_vecPGenerators[iGenerator], g_vecPGenerators[iGenerator]->m_Files[i] ) )
+ {
+ Write( "\n" );
+ CUtlString sCompilerFlags = NULL;
+ // on mac we can only globally specify common (debug and release) per-file compiler flags
+ for ( int i=pFileConfig->m_Configurations.First(); i != pFileConfig->m_Configurations.InvalidIndex(); i=pFileConfig->m_Configurations.Next(i) )
+ {
+ sCompilerFlags += pFileConfig->m_Configurations[i]->m_pKV->GetString( g_pOption_ExtraCompilerFlags );
+ }
+ // File reference OIDs are unique per project per file
+ Write( "%024llX /* %s in Sources */ = {isa = PBXBuildFile; fileRef = %024llX /* %s */; ", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeBuildFile ), V_UnqualifiedFileName( pFileName ), makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeFileReference ), pFileName );
+ if ( !sCompilerFlags.IsEmpty() )
+ {
+ Write( "settings = { COMPILER_FLAGS = \"%s\"; };", sCompilerFlags.String() );
+ }
+ Write( " };" );
+ }
+
+ if ( IsDynamicLibrary( pFileName ) )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s in Frameworks */ = {isa = PBXBuildFile; fileRef = %024llX /* %s */; };", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeBuildFile ), V_UnqualifiedFileName( pFileName ), makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeFileReference ), pFileName );
+ }
+
+ if ( IsStaticLibrary( pFileName ) )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s in Frameworks */ = {isa = PBXBuildFile; fileRef = %024llX /* %s */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeBuildFile ), pFileName,
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pFileName, EOIDTypeFileReference ), pFileName );
+ }
+ }
+
+ // system libraries we link against
+ KeyValues *pKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ CSplitString libs( pKV->GetString( g_pOption_SystemLibraries ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < libs.Count(); i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* lib%s.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = %024llX /* lib%s.dylib */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemLibraries ), EOIDTypeBuildFile, i ), libs[i],
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemLibraries ), EOIDTypeFileReference, i ), libs[i] );
+ }
+
+ // system frameworks we link against
+ CSplitString sysFrameworks( pKV->GetString( g_pOption_SystemFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < sysFrameworks.Count(); i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %024llX /* %s.framework */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemFrameworks ), EOIDTypeBuildFile, i ), sysFrameworks[i],
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemFrameworks ), EOIDTypeFileReference, i ), sysFrameworks[i] );
+ }
+
+ // local frameworks we link against
+ CSplitString localFrameworks( pKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkName[MAX_PATH];
+ V_StripExtension( V_UnqualifiedFileName( localFrameworks[i] ), rgchFrameworkName, sizeof( rgchFrameworkName ) );
+
+ Write( "\n" );
+ Write( "%024llX /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %024llX /* %s.framework */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_LocalFrameworks ), EOIDTypeBuildFile, i ), rgchFrameworkName,
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_LocalFrameworks ), EOIDTypeFileReference, i ), rgchFrameworkName );
+ }
+
+
+ // look at everyone who depends on us, and emit a build file pointing at our output file for each of
+ // them to depend upon. We use the OutputFile (products directory) so XCode's dependency/linking
+ // logic works right.
+ //
+ // The oid has the project in question as the ordinal, so we have a unique build file OID for each
+ // project that wants to depend on us -- they all point to the same file reference.
+ CDependency_Project *pCurProject = projects[iGenerator];
+ CUtlString sGameOutputFile = GameOutputFileFromConfig( pKV );
+ CUtlString sOutputFile = OutputFileWithDirectoryFromConfig( pKV );
+
+ if ( sOutputFile.Length() && ( IsStaticLibrary( sOutputFile ) || IsDynamicLibrary( sOutputFile ) ) )
+ {
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( iGenerator == iTestProject )
+ continue;
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pTestProject, projects, additionalProjectDependencies );
+
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pTestProject->DependsOn( pCurProject, dependsOnFlags ) || additionalProjectDependencies.Find( pCurProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ Write( "\n" );
+ Write( "%024llX /* (lib)%s */ = {isa = PBXBuildFile; fileRef = %024llX /* (lib)%s - depended on by %s */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile, EOIDTypeBuildFile, iTestProject ),
+ sOutputFile.String(),
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile, EOIDTypeFileReference ),
+ sOutputFile.String(),
+ pTestProject->m_ProjectName.String() );
+ }
+ }
+ }
+
+ // Add our our output file and game output file -1 OID for ourselves.
+ if ( sGameOutputFile.Length() )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {isa = PBXBuildFile; fileRef = %024llX /* %s */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sGameOutputFile, EOIDTypeBuildFile, -1 ),
+ sGameOutputFile.String(),
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sGameOutputFile, EOIDTypeFileReference ),
+ sGameOutputFile.String() );
+ }
+
+ if ( sOutputFile.Length() )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s in Products */ = {isa = PBXBuildFile; fileRef = %024llX /* %s */; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile, EOIDTypeBuildFile, -1 ),
+ sOutputFile.String(),
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile, EOIDTypeFileReference ),
+ sOutputFile.String() );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXBuildFile section */\n" );
+
+ Write( "\n/*Begin PBXBuildRule section */\n" );
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iGenerator];
+
+ if ( !ProjectProducesBinary( pGenerator ) )
+ continue;
+
+ char rgchProjectDir[MAX_PATH]; rgchProjectDir[0] = '\0';
+ V_strncpy( rgchProjectDir, projects[iGenerator]->m_ProjectFilename.String(), sizeof( rgchProjectDir ) );
+ V_StripFilename( rgchProjectDir );
+
+ // we don't have an output file - wander the list of files, looking for custom build steps
+ // if we find any, magic up shell scripts to run them
+ for ( int i=g_vecPGenerators[iGenerator]->m_Files.First(); i != g_vecPGenerators[iGenerator]->m_Files.InvalidIndex(); i=g_vecPGenerators[iGenerator]->m_Files.Next(i) )
+ {
+
+ CFileConfig *pFileConfig = g_vecPGenerators[iGenerator]->m_Files[i];
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1] );
+
+ // custom build rules with additional dependencies don't map to pbxbuildrules, we handle them
+ // as custom script phases
+ if ( pFileSpecificData->GetOption( g_pOption_AdditionalDependencies ) )
+ continue;
+
+ CUtlString sCustomBuildCommandLine = pFileSpecificData->GetOption( g_pOption_CustomBuildStepCommandLine );
+ CUtlString sOutputFiles = pFileSpecificData->GetOption( g_pOption_Outputs );
+ CUtlString sCommand;
+
+ if ( sOutputFiles.Length() && !sCustomBuildCommandLine.IsEmpty() )
+ {
+ CUtlString sInputFile;
+ sInputFile.SetLength( MAX_PATH );
+
+ int cCommand = MAX( sCustomBuildCommandLine.Length() * 2, 8 * 1024 );
+ sCommand.SetLength( cCommand );
+
+ Write( "\n" );
+ Write( "%024llX /* PBXbuildRule */ = {\n", makeoid( projects[iGenerator]->m_ProjectName, EOIDTypeCustomBuildRule, pGenerator->m_nCustomBuildRules++ ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXBuildRule;\n" );
+ Write( "compilerSpec = com.apple.compilers.proxy.script;\n" );
+
+ // DoStandardVisualStudioReplacements needs to know where the file is, so make sure it's got a path on it
+ if ( V_IsAbsolutePath( UsePOSIXSlashes( pFileConfig->m_Filename.String() ) ) )
+ V_snprintf( sInputFile.Get(), MAX_PATH, "%s", UsePOSIXSlashes( pFileConfig->m_Filename.String() ) );
+ else
+ {
+ V_snprintf( sInputFile.Get(), MAX_PATH, "%s/%s", rgchProjectDir, UsePOSIXSlashes( pFileConfig->m_Filename.String() ) );
+ V_RemoveDotSlashes( sInputFile.Get() );
+ }
+ Write( "filePatterns = \"%s\";\n", sInputFile.String() );
+ Write( "fileType = pattern.proxy;\n" );
+ Write( "isEditable = 1;\n" );
+
+ Write( "outputFiles = (\n" );
+ ++m_nIndent;
+ {
+ CSplitString outFiles( sOutputFiles, ";" );
+ for ( int i = 0; i < outFiles.Count(); i ++ )
+ {
+ CUtlString sOutputFile;
+ sOutputFile.SetLength( MAX_PATH );
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( outFiles[i], sInputFile, sOutputFile.Get(), MAX_PATH );
+ V_StrSubstInPlace( sOutputFile.Get(), MAX_PATH, "$(OBJ_DIR)", "${OBJECT_FILE_DIR_normal}", false );
+
+ CUtlString sOutputPath;
+ sOutputPath.SetLength( MAX_PATH );
+
+ if ( V_IsAbsolutePath( sOutputFile ) || V_strncmp( outFiles[i], "$", 1 ) == 0 )
+ V_snprintf( sOutputPath.Get(), MAX_PATH, "%s", sOutputFile.String() );
+ else
+ {
+ V_snprintf( sOutputPath.Get(), MAX_PATH, "%s/%s", rgchProjectDir, sOutputFile.String() );
+ V_RemoveDotSlashes( sOutputPath.Get() );
+ }
+ Write( "\"%s\",\n", sOutputPath.String() );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n");
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( sCustomBuildCommandLine, sInputFile, sCommand.Get(), cCommand );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "$(OBJ_DIR)", "\"${OBJECT_FILE_DIR_normal}\"", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, ";", ";\\n", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "\"", "\\\"", false );
+
+ Write( "script = \"#!/bin/bash\\n"
+ "cd %s\\n"
+ "%s\\n"
+ "exit $?\";\n", rgchProjectDir, sCommand.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ }
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/*End PBXBuildRule section */\n" );
+
+ /**
+ **
+ ** file references - any file that appears in the project browser
+ **
+ **/
+ Write( "\n/* Begin PBXFileReference section */" );
+ ++m_nIndent;
+ {
+ // include the xcconfig files
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchXCConfigFiles); iConfig++ )
+ {
+ char rgchFilePath[MAX_PATH];
+ V_snprintf( rgchFilePath, sizeof( rgchFilePath ), "%s.xcodeproj/../devtools/%s", pSolutionFilename, k_rgchXCConfigFiles[iConfig] );
+ V_RemoveDotSlashes( rgchFilePath );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = \"%s\"; path = \"%s\"; sourceTree = \"<absolute>\"; };",
+ makeoid2( oidStrSolutionRoot, k_rgchXCConfigFiles[iConfig], EOIDTypeFileReference ),
+ k_rgchXCConfigFiles[iConfig],
+ k_rgchXCConfigFiles[iConfig],
+ rgchFilePath
+ );
+ }
+
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ // find the project we're looking @ in the dependency projects vector to figure out it's location on disk
+ char rgchProjectDir[MAX_PATH]; rgchProjectDir[0] = '\0';
+ V_strncpy( rgchProjectDir, projects[iGenerator]->m_ProjectFilename.String(), sizeof( rgchProjectDir ) );
+ V_StripFilename( rgchProjectDir );
+
+
+ for ( int i=g_vecPGenerators[iGenerator]->m_Files.First(); i != g_vecPGenerators[iGenerator]->m_Files.InvalidIndex(); i=g_vecPGenerators[iGenerator]->m_Files.Next(i) )
+ {
+ char rgchFilePath[MAX_PATH];
+ V_snprintf( rgchFilePath, sizeof( rgchFilePath ), "%s/%s", rgchProjectDir, g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename.String() );
+ V_RemoveDotSlashes( rgchFilePath );
+
+ const char *pFileName = V_UnqualifiedFileName( g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename.String() );
+
+ char rgchFileType[MAX_PATH];
+
+ // Can't support compiling as different types in different configurations, but that would be insane anyway, right!? Grab the Release settings.
+ CSpecificConfig *pFileSpecificData = g_vecPGenerators[iGenerator]->m_Files[i]->GetOrCreateConfig(
+ g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1] );
+ const char *pCompileAsOption = pFileSpecificData->GetOption( g_pOption_CompileAs );
+ if ( pCompileAsOption && strstr( pCompileAsOption, "(/TC)" ) ) // Compile as C Code (/TC)
+ {
+ strcpy( rgchFileType, "sourcecode.c.c" );
+ }
+ else
+ {
+ XcodeFileTypeFromFileName( pFileName, rgchFileType, sizeof( rgchFileType ) );
+ }
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {isa = PBXFileReference; fileEncoding = 4; explicitFileType = \"%s\"; name = \"%s\"; path = \"%s\"; sourceTree = \"<absolute>\"; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename, EOIDTypeFileReference ),
+ pFileName,
+ rgchFileType,
+ pFileName,
+ rgchFilePath );
+ }
+ KeyValues *pKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+
+ // system libraries we link against
+ CSplitString libs( pKV->GetString( g_pOption_SystemLibraries ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < libs.Count(); i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* lib%s.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = \"lib%s.dylib\"; path = \"usr/lib/lib%s.dylib\"; sourceTree = SDKROOT; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemLibraries ), EOIDTypeFileReference, i ), libs[i], libs[i], libs[i] );
+ }
+
+ // system frameworks we link against
+ CSplitString sysFrameworks( pKV->GetString( g_pOption_SystemFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < sysFrameworks.Count(); i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = \"%s.framework\"; path = \"System/Library/Frameworks/%s.framework\"; sourceTree = SDKROOT; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemFrameworks ), EOIDTypeFileReference, i ), sysFrameworks[i], sysFrameworks[i], sysFrameworks[i] );
+ }
+
+ // local frameworks we link against
+ CSplitString localFrameworks( pKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkName[MAX_PATH];
+ V_StripExtension( V_UnqualifiedFileName( localFrameworks[i] ), rgchFrameworkName, sizeof( rgchFrameworkName ) );
+
+ char rgchFrameworkPath[MAX_PATH];
+ V_snprintf( rgchFrameworkPath, sizeof( rgchFrameworkPath ), "%s/%s", rgchProjectDir, localFrameworks[i] );
+ V_RemoveDotSlashes( rgchFrameworkPath );
+
+ Write( "\n" );
+ Write( "%024llX /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = \"%s.framework\"; path = \"%s\"; sourceTree = \"<absolute>\"; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_LocalFrameworks ), EOIDTypeFileReference, i ), rgchFrameworkName, rgchFrameworkName, rgchFrameworkPath );
+ }
+
+
+ // include the output files (build products) We don't support these changing between configs -- We
+ // check for and warn about this in EmitBuildSettings
+ KeyValues *pConfigKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ const char *pszConfigName = k_rgchConfigNames[0];
+ CUtlString sOutputFile = OutputFileWithDirectoryFromConfig( pConfigKV );
+ if ( sOutputFile.Length() )
+ {
+ char rgchFileType[MAX_PATH];
+ XcodeFileTypeFromFileName( sOutputFile, rgchFileType, sizeof( rgchFileType ) );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {isa = PBXFileReference; explicitFileType = \"%s\"; includeInIndex = 0; path = \"%s\"; sourceTree = BUILT_PRODUCTS_DIR; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile, EOIDTypeFileReference ), sOutputFile.String(), rgchFileType, sOutputFile.String() );
+ }
+
+ // and the gameoutputfile
+ CUtlString sGameOutputFile = GameOutputFileFromConfig( pKV );
+ if ( sGameOutputFile.Length() )
+ {
+ char rgchFilePath[MAX_PATH];
+ V_snprintf( rgchFilePath, sizeof( rgchFilePath ), "%s/%s", rgchProjectDir, sGameOutputFile.String() );
+ V_RemoveDotSlashes( rgchFilePath );
+
+ char rgchFileType[MAX_PATH];
+ XcodeFileTypeFromFileName( sGameOutputFile, rgchFileType, sizeof( rgchFileType ) );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {isa = PBXFileReference; explicitFileType = \"%s\"; includeInIndex = 0; path = \"%s\"; sourceTree = \"<absolute>\"; };",
+ makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sGameOutputFile, EOIDTypeFileReference ), sGameOutputFile.String(), rgchFileType, rgchFilePath );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXFileReference section */\n" );
+
+ /**
+ **
+ ** groups - the file hierarchy displayed in the project
+ **
+ **/
+ Write( "\n/* Begin PBXGroup section */\n" );
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ CUtlVector<char*> folderNames;
+ V_SplitString( "Source Files;Header Files;Resources;VPC Files", ";", folderNames );
+
+ static const char* folderExtensions[] =
+ {
+ "*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.tcl;*.py;*.pl;*.m;*.mm",
+ "*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if",
+ "*.plist;*.strings;*.xib;*.rc;*.proto;*.nut",
+ "*.vpc"
+ };
+
+ FOR_EACH_VEC( folderNames, iFolder )
+ {
+ WriteFilesFolder( makeoid( g_vecPGenerators[iGenerator]->m_ProjectName, EOIDTypeGroup, iFolder+1 ), folderNames[iFolder], folderExtensions[iFolder], g_vecPGenerators[iGenerator] );
+ }
+
+ Write( "%024llX /* %s */ = {\n", makeoid( g_vecPGenerators[iGenerator]->m_ProjectName, EOIDTypeGroup ), g_vecPGenerators[iGenerator]->GetProjectName().String() );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXGroup;\n" );
+ Write( "children = (\n" );
+
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( folderNames, iFolder )
+ {
+ Write( "%024llX /* %s */,\n", makeoid( g_vecPGenerators[iGenerator]->m_ProjectName, EOIDTypeGroup, iFolder+1 ), folderNames[iFolder] );
+ }
+
+ // XCode does not easily support having differing membership/output names per config. We'll
+ // only output the file names for release, then warn below that they are not shifting.
+ KeyValues *pKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+
+ // system libraries we link against
+ CSplitString libs( pKV->GetString( g_pOption_SystemLibraries ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < libs.Count(); i++ )
+ {
+ Write( "%024llX /* lib%s.dylib (system library) */,\n", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemLibraries ), EOIDTypeFileReference, i ), libs[i] );
+ }
+
+ // system frameworks we link against
+ CSplitString sysFrameworks( pKV->GetString( g_pOption_SystemFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < sysFrameworks.Count(); i++ )
+ {
+ Write( "%024llX /* %s.framework (system framework) */,\n", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_SystemFrameworks ), EOIDTypeFileReference, i ), sysFrameworks[i] );
+ }
+
+ // local frameworks we link against
+ CSplitString localFrameworks( pKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkName[MAX_PATH];
+ V_StripExtension( V_UnqualifiedFileName( localFrameworks[i] ), rgchFrameworkName, sizeof( rgchFrameworkName ) );
+
+ Write( "%024llX /* %s.framework (local framework) */,\n", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), pKV->GetString( g_pOption_LocalFrameworks ), EOIDTypeFileReference, i ), rgchFrameworkName );
+ }
+
+ // libraries we consume (specified in our files list)
+ for ( int i=g_vecPGenerators[iGenerator]->m_Files.First(); i != g_vecPGenerators[iGenerator]->m_Files.InvalidIndex(); i=g_vecPGenerators[iGenerator]->m_Files.Next(i) )
+ {
+ CUtlString sFileName = UsePOSIXSlashes( g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename.String() );
+ bool bInclude = IsDynamicLibrary( sFileName );
+ if ( IsStaticLibrary( sFileName ) )
+ {
+ char szAbsoluteFileName[MAX_PATH] = { 0 };
+ V_MakeAbsolutePath( szAbsoluteFileName, sizeof( szAbsoluteFileName ),
+ UsePOSIXSlashes( g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename.String() ),
+ projects[iGenerator]->m_szStoredCurrentDirectory );
+
+ bInclude = true;
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator2 )
+ {
+ // don't include static libs generated by other projects - we'll pull them out of the built products tree
+ KeyValues *pKV = g_vecPGenerators[iGenerator2]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ char szAbsoluteGameOutputFile[MAX_PATH] = { 0 };
+ V_MakeAbsolutePath( szAbsoluteGameOutputFile, sizeof( szAbsoluteGameOutputFile ),
+ GameOutputFileFromConfig( pKV ).String(),
+ projects[iGenerator2]->m_szStoredCurrentDirectory );
+ if ( !V_stricmp( szAbsoluteFileName, szAbsoluteGameOutputFile ) )
+ {
+ bInclude = false;
+ break;
+ }
+ }
+ }
+
+ if ( bInclude )
+ {
+ Write( "%024llX /* %s in Frameworks (explicit) */,\n", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), g_vecPGenerators[iGenerator]->m_Files[i]->m_Filename, EOIDTypeFileReference ), sFileName.String() );
+ }
+ }
+
+ CUtlString sOutputFile = OutputFileWithDirectoryFromConfig( pKV );
+ if ( sOutputFile.Length() )
+ Write( "%024llX /* %s */,\n", makeoid2( g_vecPGenerators[iGenerator]->GetProjectName(), sOutputFile.String(), EOIDTypeFileReference ), sOutputFile.String() );
+ }
+
+ --m_nIndent;
+
+ Write( ");\n" );
+ Write( "name = \"%s\";\n", g_vecPGenerators[iGenerator]->GetProjectName().String() );
+ Write( "sourceTree = \"<group>\";\n" );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+
+ }
+
+ // root group - the top of the displayed hierarchy
+ Write( "%024llX = {\n", makeoid( oidStrProjectsRoot, EOIDTypeGroup ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXGroup;\n" );
+ Write( "children = (\n" );
+
+ // sort the projects by name before we emit the list
+ CUtlSortVector< CUtlString, CStringLess > vecSortedProjectNames;
+ FOR_EACH_VEC( g_vecPGenerators, iGen )
+ {
+ // fprintf( stderr, "inserting %s (%p)\n", g_vecPGenerators[iGen]->GetProjectName().String(), &g_vecPGenerators[iGen]->GetProjectName() );
+ vecSortedProjectNames.Insert( g_vecPGenerators[iGen]->GetProjectName() );
+ }
+
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( vecSortedProjectNames, iProjectName )
+ {
+ // fprintf( stderr, "looking for %s\n", vecSortedProjectNames[iProjectName].String() );
+ // and each project's group (of groups)
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ if ( strcmp( g_vecPGenerators[iGenerator]->m_ProjectName.String(), vecSortedProjectNames[iProjectName] ) )
+ {
+ // fprintf( stderr, " skipping '%s' (%p) != '%s' (%p) (%d, %d)\n", g_vecPGenerators[iGenerator]->GetProjectName().String(), g_vecPGenerators[iGenerator]->GetProjectName().String(), vecSortedProjectNames[iProjectName].String(), vecSortedProjectNames[iProjectName].String(), iGenerator, iProjectName );
+ continue;
+ }
+ // fprintf( stderr, "emitting %s (%d, %d)\n", g_vecPGenerators[iGenerator]->GetProjectName().String(), iGenerator, iProjectName );
+
+ Write( "%024llX /* %s */,\n", makeoid( g_vecPGenerators[iGenerator]->m_ProjectName, EOIDTypeGroup ), g_vecPGenerators[iGenerator]->GetProjectName().String() );
+ break;
+ }
+ }
+
+ // add the build config (.xcconfig) files
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchXCConfigFiles); iConfig++ )
+ {
+ Write( "%024llX /* %s */, \n", makeoid2( oidStrSolutionRoot, k_rgchXCConfigFiles[iConfig], EOIDTypeFileReference ), k_rgchXCConfigFiles[iConfig] );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "sourceTree = \"<group>\";\n" );
+ // make the project follow our coding standards, and use tabs.
+ Write( "usesTabs = 1;\n" );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ m_nIndent--;
+ Write( "\n/* End PBXGroup section */\n" );
+
+
+ /**
+ **
+ ** the sources build phases - each target that compiles source references on of these, it in turn references the source files to be compiled
+ **
+ **/
+ Write( "\n/* Begin PBXSourcesBuildPhase section */" );
+ ++m_nIndent;
+ FOR_EACH_VEC( projects, iProject )
+ {
+ Write( "\n" );
+ Write( "%024llX /* Sources */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeSourcesBuildPhase ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXSourcesBuildPhase;\n" );
+ Write( "buildActionMask = 2147483647;\n" );
+ Write( "files = (\n" );
+ ++m_nIndent;
+ {
+ for ( int i=g_vecPGenerators[iProject]->m_Files.First(); i != g_vecPGenerators[iProject]->m_Files.InvalidIndex(); i=g_vecPGenerators[iProject]->m_Files.Next(i) )
+ {
+ const char *pFileName = g_vecPGenerators[iProject]->m_Files[i]->m_Filename.String();
+ CFileConfig *pFileConfig = g_vecPGenerators[iProject]->m_Files[i];
+
+ if ( AppearsInSourcesBuildPhase( g_vecPGenerators[iProject], pFileConfig ) )
+ {
+ Write( "%024llX /* %s in Sources */,\n", makeoid2( g_vecPGenerators[iProject]->GetProjectName(), pFileName, EOIDTypeBuildFile ), V_UnqualifiedFileName( UsePOSIXSlashes( pFileName ) ) );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( ");\n");
+ Write( "runOnlyForDeploymentPostprocessing = 0;\n" );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXSourcesBuildPhase section */\n" );
+
+
+ /**
+ **
+ ** the frameworks build phases - each target that links libraries (static, dyamic, framework) has one of these, it references the linked thing
+ **
+ **/
+ Write( "\n/* Begin PBXFrameworksBuildPhase section */" );
+ ++m_nIndent;
+ FOR_EACH_VEC( projects, iProject )
+ {
+ Write( "\n" );
+ Write( "%024llX /* Frameworks */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeFrameworksBuildPhase ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXFrameworksBuildPhase;\n" );
+ Write( "buildActionMask = 2147483647;\n" );
+ Write( "files = (\n" );
+ ++m_nIndent;
+ {
+ // libraries we consume (specified in our files list)
+ for ( int i=g_vecPGenerators[iProject]->m_Files.First(); i != g_vecPGenerators[iProject]->m_Files.InvalidIndex(); i=g_vecPGenerators[iProject]->m_Files.Next(i) )
+ {
+ const char *pFileName = g_vecPGenerators[iProject]->m_Files[i]->m_Filename.String();
+ if ( IsStaticLibrary( UsePOSIXSlashes( pFileName ) ) || IsDynamicLibrary( UsePOSIXSlashes( pFileName ) ) )
+ {
+ char szAbsoluteFileName[MAX_PATH] = { 0 };
+ V_MakeAbsolutePath( szAbsoluteFileName, sizeof( szAbsoluteFileName ),
+ UsePOSIXSlashes( g_vecPGenerators[iProject]->m_Files[i]->m_Filename.String() ),
+ projects[iProject]->m_szStoredCurrentDirectory );
+ bool bInclude = true;
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ // Don't include libs generated by other projects - we'll pull them out of the built
+ // products tree. Resolve the absolute path of both, since they are relative to
+ // different projects.
+ KeyValues *pKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ char szAbsoluteGameOutputFile[MAX_PATH] = { 0 };
+ V_MakeAbsolutePath( szAbsoluteGameOutputFile, sizeof( szAbsoluteGameOutputFile ),
+ GameOutputFileFromConfig( pKV ).String(),
+ projects[iGenerator]->m_szStoredCurrentDirectory );
+
+ if ( !V_stricmp( szAbsoluteFileName, szAbsoluteGameOutputFile ) )
+ {
+ bInclude = false;
+ break;
+ }
+ }
+
+ if ( bInclude )
+ {
+ Write( "%024llX /* %s in Frameworks (explicit) */,\n", makeoid2( g_vecPGenerators[iProject]->GetProjectName(), pFileName, EOIDTypeBuildFile ), pFileName );
+ }
+
+ }
+ }
+
+ // libraries from projects we depend on
+ CDependency_Project *pCurProject = projects[iProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ for ( int iTestProject=projects.Count()-1; iTestProject >= 0; --iTestProject )
+ {
+ if ( iProject == iTestProject )
+ continue;
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ // In the PBXBuildFile section each of our dependencies generated an OID pointing to
+ // their output file with our project index as the ordinal. We use the PRODUCTS
+ // directory build file as depending on the final GameOutputFile confuses XCode's linker
+ // logic, and it should not matter (since GameOutputFile is just copying it to a final
+ // destination, so we can depend/link on the products directory intermediate)
+ KeyValues *pKV = g_vecPGenerators[iTestProject]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ CUtlString sOutputFile = OutputFileWithDirectoryFromConfig( pKV );
+ if ( sOutputFile.Length() && ( IsStaticLibrary( sOutputFile ) || IsDynamicLibrary( sOutputFile ) ) )
+ {
+ // The project in question will have generated a BuildFile dependency for us under its name with ordinal set to our index
+ Write( "%024llX /* (lib)%s (dependency) */,\n",
+ makeoid2( g_vecPGenerators[iTestProject]->GetProjectName(), sOutputFile, EOIDTypeBuildFile, iProject ), sOutputFile.String() );
+ }
+ }
+ }
+
+ KeyValues *pKV = g_vecPGenerators[iProject]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+
+ // local frameworks we link against
+ CSplitString localFrameworks( pKV->GetString( g_pOption_LocalFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < localFrameworks.Count(); i++ )
+ {
+ char rgchFrameworkName[MAX_PATH];
+ V_StripExtension( V_UnqualifiedFileName( localFrameworks[i] ), rgchFrameworkName, sizeof( rgchFrameworkName ) );
+
+ Write( "%024llX /* %s in Frameworks (local framework) */,\n", makeoid2( g_vecPGenerators[iProject]->GetProjectName(), pKV->GetString( g_pOption_LocalFrameworks ), EOIDTypeBuildFile, i ), rgchFrameworkName );
+ }
+
+ // system frameworks we link against
+ CSplitString sysFrameworks( pKV->GetString( g_pOption_SystemFrameworks ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < sysFrameworks.Count(); i++ )
+ {
+ Write( "%024llX /* %s in Frameworks (system framework) */,\n", makeoid2( g_vecPGenerators[iProject]->GetProjectName(), pKV->GetString( g_pOption_SystemFrameworks ), EOIDTypeBuildFile, i ), sysFrameworks[i] );
+ }
+
+ // system libraries we link against
+ CSplitString libs( pKV->GetString( g_pOption_SystemLibraries ), (const char**)g_IncludeSeparators, V_ARRAYSIZE(g_IncludeSeparators) );
+ for ( int i=0; i < libs.Count(); i++ )
+ {
+ Write( "%024llX /* %s in Frameworks (system library) */,\n", makeoid2( g_vecPGenerators[iProject]->GetProjectName(), pKV->GetString( g_pOption_SystemLibraries ), EOIDTypeBuildFile, i ), libs[i] );
+ }
+
+ }
+ --m_nIndent;
+ Write( ");\n");
+ Write( "runOnlyForDeploymentPostprocessing = 0;\n" );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXFrameworksBuildPhase section */\n" );
+
+
+ /**
+ **
+ ** the shell script (pre/post build step) build phases - each target that generates a "gameoutputfile" has one of these,
+ ** to p4 edit the target and copy the build result there.
+ **
+ **/
+ Write( "\n/* Begin PBXShellScriptBuildPhase section */" );
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iGenerator];
+ char rgchProjectDir[MAX_PATH]; rgchProjectDir[0] = '\0';
+ V_strncpy( rgchProjectDir, projects[iGenerator]->m_ProjectFilename.String(), sizeof( rgchProjectDir ) );
+ V_StripFilename( rgchProjectDir );
+
+ CUtlString sPreBuildCommandLine = g_vecPGenerators[iGenerator]->m_Files[0]->GetOrCreateConfig( g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1] )->GetOption( g_pOption_PreBuildEventCommandLine );
+ if ( sPreBuildCommandLine.Length() )
+ {
+ CUtlString sCommand;
+ int cCommand = MAX( sPreBuildCommandLine.Length() * 2, 8 * 1024 );
+ sCommand.SetLength( cCommand );
+
+ Write( "\n" );
+ Write( "%024llX /* ShellScript */ = {\n", makeoid( projects[iGenerator]->m_ProjectName, EOIDTypePreBuildPhase, pGenerator->m_nPreBuildEvents++ ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXShellScriptBuildPhase;\n" );
+ Write( "buildActionMask = 2147483647;\n" );
+ Write( "files = (\n" );
+ Write( ");\n" );
+ Write( "inputPaths = (\n);\n" );
+ Write( "name = \"%s\";\n", CFmtStr( "PreBuild Event for %s", projects[iGenerator]->m_ProjectName.String() ).Access() );
+ Write( "outputPaths = (\n);\n" );
+ Write( "runOnlyForDeploymentPostprocessing = 0;\n" );
+ Write( "shellPath = /bin/bash;\n" );
+
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( sPreBuildCommandLine, CFmtStr( "%s/dummy.txt", rgchProjectDir ).Access(), sCommand.Get(), cCommand );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "$(OBJ_DIR)", "\"${OBJECT_FILE_DIR_normal}\"", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, ";", ";\\n", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "\"", "\\\"", false );
+
+ // xcode wants to run your custom shell scripts anytime the pbxproj has changed (which makes some sense - the script might
+ // be different) - we can't and don't want to early out in this case.
+ Write( "shellScript = \"cd %s\\n"
+ "%s\";\n", rgchProjectDir, sCommand.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ // we don't have an output file - wander the list of files, looking for custom build steps
+ // if we find any, magic up shell scripts to run them
+ for ( int i=g_vecPGenerators[iGenerator]->m_Files.First(); i != g_vecPGenerators[iGenerator]->m_Files.InvalidIndex(); i=g_vecPGenerators[iGenerator]->m_Files.Next(i) )
+ {
+
+ CFileConfig *pFileConfig = g_vecPGenerators[iGenerator]->m_Files[i];
+ CSpecificConfig *pFileSpecificData = pFileConfig->GetOrCreateConfig( g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1]->GetConfigName(),
+ g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1] );
+
+ CUtlString sCustomBuildCommandLine = pFileSpecificData->GetOption( g_pOption_CustomBuildStepCommandLine );
+ CUtlString sOutputFiles = pFileSpecificData->GetOption( g_pOption_Outputs );
+ CUtlString sAdditionalDeps = pFileSpecificData->GetOption( g_pOption_AdditionalDependencies );
+ CUtlString sCommand;
+
+ // if the project produces a binary, it's a native target and we'll handle this custom build step
+ // as a build rule unless the custom build has additional dependencies
+ if ( ProjectProducesBinary( pGenerator ) && !sAdditionalDeps.Length() )
+ continue;
+
+ if ( sOutputFiles.Length() && !sCustomBuildCommandLine.IsEmpty() )
+ {
+ CUtlString sInputFile;
+ sInputFile.SetLength( MAX_PATH );
+
+ int cCommand = MAX( sCustomBuildCommandLine.Length() * 2, 8 * 1024 );
+ sCommand.SetLength( cCommand );
+
+ Write( "\n" );
+ Write( "%024llX /* ShellScript */ = {\n", makeoid( projects[iGenerator]->m_ProjectName, EOIDTypeShellScriptBuildPhase, pGenerator->m_nShellScriptPhases++ ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXShellScriptBuildPhase;\n" );
+ Write( "buildActionMask = 2147483647;\n" );
+ Write( "files = (\n" );
+ Write( ");\n" );
+ Write( "inputPaths = (\n" );
+ ++m_nIndent;
+ {
+ // DoStandardVisualStudioReplacements needs to know where the file is, so make sure it's got a path on it
+ if ( V_IsAbsolutePath( UsePOSIXSlashes( pFileConfig->m_Filename.String() ) ) )
+ V_snprintf( sInputFile.Get(), MAX_PATH, "%s", UsePOSIXSlashes( pFileConfig->m_Filename.String() ) );
+ else
+ {
+ V_snprintf( sInputFile.Get(), MAX_PATH, "%s/%s", rgchProjectDir, UsePOSIXSlashes( pFileConfig->m_Filename.String() ) );
+ V_RemoveDotSlashes( sInputFile.Get() );
+ }
+ Write( "\"%s\",\n", sInputFile.String() );
+
+ CSplitString additionalDeps( sAdditionalDeps, ";" );
+ FOR_EACH_VEC( additionalDeps, i )
+ {
+ const char *pchOneFile = additionalDeps[i];
+ if ( *pchOneFile != '\0' )
+ {
+ char szDependency[MAX_PATH];
+ // DoStandardVisualStudioReplacements needs to know where the file is, so make sure it's got a path on it
+ if ( V_IsAbsolutePath( UsePOSIXSlashes( pchOneFile ) ) )
+ V_snprintf( szDependency, MAX_PATH, "%s", UsePOSIXSlashes( pchOneFile ) );
+ else
+ {
+ V_snprintf( szDependency, MAX_PATH, "%s/%s", rgchProjectDir, UsePOSIXSlashes( pchOneFile ) );
+ V_RemoveDotSlashes( szDependency );
+ }
+ Write( "\"%s\",\n", szDependency );
+ }
+ }
+
+ }
+ --m_nIndent;
+ Write( ");\n" );
+
+ CUtlString sDescription;
+ if ( pFileSpecificData->GetOption( g_pOption_Description ) )
+ {
+ int cDescription = V_strlen( pFileSpecificData->GetOption( g_pOption_Description ) ) * 2;
+ sDescription.SetLength( cDescription );
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( pFileSpecificData->GetOption( g_pOption_Description ), sInputFile, sDescription.Get(), cDescription );
+ }
+ else
+ sDescription = CFmtStr( "Custom Build Step for %s", pFileConfig->m_Filename.String() ).Access();
+
+ Write( "name = \"%s\";\n", sDescription.String() );
+
+ Write( "outputPaths = (\n" );
+#define TELL_XCODE_ABOUT_OUTPUT_FILES 1
+#ifdef TELL_XCODE_ABOUT_OUTPUT_FILES
+ // telling xcode about the output files used to cause it's dependency evaluation to
+ // assume that those files had changed anytime the script had run, even if the script
+ // doesn't change them, which caused us to rebuild a bunch of stuff we didn't need to rebuild
+ // but testing with Xcode 6 suggests they fixed that bug, and lying less to the build system is
+ // generally good.
+ ++m_nIndent;
+ {
+ CSplitString outFiles( sOutputFiles, ";" );
+ for ( int i = 0; i < outFiles.Count(); i ++ )
+ {
+ CUtlString sOutputFile;
+ sOutputFile.SetLength( MAX_PATH );
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( outFiles[i], sInputFile, sOutputFile.Get(), MAX_PATH );
+ V_StrSubstInPlace( sOutputFile.Get(), MAX_PATH, "$(OBJ_DIR)", "${OBJECT_FILE_DIR_normal}", false );
+
+ CUtlString sOutputPath;
+ sOutputPath.SetLength( MAX_PATH );
+
+ if ( V_IsAbsolutePath( sOutputFile ) || V_strncmp( outFiles[i], "$", 1 ) == 0 )
+ V_snprintf( sOutputPath.Get(), MAX_PATH, "%s", sOutputFile.String() );
+ else
+ {
+ V_snprintf( sOutputPath.Get(), MAX_PATH, "%s/%s", rgchProjectDir, sOutputFile.String() );
+ V_RemoveDotSlashes( sOutputPath.Get() );
+ }
+ Write( "\"%s\",\n", sOutputPath.String() );
+ }
+ }
+ --m_nIndent;
+#endif
+ Write( ");\n");
+ Write( "runOnlyForDeploymentPostprocessing = 0;\n" );
+ Write( "shellPath = /bin/bash;\n" );
+
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( sCustomBuildCommandLine, sInputFile, sCommand.Get(), cCommand );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "$(OBJ_DIR)", "\"${OBJECT_FILE_DIR_normal}\"", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, ";", ";\\n", false );
+ V_StrSubstInPlace( sCommand.Get(), cCommand, "\"", "\\\"", false );
+
+ // this is something of a dirty ugly hack. it seems that xcode wants to run your custom shell
+ // scripts anytime the pbxproj has changed (which makes some sense - the script might be different)
+ // since we generate one big project, any vpc change means we'll run all the custom
+ // build steps again, which will generate code, and link code, and generally take time
+ // so if this project was up-to-date (i.e. no vpc changes), add an early out that checks if
+ // all the output files are newer than the input files and early out if that's the case
+ CUtlString sConditionalBlock = CFmtStr( "export CANARY_FILE=\\\"%s\\\";\\n", pGenerator->m_OutputFilename.String() ).Access();
+ // uncomment this line to debug the embedded shell script
+ // sConditionalBlock += "set -x\\n";
+ sConditionalBlock += "EARLY_OUT=1\\n"
+ "let LI=$SCRIPT_INPUT_FILE_COUNT-1\\n"
+ "let LO=$SCRIPT_OUTPUT_FILE_COUNT-1\\n"
+ "for j in $(seq 0 $LO); do\\n"
+ " OUTPUT=SCRIPT_OUTPUT_FILE_$j\\n"
+ " if [ \\\"${CANARY_FILE}\\\" -nt \\\"${!OUTPUT}\\\" ]; then\\n"
+ " EARLY_OUT=0\\n"
+ " break\\n"
+ " fi\\n"
+ " for i in $(seq 0 $LI); do\\n"
+ " INPUT=SCRIPT_INPUT_FILE_$i\\n"
+ " if [ \\\"${!INPUT}\\\" -nt \\\"${!OUTPUT}\\\" ]; then\\n"
+ " EARLY_OUT=0\\n"
+ " break 2\\n"
+ " fi\\n"
+ " done\\n"
+ "done\\n";
+
+ sConditionalBlock += "if [ $EARLY_OUT -eq 1 ]; then\\n"
+ " echo \\\"outputs are newer than input, skipping execution...\\\"\\n"
+ " exit 0\\n"
+ "fi\\n";
+ Write( "shellScript = \"cd %s\\n"
+ "%s"
+ "%s\";\n", rgchProjectDir, sConditionalBlock.String(), sCommand.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ }
+ }
+
+ KeyValues *pDebugKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ CUtlString sDebugGameOutputFile = GameOutputFileFromConfig( pDebugKV );
+
+ KeyValues *pReleaseKV = g_vecPGenerators[iGenerator]->m_BaseConfigData.m_Configurations[1]->m_pKV;
+ CUtlString sReleaseGameOutputFile = GameOutputFileFromConfig( pReleaseKV );
+
+ if ( sDebugGameOutputFile.Length() || sReleaseGameOutputFile.Length() )
+ {
+ char rgchDebugFilePath[MAX_PATH];
+ V_snprintf( rgchDebugFilePath, sizeof( rgchDebugFilePath ), "%s/%s", rgchProjectDir, sDebugGameOutputFile.String() );
+ V_RemoveDotSlashes( rgchDebugFilePath );
+
+ char rgchReleaseFilePath[MAX_PATH];
+ V_snprintf( rgchReleaseFilePath, sizeof( rgchReleaseFilePath ), "%s/%s", rgchProjectDir, sReleaseGameOutputFile.String() );
+ V_RemoveDotSlashes( rgchReleaseFilePath );
+
+ Write( "\n" );
+ Write( "%024llX /* ShellScript */ = {\n", makeoid( projects[iGenerator]->m_ProjectName, EOIDTypePostBuildPhase, 0 ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXShellScriptBuildPhase;\n" );
+ Write( "buildActionMask = 2147483647;\n" );
+ Write( "files = (\n" );
+ Write( ");\n" );
+ Write( "inputPaths = (\n" );
+ ++m_nIndent;
+ {
+ Write( "\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}\",\n" );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "name = \"Post-Build Step\";\n" );
+ Write( "outputPaths = (\n" );
+ ++m_nIndent;
+ {
+ V_StrSubstInPlace( rgchDebugFilePath, sizeof( rgchDebugFilePath ), "/lib/osx32/debug/", "/lib/osx32/${CONFIGURATION}/", false );
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( rgchDebugFilePath, rgchDebugFilePath, rgchDebugFilePath, sizeof( rgchDebugFilePath ) );
+ V_StrSubstInPlace( rgchReleaseFilePath, sizeof( rgchReleaseFilePath ), "/lib/osx32/release/", "/lib/osx32/${CONFIGURATION}/", false );
+ CBaseProjectDataCollector::DoStandardVisualStudioReplacements( rgchReleaseFilePath, rgchReleaseFilePath, rgchReleaseFilePath, sizeof( rgchReleaseFilePath ) );
+
+ Write( "\"%s\",\n", rgchDebugFilePath );
+ if ( V_strcmp( rgchDebugFilePath, rgchReleaseFilePath ) )
+ Write( "\"%s\",\n", rgchReleaseFilePath );
+ }
+ --m_nIndent;
+ Write( ");\n");
+ Write( "runOnlyForDeploymentPostprocessing = 0;\n" );
+ Write( "shellPath = /bin/bash;\n" );
+
+ CUtlString strScript( CFmtStr( "shellScript = \"cd %s;\\n", rgchProjectDir ) );
+
+ CUtlString strScriptExtra;
+ bool bHasReleasePostBuildCmd = V_strlen( SkipLeadingWhitespace( pReleaseKV->GetString( g_pOption_PostBuildEventCommandLine, "" ) ) ) > 0;
+ bool bHasDebugPostBuildCmd = V_strlen( SkipLeadingWhitespace( pDebugKV->GetString( g_pOption_PostBuildEventCommandLine, "" ) ) ) > 0;
+ strScriptExtra.Format(
+ "if [ -z \\\"$CONFIGURATION\\\" -a -n \\\"$BUILD_STYLE\\\" ]; then\\n"
+ " CONFIGURATION=${BUILD_STYLE}\\n"
+ "fi\\n"
+ "if [ -z \\\"$CONFIGURATION\\\" ]; then\\n"
+ " echo \\\"Could not determine build configuration.\\\";\\n"
+ " exit 1; \\n"
+ "fi\\n"
+ "CONFIGURATION=$(echo $CONFIGURATION | tr [A-Z] [a-z])\\n"
+ "OUTPUTFILE=\\\"%s\\\"\\n"
+ "if [ -z \\\"$VALVE_NO_AUTO_P4\\\" ]; then\\n"
+ " P4_EDIT_CHANGELIST_CMD=\\\"p4 changes -c $(p4 client -o | grep ^Client | cut -f 2) -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1\\\"\\n"
+ " P4_EDIT_CHANGELIST=$(eval \\\"$P4_EDIT_CHANGELIST_CMD\\\")\\n"
+ " if [ -z \\\"$P4_EDIT_CHANGELIST\\\" ]; then\\n"
+ " P4_EDIT_CHANGELIST=$(echo -e \\\"Change: new\\\\nDescription: POSIX Auto Checkout\\\" | p4 change -i | cut -f 2 -d ' ')\\n"
+ " fi\\n"
+ "fi\\n"
+ "if [ -f \\\"$OUTPUTFILE\\\" -o -d \\\"$OUTPUTFILE.dSYM\\\" ]; then\\n"
+ " if [ -z \\\"$VALVE_NO_AUTO_P4\\\" ]; then\\n"
+ " p4 edit -c $P4_EDIT_CHANGELIST \\\"$OUTPUTFILE...\\\" | grep -v \\\"also opened\\\"\\n"
+ " else\\n"
+ " if [ -f \\\"$OUTPUTFILE\\\" ]; then\\n"
+ " chmod -f +w \\\"$OUTPUTFILE\\\"\\n"
+ " fi\\n"
+ " if [ -d \\\"$OUTPUTFILE.dSYM\\\" ]; then\\n"
+ " chmod -R -f +w \\\"$OUTPUTFILE.dSYM\\\"\\n"
+ " fi\\n"
+ " fi\\n"
+ "fi\\n"
+ "set -eu\\n"
+ "if [ -d \\\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}.dSYM\\\" ]; then\\n"
+ " echo \\\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}.dSYM -> ${OUTPUTFILE}.dSYM\\\"\\n"
+ " rm -rf \\\"${OUTPUTFILE}.dSYM\\\"\\n"
+ " cp -pR \\\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}.dSYM\\\" \\\"${OUTPUTFILE}.dSYM\\\"\\n"
+ "fi\\n"
+ "cp -pv \\\"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}\\\" \\\"$OUTPUTFILE\\\"\\n"
+ "# POST-BUILD:\\n"
+ "set -e\\n"
+ "if [ ${CONFIGURATION} == \\\"release\\\" ]; then\\n"
+ " %s\\n"
+ "elif [ ${CONFIGURATION} == \\\"debug\\\" ]; then\\n"
+ " %s\\n"
+ "fi\\n"
+ "\";\n",
+ rgchReleaseFilePath,
+ bHasReleasePostBuildCmd ? UsePOSIXSlashes( pReleaseKV->GetString( g_pOption_PostBuildEventCommandLine, "true" ) ) : "true",
+ bHasDebugPostBuildCmd ? UsePOSIXSlashes( pDebugKV->GetString( g_pOption_PostBuildEventCommandLine, "true" ) ) : "true" );
+
+ strScript += strScriptExtra;
+ Write( strScript.Get() );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXShellScriptBuildPhase section */\n" );
+
+ /**
+ **
+ ** nativetargets section - build targets, which ultimately reference build phases
+ **
+ **/
+ Write( "\n/* Begin PBXNativeTarget section */" );
+ ++m_nIndent;
+ FOR_EACH_VEC( projects, iProject )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iProject];
+
+ KeyValues *pKV = g_vecPGenerators[iProject]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ CUtlString sGameOutputFile = GameOutputFileFromConfig( pKV );
+ if ( !sGameOutputFile.Length() )
+ continue;
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget ), projects[iProject]->m_ProjectName.String() );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXNativeTarget;\n" );
+
+ Write( "buildConfigurationList = %024llX /* Build configuration list for PBXNativeTarget \"%s\" */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeConfigurationList ), projects[iProject]->m_ProjectName.String() );
+ Write( "buildPhases = (\n" );
+ ++m_nIndent;
+ {
+ for ( int i = 0; i < pGenerator->m_nPreBuildEvents; i++ )
+ Write( "%024llX /* PreBuildEvent */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypePreBuildPhase, i ) );
+ for ( int i = 0; i < pGenerator->m_nShellScriptPhases; i++ )
+ Write( "%024llX /* ShellScript */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeShellScriptBuildPhase, i ) );
+ Write( "%024llX /* Sources */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeSourcesBuildPhase ) );
+ Write( "%024llX /* Frameworks */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeFrameworksBuildPhase ) );
+ Write( "%024llX /* PostBuildPhase */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypePostBuildPhase, 0 ) );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "buildRules = (\n" );
+ ++m_nIndent;
+ {
+ for ( int i = 0; i < pGenerator->m_nCustomBuildRules; i++ )
+ Write( "%024llX /* PBXBuildRule */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeCustomBuildRule, i ) );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "dependencies = (\n" );
+ ++m_nIndent;
+ {
+ // these dependencies point to the dependency objects, which reference other projects through the container item proxy objects
+ CDependency_Project *pCurProject = projects[iProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( iProject == iTestProject )
+ continue;
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ Write( "%024llX /* %s */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, (uint16_t)iTestProject ), pTestProject->GetName() );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "productName = \"%s\";\n", projects[iProject]->m_ProjectName.String() );
+ Write( "name = \"%s\";\n", projects[iProject]->m_ProjectName.String() );
+
+ if ( sGameOutputFile.Length() )
+ {
+ Write( "productReference = %024llX /* %s */;\n", makeoid2( projects[iProject]->m_ProjectName, sGameOutputFile, EOIDTypeFileReference ), sGameOutputFile.String() );
+ }
+
+ char rgchProductType[MAX_PATH];
+ XcodeProductTypeFromFileName( V_UnqualifiedFileName( sGameOutputFile ), rgchProductType, sizeof( rgchProductType ) );
+ Write( "productType = \"%s\";\n", rgchProductType );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXNativeTarget section */\n" );
+
+ /**
+ **
+ ** aggregate targets - for targets that have no output files (i.e. are scripts)
+ ** and the "all" target
+ **
+ **/
+ Write( "\n/* Begin PBXAggregateTarget section */\n" );
+ ++m_nIndent;
+ {
+ Write( "%024llX /* All */ = {\n", makeoid( oidStrSolutionRoot, EOIDTypeAggregateTarget ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXAggregateTarget;\n" );
+ Write( "buildConfigurationList = %024llX /* Build configuration list for PBXAggregateTarget \"All\" */;\n", makeoid( oidStrSolutionRoot, EOIDTypeConfigurationList, 1 ) );
+ Write( "buildPhases = (\n" );
+ Write( ");\n" );
+ Write( "dependencies = (\n" );
+ ++m_nIndent;
+ {
+ FOR_EACH_VEC( projects, iProject )
+ {
+ // note the sneaky -1 ordinal here, is we can later generate a dependency block for the target thats not tied to any other targets dependency.
+ Write( "%024llX /* PBXProjectDependency */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, -1 ) );
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "name = All;\n" );
+ Write( "productName = All;\n" );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+
+ FOR_EACH_VEC( projects, iProject )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iProject];
+ KeyValues *pKV = g_vecPGenerators[iProject]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ CUtlString sOutputFile = OutputFileWithDirectoryFromConfig( pKV );
+ if ( sOutputFile.Length() )
+ continue;
+
+ // NOTE: the use of EOIDTypeNativeTarget here is intentional - a project will never appear as both, and this makes things link up without
+ // having to special case in dependencies and aggregate targets
+ // NOTE: the driving loop is the number of shell script phases we have - aggregate targets with > 1 shell script phase
+ // get broken into N aggregate targets, each with 1 shell script phase so xcode can execute them in parallel
+ int cSubAggregateTargets = ( pGenerator->m_nShellScriptPhases / k_nShellScriptPhasesPerAggregateTarget ) + ( pGenerator->m_nShellScriptPhases % k_nShellScriptPhasesPerAggregateTarget ? 1 : 0);
+ for ( int i = 0; i < cSubAggregateTargets; i++ )
+ {
+ Write( "%024llX /* %s_%d */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget, i ), projects[iProject]->m_ProjectName.String(), i );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXAggregateTarget;\n" );
+
+ Write( "buildConfigurationList = %024llX /* Build configuration list for PBXAggregateTarget \"%s\" */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeConfigurationList ), projects[iProject]->m_ProjectName.String() );
+ Write( "buildPhases = (\n" );
+ ++m_nIndent;
+ {
+ for (int j = 0; j < k_nShellScriptPhasesPerAggregateTarget; j++)
+ Write( "%024llX /* ShellScript %d/%d*/,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeShellScriptBuildPhase, i*k_nShellScriptPhasesPerAggregateTarget+j ), i*k_nShellScriptPhasesPerAggregateTarget+j+1, pGenerator->m_nShellScriptPhases );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+
+ Write( "buildRules = (\n" );
+ ++m_nIndent;
+ {
+ // Aggregate targets don't get build rules
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "dependencies = (\n" );
+ ++m_nIndent;
+ {
+ // these dependencies point to the dependency objects, which reference other projects through the container item proxy objects
+ CDependency_Project *pCurProject = projects[iProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( iProject == iTestProject )
+ {
+ // the "parent" aggregate depends on all the subaggregates, so the vpc dependency structure doesn't need to
+ // change.
+ if ( i == 0)
+ for ( int j = 1; j < cSubAggregateTargets; j++)
+ // the 0-(j+1) is to avoid colliding with the All aggregate dependency at -1
+ Write( "%024llX /* %s_%d (subproject) */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, 0-(j+1) ), pCurProject->m_ProjectName.String(), j );
+ continue;
+ }
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ Write( "%024llX /* %s */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, (uint16_t)iTestProject ), pTestProject->GetName() );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ if ( i == 0 )
+ {
+ Write( "name = \"%s\";\n", projects[iProject]->m_ProjectName.String() );
+ Write( "productName = \"%s\";\n", projects[iProject]->m_ProjectName.String() );
+ }
+ else
+ {
+ Write( "name = \"%s_%d\";\n", projects[iProject]->m_ProjectName.String(), i );
+ Write( "productName = \"%s_%d\";\n", projects[iProject]->m_ProjectName.String(), i );
+ }
+ }
+ --m_nIndent;
+ Write( "};\n" );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXAggregateTarget section */\n" );
+
+ /**
+ **
+ ** project section - the top-level object that ties all the bits (targets, groups, ...) together
+ **
+ **/
+ Write( "\n/* Begin PBXProject section */\n" );
+ ++m_nIndent;
+ Write( "%024llX /* project object */ = {\n", makeoid( oidStrSolutionRoot, EOIDTypeProject ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXProject;\n" );
+ Write( "attributes = {\n" );
+ ++m_nIndent;
+ {
+ Write( "BuildIndependentTargetsInParallel = YES;\n" );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+ Write( "buildConfigurationList = %024llX /* Build configuration list for PBXProject \"%s\" */;\n", makeoid( oidStrSolutionRoot, EOIDTypeConfigurationList ), V_UnqualifiedFileName( UsePOSIXSlashes( pSolutionFilename ) ) );
+ Write( "compatibilityVersion = \"Xcode 3.0\";\n" );
+ Write( "hasScannedForEncodings = 0;\n" );
+ Write( "mainGroup = %024llX;\n", makeoid( oidStrProjectsRoot, EOIDTypeGroup ) );
+ Write( "productRefGroup = %024llX /* Products */;\n", makeoid( oidStrSolutionRoot, EOIDTypeGroup ) );
+ Write( "projectDirPath = \"\";\n" );
+ Write( "projectRoot = \"\";\n" );
+ Write( "targets = (\n" );
+ ++m_nIndent;
+ {
+ Write( "%024llX /* All */,\n", makeoid( oidStrSolutionRoot, EOIDTypeAggregateTarget ) );
+ // sort the projects by name before we emit the list
+ CUtlSortVector< CUtlString, CStringLess > vecSortedProjectNames;
+ FOR_EACH_VEC( g_vecPGenerators, iGen )
+ {
+ vecSortedProjectNames.Insert( g_vecPGenerators[iGen]->GetProjectName() );
+ }
+ FOR_EACH_VEC( vecSortedProjectNames, iProjectName )
+ {
+ FOR_EACH_VEC( projects, iProject )
+ {
+ if ( strcmp( projects[iProject]->m_ProjectName.String(), vecSortedProjectNames[iProjectName] ) )
+ {
+ continue;
+ }
+ Write( "%024llX /* %s */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget ), projects[iProject]->m_ProjectName.String() );
+ // if this is an aggregate target with more than one shell script, emit the "child" aggregates
+ if ( !ProjectProducesBinary( ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject]) ) )
+ {
+ int cSubAggregateTargets = ( ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject])->m_nShellScriptPhases / k_nShellScriptPhasesPerAggregateTarget ) + ( ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject])->m_nShellScriptPhases % k_nShellScriptPhasesPerAggregateTarget ? 1 : 0 );
+ for ( int i=1; i < cSubAggregateTargets; i++ )
+ Write( "%024llX /* %s_%d */,\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget, i ), projects[iProject]->m_ProjectName.String(), i );
+ }
+ }
+ }
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ }
+ --m_nIndent;
+ Write( "};" );
+ Write( "\n/* End PBXProject section */\n" );
+
+ /**
+ **
+ ** container item proxies (no clue, I just work here...) - they sit between projects when expressing dependencies
+ **
+ **/
+ Write( "\n/* Begin PBXContainerItemProxy section */" );
+ {
+ FOR_EACH_VEC( projects, iProject )
+ {
+
+ // for the aggregate target
+ Write( "\n" );
+ Write( "%024llX /* PBXContainerItemProxy */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, -1 ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXContainerItemProxy;\n" );
+ // it looks like if you cross ref between xcodeprojs, this is the oid for the other xcode proj
+ Write( "containerPortal = %024llX; /* Project object */\n", makeoid( oidStrSolutionRoot, EOIDTypeProject ) );
+ Write( "proxyType = 1;\n" );
+ Write( "remoteGlobalIDString = %024llX;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget ) );
+ Write( "remoteInfo = \"%s\";\n", projects[iProject]->m_ProjectName.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ // for each project, figure out what projects it depends on, and spit out a containeritemproxy for that dependency
+ // of particular note is that there are many item proxies for a given project, so we make their oids with the ordinal
+ // of the project they depend on - this must be consistent within the generated solution
+ CDependency_Project *pCurProject = projects[iProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( iProject == iTestProject )
+ {
+ int cSubAggregateTargets = ( ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject])->m_nShellScriptPhases / k_nShellScriptPhasesPerAggregateTarget ) + ( ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject])->m_nShellScriptPhases % k_nShellScriptPhasesPerAggregateTarget ? 1 : 0 );
+ for ( int i = 1; i < cSubAggregateTargets; i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* PBXContainerItemProxy (subproject) */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, 0-(i+1) ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXContainerItemProxy;\n" );
+ // it looks like if you cross ref between xcodeprojs, this is the oid for the other xcode proj
+ Write( "containerPortal = %024llX; /* Project object */\n", makeoid( oidStrSolutionRoot, EOIDTypeProject ) );
+ Write( "proxyType = 1;\n" );
+ Write( "remoteGlobalIDString = %024llX;\n", makeoid( projects[iTestProject]->m_ProjectName, EOIDTypeNativeTarget, i ) );
+ Write( "remoteInfo = \"%s\";\n", projects[iTestProject]->m_ProjectName.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ continue;
+ }
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ Write( "\n" );
+ Write( "%024llX /* PBXContainerItemProxy */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, (uint16_t)iTestProject ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXContainerItemProxy;\n" );
+ // it looks like if you cross ref between xcodeprojs, this is the oid for the other xcode proj
+ Write( "containerPortal = %024llX; /* Project object */\n", makeoid( oidStrSolutionRoot, EOIDTypeProject ) );
+ Write( "proxyType = 1;\n" );
+ Write( "remoteGlobalIDString = %024llX;\n", makeoid( projects[iTestProject]->m_ProjectName, EOIDTypeNativeTarget ) );
+ Write( "remoteInfo = \"%s\";\n", projects[iTestProject]->m_ProjectName.String() );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ }
+ }
+ }
+ Write( "\n/* End PBXContainerItemProxy section */\n" );
+
+ /**
+ **
+ ** target dependencies - referenced by each project, in turn references the proxy container objects to express dependencies between targets
+ **
+ **/
+ Write( "\n/* Begin PBXTargetDependency section */" );
+ FOR_EACH_VEC( projects, iProject )
+ {
+ Write( "\n" );
+ Write( "%024llX /* PBXTargetDependency */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, -1 ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXTargetDependency;\n" );
+ Write( "target = %024llX /* %s */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget ), projects[iProject]->m_ProjectName.String() );
+ Write( "targetProxy = %024llX /* PBXContainerItemProxy */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, -1 ) );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ CDependency_Project *pCurProject = projects[iProject];
+
+ CUtlVector<CDependency_Project*> additionalProjectDependencies;
+ ResolveAdditionalProjectDependencies( pCurProject, projects, additionalProjectDependencies );
+
+ for ( int iTestProject=0; iTestProject < projects.Count(); iTestProject++ )
+ {
+ if ( iProject == iTestProject )
+ {
+ for ( int i = 1; i < ((CProjectGenerator_Xcode*)g_vecPGenerators[iProject])->m_nShellScriptPhases; i++ )
+ {
+ Write( "\n" );
+ Write( "%024llX /* PBXTargetDependency */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, 0-(i+1) ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXTargetDependency;\n" );
+ Write( "target = %024llX /* %s_%d */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget, i ), projects[iProject]->m_ProjectName.String(), i );
+ Write( "targetProxy = %024llX /* PBXContainerItemProxy */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, 0-(i+1) ) );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ continue;
+ }
+
+ CDependency_Project *pTestProject = projects[iTestProject];
+ int dependsOnFlags = k_EDependsOnFlagTraversePastLibs | k_EDependsOnFlagCheckNormalDependencies | k_EDependsOnFlagRecurse;
+ if ( pCurProject->DependsOn( pTestProject, dependsOnFlags ) || additionalProjectDependencies.Find( pTestProject ) != additionalProjectDependencies.InvalidIndex() )
+ {
+ // project_t *pTestProjectT = &g_projects[ pTestProject->m_iProjectIndex ];
+ Write( "\n" );
+ Write( "%024llX /* PBXTargetDependency */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeTargetDependency, (uint16_t)iTestProject ) );
+ ++m_nIndent;
+ {
+ Write( "isa = PBXTargetDependency;\n" );
+ Write( "target = %024llX /* %s */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeNativeTarget ), projects[iProject]->m_ProjectName.String() );
+ Write( "targetProxy = %024llX /* PBXContainerItemProxy */;\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeContainerItemProxy, (uint16_t)iTestProject ) );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End PBXTargetDependency section */\n" );
+
+
+ /**
+ **
+ ** build configurations - each target (and the project) has a set of build configurations (one release, one debug), each with their own set of build settings
+ ** the "baseConfigurationReference" points back to the appropriate .xcconfig file that gets referenced by the project and has all the non-target specific settings
+ **
+ **/
+
+ Write( "\n/* Begin XCBuildConfiguration section */" );
+ ++m_nIndent;
+ {
+ // project and aggregate "all" target
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ bool bIsDebug = !V_stristr( k_rgchConfigNames[iConfig], "release" );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {\n", makeoid2( oidStrSolutionRoot, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration ), k_rgchConfigNames[iConfig] );
+ ++m_nIndent;
+ {
+ Write( "isa = XCBuildConfiguration;\n" );
+ Write( "baseConfigurationReference = %024llX /* %s */;\n", makeoid2( oidStrSolutionRoot, k_rgchXCConfigFiles[iConfig], EOIDTypeFileReference ), k_rgchXCConfigFiles[iConfig] );
+ Write( "buildSettings = {\n" );
+ ++m_nIndent;
+ {
+ EmitBuildSettings( "All", NULL, NULL, NULL, NULL, bIsDebug );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+ Write( "name = \"%s\";\n", k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {\n", makeoid2( oidStrSolutionRoot, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration, 1 ), k_rgchConfigNames[iConfig] );
+ ++m_nIndent;
+ {
+ Write( "isa = XCBuildConfiguration;\n" );
+ Write( "baseConfigurationReference = %024llX /* %s */;\n", makeoid2( oidStrSolutionRoot, k_rgchXCConfigFiles[iConfig], EOIDTypeFileReference ), k_rgchXCConfigFiles[iConfig] );
+ Write( "buildSettings = {\n" );
+ ++m_nIndent;
+ {
+ EmitBuildSettings( "All", NULL, NULL, NULL, NULL, bIsDebug );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+ Write( "name = \"%s\";\n", k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+
+ FOR_EACH_VEC( projects, iProject )
+ {
+ KeyValues *pReleaseKV = g_vecPGenerators[iProject]->m_BaseConfigData.m_Configurations[0]->m_pKV;
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ bool bIsDebug = !V_stristr( k_rgchConfigNames[iConfig], "release" );
+
+ Write( "\n" );
+ Write( "%024llX /* %s */ = {\n", makeoid3( oidStrSolutionRoot, projects[iProject]->m_ProjectName, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration ), k_rgchConfigNames[iConfig] );
+ ++m_nIndent;
+ {
+ Write( "isa = XCBuildConfiguration;\n" );
+ Write( "baseConfigurationReference = %024llX /* %s */;\n", makeoid2( oidStrSolutionRoot, k_rgchXCConfigFiles[iConfig], EOIDTypeFileReference ), k_rgchXCConfigFiles[iConfig] );
+ Write( "buildSettings = {\n" );
+ ++m_nIndent;
+ {
+ KeyValues *pConfigKV = g_vecPGenerators[iProject]->m_BaseConfigData.m_Configurations[iConfig]->m_pKV;
+ char rgchProjectDir[MAX_PATH];
+ V_strncpy( rgchProjectDir, projects[iProject]->m_ProjectFilename.String(), sizeof( rgchProjectDir ) );
+ V_StripFilename( rgchProjectDir );
+
+ EmitBuildSettings( projects[iProject]->m_ProjectName, rgchProjectDir, &(g_vecPGenerators[iProject]->m_Files), pConfigKV, pReleaseKV, bIsDebug );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+ Write( "name = \"%s\";\n", k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End XCBuildConfiguration section */\n" );
+
+ /**
+ **
+ ** configuration lists - aggregates the build configurations above into sets, which are referenced by the individual targets.
+ **
+ **/
+ Write( "\n/* Begin XCConfigurationList section */\n" );
+ ++m_nIndent;
+ {
+ Write( "%024llX /* Build configuration list for PBXProject \"%s\" */ = {\n", makeoid( oidStrSolutionRoot, EOIDTypeConfigurationList ), V_UnqualifiedFileName( UsePOSIXSlashes( pSolutionFilename ) ) );
+ ++m_nIndent;
+ {
+ Write( "isa = XCConfigurationList;\n" );
+ Write( "buildConfigurations = (\n" );
+ ++m_nIndent;
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ Write( "%024llX /* %s */,\n", makeoid2( oidStrSolutionRoot, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration ), k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "defaultConfigurationIsVisible = 0;\n" );
+ Write( "defaultConfigurationName = \"%s\";\n", k_rgchConfigNames[0] );
+ }
+ --m_nIndent;
+ Write( "};\n" );
+
+ Write( "%024llX /* Build configuration list for PBXAggregateTarget \"All\" */ = {\n", makeoid( oidStrSolutionRoot, EOIDTypeConfigurationList, 1 ) );
+ ++m_nIndent;
+ {
+ Write( "isa = XCConfigurationList;\n" );
+ Write( "buildConfigurations = (\n" );
+ ++m_nIndent;
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ Write( "%024llX /* %s */,\n", makeoid2( oidStrSolutionRoot, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration, 1 ), k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "defaultConfigurationIsVisible = 0;\n" );
+ Write( "defaultConfigurationName = \"%s\";\n", k_rgchConfigNames[0] );
+ }
+ --m_nIndent;
+ Write( "};" );
+
+ FOR_EACH_VEC( projects, iProject )
+ {
+ Write( "\n" );
+ Write( "%024llX /* Build configuration list for PBXNativeTarget \"%s\" */ = {\n", makeoid( projects[iProject]->m_ProjectName, EOIDTypeConfigurationList ), projects[iProject]->m_ProjectName.String() );
+ ++m_nIndent;
+ {
+ Write( "isa = XCConfigurationList;\n" );
+ Write( "buildConfigurations = (\n" );
+ ++m_nIndent;
+ for ( int iConfig = 0; iConfig < V_ARRAYSIZE(k_rgchConfigNames); iConfig++ )
+ {
+ Write( "%024llX /* %s */,\n", makeoid3( oidStrSolutionRoot, projects[iProject]->m_ProjectName, k_rgchConfigNames[iConfig], EOIDTypeBuildConfiguration ), k_rgchConfigNames[iConfig] );
+ }
+ --m_nIndent;
+ Write( ");\n" );
+ Write( "defaultConfigurationIsVisible = 0;\n" );
+ Write( "defaultConfigurationName = \"%s\";\n", k_rgchConfigNames[0] );
+ }
+ --m_nIndent;
+ Write( "};" );
+ }
+ }
+ --m_nIndent;
+ Write( "\n/* End XCConfigurationList section */\n" );
+ }
+ Write( "};\n" ); // objects = { ...
+
+ /**
+ **
+ ** root object in the graph
+ **
+ **/
+ Write( "rootObject = %024llX /* Project object */;\n", makeoid( oidStrSolutionRoot, EOIDTypeProject ) );
+ }
+ --m_nIndent;
+
+ Write( "}\n" );
+ fclose( m_fp );
+
+ // and now write a .projects file inside the xcode project so we can detect the list of projects changing
+ // (specifically a vpc project dissapearing from our target list)
+ FILE *fp = fopen( sProjProjectListFile, "wt" );
+ if ( !fp )
+ {
+ g_pVPC->VPCError( "Unable to open %s to write projects into.", sProjProjectListFile );
+ }
+ // we don't need to be quite as careful as project script, as we're only looking to catch cases where the rest of VPC thinks we're up-to-date
+ fprintf( fp, "%s\n", VPCCRCCHECK_FILE_VERSION_STRING );
+ FOR_EACH_VEC( g_vecPGenerators, iGenerator )
+ {
+ CProjectGenerator_Xcode *pGenerator = (CProjectGenerator_Xcode*)g_vecPGenerators[iGenerator];
+
+ fprintf( fp, "%s\n", pGenerator->m_ProjectName.String() );
+ }
+ fclose( fp );
+}
+
+void CSolutionGenerator_Xcode::Write( const char *pMsg, ... )
+{
+ for ( int i=0; i < m_nIndent; i++ )
+ fprintf( m_fp, "\t" );
+
+ va_list marker;
+ va_start( marker, pMsg );
+ vfprintf( m_fp, pMsg, marker );
+ va_end( marker );
+}
+
+static CSolutionGenerator_Xcode g_SolutionGenerator_Xcode;
+IBaseSolutionGenerator* GetXcodeSolutionGenerator()
+{
+ return &g_SolutionGenerator_Xcode;
+}
+
+static CProjectGenerator_Xcode g_ProjectGenerator_Xcode;
+IBaseProjectGenerator* GetXcodeProjectGenerator()
+{
+ return &g_ProjectGenerator_Xcode;
+}
diff --git a/external/vpc/utils/vpc/sys_utils.cpp b/external/vpc/utils/vpc/sys_utils.cpp
new file mode 100644
index 0000000..63684d8
--- /dev/null
+++ b/external/vpc/utils/vpc/sys_utils.cpp
@@ -0,0 +1,781 @@
+//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#include "vpc.h"
+
+#ifdef STEAM
+#include "tier1/utlintrusivelist.h"
+#endif
+
+#ifdef POSIX
+#define _O_RDONLY O_RDONLY
+#define _open open
+#include <sys/errno.h>
+#define _lseek lseek
+#define _read read
+#define _close close
+#define _stat stat
+#include <glob.h>
+#else
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <io.h>
+#include <ShellAPI.h>
+#endif
+
+#ifdef OSX
+#include <mach-o/dyld.h>
+#endif
+
+CXMLWriter::CXMLWriter()
+{
+ m_fp = NULL;
+ m_b2010Format = false;
+}
+
+bool CXMLWriter::Open( const char *pFilename, bool b2010Format )
+{
+ m_FilenameString = pFilename;
+ m_b2010Format = b2010Format;
+
+ m_fp = fopen( pFilename, "wt" );
+ if ( !m_fp )
+ return false;
+
+ if ( b2010Format )
+ {
+ Write( "\xEF\xBB\xBF<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
+ }
+ else
+ {
+ // 2005 format
+ Write( "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n" );
+ }
+
+ return true;
+}
+
+void CXMLWriter::Close()
+{
+ if ( !m_fp )
+ return;
+ fclose( m_fp );
+
+ Sys_CopyToMirror( m_FilenameString.Get() );
+
+ m_fp = NULL;
+ m_FilenameString = NULL;
+}
+
+void CXMLWriter::PushNode( const char *pName )
+{
+ Indent();
+
+ char *pNewName = strdup( pName );
+ m_Nodes.Push( pNewName );
+
+ fprintf( m_fp, "<%s%s\n", pName, m_Nodes.Count() == 2 ? ">" : "" );
+}
+
+void CXMLWriter::PushNode( const char *pName, const char *pString )
+{
+ Indent();
+
+ char *pNewName = strdup( pName );
+ m_Nodes.Push( pNewName );
+
+ fprintf( m_fp, "<%s%s%s>\n", pName, pString ? " " : "", pString ? pString : "" );
+}
+
+void CXMLWriter::WriteLineNode( const char *pName, const char *pExtra, const char *pString )
+{
+ Indent();
+
+ fprintf( m_fp, "<%s%s>%s</%s>\n", pName, pExtra ? pExtra : "", pString, pName );
+}
+
+void CXMLWriter::PopNode( bool bEmitLabel )
+{
+ char *pName;
+ m_Nodes.Pop( pName );
+
+ Indent();
+ if ( bEmitLabel )
+ {
+ fprintf( m_fp, "</%s>\n", pName );
+ }
+ else
+ {
+ fprintf( m_fp, "/>\n" );
+ }
+
+ free( pName );
+}
+
+void CXMLWriter::Write( const char *p )
+{
+ if ( m_fp )
+ {
+ Indent();
+ fprintf( m_fp, "%s\n", p );
+ }
+}
+
+CUtlString CXMLWriter::FixupXMLString( const char *pInput )
+{
+ struct XMLFixup_t
+ {
+ const char *m_pFrom;
+ const char *m_pTo;
+ bool m_b2010Only;
+ };
+
+ // these tokens are not allowed in xml vcproj and be be escaped per msdev docs
+ XMLFixup_t xmlFixups[] =
+ {
+ {"&", "&amp;", false},
+ {"\"", "&quot;", false},
+ {"\'", "&apos;", false},
+ {"\n", "&#x0D;&#x0A;", false},
+ {">", "&gt;", false},
+ {"<", "&lt;", false},
+ {"$(InputFileName)", "%(Filename)%(Extension)", true},
+ {"$(InputName)", "%(Filename)", true},
+ {"$(InputPath)", "%(FullPath)", true},
+ {"$(InputDir)", "%(RootDir)%(Directory)", true},
+ };
+
+ bool bNeedsFixups = false;
+ CUtlVector< bool > needsFixups;
+ CUtlString outString;
+
+ needsFixups.SetCount( ARRAYSIZE( xmlFixups ) );
+ for ( int i = 0; i < ARRAYSIZE( xmlFixups ); i++ )
+ {
+ needsFixups[i] = false;
+
+ if ( !m_b2010Format && xmlFixups[i].m_b2010Only )
+ continue;
+
+ if ( V_stristr( pInput, xmlFixups[i].m_pFrom ) )
+ {
+ needsFixups[i] = true;
+ bNeedsFixups = true;
+ }
+ }
+
+ if ( !bNeedsFixups )
+ {
+ outString = pInput;
+ }
+ else
+ {
+ int flip = 0;
+ char bigBuffer[2][8192];
+ V_strncpy( bigBuffer[flip], pInput, sizeof( bigBuffer[0] ) );
+
+ for ( int i = 0; i < ARRAYSIZE( xmlFixups ); i++ )
+ {
+ if ( !needsFixups[i] )
+ continue;
+
+ if ( !V_StrSubst( bigBuffer[flip], xmlFixups[i].m_pFrom, xmlFixups[i].m_pTo, bigBuffer[flip ^ 1], sizeof( bigBuffer[0] ), false ) )
+ {
+ g_pVPC->VPCError( "XML overflow - Increase big buffer" );
+ }
+ flip ^= 1;
+ }
+ outString = bigBuffer[flip];
+ }
+
+ return outString;
+}
+
+void CXMLWriter::Indent()
+{
+ for ( int i = 0; i < m_Nodes.Count(); i++ )
+ {
+ if ( m_b2010Format )
+ {
+ fprintf( m_fp, " " );
+ }
+ else
+ {
+ fprintf( m_fp, "\t" );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Sys_LoadFile
+//
+//-----------------------------------------------------------------------------
+int Sys_LoadFile( const char* filename, void** bufferptr, bool bText )
+{
+ int handle;
+ long length;
+ char* buffer;
+
+ *bufferptr = NULL;
+
+ if ( !Sys_Exists( filename ) )
+ return ( -1 );
+
+ int flags = _O_RDONLY;
+#if !defined( POSIX )
+ flags |= (bText ? _O_TEXT : _O_BINARY);
+#endif
+ handle = _open( filename, flags );
+ if ( handle == -1 )
+ Sys_Error( "Sys_LoadFile(): Error opening %s: %s", filename, strerror( errno ) );
+
+ length = _lseek( handle, 0, SEEK_END );
+ _lseek( handle, 0, SEEK_SET );
+ buffer = ( char* )malloc( length+1 );
+
+ int bytesRead = _read( handle, buffer, length );
+ if ( !bText && ( bytesRead != length ) )
+ Sys_Error( "Sys_LoadFile(): read truncated failure" );
+
+ _close( handle );
+
+ // text mode is truncated, add null for parsing
+ buffer[bytesRead] = '\0';
+
+ *bufferptr = ( void* )buffer;
+
+ return ( length );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_LoadFileIntoBuffer
+//
+//-----------------------------------------------------------------------------
+bool Sys_LoadFileIntoBuffer( const char *pchFileIn, CUtlBuffer &buf, bool bText )
+{
+ buf.SetBufferType( bText, bText );
+ struct stat statBuf;
+ if ( stat( pchFileIn, &statBuf ) != 0 )
+ return false;
+ buf.EnsureCapacity( (int)(statBuf.st_size + 1) );
+ if ( !buf.IsValid() )
+ return false;
+
+ FILE *fp = fopen( pchFileIn, "rb" );
+ if ( !fp )
+ return false;
+
+ char *pBuffer = (char*)buf.Base();
+ int nBytesRead = statBuf.st_size * fread( pBuffer, statBuf.st_size, 1, fp );
+ fclose( fp );
+ buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead );
+ pBuffer[statBuf.st_size] = 0; // terminate buffer without changing put size
+ return nBytesRead == statBuf.st_size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Sys_FileLength
+//-----------------------------------------------------------------------------
+long Sys_FileLength( const char* filename, bool bText )
+{
+ long length;
+
+ if ( filename )
+ {
+ int flags = _O_RDONLY;
+#if !defined( POSIX )
+ flags |= (bText ? _O_TEXT : _O_BINARY);
+#endif
+ int handle = _open( filename, flags );
+ if ( handle == -1 )
+ {
+ // file does not exist
+ return ( -1 );
+ }
+
+ length = _lseek( handle, 0, SEEK_END );
+ _close( handle );
+ }
+ else
+ {
+ return ( -1 );
+ }
+
+ return ( length );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_StripPath
+//
+// Removes path portion from a fully qualified name, leaving filename and extension.
+//-----------------------------------------------------------------------------
+void Sys_StripPath( const char* inpath, char* outpath )
+{
+ const char* src;
+
+ src = inpath + strlen( inpath );
+ while ( ( src != inpath ) && ( *( src-1 ) != '\\' ) && ( *( src-1 ) != '/' ) && ( *( src-1 ) != ':' ) )
+ src--;
+
+ strcpy( outpath,src );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_Exists
+//
+// Returns TRUE if file exists.
+//-----------------------------------------------------------------------------
+bool Sys_Exists( const char* filename )
+{
+ FILE* test;
+
+ if ( ( test = fopen( filename, "rb" ) ) == NULL )
+ return ( false );
+
+ fclose( test );
+
+ return ( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Sys_Touch
+//
+// Returns TRUE if the file could be accessed for write
+//-----------------------------------------------------------------------------
+bool Sys_Touch( const char* filename )
+{
+ FILE* test;
+
+ if ( ( test = fopen( filename, "wb" ) ) == NULL )
+ return ( false );
+
+ fclose( test );
+
+ return ( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Sys_FileInfo
+//-----------------------------------------------------------------------------
+bool Sys_FileInfo( const char *pFilename, int64 &nFileSize, int64 &nModifyTime )
+{
+ struct _stat statData;
+ int rt = _stat( pFilename, &statData );
+ if ( rt != 0 )
+ return false;
+
+ nFileSize = statData.st_size;
+ nModifyTime = statData.st_mtime;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Ignores allowable trailing characters.
+//-----------------------------------------------------------------------------
+bool Sys_StringToBool( const char *pString )
+{
+ if ( !V_strnicmp( pString, "no", 2 ) ||
+ !V_strnicmp( pString, "off", 3 ) ||
+ !V_strnicmp( pString, "false", 5 ) ||
+ !V_strnicmp( pString, "not set", 7 ) ||
+ !V_strnicmp( pString, "disabled", 8 ) ||
+ !V_strnicmp( pString, "0", 1 ) )
+ {
+ // false
+ return false;
+ }
+ else if ( !V_strnicmp( pString, "yes", 3 ) ||
+ !V_strnicmp( pString, "on", 2 ) ||
+ !V_strnicmp( pString, "true", 4 ) ||
+ !V_strnicmp( pString, "set", 3 ) ||
+ !V_strnicmp( pString, "enabled", 7 ) ||
+ !V_strnicmp( pString, "1", 1 ) )
+ {
+ // true
+ return true;
+ }
+ else
+ {
+ // unknown boolean expression
+ g_pVPC->VPCSyntaxError( "Unknown boolean expression '%s'", pString );
+ }
+
+ // assume false
+ return false;
+}
+
+bool Sys_ReplaceString( const char *pStream, const char *pSearch, const char *pReplace, char *pOutBuff, int outBuffSize )
+{
+ const char *pFind;
+ const char *pStart = pStream;
+ char *pOut = pOutBuff;
+ int len;
+ bool bReplaced = false;
+
+ while ( 1 )
+ {
+ // find sub string
+ pFind = V_stristr( pStart, pSearch );
+ if ( !pFind )
+ {
+ /// end of string
+ len = strlen( pStart );
+ pFind = pStart + len;
+ memcpy( pOut, pStart, len );
+ pOut += len;
+ break;
+ }
+ else
+ {
+ bReplaced = true;
+ }
+
+ // copy up to sub string
+ len = pFind - pStart;
+ memcpy( pOut, pStart, len );
+ pOut += len;
+
+ // substitute new string
+ len = strlen( pReplace );
+ memcpy( pOut, pReplace, len );
+ pOut += len;
+
+ // advance past sub string
+ pStart = pFind + strlen( pSearch );
+ }
+
+ *pOut = '\0';
+
+ return bReplaced;
+}
+
+//--------------------------------------------------------------------------------
+// string match with wildcards.
+// '?' = match any char
+//--------------------------------------------------------------------------------
+bool Sys_StringPatternMatch( char const *pSrcPattern, char const *pString )
+{
+ for (;;)
+ {
+ char nPat = *(pSrcPattern++);
+ char nString= *(pString++);
+ if ( !( ( nPat == nString ) || ( ( nPat == '?' ) && nString ) ) )
+ return false;
+ if ( !nString )
+ return true; // end of string
+ }
+}
+
+bool Sys_EvaluateEnvironmentExpression( const char *pExpression, const char *pDefault, char *pOutBuff, int nOutBuffSize )
+{
+ char *pEnvVarName = (char*)StringAfterPrefix( pExpression, "$env(" );
+ if ( !pEnvVarName )
+ {
+ // not an environment specification
+ return false;
+ }
+
+ char *pLastChar = &pEnvVarName[ V_strlen( pEnvVarName ) - 1 ];
+ if ( !*pEnvVarName || *pLastChar != ')' )
+ {
+ g_pVPC->VPCSyntaxError( "$env() must have a closing ')' in \"%s\"\n", pExpression );
+ }
+
+ // get the contents of the $env( blah..blah ) expressions
+ // handles expresions that could have whitepsaces
+ g_pVPC->GetScript().PushScript( pExpression, pEnvVarName );
+ const char *pToken = g_pVPC->GetScript().GetToken( false );
+ g_pVPC->GetScript().PopScript();
+
+ if ( pToken && pToken[0] )
+ {
+ const char *pResolve = getenv( pToken );
+ if ( !pResolve )
+ {
+ // not defined, use default
+ pResolve = pDefault ? pDefault : "";
+ }
+
+ V_strncpy( pOutBuff, pResolve, nOutBuffSize );
+ }
+
+ return true;
+}
+
+bool Sys_ExpandFilePattern( const char *pPattern, CUtlVector< CUtlString > &vecResults )
+{
+#if defined( _WIN32 )
+ char rgchPathPart[MAX_PATH];
+ V_strncpy( rgchPathPart, pPattern, V_ARRAYSIZE( rgchPathPart ) );
+ V_StripFilename( rgchPathPart );
+ if ( V_strlen( rgchPathPart ) )
+ V_strncat( rgchPathPart, "\\", V_ARRAYSIZE( rgchPathPart ) );
+
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = FindFirstFile( pPattern, &findData );
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ vecResults.AddToTail( CFmtStr( "%s%s", rgchPathPart, findData.cFileName ).Access() );
+ BOOL bMore = TRUE;
+ while ( bMore )
+ {
+ bMore = FindNextFile( hFind, &findData );
+ if ( bMore )
+ vecResults.AddToTail( CFmtStr( "%s%s", rgchPathPart, findData.cFileName ).Access() );
+ }
+ FindClose( hFind );
+ }
+#elif defined( POSIX )
+ glob_t gr;
+ if ( glob( pPattern, 0, NULL, &gr ) == 0 )
+ {
+ for ( int i = 0; i < gr.gl_pathc; i++ )
+ {
+ vecResults.AddToTail( gr.gl_pathv[i] );
+ }
+ globfree( &gr );
+ }
+#else
+#error
+#endif
+ return vecResults.Count() > 0;
+}
+
+bool Sys_GetExecutablePath( char *pBuf, int cbBuf )
+{
+#if defined( _WIN32 )
+ return ( 0 != GetModuleFileNameA( NULL, pBuf, cbBuf ) );
+#elif defined(OSX)
+ uint32_t _nBuff = cbBuf;
+ bool bSuccess = _NSGetExecutablePath(pBuf, &_nBuff) == 0;
+ pBuf[cbBuf-1] = '\0';
+ return bSuccess;
+#elif defined LINUX
+ ssize_t nRead = readlink("/proc/self/exe", pBuf, cbBuf-1 );
+ if ( nRead != -1 )
+ {
+ pBuf[ nRead ] = 0;
+ return true;
+ }
+
+ pBuf[0] = 0;
+ return false;
+#else
+#error Sys_GetExecutablePath
+#endif
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void Sys_CreatePath( const char *path )
+{
+#if defined( _WIN32 )
+ char pFullPath[MAX_PATH];
+ V_MakeAbsolutePath( pFullPath, sizeof(pFullPath), path );
+
+ // If Sys_CreatePath is called with a filename, all is well.
+ // If it is called with a folder name, it must have a trailing slash:
+ if ( !V_GetFileExtension( pFullPath ) )
+ V_AppendSlash( pFullPath, sizeof(pFullPath) );
+
+ char *ptr;
+
+ // skip past the drive path, but don't strip
+ if ( pFullPath[1] == ':' )
+ {
+ ptr = strchr( pFullPath, '\\' );
+ }
+ else
+ {
+ ptr = pFullPath;
+ }
+ while ( ptr )
+ {
+ ptr = strchr( ptr+1, '\\' );
+ if ( ptr )
+ {
+ *ptr = '\0';
+
+#if defined( _WIN32 ) || defined( WIN32 )
+ CreateDirectory( pFullPath, NULL );
+#else
+#error Sys_CreatePath: this mkdir is probably correct but has not been tested
+ mkdir( pFullPath, 0777 );
+#endif
+ *ptr = '\\';
+ }
+ }
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Given some arbitrary case filename, provides what the OS thinks it is.
+// Windows specific. Returns false if file cannot be resolved (i.e. does not exist).
+//-----------------------------------------------------------------------------
+bool Sys_GetActualFilenameCase( const char *pFilename, char *pOutputBuffer, int nOutputBufferSize )
+{
+#if defined( _WINDOWS )
+ char filenameBuffer[MAX_PATH];
+ V_strncpy( filenameBuffer, pFilename, sizeof( filenameBuffer ) );
+ V_FixSlashes( filenameBuffer );
+ V_RemoveDotSlashes( filenameBuffer );
+
+ int nFilenameLength = V_strlen( filenameBuffer );
+
+ CUtlString actualFilename;
+
+ // march along filename, resolving up to next seperator
+ int nLastComponentStart = 0;
+ bool bAddSeparator = false;
+ int i = 0;
+ while ( i < nFilenameLength )
+ {
+ // cannot resolve these, emit as-is
+ if ( !V_strnicmp( filenameBuffer + i, ".\\", 2 ) )
+ {
+ i += 2;
+ actualFilename += CUtlString( ".\\" );
+ continue;
+ }
+
+ // cannot resolve these, emit as-is
+ if ( !V_strnicmp( filenameBuffer + i, "..\\", 3 ) )
+ {
+ i += 3;
+ actualFilename += CUtlString( "..\\" );
+ continue;
+ }
+
+ // skip until path separator
+ while ( i < nFilenameLength && filenameBuffer[i] != '\\' )
+ {
+ ++i;
+ }
+
+ bool bFoundSeparator = ( i < nFilenameLength );
+
+ // truncate at separator, windows resolves each component in pieces
+ filenameBuffer[i] = 0;
+
+ SHFILEINFOA info = {0};
+ HRESULT hr = SHGetFileInfoA( filenameBuffer, 0, &info, sizeof( info ), SHGFI_DISPLAYNAME );
+ if ( SUCCEEDED( hr ) )
+ {
+ // reassemble based on actual component
+ if ( bAddSeparator )
+ {
+ actualFilename += CUtlString( "\\" );
+ }
+ actualFilename += CUtlString( info.szDisplayName );
+ }
+ else
+ {
+ return false;
+ }
+
+ // restore path separator
+ if ( bFoundSeparator )
+ {
+ filenameBuffer[i] = '\\';
+ }
+
+ ++i;
+ nLastComponentStart = i;
+ bAddSeparator = true;
+ }
+
+ V_strncpy( pOutputBuffer, actualFilename.Get(), nOutputBufferSize );
+ return true;
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Given some arbitrary case filename, determine if OS version matches.
+//-----------------------------------------------------------------------------
+bool Sys_IsFilenameCaseConsistent( const char *pFilename, char *pOutputBuffer, int nOutputBufferSize )
+{
+ V_strncpy( pOutputBuffer, pFilename, nOutputBufferSize );
+
+ // normalize the provided filename separators
+ CUtlString filename = pFilename;
+ V_FixSlashes( filename.Get() );
+ V_RemoveDotSlashes( filename.Get() );
+
+ if ( !Sys_GetActualFilenameCase( filename.Get(), pOutputBuffer, nOutputBufferSize ) )
+ return false;
+
+ if ( !V_strcmp( filename.Get(), pOutputBuffer ) )
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool Sys_CopyToMirror( const char *pFilename )
+{
+ if ( !pFilename || !pFilename[0] )
+ return false;
+
+ const char *pMirrorPath = g_pVPC->GetOutputMirrorPath();
+ if ( !pMirrorPath || !pMirrorPath[0] )
+ return false;
+
+ char absolutePathToOriginal[MAX_PATH];
+ if ( V_IsAbsolutePath( pFilename ) )
+ {
+ V_strncpy( absolutePathToOriginal, pFilename, sizeof( absolutePathToOriginal ) );
+ }
+ else
+ {
+ // need to determine where file resides for mirroring
+ char currentDirectory[MAX_PATH] = { 0 };
+ V_GetCurrentDirectory( currentDirectory, sizeof( currentDirectory ) );
+ V_ComposeFileName( currentDirectory, pFilename, absolutePathToOriginal, sizeof( absolutePathToOriginal ) );
+ }
+
+ if ( !Sys_Exists( absolutePathToOriginal ) )
+ {
+ g_pVPC->VPCWarning( "Cannot mirror '%s', cannot resolve to expected '%s'", pFilename, absolutePathToOriginal );
+ return false;
+ }
+
+ const char *pTargetPath = StringAfterPrefix( absolutePathToOriginal, g_pVPC->GetSourcePath() );
+ if ( !pTargetPath || !pTargetPath[0] )
+ {
+ g_pVPC->VPCWarning( "Cannot mirror '%s', missing expected prefix '%s' in '%s'", pFilename, g_pVPC->GetSourcePath(), absolutePathToOriginal );
+ return false;
+ }
+
+ // supply the mirror path head
+ char absolutePathToMirror[MAX_PATH];
+ if ( pTargetPath[0] == '\\' )
+ {
+ pTargetPath++;
+ }
+ V_ComposeFileName( pMirrorPath, pTargetPath, absolutePathToMirror, sizeof( absolutePathToMirror ) );
+
+#ifdef _WIN32
+ Sys_CreatePath( absolutePathToMirror );
+
+ if ( !CopyFile( absolutePathToOriginal, absolutePathToMirror, FALSE ) )
+ {
+ g_pVPC->VPCWarning( "Cannot mirror '%s' to '%s'", absolutePathToOriginal, absolutePathToMirror );
+ return false;
+ }
+ else
+ {
+ g_pVPC->VPCStatus( true, "Mirror: '%s' to '%s'", absolutePathToOriginal, absolutePathToMirror );
+ }
+#endif
+
+ return true;
+} \ No newline at end of file
diff --git a/external/vpc/utils/vpc/sys_utils.h b/external/vpc/utils/vpc/sys_utils.h
new file mode 100644
index 0000000..7cd457f
--- /dev/null
+++ b/external/vpc/utils/vpc/sys_utils.h
@@ -0,0 +1,157 @@
+//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// File Utilities.
+//
+//===========================================================================//
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+
+#ifdef POSIX
+#include <unistd.h>
+#endif
+
+#if defined( LINUX ) || defined( _LINUX )
+ #include <sys/io.h>
+#endif
+
+#include "tier0/platform.h"
+#include "../vpccrccheck/crccheck_shared.h"
+
+template< class T, class NullType, int nMax >
+class CSimplePointerStack
+{
+public:
+ inline CSimplePointerStack()
+ {
+ m_nCount = 0;
+ }
+
+ inline void Purge()
+ {
+ for ( int i=0; i < m_nCount; i++ )
+ m_Values[i] = (NullType)NULL;
+ m_nCount = 0;
+ }
+
+ inline int Count()
+ {
+ return m_nCount;
+ }
+
+ inline T& Top()
+ {
+ Assert( m_nCount > 0 );
+ return m_Values[m_nCount-1];
+ }
+
+ inline void Pop( T &val )
+ {
+ Assert( m_nCount > 0 );
+ --m_nCount;
+ val = m_Values[m_nCount];
+ m_Values[m_nCount] = (NullType)NULL;
+ }
+
+ inline void Pop()
+ {
+ Assert( m_nCount > 0 );
+ --m_nCount;
+ m_Values[m_nCount] = (NullType)NULL;
+ }
+
+ inline void Push( T &val )
+ {
+ Assert( m_nCount+1 < nMax );
+ m_Values[m_nCount] = val;
+ ++m_nCount;
+ }
+
+public:
+ T m_Values[nMax];
+ int m_nCount;
+};
+
+class CXMLWriter
+{
+public:
+ CXMLWriter();
+
+ bool Open( const char *pFilename, bool bIs2010Format = false );
+ void Close();
+
+ void PushNode( const char *pName );
+ void PopNode( bool bEmitLabel );
+
+ void WriteLineNode( const char *pName, const char *pExtra, const char *pString );
+ void PushNode( const char *pName, const char *pString );
+
+ void Write( const char *p );
+ CUtlString FixupXMLString( const char *pInput );
+
+private:
+ void Indent();
+
+ bool m_b2010Format;
+ FILE *m_fp;
+
+ CUtlString m_FilenameString;
+
+ CSimplePointerStack< char *, char *, 128 > m_Nodes;
+};
+
+long Sys_FileLength( const char* filename, bool bText = false );
+int Sys_LoadFile( const char *filename, void **bufferptr, bool bText = false );
+bool Sys_LoadFileIntoBuffer( const char *pchFileIn, CUtlBuffer &buf, bool bText );
+void Sys_StripPath( const char *path, char *outpath );
+bool Sys_Exists( const char *filename );
+bool Sys_Touch( const char *filename );
+bool Sys_FileInfo( const char *pFilename, int64 &nFileSize, int64 &nModifyTime );
+
+bool Sys_StringToBool( const char *pString );
+bool Sys_ReplaceString( const char *pStream, const char *pSearch, const char *pReplace, char *pOutBuff, int outBuffSize );
+bool Sys_StringPatternMatch( char const *pSrcPattern, char const *pString );
+
+bool Sys_EvaluateEnvironmentExpression( const char *pExpression, const char *pDefault, char *pOutBuff, int nOutBuffSize );
+
+bool Sys_ExpandFilePattern( const char *pPattern, CUtlVector< CUtlString > &vecResults );
+bool Sys_GetExecutablePath( char *pBuf, int cbBuf );
+
+bool Sys_CopyToMirror( const char *pFilename );
+inline bool IsCFileExtension( const char *pExtension )
+{
+ if ( !pExtension )
+ return false;
+
+ return !V_stricmp( pExtension, "cpp" ) ||
+ !V_stricmp( pExtension, "cxx" ) ||
+ !V_stricmp( pExtension, "cc" ) ||
+ !V_stricmp( pExtension, "c" );
+}
+
+bool Sys_GetActualFilenameCase( const char *pFilename, char *pOutputBuffer, int nOutputBufferSize );
+bool Sys_IsFilenameCaseConsistent( const char *pFilename, char *pOutputBuffer, int nOutputBufferSize );
+inline bool IsHFileExtension( const char *pExtension )
+{
+ if ( !pExtension )
+ return false;
+
+ return !V_stricmp( pExtension, "hpp" ) ||
+ !V_stricmp( pExtension, "hxx" ) ||
+ !V_stricmp( pExtension, "hh" ) ||
+ !V_stricmp( pExtension, "h" );
+}
+
+
diff --git a/external/vpc/utils/vpc/vpc.h b/external/vpc/utils/vpc/vpc.h
new file mode 100644
index 0000000..4ff493e
--- /dev/null
+++ b/external/vpc/utils/vpc/vpc.h
@@ -0,0 +1,482 @@
+//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VPC
+//
+//=====================================================================================//
+
+#pragma once
+
+// Exclude rarely-used stuff from Windows headers
+#define WIN32_LEAN_AND_MEAN
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN
+#endif
+
+#include "utlstring.h"
+#include "utlrbtree.h"
+#include "utlvector.h"
+#include "utlbuffer.h"
+#include "utlstack.h"
+#include "utldict.h"
+#include "utlsortvector.h"
+#include "checksum_crc.h"
+#include "checksum_md5.h"
+#include "fmtstr.h"
+#include "exprevaluator.h"
+#include "tier1/interface.h"
+#include "p4lib/ip4.h"
+#include "scriptsource.h"
+#include "logging.h"
+#ifdef STEAM
+#include "vstdlib/strtools.h"
+#else
+#include "tier1/strtools.h"
+#endif
+#include "sys_utils.h"
+#include "keyvalues.h"
+#include "generatordefinition.h"
+
+DECLARE_LOGGING_CHANNEL( LOG_VPC );
+
+#if defined( WIN32 )
+#include <atlbase.h>
+#include <io.h>
+#endif // WIN32
+
+struct KeywordName_t
+{
+ const char *m_pName;
+ configKeyword_e m_Keyword;
+};
+
+typedef bool (*procptr_t)( const char *pPropertyName );
+typedef bool (*GetSymbolProc_t)( const char *pKey );
+
+#define INVALID_INDEX -1
+
+struct property_t
+{
+ const char *pName;
+ procptr_t handler;
+ int platformMask;
+};
+
+enum conditionalType_e
+{
+ CONDITIONAL_NULL,
+ CONDITIONAL_PLATFORM,
+ CONDITIONAL_GAME,
+ CONDITIONAL_CUSTOM
+};
+
+struct conditional_t
+{
+ conditional_t()
+ {
+ type = CONDITIONAL_NULL;
+ m_bDefined = false;
+ m_bGameConditionActive = false;
+ }
+
+ CUtlString name;
+ CUtlString upperCaseName;
+ conditionalType_e type;
+
+ // a conditional can be present in the table but not defined
+ // e.g. default conditionals that get set by command line args
+ bool m_bDefined;
+
+ // only used during multiple game iterations for game conditionals as each 'defined' game becomes active
+ bool m_bGameConditionActive;
+};
+
+struct macro_t
+{
+ macro_t()
+ {
+ m_bSetupDefineInProjectFile = false;
+ m_bInternalCreatedMacro = false;
+ }
+
+ CUtlString name;
+ CUtlString value;
+
+ // If set to true, then VPC will add this as a -Dname=value parameter to the compiler's command line.
+ bool m_bSetupDefineInProjectFile;
+
+ // VPC created this macro itself rather than the macro being created from a script file.
+ bool m_bInternalCreatedMacro;
+};
+
+typedef int scriptIndex_t;
+struct script_t
+{
+ CUtlString name;
+ CUtlString m_condition;
+};
+
+typedef int projectIndex_t;
+struct project_t
+{
+ CUtlString name;
+ CUtlVector< script_t > scripts;
+};
+
+typedef int groupIndex_t;
+struct group_t
+{
+ CUtlVector< projectIndex_t > projects;
+};
+
+typedef int groupTagIndex_t;
+struct groupTag_t
+{
+ groupTag_t()
+ {
+ bSameAsProject = false;
+ }
+
+ CUtlString name;
+ CUtlVector< groupIndex_t > groups;
+
+ // this tag is an implicit definition of the project
+ bool bSameAsProject;
+};
+
+struct scriptList_t
+{
+ scriptList_t()
+ {
+ m_crc = 0;
+ }
+
+ CUtlString m_scriptName;
+ CRC32_t m_crc;
+};
+
+class IProjectIterator
+{
+public:
+ // iProject indexes g_projectList.
+ virtual bool VisitProject( projectIndex_t iProject, const char *szScriptPath ) = 0;
+};
+
+#include "ibasesolutiongenerator.h"
+#include "ibaseprojectgenerator.h"
+#if defined( WIN32 )
+#include "baseprojectdatacollector.h"
+#include "projectgenerator_vcproj.h"
+#include "projectgenerator_win32.h"
+#include "projectgenerator_win32_2010.h"
+#include "projectgenerator_xbox360.h"
+#include "projectgenerator_xbox360_2010.h"
+#include "projectgenerator_ps3.h"
+#endif
+
+enum EVSVersion
+{
+ k_EVSVersion_Invalid,
+ k_EVSVersion_2005,
+ k_EVSVersion_2008,
+ k_EVSVersion_2010,
+ k_EVSVersion_2012,
+ k_EVSVersion_2013,
+ k_EVSVersion_2015,
+};
+
+class CVPC
+{
+public:
+ CVPC();
+ ~CVPC();
+
+ bool Init( int argc, char **argv );
+ void Shutdown( bool bHasError = false );
+
+ void VPCError( PRINTF_FORMAT_STRING const char *pFormat, ... );
+ void VPCWarning( PRINTF_FORMAT_STRING const char *pFormat, ... );
+ void VPCStatus( bool bAlwaysSpew, PRINTF_FORMAT_STRING const char *pFormat, ... );
+ void VPCSyntaxError( PRINTF_FORMAT_STRING const char *pFormat = NULL, ... );
+
+ bool IsProjectCurrent( const char *pVCProjFilename, bool bSpewStatus );
+
+ bool HasCommandLineParameter( const char *pParamName );
+ bool HasP4SLNCommand();
+
+ CScript &GetScript() { return m_Script; }
+
+ bool IsVerbose() { return m_bVerbose; }
+ bool IsQuiet() { return m_bQuiet; }
+ bool IsShowDependencies() { return m_bShowDeps; }
+ bool IsForceGenerate() { return m_bForceGenerate; }
+ bool IsPosixPCHDisabled() { return m_bNoPosixPCH; }
+ bool IsForceIterate() { return m_bForceIterate; }
+ bool IsDecorateProject() { return m_bDecorateProject; }
+ const char *GetDecorateString() { return m_strDecorate.String(); }
+ bool IsCheckFiles() { return m_bCheckFiles; }
+ bool Is2010() { return m_bUseVS2010FileFormat || m_eVSVersion == k_EVSVersion_2010; }
+ bool Is2012() { return m_eVSVersion == k_EVSVersion_2012; } // When this returns true so does Is2010() because of the file format similarities
+ bool Is2013() { return m_eVSVersion == k_EVSVersion_2013; } // When this returns true so does Is2010() because of the file format similarities
+ bool Is2015() { return m_eVSVersion == k_EVSVersion_2015; } // When this returns true so does Is2010() because of the file format similarities
+ bool BUse2008() { return m_eVSVersion == k_EVSVersion_2008; }
+ bool IsDedicatedBuild() { return m_bDedicatedBuild; }
+ bool IsUnity() { return m_bUseUnity; }
+ bool IsShowCaseIssues() { return m_bShowCaseIssues; }
+ bool UseValveBinDir() { return m_bUseValveBinDir; }
+ bool IsVerboseMakefile() { return m_bVerboseMakefile; }
+ bool BUseP4SCC() { return m_bP4SCC; }
+ bool BUse32BitTools() { return m_b32BitTools; }
+
+ void DecorateProjectName( char *pchProjectName );
+
+ int GetMissingFilesCount() const { return m_FilesMissing; }
+ void IncrementFileMissing() { ++m_FilesMissing; }
+ void ResetMissingFilesCount() { m_FilesMissing = 0; }
+
+ bool IsIgnoreRedundancyWarning() { return m_bIgnoreRedundancyWarning; }
+ void SetIgnoreRedundancyWarning( bool bSet ) { m_bIgnoreRedundancyWarning = bSet; }
+
+ const char *GetStartDirectory() { return m_StartDirectory.Get(); }
+ const char *GetSourcePath() { return m_SourcePath.Get(); }
+ const char *GetProjectPath() { return m_ProjectPath.Get(); }
+ const char *GetCRCString() { return m_SupplementalCRCString.Get(); }
+ const char *GetSolutionItemsFilename() { return m_SolutionItemsFilename.Get(); }
+
+ const char *GetOutputFilename() { return m_OutputFilename.Get(); }
+ void SetOutputFilename( const char *pOutputFilename ) { m_OutputFilename = pOutputFilename; }
+
+ const char *GetProjectName() { return m_ProjectName.Get(); }
+ void SetProjectName( const char *pProjectName ) { m_ProjectName = pProjectName; }
+
+ const char *GetLoadAddressName() { return m_LoadAddressName.Get(); }
+ void SetLoadAddressName( const char *pLoadAddressName ) { m_LoadAddressName = pLoadAddressName; }
+
+ const char *GetOutputMirrorPath() { return m_OutputMirrorString.Get(); }
+
+ int ProcessCommandLine();
+
+ // Returns the mask identifying what platforms whould be built
+ bool IsPlatformDefined( const char *pName );
+ const char *GetTargetPlatformName();
+
+ void GetProjectDependencies( CUtlVector<CDependency_Project *> &referencedProjects );
+ void SetPhase1Projects( CUtlVector<CDependency_Project *> *pPhase1Projects ) { m_pPhase1Projects = pPhase1Projects; }
+
+ IBaseProjectGenerator *GetProjectGenerator() { return m_pProjectGenerator; }
+ void SetProjectGenerator( IBaseProjectGenerator *pGenerator ) { m_pProjectGenerator = pGenerator; }
+
+ IBaseSolutionGenerator *GetSolutionGenerator() { return m_pSolutionGenerator; }
+
+ // Conditionals
+ conditional_t *FindOrCreateConditional( const char *pName, bool bCreate, conditionalType_e type );
+ void ResolveMacrosInConditional( char const *pString, char *pOutBuff, int outBuffSize );
+ bool ResolveConditionalSymbol( const char *pSymbol );
+ bool EvaluateConditionalExpression( const char *pExpression );
+ bool ConditionHasDefinedType( const char* pCondition, conditionalType_e type );
+ void SetConditional( const char *pName, bool bSet = true );
+
+ // Macros
+ macro_t *FindOrCreateMacro( const char *pName, bool bCreate, const char *pValue );
+ void ResolveMacrosInString( char const *pString, char *pOutBuff, int outBuffSize );
+ int GetMacrosMarkedForCompilerDefines( CUtlVector< macro_t* > &macroDefines );
+ void RemoveScriptCreatedMacros();
+ const char *GetMacroValue( const char *pName );
+ void SetMacro( const char *pName, const char *pValue, bool bSetupDefineInProjectFile );
+
+ // Iterates all the projects in the specified list, checks their conditionals, and calls pIterator->VisitProject for
+ // each one that passes the conditional tests.
+ //
+ // If bForce is false, then it does a CRC check before visiting any project to see if the target project file is
+ // already up-to-date with its .vpc file.
+ void IterateTargetProjects( CUtlVector<projectIndex_t> &projectList, IProjectIterator *pIterator );
+
+ bool ParseProjectScript( const char *pScriptName, int depth, bool bQuiet, bool bWriteCRCCheckFile );
+
+ void AddScriptToCRCCheck( const char *pScriptName, CRC32_t crc );
+
+ const char *KeywordToName( configKeyword_e keyword );
+ configKeyword_e NameToKeyword( const char *pKeywordName );
+
+ int GetProjectsInGroup( CUtlVector< projectIndex_t > &projectList, const char *pGroupHame );
+
+private:
+ void SpewUsage( void );
+
+ bool LoadPerforceInterface();
+ void UnloadPerforceInterface();
+
+ void InProcessCRCCheck();
+ void CheckForInstalledXDK();
+
+ void DetermineSourcePath();
+ void SetDefaultSourcePath();
+
+ void SetupGenerators();
+ void SetupDefaultConditionals();
+ void SetMacrosAndConditionals();
+ void ResolveMacrosInStringInternal( char const *pString, char *pOutBuff, int outBuffSize, bool bStringIsConditional );
+
+ void HandleSingleCommandLineArg( const char *pArg );
+ void ParseBuildOptions( int argc, char *argv[] );
+
+ bool CheckBinPath( char *pOutBinPath, int outBinPathSize );
+ bool RestartFromCorrectLocation( bool *pIsChild );
+
+ void GenerateOptionsCRCString();
+ void CreateOutputFilename( project_t *pProject, const char *pchPlatform, const char *pchPhase, const char *pGameName, const char *pchExtension );
+ void FindProjectFromVCPROJ( const char *pScriptNameVCProj );
+ const char *BuildTempGroupScript( const char *pScriptName );
+
+ bool HandleP4SLN( IBaseSolutionGenerator *pSolutionGenerator );
+ void HandleMKSLN( IBaseSolutionGenerator *pSolutionGenerator );
+
+ void GenerateBuildSet( CProjectDependencyGraph &dependencyGraph );
+ bool BuildTargetProjects();
+ bool BuildTargetProject( IProjectIterator *pIterator, projectIndex_t projectIndex, script_t *pProjectScript, const char *pGameName );
+
+ bool m_bVerbose;
+ bool m_bQuiet;
+ bool m_bUsageOnly;
+ bool m_bHelp;
+ bool m_bSpewPlatforms;
+ bool m_bSpewGames;
+ bool m_bSpewGroups;
+ bool m_bSpewProjects;
+ bool m_bIgnoreRedundancyWarning;
+ bool m_bSpewProperties;
+ bool m_bTestMode;
+ bool m_bForceGenerate;
+ bool m_bNoPosixPCH;
+ bool m_bForceIterate;
+ bool m_bEnableVpcGameMacro;
+ bool m_bCheckFiles;
+ bool m_bDecorateProject;
+ bool m_bShowDeps;
+ bool m_bP4AutoAdd;
+ bool m_bP4SlnCheckEverything;
+ bool m_bDedicatedBuild;
+ bool m_bAppendSrvToDedicated; // concat "_srv" to dedicated server .so's.
+ bool m_bUseValveBinDir; // On Linux, use gcc toolchain from /valve/bin/
+ bool m_bAnyProjectQualified;
+ EVSVersion m_eVSVersion;
+ bool m_bUseVS2010FileFormat;
+ bool m_bUseUnity;
+ bool m_bShowCaseIssues;
+ bool m_bVerboseMakefile;
+ bool m_bP4SCC; // VPC_SCC_INTEGRATION define, or "/srcctl" cmd line option, or env var VPC_SRCCTL=1
+ bool m_b32BitTools; // Normally we prefer the 64-bit toolchain when building a 64-bit target. This turns that off.
+
+ // How many of the files listed in the VPC files are missing?
+ int m_FilesMissing;
+
+ int m_nArgc;
+ char **m_ppArgv;
+
+ CColorizedLoggingListener m_LoggingListener;
+
+ CSysModule *m_pP4Module;
+ CSysModule *m_pFilesystemModule;
+
+ CScript m_Script;
+
+ // Path where vpc was started from
+ CUtlString m_StartDirectory;
+
+ // Root path to the sources (i.e. the directory where the vpc_scripts directory can be found in).
+ CUtlString m_SourcePath;
+
+ // path to the project being processed (i.e. the directory where this project's .vpc can be found).
+ CUtlString m_ProjectPath;
+
+ // strings derived from command-line commands which is checked alongside project CRCs:
+ CUtlString m_SupplementalCRCString;
+ CUtlString m_ExtraOptionsCRCString;
+
+ CUtlString m_MKSolutionFilename;
+
+ CUtlString m_SolutionItemsFilename; // For /slnitems
+
+ CUtlString m_P4SolutionFilename; // For /p4sln
+ CUtlVector< int > m_iP4Changelists;
+
+ CUtlString m_OutputFilename;
+ CUtlString m_ProjectName;
+ CUtlString m_LoadAddressName;
+
+ CUtlString m_OutputMirrorString;
+
+ CUtlString m_TempGroupScriptFilename;
+
+ CUtlString m_strDecorate;
+
+ // This abstracts the differences between different output methods.
+ IBaseProjectGenerator *m_pProjectGenerator;
+ IBaseSolutionGenerator *m_pSolutionGenerator;
+
+ CUtlVector< CUtlString > m_BuildCommands;
+
+ CUtlVector<CDependency_Project *> *m_pPhase1Projects;
+
+public:
+ CUtlVector< conditional_t > m_Conditionals;
+ CUtlVector< macro_t > m_Macros;
+
+ CUtlVector< scriptList_t > m_ScriptList;
+
+ CUtlVector< project_t > m_Projects;
+ CUtlVector< projectIndex_t > m_TargetProjects;
+
+ CProjectDependencyGraph m_dependencyGraph;
+
+ CUtlVector< group_t > m_Groups;
+ CUtlVector< groupTag_t > m_GroupTags;
+
+ CUtlVector< CUtlString > m_P4GroupRestrictions;
+
+ CUtlVector< CUtlString > m_SchemaFiles;
+
+ CUtlDict< CUtlString, int > m_CustomBuildSteps;
+
+ bool m_bGeneratedProject;
+
+ CUtlDict< bool > m_UnityFilesSeen;
+ CUtlStack< CUtlString > m_UnityStack;
+ CUtlString m_sUnityCurrent;
+ bool m_bInMkSlnPass;
+};
+
+extern CVPC *g_pVPC;
+
+extern const char *g_pOption_ImportLibrary; // "$ImportLibrary";
+extern const char *g_pOption_OutputFile; // "$OutputFile";
+extern const char *g_pOption_GameOutputFile; // "$GameOutputFile";
+extern const char *g_pOption_AdditionalIncludeDirectories; // "$AdditionalIncludeDirectories"
+extern const char *g_pOption_AdditionalProjectDependencies; // "$AdditionalProjectDependencies"
+extern const char *g_pOption_AdditionalOutputFiles; // "$AdditionalOutputFiles"
+extern const char *g_pOption_PreprocessorDefinitions; // "$PreprocessorDefinitions"
+extern char *g_IncludeSeparators[2];
+
+extern void VPC_ParseGroupScript( const char *pScriptName );
+
+extern groupTagIndex_t VPC_Group_FindOrCreateGroupTag( const char *pName, bool bCreate );
+
+extern void VPC_Keyword_Configuration();
+extern void VPC_Keyword_FileConfiguration();
+
+
+struct folderConfig_t
+{
+ CUtlVector<CUtlString> vecConfigurationNames;
+ CScriptSource scriptSource;
+
+ bool BHasConfig() { return vecConfigurationNames.Count() > 0; }
+ void Clear() { vecConfigurationNames.RemoveAll(); }
+};
+
+void VPC_Keyword_FolderConfiguration( folderConfig_t *pFolderConfig );
+void VPC_ApplyFolderConfigurationToFile( const folderConfig_t &folderConfig );
+
+extern void VPC_Config_SpewProperties( configKeyword_e keyword );
+extern bool VPC_Config_IgnoreOption( const char *pPropertyName );
+
+extern void VPC_FakeKeyword_SchemaFolder( class CBaseProjectDataCollector *pDataCollector );
diff --git a/external/vpc/utils/vpc/vpc.sln b/external/vpc/utils/vpc/vpc.sln
new file mode 100644
index 0000000..9e106f5
--- /dev/null
+++ b/external/vpc/utils/vpc/vpc.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpc", "vpc.vcxproj", "{36C5F545-588F-4091-B480-89E03EDBDA93}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {36C5F545-588F-4091-B480-89E03EDBDA93}.Debug|Win32.ActiveCfg = Debug|Win32
+ {36C5F545-588F-4091-B480-89E03EDBDA93}.Debug|Win32.Build.0 = Debug|Win32
+ {36C5F545-588F-4091-B480-89E03EDBDA93}.Release|Win32.ActiveCfg = Release|Win32
+ {36C5F545-588F-4091-B480-89E03EDBDA93}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/vpc/utils/vpc/vpc.vcxproj b/external/vpc/utils/vpc/vpc.vcxproj
new file mode 100644
index 0000000..be37d59
--- /dev/null
+++ b/external/vpc/utils/vpc/vpc.vcxproj
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{36C5F545-588F-4091-B480-89E03EDBDA93}</ProjectGuid>
+ <RootNamespace>vpc</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>NotSet</CharacterSet>
+ <PlatformToolset>v140_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>NotSet</CharacterSet>
+ <PlatformToolset>v140_xp</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\public;..\..\public\tier0;..\..\public\tier1;..\..\public\vstdlib;..\..\common\;..\..\common\p4api</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;PLATFORM_WINDOWS;COMPILER_MSVC;COMPILER_MSVC32;_USE_32BIT_TIME_T;STATIC_TIER0;NO_MALLOC_OVERRIDE;STATIC_VSTDLIB;STANDALONE_VPC;_MBCS;_CRT_NO_VA_START_VALIDATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <ExceptionHandling>Async</ExceptionHandling>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <PostBuildEvent>
+ <Command>p4 edit ..\..\..\..\devtools\bin\vpc.exe &amp;&amp; copy /y $(TargetPath) ..\..\..\..\devtools\bin\vpc.exe
+p4 edit ..\..\..\..\devtools\bin\vpc.pdb &amp;&amp; copy /y $(TargetDir)\vpc.pdb ..\..\..\..\devtools\bin\vpc.pdb
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..\public;..\..\public\tier0;..\..\public\tier1;..\..\public\vstdlib;..\..\common\;..\..\common\p4api</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;PLATFORM_WINDOWS;COMPILER_MSVC;COMPILER_MSVC32;_USE_32BIT_TIME_T;STATIC_TIER0;NO_MALLOC_OVERRIDE;STATIC_VSTDLIB;STANDALONE_VPC;_MBCS;_CRT_NO_VA_START_VALIDATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <PostBuildEvent>
+ <Command>p4 edit ..\..\..\..\devtools\bin\vpc.exe &amp;&amp; copy /y $(TargetPath) ..\..\..\..\devtools\bin\vpc.exe
+p4 edit ..\..\..\..\devtools\bin\vpc.pdb &amp;&amp; copy /y $(TargetDir)\vpc.pdb ..\..\..\..\devtools\bin\vpc.pdb
+</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\interfaces\interfaces.cpp" />
+ <ClCompile Include="..\..\p4lib\p4.cpp" />
+ <ClCompile Include="..\..\tier0\assert_dialog.cpp" />
+ <ClCompile Include="..\..\tier0\commandline.cpp" />
+ <ClCompile Include="..\..\tier0\cpu.cpp" />
+ <ClCompile Include="..\..\tier0\cputopology.cpp" />
+ <ClCompile Include="..\..\tier0\dbg.cpp" />
+ <ClCompile Include="..\..\tier0\fasttimer.cpp" />
+ <ClCompile Include="..\..\tier0\logging.cpp" />
+ <ClCompile Include="..\..\tier0\mem.cpp" />
+ <ClCompile Include="..\..\tier0\memdbg.cpp" />
+ <ClCompile Include="..\..\tier0\memstd.cpp" />
+ <ClCompile Include="..\..\tier0\memvalidate.cpp" />
+ <ClCompile Include="..\..\tier0\mem_helpers.cpp" />
+ <ClCompile Include="..\..\tier0\minidump.cpp" />
+ <ClCompile Include="..\..\tier0\pch_tier0.cpp" />
+ <ClCompile Include="..\..\tier0\platform.cpp" />
+ <ClCompile Include="..\..\tier0\pme.cpp" />
+ <ClCompile Include="..\..\tier0\pmelib.cpp" />
+ <ClCompile Include="..\..\tier0\stacktools.cpp" />
+ <ClCompile Include="..\..\tier0\threadtools.cpp" />
+ <ClCompile Include="..\..\tier0\tier0_strtools.cpp" />
+ <ClCompile Include="..\..\tier0\valobject.cpp" />
+ <ClCompile Include="..\..\tier0\vprof.cpp" />
+ <ClCompile Include="..\..\tier0\win32consoleio.cpp" />
+ <ClCompile Include="..\..\tier1\characterset.cpp" />
+ <ClCompile Include="..\..\tier1\checksum_crc.cpp" />
+ <ClCompile Include="..\..\tier1\checksum_md5.cpp" />
+ <ClCompile Include="..\..\tier1\convar.cpp" />
+ <ClCompile Include="..\..\tier1\exprevaluator.cpp" />
+ <ClCompile Include="..\..\tier1\generichash.cpp" />
+ <ClCompile Include="..\..\tier1\interface.cpp" />
+ <ClCompile Include="..\..\tier1\keyvalues.cpp" />
+ <ClCompile Include="..\..\tier1\mempool.cpp" />
+ <ClCompile Include="..\..\tier1\memstack.cpp" />
+ <ClCompile Include="..\..\tier1\splitstring.cpp" />
+ <ClCompile Include="..\..\tier1\stringpool.cpp" />
+ <ClCompile Include="..\..\tier1\strtools.cpp" />
+ <ClCompile Include="..\..\tier1\tier1.cpp" />
+ <ClCompile Include="..\..\tier1\utlbuffer.cpp" />
+ <ClCompile Include="..\..\tier1\utlstring.cpp" />
+ <ClCompile Include="..\..\tier1\utlsymbol.cpp" />
+ <ClCompile Include="..\..\vstdlib\cvar.cpp" />
+ <ClCompile Include="..\..\vstdlib\keyvaluessystem.cpp" />
+ <ClCompile Include="..\..\vstdlib\random.cpp" />
+ <ClCompile Include="..\..\vstdlib\vstrtools.cpp" />
+ <ClCompile Include="..\vpccrccheck\crccheck_shared.cpp" />
+ <ClCompile Include="baseprojectdatacollector.cpp" />
+ <ClCompile Include="conditionals.cpp" />
+ <ClCompile Include="configuration.cpp" />
+ <ClCompile Include="dependencies.cpp" />
+ <ClCompile Include="exprsimplifier.cpp" />
+ <ClCompile Include="generatordefinition.cpp" />
+ <ClCompile Include="groupscript.cpp" />
+ <ClCompile Include="macros.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="p4sln.cpp" />
+ <ClCompile Include="projectgenerator_codelite.cpp" />
+ <ClCompile Include="projectgenerator_makefile.cpp" />
+ <ClCompile Include="projectgenerator_ps3.cpp" />
+ <ClCompile Include="projectgenerator_vcproj.cpp" />
+ <ClCompile Include="projectgenerator_win32.cpp" />
+ <ClCompile Include="projectgenerator_win32_2010.cpp" />
+ <ClCompile Include="projectgenerator_xbox360.cpp" />
+ <ClCompile Include="projectgenerator_xbox360_2010.cpp" />
+ <ClCompile Include="projectscript.cpp" />
+ <ClCompile Include="scriptsource.cpp" />
+ <ClCompile Include="solutiongenerator_codelite.cpp" />
+ <ClCompile Include="solutiongenerator_makefile.cpp" />
+ <ClCompile Include="solutiongenerator_win32.cpp" />
+ <ClCompile Include="solutiongenerator_xcode.cpp" />
+ <ClCompile Include="sys_utils.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\tier0\cputopology.h" />
+ <ClInclude Include="..\..\tier0\memstd.h" />
+ <ClInclude Include="..\..\tier0\mem_helpers.h" />
+ <ClInclude Include="..\..\tier0\mem_impl_type.h" />
+ <ClInclude Include="..\..\tier0\pch_tier0.h" />
+ <ClInclude Include="..\..\tier0\resource.h" />
+ <ClInclude Include="..\..\tier0\tier0_strtools.h" />
+ <ClInclude Include="..\..\vstdlib\concommandhash.h" />
+ <ClInclude Include="..\vpccrccheck\crccheck_shared.h" />
+ <ClInclude Include="baseprojectdatacollector.h" />
+ <ClInclude Include="dependencies.h" />
+ <ClInclude Include="generatordefinition.h" />
+ <ClInclude Include="ibaseprojectgenerator.h" />
+ <ClInclude Include="ibasesolutiongenerator.h" />
+ <ClInclude Include="p4sln.h" />
+ <ClInclude Include="projectgenerator_codelite.h" />
+ <ClInclude Include="projectgenerator_ps3.h" />
+ <ClInclude Include="projectgenerator_vcproj.h" />
+ <ClInclude Include="projectgenerator_win32.h" />
+ <ClInclude Include="projectgenerator_win32_2010.h" />
+ <ClInclude Include="projectgenerator_xbox360.h" />
+ <ClInclude Include="projectgenerator_xbox360_2010.h" />
+ <ClInclude Include="projectgenerator_xcode.h" />
+ <ClInclude Include="scriptsource.h" />
+ <ClInclude Include="sys_utils.h" />
+ <ClInclude Include="vpc.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\vpc_scripts\definitions\ps3.def" />
+ <None Include="..\..\vpc_scripts\definitions\win32_2005.def" />
+ <None Include="..\..\vpc_scripts\definitions\win32_2010.def" />
+ <None Include="..\..\vpc_scripts\definitions\xbox360.def" />
+ <None Include="..\..\vpc_scripts\definitions\xbox360_2010.def" />
+ <None Include="Makefile" />
+ <None Include="projectgenerator_ps3.inc" />
+ <None Include="projectgenerator_win32.inc" />
+ <None Include="projectgenerator_win32_2010.inc" />
+ <None Include="projectgenerator_xbox360.inc" />
+ <None Include="projectgenerator_xbox360_2010.inc" />
+ <None Include="vpc.opensdf" />
+ <None Include="vpc.vpc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\..\lib\common\debug\libclient.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\debug\libp4sslstub.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\debug\librpc.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\debug\libsupp.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\libclient.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\libp4sslstub.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\librpc.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ </Library>
+ <Library Include="..\..\lib\common\libsupp.lib">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ </Library>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/external/vpc/utils/vpc/vpc.vcxproj.filters b/external/vpc/utils/vpc/vpc.vcxproj.filters
new file mode 100644
index 0000000..be39a00
--- /dev/null
+++ b/external/vpc/utils/vpc/vpc.vcxproj.filters
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="VPC">
+ <UniqueIdentifier>{46bac1ee-3374-43a2-9761-f79ee2691007}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="VPC\Header Files">
+ <UniqueIdentifier>{38599379-561b-43c5-bdc9-e84eee3ab186}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="VPC\Source Files">
+ <UniqueIdentifier>{13ae58f1-21cb-4159-82ae-3d2dbd5238a7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Dependencies">
+ <UniqueIdentifier>{e86543a4-b232-42c1-91e4-ddd9dd9c36a8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Dependencies\Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Dependencies\Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="VPC\definitions">
+ <UniqueIdentifier>{f5d738f6-132d-42e7-9f03-05388b11b408}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="VPC\VPCCRCCheck">
+ <UniqueIdentifier>{90afaed2-cb09-4747-bb13-2186c417c0f2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="P4 Libs">
+ <UniqueIdentifier>{7bc720f7-b058-4998-9fa5-03df7999beef}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\interfaces\interfaces.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\assert_dialog.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\commandline.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\cpu.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\dbg.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\fasttimer.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\logging.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\mem.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\mem_helpers.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\memdbg.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\memstd.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\memvalidate.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\minidump.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\pch_tier0.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\threadtools.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\tier0_strtools.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\valobject.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\vprof.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\win32consoleio.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\characterset.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\checksum_crc.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\checksum_md5.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\convar.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\exprevaluator.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\generichash.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\interface.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\keyvalues.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\mempool.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\memstack.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\splitstring.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\stringpool.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\strtools.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\tier1.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\utlbuffer.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\utlstring.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier1\utlsymbol.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\vstdlib\cvar.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\vstdlib\keyvaluessystem.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\vstdlib\random.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\vstdlib\vstrtools.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\platform.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\cputopology.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\stacktools.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\pme.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\tier0\pmelib.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="baseprojectdatacollector.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="conditionals.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="configuration.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dependencies.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="exprsimplifier.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="generatordefinition.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="groupscript.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="macros.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="p4sln.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_makefile.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_ps3.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_vcproj.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_win32.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_win32_2010.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_xbox360.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_xbox360_2010.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="projectscript.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptsource.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="solutiongenerator_makefile.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="solutiongenerator_win32.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="solutiongenerator_xcode.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="sys_utils.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\vpccrccheck\crccheck_shared.cpp">
+ <Filter>VPC\VPCCRCCheck</Filter>
+ </ClCompile>
+ <ClCompile Include="projectgenerator_codelite.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="solutiongenerator_codelite.cpp">
+ <Filter>VPC\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\p4lib\p4.cpp">
+ <Filter>Dependencies\Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\tier0\mem_helpers.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\mem_impl_type.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\memstd.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\pch_tier0.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\resource.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\tier0_strtools.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\vstdlib\concommandhash.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\tier0\cputopology.h">
+ <Filter>Dependencies\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="baseprojectdatacollector.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="dependencies.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="generatordefinition.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ibaseprojectgenerator.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ibasesolutiongenerator.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="p4sln.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_ps3.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_vcproj.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_win32.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_win32_2010.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_xbox360.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_xbox360_2010.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_xcode.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="scriptsource.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="sys_utils.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="vpc.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\vpccrccheck\crccheck_shared.h">
+ <Filter>VPC\VPCCRCCheck</Filter>
+ </ClInclude>
+ <ClInclude Include="projectgenerator_codelite.h">
+ <Filter>VPC\Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Makefile" />
+ <None Include="vpc.opensdf" />
+ <None Include="vpc.vpc" />
+ <None Include="projectgenerator_ps3.inc">
+ <Filter>VPC\Header Files</Filter>
+ </None>
+ <None Include="projectgenerator_win32.inc">
+ <Filter>VPC\Header Files</Filter>
+ </None>
+ <None Include="projectgenerator_win32_2010.inc">
+ <Filter>VPC\Header Files</Filter>
+ </None>
+ <None Include="projectgenerator_xbox360.inc">
+ <Filter>VPC\Header Files</Filter>
+ </None>
+ <None Include="projectgenerator_xbox360_2010.inc">
+ <Filter>VPC\Header Files</Filter>
+ </None>
+ <None Include="..\..\vpc_scripts\definitions\ps3.def">
+ <Filter>VPC\definitions</Filter>
+ </None>
+ <None Include="..\..\vpc_scripts\definitions\win32_2005.def">
+ <Filter>VPC\definitions</Filter>
+ </None>
+ <None Include="..\..\vpc_scripts\definitions\win32_2010.def">
+ <Filter>VPC\definitions</Filter>
+ </None>
+ <None Include="..\..\vpc_scripts\definitions\xbox360.def">
+ <Filter>VPC\definitions</Filter>
+ </None>
+ <None Include="..\..\vpc_scripts\definitions\xbox360_2010.def">
+ <Filter>VPC\definitions</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Library Include="..\..\lib\common\libsupp.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\libclient.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\librpc.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\libp4sslstub.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\debug\libclient.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\debug\libp4sslstub.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\debug\librpc.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ <Library Include="..\..\lib\common\debug\libsupp.lib">
+ <Filter>P4 Libs</Filter>
+ </Library>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/external/vpc/utils/vpc/vpc.xcodeproj/project.pbxproj b/external/vpc/utils/vpc/vpc.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..e468cfd
--- /dev/null
+++ b/external/vpc/utils/vpc/vpc.xcodeproj/project.pbxproj
@@ -0,0 +1,529 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 976DE7B71239412500E8D60A /* crccheck_shared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976DE7B51239412500E8D60A /* crccheck_shared.cpp */; };
+ 976DE7BA1239423E00E8D60A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 976DE7B91239423E00E8D60A /* Foundation.framework */; };
+ 976DE7BC1239424500E8D60A /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 976DE7BB1239424500E8D60A /* CoreServices.framework */; };
+ 976DE7BE1239424E00E8D60A /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 976DE7BD1239424E00E8D60A /* libiconv.dylib */; };
+ 977F706212393A2A008D8433 /* baseprojectdatacollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705012393A2A008D8433 /* baseprojectdatacollector.cpp */; };
+ 977F706312393A2A008D8433 /* configuration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705212393A2A008D8433 /* configuration.cpp */; };
+ 977F706412393A2A008D8433 /* dependencies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705312393A2A008D8433 /* dependencies.cpp */; };
+ 977F706512393A2A008D8433 /* ExprSimplifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705512393A2A008D8433 /* ExprSimplifier.cpp */; };
+ 977F706612393A2A008D8433 /* GroupScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705612393A2A008D8433 /* GroupScript.cpp */; };
+ 977F706712393A2A008D8433 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705912393A2A008D8433 /* main.cpp */; };
+ 977F706812393A2A008D8433 /* projectgenerator_makefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705A12393A2A008D8433 /* projectgenerator_makefile.cpp */; };
+ 977F706912393A2A008D8433 /* projectgenerator_xcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705B12393A2A008D8433 /* projectgenerator_xcode.cpp */; };
+ 977F706A12393A2A008D8433 /* ProjectScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705D12393A2A008D8433 /* ProjectScript.cpp */; };
+ 977F706B12393A2A008D8433 /* solutiongenerator_makefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705E12393A2A008D8433 /* solutiongenerator_makefile.cpp */; };
+ 977F706C12393A2A008D8433 /* solutiongenerator_xcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F705F12393A2A008D8433 /* solutiongenerator_xcode.cpp */; };
+ 977F706D12393A2A008D8433 /* sys_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F706012393A2A008D8433 /* sys_utils.cpp */; };
+ 977F708912393ADD008D8433 /* assert_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707212393ADD008D8433 /* assert_dialog.cpp */; };
+ 977F708A12393ADD008D8433 /* cpu_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707312393ADD008D8433 /* cpu_posix.cpp */; };
+ 977F708B12393ADD008D8433 /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707412393ADD008D8433 /* cpu.cpp */; };
+ 977F708C12393ADD008D8433 /* dbg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707512393ADD008D8433 /* dbg.cpp */; };
+ 977F708D12393ADD008D8433 /* fasttimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707612393ADD008D8433 /* fasttimer.cpp */; };
+ 977F708E12393ADD008D8433 /* mem_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707712393ADD008D8433 /* mem_helpers.cpp */; };
+ 977F708F12393ADD008D8433 /* memblockhdr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707812393ADD008D8433 /* memblockhdr.cpp */; };
+ 977F709012393ADD008D8433 /* memdbg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707912393ADD008D8433 /* memdbg.cpp */; };
+ 977F709112393ADD008D8433 /* memstd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707A12393ADD008D8433 /* memstd.cpp */; };
+ 977F709212393ADD008D8433 /* memvalidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707B12393ADD008D8433 /* memvalidate.cpp */; };
+ 977F709312393ADD008D8433 /* minidump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707C12393ADD008D8433 /* minidump.cpp */; };
+ 977F709412393ADD008D8433 /* pch_tier0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707D12393ADD008D8433 /* pch_tier0.cpp */; };
+ 977F709512393ADD008D8433 /* platform_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707E12393ADD008D8433 /* platform_posix.cpp */; };
+ 977F709612393ADD008D8433 /* pme_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F707F12393ADD008D8433 /* pme_posix.cpp */; };
+ 977F709712393ADD008D8433 /* pmelib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708012393ADD008D8433 /* pmelib.cpp */; };
+ 977F709812393ADD008D8433 /* testthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708112393ADD008D8433 /* testthread.cpp */; };
+ 977F709912393ADD008D8433 /* thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708212393ADD008D8433 /* thread.cpp */; };
+ 977F709A12393ADD008D8433 /* threadtools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708312393ADD008D8433 /* threadtools.cpp */; };
+ 977F709B12393ADD008D8433 /* tier0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708412393ADD008D8433 /* tier0.cpp */; };
+ 977F709C12393ADD008D8433 /* validator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708512393ADD008D8433 /* validator.cpp */; };
+ 977F709D12393ADD008D8433 /* valobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708612393ADD008D8433 /* valobject.cpp */; };
+ 977F709E12393ADD008D8433 /* vcrmode_posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708712393ADD008D8433 /* vcrmode_posix.cpp */; };
+ 977F709F12393ADD008D8433 /* vprof.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F708812393ADD008D8433 /* vprof.cpp */; };
+ 977F70AB12393B10008D8433 /* checksum_crc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A012393B10008D8433 /* checksum_crc.cpp */; };
+ 977F70AC12393B10008D8433 /* checksum_md5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A112393B10008D8433 /* checksum_md5.cpp */; };
+ 977F70AD12393B10008D8433 /* convar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A212393B10008D8433 /* convar.cpp */; };
+ 977F70AE12393B10008D8433 /* generichash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A312393B10008D8433 /* generichash.cpp */; };
+ 977F70AF12393B10008D8433 /* interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A412393B10008D8433 /* interface.cpp */; };
+ 977F70B012393B10008D8433 /* KeyValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A512393B10008D8433 /* KeyValues.cpp */; };
+ 977F70B112393B10008D8433 /* mempool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A612393B10008D8433 /* mempool.cpp */; };
+ 977F70B212393B10008D8433 /* memstack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A712393B10008D8433 /* memstack.cpp */; };
+ 977F70B312393B10008D8433 /* stringpool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A812393B10008D8433 /* stringpool.cpp */; };
+ 977F70B412393B10008D8433 /* utlbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70A912393B10008D8433 /* utlbuffer.cpp */; };
+ 977F70B512393B10008D8433 /* utlsymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70AA12393B10008D8433 /* utlsymbol.cpp */; };
+ 977F70BF12393B49008D8433 /* commandline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70B612393B49008D8433 /* commandline.cpp */; };
+ 977F70C012393B49008D8433 /* cvar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70B712393B49008D8433 /* cvar.cpp */; };
+ 977F70C112393B49008D8433 /* keyvaluessystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70B812393B49008D8433 /* keyvaluessystem.cpp */; };
+ 977F70C212393B49008D8433 /* osversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70B912393B49008D8433 /* osversion.cpp */; };
+ 977F70C312393B49008D8433 /* qsort_s.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70BA12393B49008D8433 /* qsort_s.cpp */; };
+ 977F70C412393B49008D8433 /* random.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70BB12393B49008D8433 /* random.cpp */; };
+ 977F70C512393B49008D8433 /* splitstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70BC12393B49008D8433 /* splitstring.cpp */; };
+ 977F70C612393B49008D8433 /* stringnormalize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70BD12393B49008D8433 /* stringnormalize.cpp */; };
+ 977F70C712393B49008D8433 /* strtools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 977F70BE12393B49008D8433 /* strtools.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 977F703E12393174008D8433 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 976DE7B51239412500E8D60A /* crccheck_shared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = crccheck_shared.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpccrccheck/crccheck_shared.cpp; sourceTree = "<absolute>"; };
+ 976DE7B61239412500E8D60A /* crccheck_shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crccheck_shared.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpccrccheck/crccheck_shared.h; sourceTree = "<absolute>"; };
+ 976DE7B91239423E00E8D60A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Xcode4/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 976DE7BB1239424500E8D60A /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Xcode4/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+ 976DE7BD1239424E00E8D60A /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = Xcode4/SDKs/MacOSX10.5.sdk/usr/lib/libiconv.dylib; sourceTree = SDKROOT; };
+ 977F704012393174008D8433 /* vpc_osx */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vpc_osx; sourceTree = BUILT_PRODUCTS_DIR; };
+ 977F705012393A2A008D8433 /* baseprojectdatacollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = baseprojectdatacollector.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/baseprojectdatacollector.cpp; sourceTree = "<absolute>"; };
+ 977F705112393A2A008D8433 /* baseprojectdatacollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprojectdatacollector.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/baseprojectdatacollector.h; sourceTree = "<absolute>"; };
+ 977F705212393A2A008D8433 /* configuration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = configuration.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/configuration.cpp; sourceTree = "<absolute>"; };
+ 977F705312393A2A008D8433 /* dependencies.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dependencies.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/dependencies.cpp; sourceTree = "<absolute>"; };
+ 977F705412393A2A008D8433 /* dependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dependencies.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/dependencies.h; sourceTree = "<absolute>"; };
+ 977F705512393A2A008D8433 /* ExprSimplifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExprSimplifier.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/ExprSimplifier.cpp; sourceTree = "<absolute>"; };
+ 977F705612393A2A008D8433 /* GroupScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GroupScript.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/GroupScript.cpp; sourceTree = "<absolute>"; };
+ 977F705712393A2A008D8433 /* ibaseprojectgenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ibaseprojectgenerator.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/ibaseprojectgenerator.h; sourceTree = "<absolute>"; };
+ 977F705812393A2A008D8433 /* ibasesolutiongenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ibasesolutiongenerator.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/ibasesolutiongenerator.h; sourceTree = "<absolute>"; };
+ 977F705912393A2A008D8433 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/main.cpp; sourceTree = "<absolute>"; };
+ 977F705A12393A2A008D8433 /* projectgenerator_makefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = projectgenerator_makefile.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/projectgenerator_makefile.cpp; sourceTree = "<absolute>"; };
+ 977F705B12393A2A008D8433 /* projectgenerator_xcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = projectgenerator_xcode.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/projectgenerator_xcode.cpp; sourceTree = "<absolute>"; };
+ 977F705C12393A2A008D8433 /* projectgenerator_xcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = projectgenerator_xcode.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/projectgenerator_xcode.h; sourceTree = "<absolute>"; };
+ 977F705D12393A2A008D8433 /* ProjectScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProjectScript.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/ProjectScript.cpp; sourceTree = "<absolute>"; };
+ 977F705E12393A2A008D8433 /* solutiongenerator_makefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = solutiongenerator_makefile.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/solutiongenerator_makefile.cpp; sourceTree = "<absolute>"; };
+ 977F705F12393A2A008D8433 /* solutiongenerator_xcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = solutiongenerator_xcode.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/solutiongenerator_xcode.cpp; sourceTree = "<absolute>"; };
+ 977F706012393A2A008D8433 /* sys_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sys_utils.cpp; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/sys_utils.cpp; sourceTree = "<absolute>"; };
+ 977F706112393A2A008D8433 /* sys_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sys_utils.h; path = /Users/dberger/P4Clients/steam3_main/src/utils/vpc/sys_utils.h; sourceTree = "<absolute>"; };
+ 977F707212393ADD008D8433 /* assert_dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = assert_dialog.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/assert_dialog.cpp; sourceTree = "<absolute>"; };
+ 977F707312393ADD008D8433 /* cpu_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cpu_posix.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/cpu_posix.cpp; sourceTree = "<absolute>"; };
+ 977F707412393ADD008D8433 /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cpu.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/cpu.cpp; sourceTree = "<absolute>"; };
+ 977F707512393ADD008D8433 /* dbg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dbg.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/dbg.cpp; sourceTree = "<absolute>"; };
+ 977F707612393ADD008D8433 /* fasttimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fasttimer.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/fasttimer.cpp; sourceTree = "<absolute>"; };
+ 977F707712393ADD008D8433 /* mem_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mem_helpers.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/mem_helpers.cpp; sourceTree = "<absolute>"; };
+ 977F707812393ADD008D8433 /* memblockhdr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memblockhdr.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/memblockhdr.cpp; sourceTree = "<absolute>"; };
+ 977F707912393ADD008D8433 /* memdbg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memdbg.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/memdbg.cpp; sourceTree = "<absolute>"; };
+ 977F707A12393ADD008D8433 /* memstd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memstd.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/memstd.cpp; sourceTree = "<absolute>"; };
+ 977F707B12393ADD008D8433 /* memvalidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memvalidate.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/memvalidate.cpp; sourceTree = "<absolute>"; };
+ 977F707C12393ADD008D8433 /* minidump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/minidump.cpp; sourceTree = "<absolute>"; };
+ 977F707D12393ADD008D8433 /* pch_tier0.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pch_tier0.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/pch_tier0.cpp; sourceTree = "<absolute>"; };
+ 977F707E12393ADD008D8433 /* platform_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = platform_posix.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/platform_posix.cpp; sourceTree = "<absolute>"; };
+ 977F707F12393ADD008D8433 /* pme_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pme_posix.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/pme_posix.cpp; sourceTree = "<absolute>"; };
+ 977F708012393ADD008D8433 /* pmelib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pmelib.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/pmelib.cpp; sourceTree = "<absolute>"; };
+ 977F708112393ADD008D8433 /* testthread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testthread.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/testthread.cpp; sourceTree = "<absolute>"; };
+ 977F708212393ADD008D8433 /* thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = thread.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/thread.cpp; sourceTree = "<absolute>"; };
+ 977F708312393ADD008D8433 /* threadtools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = threadtools.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/threadtools.cpp; sourceTree = "<absolute>"; };
+ 977F708412393ADD008D8433 /* tier0.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tier0.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/tier0.cpp; sourceTree = "<absolute>"; };
+ 977F708512393ADD008D8433 /* validator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = validator.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/validator.cpp; sourceTree = "<absolute>"; };
+ 977F708612393ADD008D8433 /* valobject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = valobject.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/valobject.cpp; sourceTree = "<absolute>"; };
+ 977F708712393ADD008D8433 /* vcrmode_posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vcrmode_posix.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/vcrmode_posix.cpp; sourceTree = "<absolute>"; };
+ 977F708812393ADD008D8433 /* vprof.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vprof.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier0/vprof.cpp; sourceTree = "<absolute>"; };
+ 977F70A012393B10008D8433 /* checksum_crc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checksum_crc.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/checksum_crc.cpp; sourceTree = "<absolute>"; };
+ 977F70A112393B10008D8433 /* checksum_md5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checksum_md5.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/checksum_md5.cpp; sourceTree = "<absolute>"; };
+ 977F70A212393B10008D8433 /* convar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = convar.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/convar.cpp; sourceTree = "<absolute>"; };
+ 977F70A312393B10008D8433 /* generichash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = generichash.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/generichash.cpp; sourceTree = "<absolute>"; };
+ 977F70A412393B10008D8433 /* interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = interface.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/interface.cpp; sourceTree = "<absolute>"; };
+ 977F70A512393B10008D8433 /* KeyValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyValues.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/KeyValues.cpp; sourceTree = "<absolute>"; };
+ 977F70A612393B10008D8433 /* mempool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mempool.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/mempool.cpp; sourceTree = "<absolute>"; };
+ 977F70A712393B10008D8433 /* memstack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = memstack.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/memstack.cpp; sourceTree = "<absolute>"; };
+ 977F70A812393B10008D8433 /* stringpool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stringpool.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/stringpool.cpp; sourceTree = "<absolute>"; };
+ 977F70A912393B10008D8433 /* utlbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utlbuffer.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/utlbuffer.cpp; sourceTree = "<absolute>"; };
+ 977F70AA12393B10008D8433 /* utlsymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utlsymbol.cpp; path = /Users/dberger/P4Clients/steam3_main/src/tier1/utlsymbol.cpp; sourceTree = "<absolute>"; };
+ 977F70B612393B49008D8433 /* commandline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = commandline.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/commandline.cpp; sourceTree = "<absolute>"; };
+ 977F70B712393B49008D8433 /* cvar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cvar.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/cvar.cpp; sourceTree = "<absolute>"; };
+ 977F70B812393B49008D8433 /* keyvaluessystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = keyvaluessystem.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/keyvaluessystem.cpp; sourceTree = "<absolute>"; };
+ 977F70B912393B49008D8433 /* osversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osversion.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/osversion.cpp; sourceTree = "<absolute>"; };
+ 977F70BA12393B49008D8433 /* qsort_s.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qsort_s.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/qsort_s.cpp; sourceTree = "<absolute>"; };
+ 977F70BB12393B49008D8433 /* random.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = random.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/random.cpp; sourceTree = "<absolute>"; };
+ 977F70BC12393B49008D8433 /* splitstring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = splitstring.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/splitstring.cpp; sourceTree = "<absolute>"; };
+ 977F70BD12393B49008D8433 /* stringnormalize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stringnormalize.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/stringnormalize.cpp; sourceTree = "<absolute>"; };
+ 977F70BE12393B49008D8433 /* strtools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = strtools.cpp; path = /Users/dberger/P4Clients/steam3_main/src/vstdlib/strtools.cpp; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 977F703D12393174008D8433 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 976DE7BE1239424E00E8D60A /* libiconv.dylib in Frameworks */,
+ 976DE7BC1239424500E8D60A /* CoreServices.framework in Frameworks */,
+ 976DE7BA1239423E00E8D60A /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 976DE7B41239411300E8D60A /* crccheck_shared */ = {
+ isa = PBXGroup;
+ children = (
+ 976DE7B51239412500E8D60A /* crccheck_shared.cpp */,
+ 976DE7B61239412500E8D60A /* crccheck_shared.h */,
+ );
+ name = crccheck_shared;
+ sourceTree = "<group>";
+ };
+ 976DE7BF1239425600E8D60A /* Libs */ = {
+ isa = PBXGroup;
+ children = (
+ 976DE7BD1239424E00E8D60A /* libiconv.dylib */,
+ 976DE7BB1239424500E8D60A /* CoreServices.framework */,
+ 976DE7B91239423E00E8D60A /* Foundation.framework */,
+ );
+ name = Libs;
+ sourceTree = "<group>";
+ };
+ 977F703312393173008D8433 = {
+ isa = PBXGroup;
+ children = (
+ 977F703A12393174008D8433 /* Source */,
+ 976DE7BF1239425600E8D60A /* Libs */,
+ 977F704112393174008D8433 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 977F703A12393174008D8433 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 977F706F12393A45008D8433 /* tier0 */,
+ 977F707012393A4D008D8433 /* tier1 */,
+ 977F707112393A56008D8433 /* vstdlib */,
+ 976DE7B41239411300E8D60A /* crccheck_shared */,
+ 977F706E12393A3D008D8433 /* vpc */,
+ );
+ path = Source;
+ sourceTree = "<group>";
+ };
+ 977F704112393174008D8433 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 977F704012393174008D8433 /* vpc_osx */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 977F706E12393A3D008D8433 /* vpc */ = {
+ isa = PBXGroup;
+ children = (
+ 977F705012393A2A008D8433 /* baseprojectdatacollector.cpp */,
+ 977F705112393A2A008D8433 /* baseprojectdatacollector.h */,
+ 977F705212393A2A008D8433 /* configuration.cpp */,
+ 977F705312393A2A008D8433 /* dependencies.cpp */,
+ 977F705412393A2A008D8433 /* dependencies.h */,
+ 977F705512393A2A008D8433 /* ExprSimplifier.cpp */,
+ 977F705612393A2A008D8433 /* GroupScript.cpp */,
+ 977F705712393A2A008D8433 /* ibaseprojectgenerator.h */,
+ 977F705812393A2A008D8433 /* ibasesolutiongenerator.h */,
+ 977F705912393A2A008D8433 /* main.cpp */,
+ 977F705A12393A2A008D8433 /* projectgenerator_makefile.cpp */,
+ 977F705B12393A2A008D8433 /* projectgenerator_xcode.cpp */,
+ 977F705C12393A2A008D8433 /* projectgenerator_xcode.h */,
+ 977F705D12393A2A008D8433 /* ProjectScript.cpp */,
+ 977F705E12393A2A008D8433 /* solutiongenerator_makefile.cpp */,
+ 977F705F12393A2A008D8433 /* solutiongenerator_xcode.cpp */,
+ 977F706012393A2A008D8433 /* sys_utils.cpp */,
+ 977F706112393A2A008D8433 /* sys_utils.h */,
+ );
+ name = vpc;
+ sourceTree = "<group>";
+ };
+ 977F706F12393A45008D8433 /* tier0 */ = {
+ isa = PBXGroup;
+ children = (
+ 977F707212393ADD008D8433 /* assert_dialog.cpp */,
+ 977F707312393ADD008D8433 /* cpu_posix.cpp */,
+ 977F707412393ADD008D8433 /* cpu.cpp */,
+ 977F707512393ADD008D8433 /* dbg.cpp */,
+ 977F707612393ADD008D8433 /* fasttimer.cpp */,
+ 977F707712393ADD008D8433 /* mem_helpers.cpp */,
+ 977F707812393ADD008D8433 /* memblockhdr.cpp */,
+ 977F707912393ADD008D8433 /* memdbg.cpp */,
+ 977F707A12393ADD008D8433 /* memstd.cpp */,
+ 977F707B12393ADD008D8433 /* memvalidate.cpp */,
+ 977F707C12393ADD008D8433 /* minidump.cpp */,
+ 977F707D12393ADD008D8433 /* pch_tier0.cpp */,
+ 977F707E12393ADD008D8433 /* platform_posix.cpp */,
+ 977F707F12393ADD008D8433 /* pme_posix.cpp */,
+ 977F708012393ADD008D8433 /* pmelib.cpp */,
+ 977F708112393ADD008D8433 /* testthread.cpp */,
+ 977F708212393ADD008D8433 /* thread.cpp */,
+ 977F708312393ADD008D8433 /* threadtools.cpp */,
+ 977F708412393ADD008D8433 /* tier0.cpp */,
+ 977F708512393ADD008D8433 /* validator.cpp */,
+ 977F708612393ADD008D8433 /* valobject.cpp */,
+ 977F708712393ADD008D8433 /* vcrmode_posix.cpp */,
+ 977F708812393ADD008D8433 /* vprof.cpp */,
+ );
+ name = tier0;
+ sourceTree = "<group>";
+ };
+ 977F707012393A4D008D8433 /* tier1 */ = {
+ isa = PBXGroup;
+ children = (
+ 977F70A012393B10008D8433 /* checksum_crc.cpp */,
+ 977F70A112393B10008D8433 /* checksum_md5.cpp */,
+ 977F70A212393B10008D8433 /* convar.cpp */,
+ 977F70A312393B10008D8433 /* generichash.cpp */,
+ 977F70A412393B10008D8433 /* interface.cpp */,
+ 977F70A512393B10008D8433 /* KeyValues.cpp */,
+ 977F70A612393B10008D8433 /* mempool.cpp */,
+ 977F70A712393B10008D8433 /* memstack.cpp */,
+ 977F70A812393B10008D8433 /* stringpool.cpp */,
+ 977F70A912393B10008D8433 /* utlbuffer.cpp */,
+ 977F70AA12393B10008D8433 /* utlsymbol.cpp */,
+ );
+ name = tier1;
+ sourceTree = "<group>";
+ };
+ 977F707112393A56008D8433 /* vstdlib */ = {
+ isa = PBXGroup;
+ children = (
+ 977F70B612393B49008D8433 /* commandline.cpp */,
+ 977F70B712393B49008D8433 /* cvar.cpp */,
+ 977F70B812393B49008D8433 /* keyvaluessystem.cpp */,
+ 977F70B912393B49008D8433 /* osversion.cpp */,
+ 977F70BA12393B49008D8433 /* qsort_s.cpp */,
+ 977F70BB12393B49008D8433 /* random.cpp */,
+ 977F70BC12393B49008D8433 /* splitstring.cpp */,
+ 977F70BD12393B49008D8433 /* stringnormalize.cpp */,
+ 977F70BE12393B49008D8433 /* strtools.cpp */,
+ );
+ name = vstdlib;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 977F703F12393174008D8433 /* vpc */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 977F704812393174008D8433 /* Build configuration list for PBXNativeTarget "vpc" */;
+ buildPhases = (
+ 977F703C12393174008D8433 /* Sources */,
+ 977F703D12393174008D8433 /* Frameworks */,
+ 977F703E12393174008D8433 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = vpc;
+ productName = vpc;
+ productReference = 977F704012393174008D8433 /* vpc_osx */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 977F703512393173008D8433 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 977F703812393173008D8433 /* Build configuration list for PBXProject "vpc" */;
+ compatibilityVersion = "Xcode 3.2";
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 977F703312393173008D8433;
+ productRefGroup = 977F704112393174008D8433 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 977F703F12393174008D8433 /* vpc */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 977F703C12393174008D8433 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 977F706212393A2A008D8433 /* baseprojectdatacollector.cpp in Sources */,
+ 977F706312393A2A008D8433 /* configuration.cpp in Sources */,
+ 977F706412393A2A008D8433 /* dependencies.cpp in Sources */,
+ 977F706512393A2A008D8433 /* ExprSimplifier.cpp in Sources */,
+ 977F706612393A2A008D8433 /* GroupScript.cpp in Sources */,
+ 977F706712393A2A008D8433 /* main.cpp in Sources */,
+ 977F706812393A2A008D8433 /* projectgenerator_makefile.cpp in Sources */,
+ 977F706912393A2A008D8433 /* projectgenerator_xcode.cpp in Sources */,
+ 977F706A12393A2A008D8433 /* ProjectScript.cpp in Sources */,
+ 977F706B12393A2A008D8433 /* solutiongenerator_makefile.cpp in Sources */,
+ 977F706C12393A2A008D8433 /* solutiongenerator_xcode.cpp in Sources */,
+ 977F706D12393A2A008D8433 /* sys_utils.cpp in Sources */,
+ 977F708912393ADD008D8433 /* assert_dialog.cpp in Sources */,
+ 977F708A12393ADD008D8433 /* cpu_posix.cpp in Sources */,
+ 977F708B12393ADD008D8433 /* cpu.cpp in Sources */,
+ 977F708C12393ADD008D8433 /* dbg.cpp in Sources */,
+ 977F708D12393ADD008D8433 /* fasttimer.cpp in Sources */,
+ 977F708E12393ADD008D8433 /* mem_helpers.cpp in Sources */,
+ 977F708F12393ADD008D8433 /* memblockhdr.cpp in Sources */,
+ 977F709012393ADD008D8433 /* memdbg.cpp in Sources */,
+ 977F709112393ADD008D8433 /* memstd.cpp in Sources */,
+ 977F709212393ADD008D8433 /* memvalidate.cpp in Sources */,
+ 977F709312393ADD008D8433 /* minidump.cpp in Sources */,
+ 977F709412393ADD008D8433 /* pch_tier0.cpp in Sources */,
+ 977F709512393ADD008D8433 /* platform_posix.cpp in Sources */,
+ 977F709612393ADD008D8433 /* pme_posix.cpp in Sources */,
+ 977F709712393ADD008D8433 /* pmelib.cpp in Sources */,
+ 977F709812393ADD008D8433 /* testthread.cpp in Sources */,
+ 977F709912393ADD008D8433 /* thread.cpp in Sources */,
+ 977F709A12393ADD008D8433 /* threadtools.cpp in Sources */,
+ 977F709B12393ADD008D8433 /* tier0.cpp in Sources */,
+ 977F709C12393ADD008D8433 /* validator.cpp in Sources */,
+ 977F709D12393ADD008D8433 /* valobject.cpp in Sources */,
+ 977F709E12393ADD008D8433 /* vcrmode_posix.cpp in Sources */,
+ 977F709F12393ADD008D8433 /* vprof.cpp in Sources */,
+ 977F70AB12393B10008D8433 /* checksum_crc.cpp in Sources */,
+ 977F70AC12393B10008D8433 /* checksum_md5.cpp in Sources */,
+ 977F70AD12393B10008D8433 /* convar.cpp in Sources */,
+ 977F70AE12393B10008D8433 /* generichash.cpp in Sources */,
+ 977F70AF12393B10008D8433 /* interface.cpp in Sources */,
+ 977F70B012393B10008D8433 /* KeyValues.cpp in Sources */,
+ 977F70B112393B10008D8433 /* mempool.cpp in Sources */,
+ 977F70B212393B10008D8433 /* memstack.cpp in Sources */,
+ 977F70B312393B10008D8433 /* stringpool.cpp in Sources */,
+ 977F70B412393B10008D8433 /* utlbuffer.cpp in Sources */,
+ 977F70B512393B10008D8433 /* utlsymbol.cpp in Sources */,
+ 977F70BF12393B49008D8433 /* commandline.cpp in Sources */,
+ 977F70C012393B49008D8433 /* cvar.cpp in Sources */,
+ 977F70C112393B49008D8433 /* keyvaluessystem.cpp in Sources */,
+ 977F70C212393B49008D8433 /* osversion.cpp in Sources */,
+ 977F70C312393B49008D8433 /* qsort_s.cpp in Sources */,
+ 977F70C412393B49008D8433 /* random.cpp in Sources */,
+ 977F70C512393B49008D8433 /* splitstring.cpp in Sources */,
+ 977F70C612393B49008D8433 /* stringnormalize.cpp in Sources */,
+ 977F70C712393B49008D8433 /* strtools.cpp in Sources */,
+ 976DE7B71239412500E8D60A /* crccheck_shared.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 977F704612393174008D8433 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 977F704712393174008D8433 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Release;
+ };
+ 977F704912393174008D8433 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_MODEL_TUNING = G5;
+ "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = (
+ _POSIX,
+ TIER0_DLL_EXPORT,
+ GNUC,
+ POSIX,
+ OSX,
+ _OSX,
+ COMPILER_GCC,
+ STEAM,
+ );
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INSTALL_PATH = ../../devtools/bin/;
+ OTHER_CFLAGS = "-fpermissive";
+ PRODUCT_NAME = vpc_osx;
+ SDKROOT = macosx10.5;
+ USER_HEADER_SEARCH_PATHS = "../../public ../../common ../../public/tier0 ../../public/tier1 ../../public/vstdlib";
+ };
+ name = Debug;
+ };
+ 977F704A12393174008D8433 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_MODEL_TUNING = G5;
+ "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = (
+ _POSIX,
+ TIER0_DLL_EXPORT,
+ GNUC,
+ POSIX,
+ OSX,
+ _OSX,
+ COMPILER_GCC,
+ STEAM,
+ );
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INSTALL_PATH = ../../devtools/bin/;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_CFLAGS = "-fpermissive";
+ PRODUCT_NAME = vpc_osx;
+ SDKROOT = macosx10.5;
+ USER_HEADER_SEARCH_PATHS = "../../public ../../common ../../public/tier0 ../../public/tier1 ../../public/vstdlib";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 977F703812393173008D8433 /* Build configuration list for PBXProject "vpc" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 977F704612393174008D8433 /* Debug */,
+ 977F704712393174008D8433 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 977F704812393174008D8433 /* Build configuration list for PBXNativeTarget "vpc" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 977F704912393174008D8433 /* Debug */,
+ 977F704A12393174008D8433 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 977F703512393173008D8433 /* Project object */;
+}
diff --git a/external/vpc/utils/vpccrccheck/crccheck_shared.cpp b/external/vpc/utils/vpccrccheck/crccheck_shared.cpp
new file mode 100644
index 0000000..7ca8cb3
--- /dev/null
+++ b/external/vpc/utils/vpccrccheck/crccheck_shared.cpp
@@ -0,0 +1,590 @@
+
+#include "../vpc/vpc.h"
+#include "crccheck_shared.h"
+#include "tier1/checksum_crc.h"
+#include "tier1/strtools.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef _WIN32
+#include <process.h>
+#else
+#include <stdlib.h>
+#define stricmp strcasecmp
+#endif
+
+#pragma warning( disable : 4996 )
+#pragma warning( disable : 4127 )
+
+#define MAX_INCLUDE_STACK_DEPTH 10
+
+
+static bool IsValidPathChar( char token )
+{
+ // does it look like a file? If this ends up too tight, can probably just check that it's not '[' or '{'
+ // cause conditional blocks are what we really want to avoid.
+ return isalpha(token) || isdigit(token) || (token == '.') || (token == '\\') || (token == '/');
+}
+
+extern const char *g_szArrPlatforms[];
+static void BuildReplacements( const char *token, char *szReplacements )
+{
+ // Now go pickup the any files that exist, but were non-matches
+ *szReplacements = '\0';
+ for ( int i = 0; g_szArrPlatforms[i] != NULL; i++ )
+ {
+ char szPath[MAX_PATH];
+ char szPathExpanded[MAX_PATH];
+
+ V_strncpy( szPath, token, sizeof(szPath) );
+ Sys_ReplaceString( szPath, "$os", g_szArrPlatforms[i], szPathExpanded, sizeof(szPathExpanded) );
+ V_FixSlashes( szPathExpanded );
+ V_RemoveDotSlashes( szPathExpanded );
+ V_FixDoubleSlashes( szPathExpanded );
+
+ // this fopen is probably using a relative path, but that's ok, as everything in
+ // the crc code is opening relative paths and assuming the cwd is set ok.
+ FILE *f = fopen( szPathExpanded, "rb" );
+ if ( f )
+ {
+ fclose(f);
+ // strcat - blech
+ strcat( szReplacements, g_szArrPlatforms[i] ); // really just need to stick the existing platforms seen in
+ strcat( szReplacements, ";" );
+ }
+
+ }
+}
+
+static const char * GetToken( const char *ln, char *token )
+{
+ *token = '\0';
+
+ while ( *ln && isspace(*ln) )
+ ln++;
+
+ if (!ln[0])
+ return NULL;
+
+ if ( ln[0] == '"' )
+ { // does vpc allow \" inside the filename string - shouldn't matter, but we're going to assume no.
+ ln++;
+ while (*ln)
+ {
+ if ( ln[0] == '"' )
+ break;
+ *token++ = *ln++;
+ }
+ *token = '\0';
+ }
+ else if ( IsValidPathChar( *ln ) )
+ {
+ while (*ln)
+ {
+ if ( isspace(*ln) )
+ break;
+ *token++ = *ln++;
+ }
+ *token = '\0';
+ }
+ else
+ {
+ token[0] = ln[0];
+ token[1] = '\0';
+ }
+
+ return ln;
+}
+
+static void PerformFileSubstitions( char * line, int linelen )
+{
+ static bool bFindFilePending = false;
+ const char *ln = line;
+
+ if ( !bFindFilePending )
+ {
+ ln = V_stristr( ln, "$file " );
+ if ( ln )
+ bFindFilePending = true;
+ }
+
+ if ( bFindFilePending )
+ {
+ char token[1024];
+ ln = GetToken( ln, token );
+ if ( !ln )
+ return; // no more tokens on line, we should try the next line
+
+ bFindFilePending = false;
+
+
+ if ( V_stristr(token, "$os") )
+ {
+ if ( !IsValidPathChar( *token ) )
+ fprintf( stderr, "Warning: can't expand %s for crc calculation. Changes to this file set won't trigger automatic rebuild\n", token );
+ char szReplacements[2048];
+ char buffer[4096];
+ BuildReplacements( token, szReplacements );
+ Sys_ReplaceString( line, "$os", szReplacements, buffer, sizeof(buffer) );
+ V_strncpy( line, buffer, linelen );
+ }
+ }
+
+ static bool bFindFilePatternPending = false;
+ ln = line;
+
+ if ( !bFindFilePatternPending )
+ {
+ ln = V_stristr( ln, "$filepattern" );
+ while ( ln )
+ {
+ ln += 13;
+ if ( isspace( ln[-1] ) )
+ {
+ bFindFilePatternPending = true;
+ break;
+ }
+ }
+ }
+
+ if ( bFindFilePatternPending )
+ {
+ char token[1024];
+ ln = GetToken( ln, token );
+ if ( !ln )
+ return; // no more tokens on line, we should try the next line
+
+ bFindFilePatternPending = false;
+
+ char szReplacements[2048]; szReplacements[0] = '\0';
+ char buffer[4096];
+ CUtlVector< CUtlString > vecResults;
+ Sys_ExpandFilePattern( token, vecResults );
+ if ( vecResults.Count() )
+ {
+ for ( int i= 0; i < vecResults.Count(); i++ )
+ {
+ V_strncat( szReplacements, CFmtStr( "%s;", vecResults[i].String() ).Access(), V_ARRAYSIZE( szReplacements ) );
+ }
+
+ CRC32_t nCRC = CRC32_ProcessSingleBuffer( szReplacements, V_strlen( szReplacements ) );
+
+ Sys_ReplaceString( line, token, CFmtStr( "%s:%u", token, nCRC ).Access(), buffer, sizeof(buffer) );
+ V_strncpy( line, buffer, linelen );
+ }
+ else
+ {
+ if ( !IsValidPathChar( *token ) )
+ fprintf( stderr, "Warning: %s couldn't be expanded during crc calculation. Changes to this file set won't trigger automatic project rebuild\n", token );
+ }
+ }
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Sys_Error
+//
+//-----------------------------------------------------------------------------
+void Sys_Error( const char* format, ... )
+{
+ va_list argptr;
+
+ va_start( argptr,format );
+ vfprintf( stderr, format, argptr );
+ va_end( argptr );
+
+ exit( 1 );
+}
+
+
+void SafeSnprintf( char *pOut, int nOutLen, const char *pFormat, ... )
+{
+ va_list marker;
+ va_start( marker, pFormat );
+ V_vsnprintf( pOut, nOutLen, pFormat, marker );
+ va_end( marker );
+
+ pOut[nOutLen-1] = 0;
+}
+
+
+// for linked lists of strings
+struct StringNode_t
+{
+ StringNode_t *m_pNext;
+ char m_Text[1]; // the string data
+};
+
+
+static StringNode_t *MakeStrNode( char const *pStr )
+{
+ size_t nLen = strlen( pStr );
+ StringNode_t *nRet = ( StringNode_t * ) new unsigned char[sizeof( StringNode_t ) + nLen ];
+ strcpy( nRet->m_Text, pStr );
+ return nRet;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_LoadTextFileWithIncludes
+//-----------------------------------------------------------------------------
+int Sys_LoadTextFileWithIncludes( const char* filename, char** bufferptr, bool bInsertFileMacroExpansion )
+{
+ FILE *pFileStack[MAX_INCLUDE_STACK_DEPTH];
+ int nSP = MAX_INCLUDE_STACK_DEPTH;
+
+ StringNode_t *pFileLines = NULL; // tail ptr for fast adds
+
+ size_t nTotalFileBytes = 0;
+ FILE *handle = fopen( filename, "r" );
+ if ( !handle )
+ return -1;
+
+ pFileStack[--nSP] = handle; // push
+ while ( nSP < MAX_INCLUDE_STACK_DEPTH )
+ {
+ // read lines
+ for (;;)
+ {
+ char lineBuffer[4096];
+ char *ln = fgets( lineBuffer, sizeof( lineBuffer ), pFileStack[nSP] );
+ if ( !ln )
+ break; // out of text
+
+ ln += strspn( ln, "\t " ); // skip white space
+
+ // Need to insert actual files to make sure crc changes if disk-matched files match
+ if ( bInsertFileMacroExpansion )
+ PerformFileSubstitions( ln, sizeof(lineBuffer) - (ln-lineBuffer) );
+
+ if ( memcmp( ln, "#include", 8 ) == 0 )
+ {
+ // omg, an include
+ ln += 8;
+ ln += strspn( ln, " \t\"<" ); // skip whitespace, ", and <
+
+ size_t nPathNameLength = strcspn( ln, " \t\">\n" );
+ if ( !nPathNameLength )
+ {
+ Sys_Error( "bad include %s via %s\n", lineBuffer, filename );
+ }
+ ln[nPathNameLength] = 0; // kill everything after end of filename
+
+ FILE *inchandle = fopen( ln, "r" );
+ if ( !inchandle )
+ {
+ Sys_Error( "can't open #include of %s\n", ln );
+ }
+ if ( !nSP )
+ {
+ Sys_Error( "include nesting too deep via %s", filename );
+ }
+ pFileStack[--nSP] = inchandle;
+ }
+ else
+ {
+ size_t nLen = strlen( ln );
+ nTotalFileBytes += nLen;
+ StringNode_t *pNewLine = MakeStrNode( ln );
+
+ pNewLine->m_pNext = pFileLines;
+ pFileLines = pNewLine;
+ }
+ }
+ fclose( pFileStack[nSP] );
+ nSP++; // pop stack
+ }
+
+
+ // Reverse the pFileLines list so it goes the right way.
+ StringNode_t *pPrev = NULL;
+ StringNode_t *pCur;
+ for( pCur = pFileLines; pCur; )
+ {
+ StringNode_t *pNext = pCur->m_pNext;
+ pCur->m_pNext = pPrev;
+ pPrev = pCur;
+ pCur = pNext;
+ }
+ pFileLines = pPrev;
+
+
+ // Now dump all the lines out into a single buffer.
+ char *buffer = new char[nTotalFileBytes + 1]; // and null
+ *bufferptr = buffer; // tell caller
+
+ // copy all strings and null terminate
+ int nLine = 0;
+ StringNode_t *pNext;
+ for( pCur=pFileLines; pCur; pCur=pNext )
+ {
+ pNext = pCur->m_pNext;
+ size_t nLen = strlen( pCur->m_Text );
+ memcpy( buffer, pCur->m_Text, nLen );
+ buffer += nLen;
+ nLine++;
+
+ // Cleanup the line..
+ //delete [] (unsigned char*)pCur;
+ }
+ *( buffer++ ) = 0; // null
+
+ return (int)nTotalFileBytes;
+}
+
+
+// Just like fgets() but it removes trailing newlines.
+char* ChompLineFromFile( char *pOut, int nOutBytes, FILE *fp )
+{
+ char *pReturn = fgets( pOut, nOutBytes, fp );
+ if ( pReturn )
+ {
+ int len = (int)strlen( pReturn );
+ if ( len > 0 && pReturn[len-1] == '\n' )
+ {
+ pReturn[len-1] = 0;
+ if ( len > 1 && pReturn[len-2] == '\r' )
+ pReturn[len-2] = 0;
+ }
+ }
+
+ return pReturn;
+}
+
+
+bool CheckSupplementalString( const char *pSupplementalString, const char *pReferenceSupplementalString )
+{
+ // The supplemental string is only checked while VPC is determining if a project file is stale or not.
+ // It's not used by the pre-build event's CRC check.
+ // The supplemental string contains various options that tell how the project was built. It's generated in VPC_GenerateCRCOptionString.
+ //
+ // If there's no reference supplemental string (which is the case if we're running vpccrccheck.exe), then we ignore it and continue.
+ if ( !pReferenceSupplementalString )
+ return true;
+
+ return ( pSupplementalString && pReferenceSupplementalString && stricmp( pSupplementalString, pReferenceSupplementalString ) == 0 );
+}
+
+bool CheckVPCExeCRC( char *pVPCCRCCheckString, const char *szFilename, char *pErrorString, int nErrorStringLength )
+{
+ if ( pVPCCRCCheckString == NULL )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Unexpected end-of-file in %s", szFilename );
+ return false;
+ }
+
+ char *pSpace = strchr( pVPCCRCCheckString, ' ' );
+ if ( !pSpace )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Invalid line ('%s') in %s", pVPCCRCCheckString, szFilename );
+ return false;
+ }
+
+ // Null-terminate it so we have the CRC by itself and the filename follows the space.
+ *pSpace = 0;
+ const char *pVPCFilename = pSpace + 1;
+
+ // Parse the CRC out.
+ unsigned int nReferenceCRC;
+ sscanf( pVPCCRCCheckString, "%x", &nReferenceCRC );
+
+ char *pBuffer;
+ int cbVPCExe = Sys_LoadFile( pVPCFilename, (void**)&pBuffer );
+ if ( !pBuffer )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Unable to load %s for comparison.", pVPCFilename );
+ return false;
+ }
+
+ if ( cbVPCExe < 0 )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Could not load file '%s' to check CRC", pVPCFilename );
+ return false;
+ }
+
+ // Calculate the CRC from the contents of the file.
+ CRC32_t nCRCFromFileContents = CRC32_ProcessSingleBuffer( pBuffer, cbVPCExe );
+ delete [] pBuffer;
+
+ // Compare them.
+ if ( nCRCFromFileContents != nReferenceCRC )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "VPC executable has changed since the project was generated." );
+ return false;
+ }
+ return true;
+}
+
+
+bool VPC_CheckProjectDependencyCRCs( const char *pProjectFilename, const char *pReferenceSupplementalString, char *pErrorString, int nErrorStringLength )
+{
+ // Build the xxxxx.vcproj.vpc_crc filename
+ char szFilename[512];
+ SafeSnprintf( szFilename, sizeof( szFilename ), "%s.%s", pProjectFilename, VPCCRCCHECK_FILE_EXTENSION );
+
+ // Open it up.
+ FILE *fp = fopen( szFilename, "rt" );
+ if ( !fp )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Unable to load %s to check CRC strings", szFilename );
+ return false;
+ }
+
+ bool bReturnValue = false;
+ char lineBuffer[2048];
+
+ // Check the version of the CRC file.
+ const char *pVersionString = ChompLineFromFile( lineBuffer, sizeof( lineBuffer ), fp );
+ if ( pVersionString && stricmp( pVersionString, VPCCRCCHECK_FILE_VERSION_STRING ) == 0 )
+ {
+ char *pVPCExeCRCString = ChompLineFromFile( lineBuffer, sizeof( lineBuffer ), fp );
+ if ( CheckVPCExeCRC( pVPCExeCRCString, szFilename, pErrorString, nErrorStringLength ) )
+ {
+ // Check the supplemental CRC string.
+ const char *pSupplementalString = ChompLineFromFile( lineBuffer, sizeof( lineBuffer ), fp );
+ if ( CheckSupplementalString( pSupplementalString, pReferenceSupplementalString ) )
+ {
+ // Now read each line. Each line has a CRC and a filename on it.
+ while ( 1 )
+ {
+ char *pLine = ChompLineFromFile( lineBuffer, sizeof( lineBuffer ), fp );
+ if ( !pLine )
+ {
+ // We got all the way through the file without a CRC error, so all's well.
+ bReturnValue = true;
+ break;
+ }
+
+ char *pSpace = strchr( pLine, ' ' );
+ if ( !pSpace )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Invalid line ('%s') in %s", pLine, szFilename );
+ break;
+ }
+
+ // Null-terminate it so we have the CRC by itself and the filename follows the space.
+ *pSpace = 0;
+ const char *pVPCFilename = pSpace + 1;
+
+ // Parse the CRC out.
+ unsigned int nReferenceCRC;
+ sscanf( pLine, "%x", &nReferenceCRC );
+
+
+ // Calculate the CRC from the contents of the file.
+ char *pBuffer;
+ int nTotalFileBytes = Sys_LoadTextFileWithIncludes( pVPCFilename, &pBuffer, true );
+ if ( nTotalFileBytes == -1 )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Unable to load %s for CRC comparison.", pVPCFilename );
+ break;
+ }
+
+ CRC32_t nCRCFromTextContents = CRC32_ProcessSingleBuffer( pBuffer, nTotalFileBytes );
+ delete [] pBuffer;
+
+ // Compare them.
+ if ( nCRCFromTextContents != nReferenceCRC )
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "This VCPROJ is out of sync with its VPC scripts.\n %s mismatches (0x%x vs 0x%x).\n Please use VPC to re-generate!\n \n", pVPCFilename, nReferenceCRC, nCRCFromTextContents );
+ break;
+ }
+ }
+ }
+ else
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "Supplemental string mismatch." );
+ }
+ }
+ }
+ else
+ {
+ SafeSnprintf( pErrorString, nErrorStringLength, "CRC file %s has an invalid version string ('%s')", szFilename, pVersionString ? pVersionString : "[null]" );
+ }
+
+ fclose( fp );
+ return bReturnValue;
+}
+
+
+int VPC_OldeStyleCRCChecks( int argc, char **argv )
+{
+ for ( int i=1; (i+2) < argc; )
+ {
+ const char *pTestArg = argv[i];
+ if ( stricmp( pTestArg, "-crc" ) != 0 )
+ {
+ ++i;
+ continue;
+ }
+
+ const char *pVPCFilename = argv[i+1];
+
+ // Get the CRC value on the command line.
+ const char *pTestCRC = argv[i+2];
+ unsigned int nCRCFromCommandLine;
+ sscanf( pTestCRC, "%x", &nCRCFromCommandLine );
+
+ // Calculate the CRC from the contents of the file.
+ char *pBuffer;
+ int nTotalFileBytes = Sys_LoadTextFileWithIncludes( pVPCFilename, &pBuffer, true );
+ if ( nTotalFileBytes == -1 )
+ {
+ Sys_Error( "Unable to load %s for CRC comparison.", pVPCFilename );
+ }
+
+ CRC32_t nCRCFromTextContents = CRC32_ProcessSingleBuffer( pBuffer, nTotalFileBytes );
+ delete [] pBuffer;
+
+ // Compare them.
+ if ( nCRCFromTextContents != nCRCFromCommandLine )
+ {
+ Sys_Error( " \n This VCPROJ is out of sync with its VPC scripts.\n %s mismatches (0x%x vs 0x%x).\n Please use VPC to re-generate!\n \n", pVPCFilename, nCRCFromCommandLine, nCRCFromTextContents );
+ }
+
+ i += 2;
+ }
+
+ return 0;
+}
+
+
+int VPC_CommandLineCRCChecks( int argc, char **argv )
+{
+ if ( argc < 2 )
+ {
+ fprintf( stderr, "Invalid arguments to " VPCCRCCHECK_EXE_FILENAME ". Format: " VPCCRCCHECK_EXE_FILENAME " [project filename]\n" );
+ return 1;
+ }
+
+ const char *pFirstCRC = argv[1];
+
+ // If the first argument starts with -crc but is not -crc2, then this is an old CRC check command line with all the CRCs and filenames
+ // directly on the command line. The new format puts all that in a separate file.
+ if ( pFirstCRC[0] == '-' && pFirstCRC[1] == 'c' && pFirstCRC[2] == 'r' && pFirstCRC[3] == 'c' && pFirstCRC[4] != '2' )
+ {
+ return VPC_OldeStyleCRCChecks( argc, argv );
+ }
+
+ if ( stricmp( pFirstCRC, "-crc2" ) != 0 )
+ {
+ fprintf( stderr, "Missing -crc2 parameter on vpc CRC check command line." );
+ return 1;
+ }
+
+ const char *pProjectFilename = argv[2];
+
+ char errorString[1024];
+ bool bCRCsValid = VPC_CheckProjectDependencyCRCs( pProjectFilename, NULL, errorString, sizeof( errorString ) );
+
+ if ( bCRCsValid )
+ {
+ return 0;
+ }
+ else
+ {
+ fprintf( stderr, "%s", errorString );
+ return 1;
+ }
+}
+
diff --git a/external/vpc/utils/vpccrccheck/crccheck_shared.h b/external/vpc/utils/vpccrccheck/crccheck_shared.h
new file mode 100644
index 0000000..ce177d0
--- /dev/null
+++ b/external/vpc/utils/vpccrccheck/crccheck_shared.h
@@ -0,0 +1,34 @@
+//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
+//
+//
+//
+//==================================================================================================
+
+#ifndef CRCCHECK_SHARED_H
+#define CRCCHECK_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifdef STANDALONE_VPC
+#define VPCCRCCHECK_EXE_FILENAME "vpc.exe"
+#else
+#define VPCCRCCHECK_EXE_FILENAME "vpccrccheck.exe"
+#endif
+
+// The file extension for the file that contains the CRCs that a vcproj depends on.
+#define VPCCRCCHECK_FILE_EXTENSION "vpc_crc"
+#define VPCCRCCHECK_FILE_VERSION_STRING "[vpc crc file version 2]"
+
+
+void Sys_Error( const char *format, ... );
+int Sys_LoadTextFileWithIncludes( const char* filename, char** bufferptr, bool bInsertFileMacroExpansion );
+
+bool VPC_CheckProjectDependencyCRCs( const char *pProjectFilename, const char *pReferenceSupplementalString, char *pErrorString, int nErrorStringLength );
+
+// Used by vpccrccheck.exe or by vpc.exe to do the CRC check that's initiated in the pre-build steps.
+int VPC_CommandLineCRCChecks( int argc, char **argv );
+
+
+#endif // CRCCHECK_SHARED_H
diff --git a/external/vpc/utils/vpccrccheck/vpccrccheck.cpp b/external/vpc/utils/vpccrccheck/vpccrccheck.cpp
new file mode 100644
index 0000000..28b5667
--- /dev/null
+++ b/external/vpc/utils/vpccrccheck/vpccrccheck.cpp
@@ -0,0 +1,16 @@
+
+#include "tier1/checksum_crc.h"
+#include "crccheck_shared.h"
+#include <stdio.h>
+#include <string.h>
+
+
+
+int main( int argc, char **argv )
+{
+ return VPC_CommandLineCRCChecks( argc, argv );
+}
+
+
+
+
diff --git a/external/vpc/utils/vpccrccheck/vpccrccheck.vpc b/external/vpc/utils/vpccrccheck/vpccrccheck.vpc
new file mode 100644
index 0000000..6cdfced
--- /dev/null
+++ b/external/vpc/utils/vpccrccheck/vpccrccheck.vpc
@@ -0,0 +1,33 @@
+ //-----------------------------------------------------------------------------
+// VPCCRCCHECK.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$Macro SRCDIR "..\.."
+$Macro OUTBINDIR "$SRCDIR\devtools\bin"
+
+$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ }
+}
+
+$Project "vpccrccheck"
+{
+ $Folder "Source Files"
+ {
+ -$File "$SRCDIR\public\tier0\memoverride.cpp"
+ $File "vpccrccheck.cpp"
+ $File "crccheck_shared.cpp"
+ $File "$SRCDIR/tier1/checksum_crc.cpp"
+ }
+
+ $Folder "Link Libraries"
+ {
+ -$Implib "$LIBPUBLIC\vstdlib"
+ }
+}