Example #1
0
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;
		}
	}
}
Example #2
0
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);
}