2024-10-14 12:14:01 +03:00
|
|
|
|
package _VisualDVM.Passes.All;
|
2024-10-07 14:22:52 +03:00
|
|
|
|
import Common.CommonConstants;
|
2024-10-11 00:00:30 +03:00
|
|
|
|
import Common.Utils.Utils_;
|
|
|
|
|
|
import Common.Visual.UI_;
|
2024-10-09 22:01:19 +03:00
|
|
|
|
import _VisualDVM.Constants;
|
2024-10-07 00:58:29 +03:00
|
|
|
|
import _VisualDVM.Global;
|
2024-10-09 22:01:19 +03:00
|
|
|
|
import _VisualDVM.Visual.UI;
|
|
|
|
|
|
import _VisualDVM.Utils;
|
2024-10-09 22:21:57 +03:00
|
|
|
|
import _VisualDVM.GlobalData.Compiler.Compiler;
|
|
|
|
|
|
import _VisualDVM.GlobalData.Compiler.CompilerType;
|
|
|
|
|
|
import _VisualDVM.GlobalData.Makefile.Makefile;
|
|
|
|
|
|
import _VisualDVM.GlobalData.Module.Module;
|
|
|
|
|
|
import _VisualDVM.GlobalData.Settings.SettingName;
|
|
|
|
|
|
import _VisualDVM.ProjectData.Files.DBProjectFile;
|
|
|
|
|
|
import _VisualDVM.ProjectData.LanguageName;
|
|
|
|
|
|
import _VisualDVM.ProjectData.Project.db_project_info;
|
2024-10-14 12:14:01 +03:00
|
|
|
|
import _VisualDVM.Passes.PassCode;
|
2024-10-10 23:57:36 +03:00
|
|
|
|
import Common.Passes.PassException;
|
|
|
|
|
|
import Common.Passes.Pass;
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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;
|
2024-10-09 23:37:58 +03:00
|
|
|
|
public class Precompilation extends Pass<db_project_info> {
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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<>();
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected boolean needsAnimation() {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected boolean canStart(Object... args) throws Exception {
|
2024-10-13 22:08:13 +03:00
|
|
|
|
target = Global.mainModule.getProject();
|
2024-10-11 00:00:30 +03:00
|
|
|
|
if (Utils_.isWindows()) {
|
2023-09-17 22:13:42 +03:00
|
|
|
|
//--
|
2024-10-12 00:17:51 +03:00
|
|
|
|
makepath = Global.mainModule.getDb().settings.get(SettingName.LocalMakePathWindows).toString();
|
2023-09-17 22:13:42 +03:00
|
|
|
|
if (makepath.isEmpty()) {
|
|
|
|
|
|
Log.Writeln_("Не задан путь к make.exe.\n " +
|
|
|
|
|
|
"Укажите его в меню глобальных настроек." +
|
|
|
|
|
|
"\nПредварительная компиляция будет отключена.");
|
2024-10-13 23:55:03 +03:00
|
|
|
|
Global.mainModule.getPass(PassCode.UpdateSetting).Do(SettingName.Precompilation, "0");
|
2023-09-17 22:13:42 +03:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!(new File(makepath).exists())) {
|
|
|
|
|
|
Log.Writeln_("Файла по пути к make.exe не существует.\n" +
|
|
|
|
|
|
"Проверьте правильность его указания в глобальных настройках."+
|
|
|
|
|
|
"\nПредварительная компиляция будет отключена.");
|
2024-10-13 23:55:03 +03:00
|
|
|
|
Global.mainModule.getPass(PassCode.UpdateSetting).Do(SettingName.Precompilation, "0");
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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();
|
|
|
|
|
|
//-
|
2024-10-13 23:55:03 +03:00
|
|
|
|
Global.mainModule.getPass(PassCode.Save).Do(); //---->
|
2023-09-17 22:13:42 +03:00
|
|
|
|
prepareForParse(); //---->
|
|
|
|
|
|
//-
|
|
|
|
|
|
performanceTime = 0;
|
2024-10-07 14:22:52 +03:00
|
|
|
|
exitCode = CommonConstants.Nan;
|
2023-09-17 22:13:42 +03:00
|
|
|
|
//------------------
|
2024-10-11 00:00:30 +03:00
|
|
|
|
workspace = Paths.get(Global.TempDirectory.getAbsolutePath(), Utils_.getDateName("precompilation")).toFile();
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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 {
|
|
|
|
|
|
UI.getMainWindow().getProjectWindow().ShowNoAnalyses();
|
2024-10-13 22:08:13 +03:00
|
|
|
|
if (Global.mainModule.HasFile()) {
|
|
|
|
|
|
Global.mainModule.getFile().form.ShowNoMessages();
|
|
|
|
|
|
Global.mainModule.getFile().form.ShowNoAnalyses();
|
2023-09-17 22:13:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
protected static void unpackPrecompilationMessages(db_project_info target, String text) throws Exception {
|
|
|
|
|
|
boolean messageStarted = false;
|
|
|
|
|
|
String messageFile = "";
|
2024-10-07 14:22:52 +03:00
|
|
|
|
int messageLine = CommonConstants.Nan;
|
|
|
|
|
|
int messageType = CommonConstants.Nan;
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2024-10-07 14:22:52 +03:00
|
|
|
|
if (messageType != CommonConstants.Nan) {
|
2023-10-17 19:16:59 +03:00
|
|
|
|
target.db.files.Data.get(messageFile).CreateAndAddNewMessage(messageType, String.join("\n", messageText), messageLine, Constants.compiler_group);
|
2023-09-17 22:13:42 +03:00
|
|
|
|
messageStarted = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!S.isEmpty())
|
|
|
|
|
|
messageText.add(S);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//анализ начала строки.
|
|
|
|
|
|
for (String name : target.db.files.Data.keySet()) {
|
2024-10-11 00:00:30 +03:00
|
|
|
|
if (S.startsWith(Utils_.toU(name))) {
|
2023-09-17 22:13:42 +03:00
|
|
|
|
String[] data = S.split(":");
|
|
|
|
|
|
if (data.length > 1) {
|
|
|
|
|
|
messageFile = name;
|
|
|
|
|
|
messageLine = Integer.parseInt(data[1]);
|
2024-10-07 14:22:52 +03:00
|
|
|
|
messageType = CommonConstants.Nan;
|
2023-09-17 22:13:42 +03:00
|
|
|
|
messageText = new Vector<>();
|
|
|
|
|
|
messageStarted = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
|
|
|
protected void body() throws Exception {
|
2024-10-11 00:00:30 +03:00
|
|
|
|
if (Utils_.isWindows()) {
|
2023-09-17 22:13:42 +03:00
|
|
|
|
name_to_kill = "make.exe";
|
2024-10-12 00:17:51 +03:00
|
|
|
|
StartProcess(Utils_.DQuotes((Global.mainModule.getDb()).settings.get(SettingName.LocalMakePathWindows).Value) + " -j " + (Global.mainModule.getDb()).settings.get(SettingName.Kernels).toString(),
|
2023-09-17 22:13:42 +03:00
|
|
|
|
target.compilation_maxtime);
|
|
|
|
|
|
} else
|
2024-10-12 00:17:51 +03:00
|
|
|
|
StartProcess("make -j " + (Global.mainModule.getDb()).settings.get(SettingName.Kernels).toString(), target.compilation_maxtime);
|
2023-09-17 22:13:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
protected void StartProcess(String command, int TA) throws Exception {
|
|
|
|
|
|
killed = false;
|
|
|
|
|
|
output = "";
|
2024-10-11 00:00:30 +03:00
|
|
|
|
process = Utils.startScript(workspace, workspace, Utils_.getDateName("start_task_script"),
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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()) {
|
2024-10-11 00:00:30 +03:00
|
|
|
|
String replacement = file.last_assembly_name + " " + Utils_.RBrackets(file.name);
|
2023-09-17 22:13:42 +03:00
|
|
|
|
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 {
|
|
|
|
|
|
UI.getMainWindow().getProjectWindow().RefreshProjectTreeAndMessages();
|
2024-10-13 22:08:13 +03:00
|
|
|
|
if (Global.mainModule.HasFile()) {
|
|
|
|
|
|
Global.mainModule.getFile().form.ShowCompilationOutput();
|
|
|
|
|
|
Global.mainModule.getFile().form.FocusCompilationOut();
|
2024-02-14 17:58:52 +03:00
|
|
|
|
}
|
2023-09-17 22:13:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void Interrupt() throws Exception {
|
2024-10-11 00:00:30 +03:00
|
|
|
|
if (Utils_.isWindows()) {
|
2023-09-17 22:13:42 +03:00
|
|
|
|
if (!name_to_kill.isEmpty()) {
|
|
|
|
|
|
killed = true;
|
|
|
|
|
|
Process killer = Runtime.getRuntime().exec("taskkill /FI \"IMAGENAME eq " + name_to_kill + "\" /F /T");
|
|
|
|
|
|
killer.waitFor();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2024-10-11 00:00:30 +03:00
|
|
|
|
UI_.Info("Прерывание процессов под Linux не реализовано");
|
2023-09-17 22:13:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|