void BuildTool::BuildModule( const std::vector<FileToBuild>& buildFileList_, const CompilerOptions& compilerOptions_, std::vector<FileSystemUtils::Path> linkLibraryList_, const FileSystemUtils::Path& moduleName_ ) { // Initial version is very basic, simply compiles them. Path objectFileExtension = m_Compiler.GetObjectFileExtension(); vector<Path> compileFileList; // List of files we pass to the compiler compileFileList.reserve( buildFileList_.size() ); vector<Path> forcedCompileFileList; // List of files which must be compiled even if object file exists vector<Path> nonForcedCompileFileList; // List of files which can be linked if already compiled // Seperate into seperate file lists of force and non-forced, // so we can ensure we don't have the same file in both for( size_t i = 0; i < buildFileList_.size(); ++i ) { Path buildFile = buildFileList_[i].filePath; if( buildFileList_[i].forceCompile ) { if( find( forcedCompileFileList.begin(), forcedCompileFileList.end(), buildFile ) == forcedCompileFileList.end() ) { forcedCompileFileList.push_back( buildFile ); } } else { if( find( nonForcedCompileFileList.begin(), nonForcedCompileFileList.end(), buildFile ) == nonForcedCompileFileList.end() ) { nonForcedCompileFileList.push_back( buildFile ); } } } // Add all forced compile files to build list for( size_t i = 0; i < forcedCompileFileList.size(); ++i ) { compileFileList.push_back( forcedCompileFileList[i] ); } // runtime folder needs to be aware of compilation level and debug/ // Add non forced files, but only if they don't exist in forced compile list for( size_t i = 0; i < nonForcedCompileFileList.size(); ++i ) { Path buildFile = nonForcedCompileFileList[i]; if( find( forcedCompileFileList.begin(), forcedCompileFileList.end(), buildFile ) == forcedCompileFileList.end() ) { // Check if we have a pre-compiled object version of this file, and if so use that. Path objectFileName = compilerOptions_.intermediatePath / buildFile.Filename(); objectFileName.ReplaceExtension(objectFileExtension.c_str()); if( objectFileName.Exists() && buildFile.Exists() ) { FileSystemUtils::filetime_t objTime = objectFileName.GetLastWriteTime(); if( objTime > buildFile.GetLastWriteTime() ) { // we only want to use the object file if it's newer than the source file buildFile = objectFileName; } } compileFileList.push_back(buildFile); } } m_Compiler.RunCompile( compileFileList, compilerOptions_, linkLibraryList_, moduleName_ ); }
void BuildTool::BuildModule( const std::vector<FileToBuild>& buildFileList, const std::vector<FileSystemUtils::Path>& includeDirList, const std::vector<FileSystemUtils::Path>& libraryDirList, const std::vector<FileSystemUtils::Path>& linkLibraryList, const char* pCompileOptions, const char* pLinkOptions, const FileSystemUtils::Path& moduleName ) { // Initial version is very basic, simply compiles them. Path objectFileExtension = m_Compiler.GetObjectFileExtension(); vector<Path> compileFileList; // List of files we pass to the compiler compileFileList.reserve( buildFileList.size() ); vector<Path> forcedCompileFileList; // List of files which must be compiled even if object file exists vector<Path> nonForcedCompileFileList; // List of files which can be linked if already compiled // Seperate into seperate file lists of force and non-forced, // so we can ensure we don't have the same file in both for( size_t i = 0; i < buildFileList.size(); ++i ) { Path buildFile = buildFileList[i].filePath; if( buildFileList[i].forceCompile ) { if( find( forcedCompileFileList.begin(), forcedCompileFileList.end(), buildFile ) == forcedCompileFileList.end() ) { forcedCompileFileList.push_back( buildFile ); } } else { if( find( nonForcedCompileFileList.begin(), nonForcedCompileFileList.end(), buildFile ) == nonForcedCompileFileList.end() ) { nonForcedCompileFileList.push_back( buildFile ); } } } // Add all forced compile files to build list for( size_t i = 0; i < forcedCompileFileList.size(); ++i ) { compileFileList.push_back( forcedCompileFileList[i] ); } // Add non forced files, but only if they don't exist in forced compile list Path runtimeFolder = m_Compiler.GetRuntimeIntermediatePath(); for( size_t i = 0; i < nonForcedCompileFileList.size(); ++i ) { Path buildFile = nonForcedCompileFileList[i]; if( find( forcedCompileFileList.begin(), forcedCompileFileList.end(), buildFile ) == forcedCompileFileList.end() ) { // Check if we have a pre-compiled object version of this file, and if so use that. Path objectFileName = runtimeFolder/buildFile.Filename(); objectFileName.ReplaceExtension(objectFileExtension.c_str()); if( objectFileName.Exists() && buildFile.Exists() ) { FileSystemUtils::filetime_t objTime = objectFileName.GetLastWriteTime(); if( objTime > m_InitTime && objTime > buildFile.GetLastWriteTime() ) { // we only want to use the object file if it's newer than our start-up time so // we know it's from the current session (so likely compiled with same settings), // and it's newer than the source file buildFile = objectFileName; } } compileFileList.push_back(buildFile); } } m_Compiler.RunCompile( compileFileList, includeDirList, libraryDirList, linkLibraryList, pCompileOptions, pLinkOptions, moduleName ); }
// returns 0 on success, -ve number of errors if there is an error and we should quit, // positive number of errors if there is an error but we should continue static int TestBuildFile( ICompilerLogger* pLog, RuntimeObjectSystem* pRTObjSys, const Path& file, ITestBuildNotifier* callback, bool bTestFileTracking ) { assert( callback ); if( pLog ) { pLog->LogInfo("Testing change to file: %s\n", file.c_str()); } int numErrors = 0; if( file.Exists() ) { if( bTestFileTracking ) { FileSystemUtils::filetime_t currTime = FileSystemUtils::GetCurrentTime(); FileSystemUtils::filetime_t oldModTime = file.GetLastWriteTime(); if( currTime == oldModTime ) { // some files may be auto-generated by the program, so may have just been created so won't // get a time change unless we force it. currTime += 1; } file.SetLastWriteTime( currTime ); // we must also change the directories time, as some of our watchers watch the dir Path directory = file.ParentPath(); directory.SetLastWriteTime( currTime ); for( int i=0; i<50; ++i ) { // wait up to 100 seconds (make configurable?) pRTObjSys->GetFileChangeNotifier()->Update( 1.0f ); // force update by using very large time delta if( pRTObjSys->GetIsCompiling() ) { break; } if( !callback->TestBuildWaitAndUpdate() ) { return -0xD1E; } } } else { AUDynArray<const char*> filelist; filelist.Add( file.c_str() ); pRTObjSys->OnFileChange( filelist ); } if( pRTObjSys->GetIsCompiling() ) { while( !pRTObjSys->GetIsCompiledComplete() ) { if( !callback->TestBuildWaitAndUpdate() ) { return -0xD1E; } } int numCurrLoadedModules = pRTObjSys->GetNumberLoadedModules(); if( pRTObjSys->LoadCompiledModule() ) { if( !callback->TestBuildCallback( file.c_str(), TESTBUILDRRESULT_SUCCESS ) ) { return -0xD1E; } return 0; } else { ++numErrors; if( pRTObjSys->GetNumberLoadedModules() == numCurrLoadedModules ) { if( !callback->TestBuildCallback( file.c_str(), TESTBUILDRRESULT_BUILD_FAILED ) ) { return -numErrors; } } else { // loaded the module but some other issue if( !callback->TestBuildCallback( file.c_str(), TESTBUILDRRESULT_OBJECT_SWAP_FAIL ) ) { return -numErrors; } } } } else { ++numErrors; if( !callback->TestBuildCallback( file.c_str(), TESTBUILDRRESULT_BUILD_NOT_STARTED ) ) { return -numErrors; } } } else { ++numErrors; if( !callback->TestBuildCallback( file.c_str(), TESTBUILDRRESULT_BUILD_FILE_GONE ) ) { return -numErrors; } } return numErrors; }