258 lines
10 KiB
Java
258 lines
10 KiB
Java
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.normalProperties.LocalMakePathWindows;
|
||
if (makepath.isEmpty()) {
|
||
Log.Writeln_("Не задан путь к make.exe.\n " +
|
||
"Укажите его в меню глобальных настроек." +
|
||
"\nПредварительная компиляция будет отключена.");
|
||
Global.mainModule.getPass(PassCode.UpdateSapforProperty).Do("Precompilation", false);
|
||
return false;
|
||
}
|
||
if (!(new File(makepath).exists())) {
|
||
Log.Writeln_("Файла по пути к make.exe не существует.\n" +
|
||
"Проверьте правильность его указания в глобальных настройках." +
|
||
"\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.normalProperties.LocalMakePathWindows) + " -j " + Global.normalProperties.Kernels,
|
||
target.compilation_maxtime);
|
||
} else
|
||
StartProcess("make -j " + Global.normalProperties.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 не реализовано");
|
||
}
|
||
}
|
||
}
|