Files
VisualSapfor/src/_VisualDVM/Passes/All/Precompilation.java

258 lines
10 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package _VisualDVM.Passes.All;
import Common.CommonConstants;
import Common.Passes.Pass;
import Common.Passes.PassException;
import Common.Utils.Utils_;
import Common.Visual.UI;
import _VisualDVM.Constants;
import _VisualDVM.Global;
import _VisualDVM.GlobalData.Compiler.Compiler;
import _VisualDVM.GlobalData.Compiler.CompilerType;
import _VisualDVM.GlobalData.Makefile.Makefile;
import _VisualDVM.GlobalData.Module.Module;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.LanguageName;
import _VisualDVM.ProjectData.Project.db_project_info;
import _VisualDVM.Utils;
import org.apache.commons.io.FileUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Vector;
public class Precompilation extends Pass<db_project_info> {
protected static String name_to_kill = "";
protected static boolean killed = false;
protected String makepath;
//----------------------->>>
protected File workspace; //рабочая папка.
protected Compiler fortranCompiler;
protected Makefile makefile;
protected File makefileFile;
protected int performanceTime;
protected int exitCode;
//----------------------->>>
protected Process process = null;
protected String output = "";
protected Vector<String> outputLines = new Vector<>();
protected static void unpackPrecompilationMessages(db_project_info target, String text) throws Exception {
boolean messageStarted = false;
String messageFile = "";
int messageLine = CommonConstants.Nan;
int messageType = CommonConstants.Nan;
Vector<String> messageText = new Vector<>();
String[] nw = text.split("\n");
for (String S : nw) {
if (messageStarted) {
String s = S.toLowerCase();
if (s.startsWith("warning:")) {
messageText.add(S.substring(9));
messageType = 0;
} else if (s.startsWith("error:")) {
messageText.add(S.substring(7));
messageType = 1;
} else if (s.startsWith("note:")) {
messageText.add(S.substring(6));
messageType = 2;
}
if (messageType != CommonConstants.Nan) {
target.db.files.Data.get(messageFile).CreateAndAddNewMessage(messageType, String.join("\n", messageText), messageLine, Constants.compiler_group);
messageStarted = false;
} else {
if (!S.isEmpty())
messageText.add(S);
}
} else {
//анализ начала строки.
for (String name : target.db.files.Data.keySet()) {
if (S.startsWith(Utils_.toU(name))) {
String[] data = S.split(":");
if (data.length > 1) {
messageFile = name;
messageLine = Integer.parseInt(data[1]);
messageType = CommonConstants.Nan;
messageText = new Vector<>();
messageStarted = true;
}
break;
}
}
}
}
}
@Override
protected boolean needsAnimation() {
return true;
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = Global.mainModule.getProject();
if (Utils_.isWindows()) {
//--
makepath = Global.properties.LocalMakePathWindows;
if (makepath.isEmpty()) {
Log.Writeln_("Не задан путь к make.exe.\n " +
"Укажите его в меню глобальных настроек." +
"\редварительная компиляция будет отключена.");
Global.mainModule.getPass(PassCode.UpdateSapforProperty).Do("Precompilation", false);
return false;
}
if (!(new File(makepath).exists())) {
Log.Writeln_("Файла по пути к make.exe не существует.\n" +
"Проверьте правильность его указания в глобальных настройках." +
"\редварительная компиляция будет отключена.");
Global.mainModule.getPass(PassCode.UpdateSapforProperty).Do("Precompilation", false);
return false;
}
//--
}
process = null;
if (!target.languageName.equals(LanguageName.fortran)) {
Log.Writeln_("Предварительная компиляция поддерживается только для FORTRAN.");
return false;
}
return true;
}
protected String getLinkFlags() {
return "";
}
protected String getFortranFlags() {
return "";
}
protected void prepareForParse() throws Exception {
target.CleanAnalyses();
}
@Override
protected void performPreparation() throws Exception {
target.CleanInterruptFile();
//-
Global.mainModule.getPass(PassCode.Save).Do(); //---->
prepareForParse(); //---->
//-
performanceTime = 0;
exitCode = CommonConstants.Nan;
//------------------
workspace = Paths.get(Global.TempDirectory.getAbsolutePath(), Utils_.getDateName("precompilation")).toFile();
FileUtils.forceMkdir(workspace);
//------------------------------>>
fortranCompiler = new Compiler();
fortranCompiler.call_command = "gfortran";
fortranCompiler.type = CompilerType.gnu;
makefileFile = Paths.get(workspace.getAbsolutePath(), "Makefile").toFile();
makefile = new Makefile() {
@Override
public Compiler getCompiler() {
return fortranCompiler;
}
};
makefile.flags = getLinkFlags();
LinkedHashMap<LanguageName, Module> modules = new LinkedHashMap<>();
Module fortranModule = new Module(LanguageName.fortran, null) {
@Override
public boolean isSelected() {
return true; //всегда выбран. нужно для генерации.
}
@Override
public Compiler getCompiler() {
return fortranCompiler;
}
};
fortranModule.flags = getFortranFlags();
modules.put(LanguageName.fortran, fortranModule);
//------------------------------>>
target.Clone(workspace, false);
//------------------------------>>
FileUtils.write(makefileFile, genMakefileText(modules));
//---
}
protected String genMakefileText(LinkedHashMap<LanguageName, Module> modules) throws Exception {
return makefile.GenerateForPrecompilation(target, modules);
}
@Override
protected void showPreparation() throws Exception {
Global.mainModule.getUI().getMainWindow().getProjectWindow().ShowNoAnalyses();
if (Global.mainModule.HasFile()) {
Global.mainModule.getFile().form.ShowNoMessages();
Global.mainModule.getFile().form.ShowNoAnalyses();
}
}
@Override
protected void body() throws Exception {
if (Utils_.isWindows()) {
name_to_kill = "make.exe";
StartProcess(Utils_.DQuotes(Global.properties.LocalMakePathWindows) + " -j " + Global.properties.Kernels,
target.compilation_maxtime);
} else
StartProcess("make -j " + Global.properties.Kernels, target.compilation_maxtime);
}
protected void StartProcess(String command, int TA) throws Exception {
killed = false;
output = "";
process = Utils.startScript(workspace, workspace, Utils_.getDateName("start_task_script"),
command,
null);
outputLines.clear();
InputStream stdout = process.getInputStream();
InputStreamReader isrStdout = new InputStreamReader(stdout);
BufferedReader brStdout = new BufferedReader(isrStdout);
String line;
//-
while ((line = brStdout.readLine()) != null) {
ShowMessage2(line);
outputLines.add(line);
}
output = String.join("\n", outputLines);
if (killed) {
throw new PassException("Процесс был убит");
}
}
@Override
protected boolean validate() {
return outputLines.stream().noneMatch(line -> line.toLowerCase().startsWith("error"));
}
@Override
protected void performDone() throws Exception {
}
@Override
protected void performFinish() throws Exception {
for (DBProjectFile file : target.db.files.Data.values()) {
if (!file.last_assembly_name.isEmpty()) {
String replacement = file.last_assembly_name + " " + Utils_.RBrackets(file.name);
output = output.replace(file.last_assembly_name, replacement);
}
}
target.updateCompilationOut(output);
//----------------------------------
target.db.BeginTransaction();
unpackPrecompilationMessages(target, output);
for (DBProjectFile file : target.db.files.Data.values())
file.father.db.Update(file);
target.db.Commit();
//----------------------------------
}
@Override
protected void showFinish() throws Exception {
Global.mainModule.getUI().getMainWindow().getProjectWindow().RefreshProjectTreeAndMessages();
if (Global.mainModule.HasFile()) {
Global.mainModule.getFile().form.ShowCompilationOutput();
Global.mainModule.getFile().form.FocusCompilationOut();
}
}
@Override
public void Interrupt() throws Exception {
if (Utils_.isWindows()) {
if (!name_to_kill.isEmpty()) {
killed = true;
Process killer = Runtime.getRuntime().exec("taskkill /FI \"IMAGENAME eq " + name_to_kill + "\" /F /T");
killer.waitFor();
}
} else {
UI.Info("Прерывание процессов под Linux не реализовано");
}
}
}