Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
8.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "makefilecreator.h"
  9. #include "cmdlib.h"
  10. //-----------------------------------------------------------------------------
  11. // Purpose: constructor
  12. //-----------------------------------------------------------------------------
  13. CMakefileCreator::CMakefileCreator() {
  14. m_FileToBaseDirMapping.SetLessFunc( DefLessFunc( int ) );
  15. }
  16. //-----------------------------------------------------------------------------
  17. // Purpose: destructor
  18. //-----------------------------------------------------------------------------
  19. CMakefileCreator::~CMakefileCreator()
  20. {
  21. }
  22. void CMakefileCreator::CreateMakefiles( CVCProjConvert & proj )
  23. {
  24. m_ProjName = proj.GetName();
  25. m_BaseDir = proj.GetBaseDir();
  26. for ( int i = 0; i < proj.GetNumConfigurations(); i++ )
  27. {
  28. m_FileToBaseDirMapping.RemoveAll();
  29. m_BuildDirectories.RemoveAll();
  30. m_BaseDirs.RemoveAll();
  31. CreateMakefileName( proj.GetName().String(), proj.GetConfiguration(i) );
  32. CreateBaseDirs( proj.GetConfiguration(i) );
  33. FileHandle_t f = g_pFileSystem->Open( m_MakefileName.String(), "w+" );
  34. if ( !f )
  35. {
  36. Warning( "failed to open %s for writing.\n", m_MakefileName.String() );
  37. continue;
  38. }
  39. OutputDirs(f);
  40. OutputIncludes( proj.GetConfiguration(i), f );
  41. OutputObjLists( proj.GetConfiguration(i), f );
  42. OutputMainBuilder(f);
  43. OutputBuildTarget(f);
  44. g_pFileSystem->Close(f);
  45. }
  46. }
  47. void CMakefileCreator::CreateBaseDirs( CVCProjConvert::CConfiguration & config )
  48. {
  49. // m_BaseDirs.Insert( "" );
  50. for ( int i = 0; i < config.GetNumFileNames(); i++ )
  51. {
  52. if ( config.GetFileType(i) == CVCProjConvert::CConfiguration::FILE_SOURCE )
  53. {
  54. char basedir[ MAX_PATH ];
  55. char fulldir[ MAX_PATH ];
  56. Q_snprintf( fulldir, sizeof(fulldir), "%s/%s", m_BaseDir.String(), config.GetFileName(i) );
  57. if ( Q_ExtractFilePath( fulldir, basedir, sizeof(basedir) ) )
  58. {
  59. Q_FixSlashes( basedir );
  60. Q_StripTrailingSlash( basedir );
  61. int index = m_BaseDirs.Find( basedir );
  62. if ( index == m_BaseDirs.InvalidIndex() )
  63. {
  64. index = m_BaseDirs.Insert( basedir );
  65. }
  66. m_FileToBaseDirMapping.Insert(i, index );
  67. }
  68. else
  69. {
  70. m_FileToBaseDirMapping.Insert(i, 0 );
  71. }
  72. }
  73. }
  74. }
  75. void CMakefileCreator::CleanupFileName( char *name )
  76. {
  77. for ( int i = Q_strlen( name ) - 1; i >= 0; --i )
  78. {
  79. if ( name[i] == ' ' || name[i] == '|' || name[i] == '\\' || name[i] == '/' || ( name[i] == '.' && i>=1 && name[i-1] == '.' ))
  80. {
  81. Q_memmove( &name[i], &name[i+1], Q_strlen( name ) - i - 1 );
  82. name[ Q_strlen( name ) - 1 ] = 0;
  83. }
  84. }
  85. }
  86. void CMakefileCreator::CreateMakefileName( const char *projectName, CVCProjConvert::CConfiguration & config )
  87. {
  88. char makefileName[ MAX_PATH ];
  89. Q_snprintf( makefileName, sizeof(makefileName), "Makefile.%s_%s", projectName, config.GetName().String() );
  90. CleanupFileName( makefileName );
  91. m_MakefileName = makefileName;
  92. }
  93. void CMakefileCreator::CreateDirectoryFriendlyName( const char *dirName, char *friendlyDirName, int friendlyDirNameSize )
  94. {
  95. Q_strncpy( friendlyDirName, dirName, friendlyDirNameSize );
  96. int i;
  97. for ( i = Q_strlen( friendlyDirName ) - 1; i >= 0; --i )
  98. {
  99. if ( friendlyDirName[i] == '/' || friendlyDirName[i] == '\\' )
  100. {
  101. friendlyDirName[i] = '_';
  102. }
  103. if ( isalpha( friendlyDirName[i] ) )
  104. {
  105. friendlyDirName[i] = toupper(friendlyDirName[i]);
  106. }
  107. if ( friendlyDirName[i] == '.' )
  108. {
  109. Q_memmove( &friendlyDirName[i], &friendlyDirName[i+1], Q_strlen( friendlyDirName ) - i - 1 );
  110. friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0;
  111. }
  112. }
  113. // strip any leading/trailing underscores
  114. while ( friendlyDirName[0] == '_' && Q_strlen(friendlyDirName)>0 )
  115. {
  116. Q_memmove( &friendlyDirName[0], &friendlyDirName[1], Q_strlen( friendlyDirName )- 1 );
  117. friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0;
  118. }
  119. while ( Q_strlen(friendlyDirName)>0 && friendlyDirName[Q_strlen(friendlyDirName)-1] == '_' )
  120. {
  121. friendlyDirName[ Q_strlen( friendlyDirName ) - 1 ] = 0;
  122. }
  123. CleanupFileName( friendlyDirName );
  124. }
  125. void CMakefileCreator::CreateObjDirectoryFriendlyName ( char *name )
  126. {
  127. #ifdef _WIN32
  128. char *updir = "..\\";
  129. #else
  130. char *updir = "../";
  131. #endif
  132. char *sep = Q_strstr( name, updir );
  133. while ( sep )
  134. {
  135. Q_strcpy( sep, sep + strlen(updir) );
  136. sep = Q_strstr( sep, updir );
  137. }
  138. }
  139. void CMakefileCreator::FileWrite( FileHandle_t f, const char *fmt, ... )
  140. {
  141. va_list args;
  142. va_start(args, fmt);
  143. char stringBuf[ 4096 ];
  144. Q_vsnprintf( stringBuf, sizeof(stringBuf), fmt, args );
  145. va_end(args);
  146. g_pFileSystem->Write( stringBuf, Q_strlen(stringBuf), f );
  147. }
  148. void CMakefileCreator::OutputIncludes( CVCProjConvert::CConfiguration & config, FileHandle_t f )
  149. {
  150. FileWrite( f, "INCLUDES=" );
  151. for ( int i = 0; i < config.GetNumIncludes(); i++ )
  152. {
  153. FileWrite( f, "-I%s ", config.GetInclude(i) );
  154. }
  155. for ( int i = 0; i < config.GetNumDefines(); i++ )
  156. {
  157. FileWrite( f, "-D%s ", config.GetDefine(i) );
  158. }
  159. FileWrite( f, "\n\n" );
  160. }
  161. void CMakefileCreator::OutputDirs( FileHandle_t f )
  162. {
  163. for ( int i = m_BaseDirs.First(); i != m_BaseDirs.InvalidIndex(); i = m_BaseDirs.Next(i) )
  164. {
  165. const char *dirName = m_BaseDirs.GetElementName(i);
  166. if ( !dirName || !Q_strlen(dirName) )
  167. {
  168. dirName = m_BaseDir.String();
  169. }
  170. char friendlyDirName[ MAX_PATH ];
  171. CreateDirectoryFriendlyName( dirName, friendlyDirName, sizeof(friendlyDirName) );
  172. int dirLen = Q_strlen(friendlyDirName);
  173. Q_strncat( friendlyDirName, "_SRC_DIR", sizeof(friendlyDirName), COPY_ALL_CHARACTERS );
  174. struct OutputDirMapping_t dirs;
  175. dirs.m_SrcDir = friendlyDirName;
  176. dirs.m_iBaseDirIndex = i;
  177. friendlyDirName[ dirLen ] = 0;
  178. Q_strncat( friendlyDirName, "_OBJ_DIR", sizeof(friendlyDirName), COPY_ALL_CHARACTERS );
  179. dirs.m_ObjDir = friendlyDirName;
  180. friendlyDirName[ dirLen ] = 0;
  181. Q_strncat( friendlyDirName, "_OBJS", sizeof(friendlyDirName), COPY_ALL_CHARACTERS );
  182. dirs.m_ObjName = friendlyDirName;
  183. char objDirName[ MAX_PATH ];
  184. Q_snprintf( objDirName, sizeof(objDirName) , "obj%c$(NAME)_$(ARCH)%c", CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR );
  185. Q_strncat( objDirName, dirName, sizeof(objDirName), COPY_ALL_CHARACTERS );
  186. CreateObjDirectoryFriendlyName( objDirName );
  187. dirs.m_ObjOutputDir = objDirName;
  188. m_BuildDirectories.AddToTail( dirs );
  189. FileWrite( f, "%s=%s\n", dirs.m_SrcDir.String(), dirName );
  190. FileWrite( f, "%s=%s\n", dirs.m_ObjDir.String(), objDirName );
  191. }
  192. FileWrite( f, "\n\n" );
  193. }
  194. void CMakefileCreator::OutputMainBuilder( FileHandle_t f )
  195. {
  196. int i;
  197. FileWrite( f, "\n\nall: dirs $(NAME)_$(ARCH).$(SHLIBEXT)\n\n" );
  198. FileWrite( f, "dirs:\n" );
  199. for ( i = 0; i < m_BuildDirectories.Count(); i++ )
  200. {
  201. FileWrite( f, "\t-mkdir -p $(%s)\n", m_BuildDirectories[i].m_ObjDir.String() );
  202. }
  203. FileWrite( f, "\n\n" );
  204. FileWrite( f, "\n\n$(NAME)_$(ARCH).$(SHLIBEXT): " );
  205. for ( i = 0; i < m_BuildDirectories.Count(); i++ )
  206. {
  207. FileWrite( f, "$(%s) ", m_BuildDirectories[i].m_ObjName.String() );
  208. }
  209. FileWrite( f, "\n\t$(CLINK) $(SHLIBLDFLAGS) $(DEBUG) -o $(BUILD_DIR)/$@ " );
  210. for ( i = 0; i < m_BuildDirectories.Count(); i++ )
  211. {
  212. FileWrite( f, "$(%s) ", m_BuildDirectories[i].m_ObjName.String() );
  213. }
  214. FileWrite( f, "$(LDFLAGS) $(CPP_LIB)\n\n" );
  215. }
  216. void CMakefileCreator::OutputObjLists( CVCProjConvert::CConfiguration & config, FileHandle_t f )
  217. {
  218. for ( int buildDirIndex = 0; buildDirIndex < m_BuildDirectories.Count(); buildDirIndex++ )
  219. {
  220. struct OutputDirMapping_t & dirs = m_BuildDirectories[buildDirIndex];
  221. FileWrite( f, "%s= \\\n", dirs.m_ObjName.String() );
  222. for ( int j = m_FileToBaseDirMapping.FirstInorder(); j != m_FileToBaseDirMapping.InvalidIndex(); j = m_FileToBaseDirMapping.NextInorder(j) )
  223. {
  224. if ( dirs.m_iBaseDirIndex == m_FileToBaseDirMapping[j] )
  225. {
  226. char baseName[ MAX_PATH ];
  227. const char *fileName = config.GetFileName(m_FileToBaseDirMapping.Key(j));
  228. Q_FileBase( fileName, baseName, sizeof(baseName) );
  229. Q_SetExtension( baseName, ".o", sizeof(baseName) );
  230. FileWrite( f, "\t$(%s)/%s \\\n", dirs.m_ObjDir.String(), baseName );
  231. }
  232. }
  233. FileWrite( f, "\n\n" );
  234. }
  235. }
  236. void CMakefileCreator::OutputBuildTarget( FileHandle_t f )
  237. {
  238. for( int i = 0; i < m_BuildDirectories.Count(); i++ )
  239. {
  240. struct OutputDirMapping_t & dirs = m_BuildDirectories[i];
  241. FileWrite( f, "$(%s)/%%.o: $(%s)/%%.cpp\n", dirs.m_ObjDir.String(), dirs.m_SrcDir.String() );
  242. FileWrite( f, "\t$(DO_CC)\n\n");
  243. }
  244. }