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

262 lines
11 KiB
Java
Raw Normal View History

package Visual_DVM_2021.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;
import _VisualDVM.Current;
2024-10-09 22:21:57 +03:00
import _VisualDVM.GlobalData.GlobalDatabase;
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-09 23:37:58 +03:00
import Visual_DVM_2021.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 {
target = Current.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 " +
"Укажите его в меню глобальных настроек." +
"\редварительная компиляция будет отключена.");
2024-10-09 23:37:58 +03:00
passes.get(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" +
"Проверьте правильность его указания в глобальных настройках."+
"\редварительная компиляция будет отключена.");
2024-10-09 23:37:58 +03:00
passes.get(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-09 23:37:58 +03:00
passes.get(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();
if (Current.HasFile()) {
Current.getFile().form.ShowNoMessages();
Current.getFile().form.ShowNoAnalyses();
}
}
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) {
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-02-14 17:58:52 +03:00
if (Current.HasFile()) {
2023-09-17 22:13:42 +03:00
Current.getFile().form.ShowCompilationOutput();
2024-02-14 17:58:52 +03:00
Current.getFile().form.FocusCompilationOut();
}
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
}
}
}