void subprocess_execute(const char*command, void*data, SubprocessOutputHandler outputHandle, SubprocessOutputHandler errorHandle, SubprocessResultHandler resultHandle, bool wait) { if(!wait) { subprocess_execute(command, data, outputHandle, errorHandle, resultHandle); } else { SubprocessThread* process = new SubprocessThread(command, data, outputHandle, errorHandle, resultHandle, false); bool success = process->exec(); if(!success) { delete process; } else { process->join(); delete process; } } }
void CompilerThread::run() { currentFile = ""; lastResult = 0; result = 0; ProjectData& projData = *(organizer->projData); ProjectData_struct projDataStruct = ProjectData_createWithData(&projData); ProjectBuildInfo& projBuildInfo = projData.getProjectBuildInfo(); ProjectBuildInfo_struct projBuildInfoStruct = ProjectBuildInfo_createWithData(&projBuildInfo); StringTree& sourceFiles = projData.getSourceFiles(); ArrayList<String> sourceFilePaths = sourceFiles.getPaths(); CompilerThread_ChangeStatus(this, "Preparing Directories..."); String projectRoot = (String)ProjLoad_getSavedProjectsFolder() + '/' + projData.getFolderName(); String binFolder = projectRoot + "/bin"; FileTools::createDirectory(binFolder); String buildFolder = binFolder + "/build"; FileTools::createDirectory(buildFolder); String releaseFolder = binFolder + "/release"; FileTools::createDirectory(releaseFolder); String srcFolder = projectRoot + "/src"; FileTools::createDirectoriesFromStringTree(buildFolder, sourceFiles); CompilerThread_ChangeStatus(this, "Checking Dependencies..."); ArrayList<String> needsCompiling; ArrayList<String> fakeCompiling; //Check which files need compiling and which ones do not for(int i=0; i<sourceFilePaths.size(); i++) { String relPath = sourceFilePaths.get(i); int dotIndex = relPath.lastIndexOf('.'); if(dotIndex!=-1) { if(!CompilerThread_stringExistsAtIndex(relPath, ".h", dotIndex) && !CompilerThread_stringExistsAtIndex(relPath, ".H", dotIndex)) //if file is not a header file { String outFullPath = buildFolder + '/' + relPath + ".o"; if(projBuildInfo.hasEditedFile(relPath)) { needsCompiling.add(relPath); } else if(!FileTools_fileExists(outFullPath)) { needsCompiling.add(relPath); } else { String depFullPath = buildFolder + '/' + relPath + ".d"; String srcFullPath = srcFolder + '/' + relPath; CompilerThread_FileDependencyList* depList = CompilerThread_parseDependencyFile(depFullPath, srcFullPath, true, srcFolder); if(depList!=NULL) { bool pleaseCompile = false; for(int i=0; i<depList->dependencies.size(); i++) { if(projBuildInfo.hasEditedFile(depList->dependencies.get(i))) { pleaseCompile = true; i = depList->dependencies.size(); } } if(pleaseCompile) { needsCompiling.add(relPath); } else { fakeCompiling.add(relPath); } } else { fakeCompiling.add(relPath); } delete depList; } } } } //"Fake" Compile already compiled files (load compile output from file) currentFile = ""; for(int i=0; i<fakeCompiling.size(); i++) { String relPath = fakeCompiling.get(i); CompilerThread_ChangeStatus(this, (String)"Reading bin/build/" + relPath + ".output"); String fullPath = buildFolder + '/' + relPath + ".output"; FILE* file = fopen(fullPath, "r"); if(file!=NULL) { char* currentLine = (char*)malloc(1024); bool success = true; while(!feof(file) && success) { if(fgets(currentLine, 1024, file)!=NULL) { String line = currentLine; if(CompilerThread_stringExistsAtIndex(line, "stdout: ", 0)) { CompilerThread_OutputReciever(this, line.substring(8)); } else if(CompilerThread_stringExistsAtIndex(line, "stderr: ", 0)) { CompilerThread_ErrorReciever(this, line.substring(8)); } else { CompilerThread_ErrorReciever(this, line); } } else { success = false; } } free(currentLine); fclose(file); } else { Console::WriteLine((String)"Error opening output file " + fullPath); } } //Assemble remaining files for(int i=0; i<needsCompiling.size(); i++) { String relPath = needsCompiling.get(i); currentFile = relPath; CompilerThread_ChangeStatus(this, (String)"(" + (i+1) + "/" + needsCompiling.size() + ") " + relPath); FileTools::writeStringToFile(buildFolder + '/' + relPath + ".output", ""); String fullPath = srcFolder + '/' + relPath; String depPath = buildFolder + '/' + relPath + ".d"; String outPath = buildFolder + '/' + relPath + ".o"; String assembleCommand = CompilerThread_createAssembleString(projData, fullPath, outPath, depPath); subprocess_execute(assembleCommand, this, &CompilerThread_OutputReciever, &CompilerThread_ErrorReciever, &CompilerThread_ResultReciever, true, NULL, true); //waits until subprocess finishes if(lastResult==0) { projBuildInfo.removeEditedFile(relPath); ProjectBuildInfo_saveBuildInfoPlist(&projBuildInfoStruct, &projDataStruct); } else { result = -1; } } if(result==0) { projBuildInfo.getEditedFiles().clear(); ProjectBuildInfo_saveBuildInfoPlist(&projBuildInfoStruct, &projDataStruct); } else { CompilerThread_ChangeStatus(this, "Failed"); CompilerThread_FinishReciever(this, result); return; } CompilerThread_ChangeStatus(this, "Enumerating Files"); //Collecting compiled files ArrayList<String> inputFiles; for(int i=0; i<needsCompiling.size(); i++) { inputFiles.add(buildFolder + '/' + needsCompiling.get(i) + ".o"); } for(int i=0; i<fakeCompiling.size(); i++) { inputFiles.add(buildFolder + '/' + fakeCompiling.get(i) + ".o"); } //FileTools::deleteFromFilesystem(releaseFolder); //FileTools::createDirectory(releaseFolder); String outputFolder; ProjectType type = projData.getProjectType(); if(type==PROJECTTYPE_APPLICATION) { outputFolder = releaseFolder + '/' + projData.getProductName() + ".app"; } else if(type==PROJECTTYPE_CONSOLE) { outputFolder = releaseFolder + '/' + projData.getProductName(); } else if(type==PROJECTTYPE_DYNAMICLIBRARY) { outputFolder = releaseFolder + '/' + projData.getProductName(); } else if(type==PROJECTTYPE_STATICLIBRARY) { outputFolder = releaseFolder + '/' + projData.getProductName(); } else { outputFolder = releaseFolder + '/' + projData.getProductName() + ".app"; } FileTools::createDirectory(outputFolder); String outputFile; if(type==PROJECTTYPE_APPLICATION) { outputFile = outputFolder + '/' + projData.getExecutableName(); } else if(type==PROJECTTYPE_CONSOLE) { outputFile = outputFolder + '/' + projData.getExecutableName(); } else if(type==PROJECTTYPE_DYNAMICLIBRARY) { outputFile = outputFolder + '/' + projData.getProductName() + ".dylib"; } else if(type==PROJECTTYPE_STATICLIBRARY) { outputFile = outputFolder + '/' + projData.getProductName() + ".a"; } //Compiling everything String compileCommand; if(type==PROJECTTYPE_APPLICATION || type==PROJECTTYPE_CONSOLE) { compileCommand = CompilerThread_createCompileString(projData, inputFiles, outputFile); } else if(type==PROJECTTYPE_DYNAMICLIBRARY || type==PROJECTTYPE_STATICLIBRARY) { compileCommand = CompilerThread_createLibtoolString(projData, inputFiles, outputFile); } currentFile = ""; CompilerThread_ChangeStatus(this, "Compiling..."); subprocess_execute(compileCommand, this, &CompilerThread_OutputReciever, &CompilerThread_ErrorReciever, &CompilerThread_ResultReciever, true, NULL, true); if(lastResult!=0) { result = -1; CompilerThread_ChangeStatus(this, "Failed"); CompilerThread_FinishReciever(this, result); return; } if(type==PROJECTTYPE_APPLICATION || type==PROJECTTYPE_CONSOLE) { CompilerThread_ChangeStatus(this, (String)"Codesigning " + projData.getExecutableName() + "..."); String codesignCommand = (String)"ldid -S \"" + outputFile + "\""; currentFile = ""; subprocess_execute(codesignCommand, this, &CompilerThread_OutputReciever, &CompilerThread_ErrorReciever, &CodesignThread_ResultReciever, true, NULL, true); if(lastResult!=0) { result = -1; } if(result==0) { CompilerThread_ChangeStatus(this, "Succeeded"); } else { CompilerThread_ChangeStatus(this, "Failed"); } } CompilerThread_FinishReciever(this, result); }