Commit 887d2280 authored by Victor Yacovlev's avatar Victor Yacovlev

Generate native executables from GUI if support

parent 96113064
......@@ -16,7 +16,7 @@ TS_MODULES = {
"KumirCompiler": "src/plugins/kumircompiler",
"KumirCodeRun": "src/plugins/kumircoderun",
"KumirCodeGenerator": "src/plugins/kumircodegenerator",
"KumirNativeGenerator": "src/plugins/kumirnativegenerator",
# "KumirNativeGenerator": "src/plugins/kumirnativegenerator",
"PascalAnalizer": "src/plugins/pascalanalizer",
# "st_funct": "src/plugins/st_funct"
}
......
This diff is collapsed.
......@@ -22,7 +22,7 @@ else()
endif()
set(CONFIGURATION_TEMPLATE
"CourseManager,Editor,Browser,Actor*,KumirAnalizer,KumirCodeGenerator,KumirCodeRun,!CoreGUI\(notabs,icon=classic,nostartpage,nosessions\)"
"CourseManager,Editor,Browser,Actor*,KumirAnalizer,*CodeGenerator,KumirCodeRun,!CoreGUI\(notabs,icon=classic,nostartpage,nosessions\)"
)
set(SPLASHSCREEN
"coregui/splashscreens/classic.png"
......
......@@ -22,7 +22,7 @@ else()
endif()
set(CONFIGURATION_TEMPLATE
"CourseManager,Editor,Browser,Actor*,KumirAnalizer\(preload=Files,preload=Strings\),KumirCodeGenerator,KumirCodeRun,!CoreGUI\(notabs,icon=highgrade,nostartpage,nosessions\)"
"CourseManager,Editor,Browser,Actor*,KumirAnalizer\(preload=Files,preload=Strings\),*CodeGenerator,KumirCodeRun,!CoreGUI\(notabs,icon=highgrade,nostartpage,nosessions\)"
)
set(SPLASHSCREEN
"coregui/splashscreens/highgrade.png"
......
......@@ -22,7 +22,7 @@ else()
endif()
set(CONFIGURATION_TEMPLATE
"CourseManager,Editor,Actor*,Browser,KumirAnalizer,KumirCodeGenerator,KumirCodeRun,!CoreGUI"
"CourseManager,Editor,Actor*,Browser,KumirAnalizer,*CodeGenerator,KumirCodeRun,!CoreGUI"
)
set(SPLASHSCREEN
......
......@@ -146,7 +146,7 @@ Shared::RunInterface * KumirProgram::runner()
return RUNNER;
}
Shared::GeneratorInterface * KumirProgram::generator()
Shared::GeneratorInterface * KumirProgram::kumirCodeGenerator()
{
using namespace ExtensionSystem;
using namespace Shared;
......@@ -154,7 +154,21 @@ Shared::GeneratorInterface * KumirProgram::generator()
static GeneratorInterface * GENERATOR = nullptr;
if (!GENERATOR) {
GENERATOR = PluginManager::instance()->findPlugin<GeneratorInterface>();
GENERATOR = PluginManager::instance()->findPlugin<GeneratorInterface>("KumirCodeGenerator");
}
return GENERATOR;
}
Shared::GeneratorInterface * KumirProgram::kumirNativeGenerator()
{
using namespace ExtensionSystem;
using namespace Shared;
static GeneratorInterface * GENERATOR = nullptr;
if (!GENERATOR) {
GENERATOR = PluginManager::instance()->findPlugin<GeneratorInterface>("LLVMCodeGenerator");
}
return GENERATOR;
......@@ -277,10 +291,10 @@ void KumirProgram::prepareKumirRunner(Shared::GeneratorInterface::DebugLevel deb
const AST::DataPtr ast = editor_->analizer()->compiler()->abstractSyntaxTree();
sourceProgramPath = editor_->documentContents().sourceUrl.toLocalFile();
QByteArray bufArray;
generator()->setOutputToText(false);
generator()->setDebugLevel(debugLevel);
kumirCodeGenerator()->setOutputToText(false);
kumirCodeGenerator()->setDebugLevel(debugLevel);
QString fileNameSuffix, mimeType;
generator()->generateExecuable(ast, bufArray, mimeType, fileNameSuffix);
kumirCodeGenerator()->generateExecuable(ast, bufArray, mimeType, fileNameSuffix);
runner()->loadProgram(sourceProgramPath, bufArray);
}
else {
......
......@@ -44,6 +44,8 @@ public:
inline bool isRunning() const { return state_!=Idle; }
inline void setMainWidget(QWidget * w) { mainWidget_ = w; }
void setTerminal(Term * t, QDockWidget * w);
static Shared::GeneratorInterface * kumirCodeGenerator();
static Shared::GeneratorInterface * kumirNativeGenerator();
inline QString endStatusText() const { return endStatusText_; }
inline RunEndStatus endStatus() const { return endStatus_; }
......@@ -72,7 +74,6 @@ private:
void createConnections();
static Shared::RunInterface * runner();
static Shared::GeneratorInterface * generator();
void setAllActorsAnimationFlag(bool animationEnabled);
void prepareKumirRunner(Shared::GeneratorInterface::DebugLevel);
......
......@@ -290,6 +290,11 @@ MainWindow::MainWindow(Plugin * p) :
qDebug() << "LINE DEBUG: " << QFileInfo(QString(__FILE__)).fileName() << ":" << __LINE__;
ui->menuFile->removeAction(ui->actionRestore_previous_session); // Not implemented yet
qDebug() << "LINE DEBUG: " << QFileInfo(QString(__FILE__)).fileName() << ":" << __LINE__;
ui->actionMake_native_executable->setVisible(manager->isPluginLoaded("LLVMCodeGenerator"));
connect(ui->actionMake_native_executable, SIGNAL(triggered()),
this, SLOT(makeNativeExecutable()));
}
//QString MainWindow::StatusbarWidgetCSS =
......@@ -916,6 +921,7 @@ void MainWindow::setupActionsForTab()
ui->actionSave_as->setEnabled(twe->type!=WWW);
ui->actionClose->setEnabled(!twe->property("uncloseable").toBool());
ui->actionMake_native_executable->setEnabled(Program==twe->type);
prepareEditMenu();
prepareInsertMenu();
......@@ -1060,6 +1066,67 @@ void MainWindow::prepareInsertMenu()
}
}
void MainWindow::makeNativeExecutable()
{
TabWidgetElement * twe = qobject_cast<TabWidgetElement*>(tabWidget_->currentWidget());
twe->editor()->ensureAnalized();
const AST::DataPtr ast = twe->editor()->analizer()->compiler()->abstractSyntaxTree();
QString fileSuffix;
QString mimeType;
QByteArray buffer;
twe->kumirProgram()->kumirNativeGenerator()->generateExecuable(ast, buffer, mimeType, fileSuffix);
QString fileName = twe->editor()->documentContents().sourceUrl.toLocalFile();
#ifndef Q_OS_WIN32
fileSuffix = "bin";
#endif
if (!fileName.isEmpty() && fileName.endsWith(".kum")) {
fileName = fileName.mid(0, fileName.length()-4);
if (fileSuffix.length() > 0)
fileName += "." + fileSuffix;
}
else if (!fileName.isEmpty() && !fileSuffix.isEmpty()) {
fileName += "." + fileSuffix;
}
QString initialPath;
if (fileName.isEmpty()) {
QString lastFileName = m_plugin->mySettings()->value(Plugin::RecentFileKey).toString();
if (lastFileName.isEmpty()) {
initialPath = QDir::currentPath();
}
else {
initialPath = QFileInfo(lastFileName).absoluteDir().absolutePath();
}
initialPath += "/" + suggestNewFileName(fileSuffix, twe->editor()->analizer(), initialPath);
}
else {
initialPath = fileName;
}
QStringList filter;
filter << tr("Native executables (*.%1)").arg(fileSuffix);
fileName = QFileDialog::getSaveFileName(this, tr("Save native executable"), initialPath, filter.join(";;"));
if (!fileName.isEmpty()) {
#ifdef Q_OS_WIN32
if (!fileName.endsWith("." + fileSuffix)) {
fileName += "." + fileSuffix;
}
#endif
QString settingsEntry = fileName;
if (settingsEntry.endsWith("." + fileSuffix)) {
settingsEntry = settingsEntry.left(settingsEntry.length()-4);
}
settingsEntry += ".kum";
m_plugin->mySettings()->setValue(Plugin::RecentFileKey, settingsEntry);
QFile f(fileName);
if (f.open(QIODevice::WriteOnly)) {
f.write(buffer);
f.close();
QFile::Permissions ps = f.permissions();
ps |= QFile::ExeGroup | QFile::ExeOwner | QFile::ExeOther;
QFile::setPermissions(fileName, ps);
}
}
}
bool MainWindow::saveCurrentFileAs()
{
using namespace ExtensionSystem;
......
......@@ -91,7 +91,8 @@ public slots:
void showUserManual();
void showHelp();
void updateSettings(ExtensionSystem::SettingsPtr settings, const QStringList & keys);
void updateBrowserTitle(const QString & title, const Shared::Browser::InstanceInterface * sender);
void updateBrowserTitle(const QString & title, const Shared::Browser::InstanceInterface * sender);
void makeNativeExecutable();
private slots:
void loadRecentFile();
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>744</width>
<height>544</height>
<width>742</width>
<height>542</height>
</rect>
</property>
<property name="windowTitle">
......@@ -44,8 +44,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>744</width>
<height>21</height>
<width>742</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
......@@ -64,6 +64,7 @@
<addaction name="actionSave"/>
<addaction name="actionSave_as"/>
<addaction name="actionSave_all"/>
<addaction name="actionMake_native_executable"/>
<addaction name="separator"/>
<addaction name="actionClose"/>
<addaction name="separator"/>
......@@ -252,6 +253,11 @@
<string>F12</string>
</property>
</action>
<action name="actionMake_native_executable">
<property name="text">
<string>Make native executable...</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......
......@@ -322,8 +322,8 @@ QByteArray LLVMCodeGeneratorPlugin::runExternalToolsToGenerateExecutable(const Q
static const QString LD = bundledToolchainPath + "\\ld.exe";
#else
static const QString LLC = "llc";
static const QString AS = "as";
static const QString LD = "ld";
static const QString AS = "clang"; // GNU AS does not support Unicode names, so use CLang
static const QString LD = "clang"; // libstdc++ might have several names in Linux, use CLang to find it
#endif
// ====== Write bitcode to external file
......@@ -379,9 +379,12 @@ QByteArray LLVMCodeGeneratorPlugin::runExternalToolsToGenerateExecutable(const Q
// ====== Assemble object using GNU as
const QStringList asArguments = QStringList()
QStringList asArguments = QStringList()
<< "-o" << QDir::toNativeSeparators(objFileName)
<< QDir::toNativeSeparators(asmFileName);
if (AS.endsWith("clang")) {
asArguments.prepend("-c");
}
#ifdef Q_OS_WIN32
process.setWorkingDirectory(bundledToolchainPath);
#endif
......
......@@ -53,6 +53,17 @@ PluginManager::~PluginManager()
}
bool PluginManager::isPluginLoaded(const QByteArray &name) const
{
for (int i=0; i<pImpl_->specs.size(); i++) {
const PluginSpec & spec = pImpl_->specs.at(i);
if (spec.name.toLatin1() == name) {
return true;
}
}
return false;
}
void PluginManager::destroy()
{
PluginManager * pm = instance();
......
......@@ -100,6 +100,22 @@ public:
return result;
}
template <class PluginInterface>
PluginInterface* findPlugin(const QByteArray & name) {
QList<KPlugin*> plugins = loadedPlugins();
PluginInterface* result = nullptr;
for (int i=0; i<plugins.size(); i++) {
KPlugin * plugin = plugins[i];
if (plugin->pluginName() == name) {
result = qobject_cast<PluginInterface*>(plugin);
}
if (result) {
break;
}
}
return result;
}
template <class PluginInterface>
KPlugin* findKPlugin() {
QList<KPlugin*> plugins = loadedPlugins();
......@@ -129,6 +145,14 @@ public:
return result;
}
bool isPluginLoaded(const QByteArray &name) const;
inline bool isPluginLoaded(const QString & name) const {
return isPluginLoaded(name.toLatin1());
}
inline bool isPluginLoaded(const char * name) const {
return isPluginLoaded(QByteArray(name));
}
void updateAllSettings();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment