diff --git a/app/main.cpp b/app/main.cpp index c6a1841371..11065c4c99 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -1,816 +1,816 @@ /*************************************************************************** * Copyright 2003-2009 Alexander Dymo * * Copyright 2007 Ralf Habacker * * Copyright 2006-2007 Matt Rogers * * Copyright 2006-2007 Hamish Rodda * * Copyright 2005-2007 Adam Treat * * Copyright 2003-2007 Jens Dagerbo * * Copyright 2001-2002 Bernd Gehrmann * * Copyright 2001-2002 Matthias Hoelzer-Kluepfel * * Copyright 2003 Roberto Raggi * * Copyright 2010 Niko Sams * * Copyright 2015 Kevin Funk * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "config-kdevelop.h" #include "kdevelop_version.h" #include "urlinfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdevideextension.h" #if KDEVELOP_SINGLE_APP #include "qtsingleapplication.h" #endif #include #ifdef Q_OS_MAC #include #endif using namespace KDevelop; namespace { #if KDEVELOP_SINGLE_APP QString serializeOpenFilesMessage(const QVector &infos) { QByteArray message; QDataStream stream(&message, QIODevice::WriteOnly); stream << QByteArrayLiteral("open"); stream << infos; return QString::fromLatin1(message.toHex()); } #endif void openFiles(const QVector& infos) { foreach (const UrlInfo& info, infos) { if (!ICore::self()->documentController()->openDocument(info.url, info.cursor)) { - qWarning() << i18n("Could not open %1", info.url.toDisplayString(QUrl::PreferLocalFile)); + qWarning(APP) << i18n("Could not open %1", info.url.toDisplayString(QUrl::PreferLocalFile)); } } } } class KDevelopApplication: #if KDEVELOP_SINGLE_APP public SharedTools::QtSingleApplication #else public QApplication #endif { public: explicit KDevelopApplication(int &argc, char **argv, bool GUIenabled = true) #if KDEVELOP_SINGLE_APP : SharedTools::QtSingleApplication(QStringLiteral("KDevelop"), argc, argv) #else : QApplication(argc, argv, GUIenabled) #endif { Q_UNUSED(GUIenabled); connect(this, &QGuiApplication::saveStateRequest, this, &KDevelopApplication::saveState); } #if KDEVELOP_SINGLE_APP public Q_SLOTS: void remoteArguments(const QString &message, QObject *socket) { Q_UNUSED(socket); QByteArray ba = QByteArray::fromHex(message.toLatin1()); QDataStream stream(ba); QByteArray command; stream >> command; qCDebug(APP) << "Received remote command: " << command; if (command == "open") { QVector infos; stream >> infos; QVector files, directories; for (const auto& info : infos) if (info.isDirectory()) directories << info; else files << info; openFiles(files); for(const auto &urlinfo : directories) ICore::self()->projectController()->openProjectForUrl(urlinfo.url); } else { qCWarning(APP) << "Unknown remote command: " << command; } } void fileOpenRequested(const QString &file) { openFiles({UrlInfo(file)}); } #endif private Q_SLOTS: void saveState( QSessionManager& sm ) { if (KDevelop::Core::self() && KDevelop::Core::self()->sessionController()) { QString x11SessionId = QStringLiteral("%1_%2").arg(sm.sessionId()).arg(sm.sessionKey()); const auto activeSession = KDevelop::Core::self()->sessionController()->activeSession(); if (!activeSession) { - qWarning() << "No active session, can't save state"; + qWarning(APP) << "No active session, can't save state"; return; } QString kdevelopSessionId = activeSession->id().toString(); sm.setRestartCommand({QCoreApplication::applicationFilePath(), "-session", x11SessionId, "-s", kdevelopSessionId}); } } }; /// Tries to find a session identified by @p data in @p sessions. /// The @p data may be either a session's name or a string-representation of its UUID. /// @return pointer to the session or NULL if nothing appropriate has been found static const KDevelop::SessionInfo* findSessionInList( const SessionInfos& sessions, const QString& data ) { // We won't search a session without input data, since that could lead to false-positives // with unnamed sessions if( data.isEmpty() ) return nullptr; for( auto it = sessions.constBegin(); it != sessions.constEnd(); ++it ) { if ( ( it->name == data ) || ( it->uuid.toString() == data ) ) { const KDevelop::SessionInfo& sessionRef = *it; return &sessionRef; } } return nullptr; } /// Tries to find sessions containing project @p projectUrl in @p sessions. static const KDevelop::SessionInfos findSessionsWithProject(const SessionInfos& sessions, const QUrl& projectUrl) { if (!projectUrl.isValid()) return {}; KDevelop::SessionInfos infos; for (auto it = sessions.constBegin(); it != sessions.constEnd(); ++it) { if (it->projects.contains(projectUrl)) { infos << *it; } } return infos; } /// Performs a DBus call to open the given @p files in the running kdev instance identified by @p pid /// Returns the exit status static int openFilesInRunningInstance(const QVector& files, qint64 pid) { const QString service = QStringLiteral("org.kdevelop.kdevelop-%1").arg(pid); QDBusInterface iface(service, QStringLiteral("/org/kdevelop/DocumentController"), QStringLiteral("org.kdevelop.DocumentController")); QStringList urls; bool errors_occured = false; foreach ( const UrlInfo& file, files ) { QDBusReply result = iface.call(QStringLiteral("openDocumentSimple"), file.url.toString(), file.cursor.line(), file.cursor.column()); if ( ! result.value() ) { QTextStream err(stderr); err << i18n("Could not open file '%1'.", file.url.toDisplayString(QUrl::PreferLocalFile)) << "\n"; errors_occured = true; } } // make the window visible QDBusMessage makeVisible = QDBusMessage::createMethodCall( service, QStringLiteral("/kdevelop/MainWindow"), QStringLiteral("org.kdevelop.MainWindow"), QStringLiteral("ensureVisible") ); QDBusConnection::sessionBus().asyncCall( makeVisible ); return errors_occured; } /// Performs a DBus call to open the given @p files in the running kdev instance identified by @p pid /// Returns the exit status static int openProjectInRunningInstance(const QVector& paths, qint64 pid) { const QString service = QStringLiteral("org.kdevelop.kdevelop-%1").arg(pid); QDBusInterface iface(service, QStringLiteral("/org/kdevelop/ProjectController"), QStringLiteral("org.kdevelop.ProjectController")); int errors = 0; foreach ( const UrlInfo& path, paths ) { QDBusReply result = iface.call(QStringLiteral("openProjectForUrl"), path.url.toString()); if ( !result.isValid() ) { QTextStream err(stderr); err << i18n("Could not open project '%1': %2", path.url.toDisplayString(QUrl::PreferLocalFile), result.error().message()) << "\n"; ++errors; } } // make the window visible QDBusMessage makeVisible = QDBusMessage::createMethodCall( service, QStringLiteral("/kdevelop/MainWindow"), QStringLiteral("org.kdevelop.MainWindow"), QStringLiteral("ensureVisible") ); QDBusConnection::sessionBus().asyncCall( makeVisible ); return errors; } /// Gets the PID of a running KDevelop instance, eventually asking the user if there is more than one. /// Returns -1 in case there are no running sessions. static qint64 getRunningSessionPid() { SessionInfos candidates; foreach( const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos() ) { if( KDevelop::SessionController::isSessionRunning(si.uuid.toString()) ) { candidates << si; } } if ( candidates.isEmpty() ) { return -1; } QString sessionUuid; if ( candidates.size() == 1 ) { sessionUuid = candidates.first().uuid.toString(); } else { const QString title = i18n("Select the session to open the document in"); sessionUuid = KDevelop::SessionController::showSessionChooserDialog(title, true); } return KDevelop::SessionController::sessionRunInfo(sessionUuid).holderPid; } static QString findSessionId(const SessionInfos& availableSessionInfos, const QString& session) { //If there is a session and a project with the same name, always open the session //regardless of the order encountered QString projectAsSession; foreach(const KDevelop::SessionInfo& si, availableSessionInfos) { if ( session == si.name || session == si.uuid.toString() ) { return si.uuid.toString(); } else if (projectAsSession.isEmpty()) { foreach(const QUrl& k, si.projects) { QString fn(k.fileName()); fn = fn.left(fn.indexOf('.')); if ( session == fn ) { projectAsSession = si.uuid.toString(); } } } } if (projectAsSession.isEmpty()) { QTextStream qerr(stderr); qerr << endl << i18n("Cannot open unknown session %1. See `--list-sessions` switch for available sessions or use `-n` to create a new one.", session) << endl; } return projectAsSession; } static qint64 findSessionPid(const QString &sessionId) { KDevelop::SessionRunInfo sessionInfo = KDevelop::SessionController::sessionRunInfo( sessionId ); return sessionInfo.holderPid; } int main( int argc, char *argv[] ) { QElapsedTimer timer; timer.start(); // TODO: Maybe generalize, add KDEVELOP_STANDALONE build option #if defined(Q_OS_WIN) || defined(Q_OS_MAC) qputenv("KDE_FORK_SLAVES", "1"); // KIO slaves will be forked off instead of being started via DBus #endif // Useful for valgrind runs, just `export KDEV_DISABLE_JIT=1` if (qEnvironmentVariableIsSet("KDEV_DISABLE_JIT")) { qputenv("KDEV_DISABLE_WELCOMEPAGE", "1"); qputenv("QT_ENABLE_REGEXP_JIT", "0"); } QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); #ifdef Q_OS_MAC CFBundleRef mainBundle = CFBundleGetMainBundle(); if (mainBundle) { // get the application's Info Dictionary. For app bundles this would live in the bundle's Info.plist, // for regular executables it is obtained in another way. CFMutableDictionaryRef infoDict = (CFMutableDictionaryRef) CFBundleGetInfoDictionary(mainBundle); if (infoDict) { // Try to prevent App Nap on OS X. This can be tricky in practice, at least in 10.9 . CFDictionarySetValue(infoDict, CFSTR("NSAppSleepDisabled"), kCFBooleanTrue); CFDictionarySetValue(infoDict, CFSTR("NSSupportsAutomaticTermination"), kCFBooleanFalse); } } #endif //we can't use KCmdLineArgs as it doesn't allow arguments for the debugee //so lookup the --debug switch and eat everything behind by decrementing argc //debugArgs is filled with args after --debug QStringList debugArgs; QString debugeeName; { bool debugFound = false; int c = argc; for (int i=0; i < c; ++i) { if (debugFound) { debugArgs << argv[i]; } else if ((qstrcmp(argv[i], "--debug") == 0) || (qstrcmp(argv[i], "-d") == 0)) { if (argc > (i + 1)) { i++; } argc = i + 1; debugFound = true; } else if (QString(argv[i]).startsWith(QLatin1String("--debug="))) { argc = i + 1; debugFound = true; } } } KDevelopApplication app(argc, argv); KLocalizedString::setApplicationDomain("kdevelop"); static const char description[] = I18N_NOOP( "The KDevelop Integrated Development Environment" ); KAboutData aboutData( QStringLiteral("kdevelop"), i18n( "KDevelop" ), QByteArray(KDEVELOP_VERSION_STRING), i18n(description), KAboutLicense::GPL, i18n("Copyright 1999-2017, The KDevelop developers"), QString(), QStringLiteral("https://www.kdevelop.org/")); aboutData.setDesktopFileName(QStringLiteral("org.kde.kdevelop")); aboutData.addAuthor( i18n("Kevin Funk"), i18n( "Co-maintainer, C++/Clang, QA, Windows Support" ), QStringLiteral("kfunk@kde.org") ); aboutData.addAuthor( i18n("Sven Brauch"), i18n( "Co-maintainer, AppImage, Python Support, User Interface improvements" ), QStringLiteral("svenbrauch@gmail.com") ); aboutData.addAuthor( i18n("Aleix Pol Gonzalez"), i18n( "CMake Support, Run Support, Kross Support" ), QStringLiteral("aleixpol@gmail.com") ); aboutData.addAuthor( i18n("Milian Wolff"), i18n( "C++/Clang, Generic manager, Webdevelopment Plugins, Snippets, Performance" ), QStringLiteral("mail@milianw.de") ); aboutData.addAuthor( i18n("Olivier JG"), i18n( "C++/Clang, DUChain, Bug Fixes" ), QStringLiteral("olivier.jg@gmail.com") ); aboutData.addAuthor( i18n("Andreas Pakulat"), i18n( "Architecture, VCS Support, Project Management Support, QMake Projectmanager" ), QStringLiteral("apaku@gmx.de") ); aboutData.addAuthor( i18n("Alexander Dymo"), i18n( "Architecture, Sublime UI, Ruby support" ), QStringLiteral("adymo@kdevelop.org") ); aboutData.addAuthor( i18n("David Nolden"), i18n( "Definition-Use Chain, C++ Support, Code Navigation, Code Completion, Coding Assistance, Refactoring" ), QStringLiteral("david.nolden.kdevelop@art-master.de") ); aboutData.addAuthor( i18n("Vladimir Prus"), i18n( "GDB integration" ), QStringLiteral("ghost@cs.msu.su") ); aboutData.addAuthor( i18n("Hamish Rodda"), i18n( "Text editor integration, definition-use chain" ), QStringLiteral("rodda@kde.org") ); aboutData.addAuthor( i18n("Amilcar do Carmo Lucas"), i18n( "Website admin, API documentation, Doxygen and autoproject patches" ), QStringLiteral("amilcar@kdevelop.org") ); aboutData.addAuthor( i18n("Niko Sams"), i18n( "GDB integration, Webdevelopment Plugins" ), QStringLiteral("niko.sams@gmail.com") ); aboutData.addCredit( i18n("Matt Rogers"), QString(), QStringLiteral("mattr@kde.org")); aboutData.addCredit( i18n("Cédric Pasteur"), i18n("astyle and indent support"), QStringLiteral("cedric.pasteur@free.fr") ); aboutData.addCredit( i18n("Evgeniy Ivanov"), i18n("Distributed VCS, Git, Mercurial"), QStringLiteral("powerfox@kde.ru") ); // QTest integration is separate in playground currently. //aboutData.addCredit( i18n("Manuel Breugelmanns"), i18n( "Veritas, QTest integration"), "mbr.nxi@gmail.com" ); aboutData.addCredit( i18n("Robert Gruber") , i18n( "SnippetPart, debugger and usability patches" ), QStringLiteral("rgruber@users.sourceforge.net") ); aboutData.addCredit( i18n("Dukju Ahn"), i18n( "Subversion plugin, Custom Make Manager, Overall improvements" ), QStringLiteral("dukjuahn@gmail.com") ); aboutData.addCredit( i18n("Harald Fernengel"), i18n( "Ported to Qt 3, patches, valgrind, diff and perforce support" ), QStringLiteral("harry@kdevelop.org") ); aboutData.addCredit( i18n("Roberto Raggi"), i18n( "C++ parser" ), QStringLiteral("roberto@kdevelop.org") ); aboutData.addCredit( i18n("The KWrite authors"), i18n( "Kate editor component" ), QStringLiteral("kwrite-devel@kde.org") ); aboutData.addCredit( i18n("Nokia Corporation/Qt Software"), i18n( "Designer code" ), QStringLiteral("qt-info@nokia.com") ); aboutData.addCredit( i18n("Contributors to older versions:"), QString(), QLatin1String("") ); aboutData.addCredit( i18n("Bernd Gehrmann"), i18n( "Initial idea, basic architecture, much initial source code" ), QStringLiteral("bernd@kdevelop.org") ); aboutData.addCredit( i18n("Caleb Tennis"), i18n( "KTabBar, bugfixes" ), QStringLiteral("caleb@aei-tech.com") ); aboutData.addCredit( i18n("Richard Dale"), i18n( "Java & Objective C support" ), QStringLiteral("Richard_Dale@tipitina.demon.co.uk") ); aboutData.addCredit( i18n("John Birch"), i18n( "Debugger frontend" ), QStringLiteral("jbb@kdevelop.org") ); aboutData.addCredit( i18n("Sandy Meier"), i18n( "PHP support, context menu stuff" ), QStringLiteral("smeier@kdevelop.org") ); aboutData.addCredit( i18n("Kurt Granroth"), i18n( "KDE application templates" ), QStringLiteral("kurth@granroth.org") ); aboutData.addCredit( i18n("Ian Reinhart Geiser"), i18n( "Dist part, bash support, application templates" ), QStringLiteral("geiseri@yahoo.com") ); aboutData.addCredit( i18n("Matthias Hoelzer-Kluepfel"), i18n( "Several components, htdig indexing" ), QStringLiteral("hoelzer@kde.org") ); aboutData.addCredit( i18n("Victor Roeder"), i18n( "Help with Automake manager and persistent class store" ), QStringLiteral("victor_roeder@gmx.de") ); aboutData.addCredit( i18n("Simon Hausmann"), i18n( "Help with KParts infrastructure" ), QStringLiteral("hausmann@kde.org") ); aboutData.addCredit( i18n("Oliver Kellogg"), i18n( "Ada support" ), QStringLiteral("okellogg@users.sourceforge.net") ); aboutData.addCredit( i18n("Jakob Simon-Gaarde"), i18n( "QMake projectmanager" ), QStringLiteral("jsgaarde@tdcspace.dk") ); aboutData.addCredit( i18n("Falk Brettschneider"), i18n( "MDI modes, QEditor, bugfixes" ), QStringLiteral("falkbr@kdevelop.org") ); aboutData.addCredit( i18n("Mario Scalas"), i18n( "PartExplorer, redesign of CvsPart, patches, bugs(fixes)" ), QStringLiteral("mario.scalas@libero.it") ); aboutData.addCredit( i18n("Jens Dagerbo"), i18n( "Replace, Bookmarks, FileList and CTags2 plugins. Overall improvements and patches" ), QStringLiteral("jens.dagerbo@swipnet.se") ); aboutData.addCredit( i18n("Julian Rockey"), i18n( "Filecreate part and other bits and patches" ), QStringLiteral("linux@jrockey.com") ); aboutData.addCredit( i18n("Ajay Guleria"), i18n( "ClearCase support" ), QStringLiteral("ajay_guleria@yahoo.com") ); aboutData.addCredit( i18n("Marek Janukowicz"), i18n( "Ruby support" ), QStringLiteral("child@t17.ds.pwr.wroc.pl") ); aboutData.addCredit( i18n("Robert Moniot"), i18n( "Fortran documentation" ), QStringLiteral("moniot@fordham.edu") ); aboutData.addCredit( i18n("Ka-Ping Yee"), i18n( "Python documentation utility" ), QStringLiteral("ping@lfw.org") ); aboutData.addCredit( i18n("Dimitri van Heesch"), i18n( "Doxygen wizard" ), QStringLiteral("dimitri@stack.nl") ); aboutData.addCredit( i18n("Hugo Varotto"), i18n( "Fileselector component" ), QStringLiteral("hugo@varotto-usa.com") ); aboutData.addCredit( i18n("Matt Newell"), i18n( "Fileselector component" ), QStringLiteral("newellm@proaxis.com") ); aboutData.addCredit( i18n("Daniel Engelschalt"), i18n( "C++ code completion, persistent class store" ), QStringLiteral("daniel.engelschalt@gmx.net") ); aboutData.addCredit( i18n("Stephane Ancelot"), i18n( "Patches" ), QStringLiteral("sancelot@free.fr") ); aboutData.addCredit( i18n("Jens Zurheide"), i18n( "Patches" ), QStringLiteral("jens.zurheide@gmx.de") ); aboutData.addCredit( i18n("Luc Willems"), i18n( "Help with Perl support" ), QStringLiteral("Willems.luc@pandora.be") ); aboutData.addCredit( i18n("Marcel Turino"), i18n( "Documentation index view" ), QStringLiteral("M.Turino@gmx.de") ); aboutData.addCredit( i18n("Yann Hodique"), i18n( "Patches" ), QStringLiteral("Yann.Hodique@lifl.fr") ); aboutData.addCredit( i18n("Tobias Gl\303\244\303\237er") , i18n( "Documentation Finder, qmake projectmanager patches, usability improvements, bugfixes ... " ), QStringLiteral("tobi.web@gmx.de") ); aboutData.addCredit( i18n("Andreas Koepfle") , i18n( "QMake project manager patches" ), QStringLiteral("koepfle@ti.uni-mannheim.de") ); aboutData.addCredit( i18n("Sascha Cunz") , i18n( "Cleanup and bugfixes for qEditor, AutoMake and much other stuff" ), QStringLiteral("mail@sacu.de") ); aboutData.addCredit( i18n("Zoran Karavla"), i18n( "Artwork for the ruby language" ), QStringLiteral("webmaster@the-error.net"), QStringLiteral("http://the-error.net") ); KAboutData::setApplicationData(aboutData); // set icon for shells which do not use desktop file metadata // but without setting replacing an existing icon with an empty one! QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("kdevelop"), QApplication::windowIcon())); KCrash::initialize(); Kdelibs4ConfigMigrator migrator(QStringLiteral("kdevelop")); migrator.setConfigFiles({QStringLiteral("kdeveloprc")}); migrator.setUiFiles({QStringLiteral("kdevelopui.rc")}); migrator.migrate(); // High DPI support app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); qCDebug(APP) << "Startup"; QCommandLineParser parser; parser.addVersionOption(); parser.addHelpOption(); aboutData.setupCommandLine(&parser); parser.addOption(QCommandLineOption{QStringList{"n", "new-session"}, i18n("Open KDevelop with a new session using the given name."), QStringLiteral("name")}); parser.addOption(QCommandLineOption{QStringList{"s", "open-session"}, i18n("Open KDevelop with the given session.\n" "You can pass either hash or the name of the session." ), QStringLiteral("session")}); parser.addOption(QCommandLineOption{QStringList{"rm", "remove-session"}, i18n("Delete the given session.\n" "You can pass either hash or the name of the session." ), QStringLiteral("session")}); parser.addOption(QCommandLineOption{QStringList{"ps", "pick-session"}, i18n("Shows all available sessions and lets you select one to open.")}); parser.addOption(QCommandLineOption{QStringList{"pss", "pick-session-shell"}, i18n("List all available sessions on shell and lets you select one to open.")}); parser.addOption(QCommandLineOption{QStringList{"l", "list-sessions"}, i18n("List available sessions and quit.")}); parser.addOption(QCommandLineOption{QStringList{"f", "fetch"}, i18n("Open KDevelop and fetch the project from the given ."), QStringLiteral("repo url")}); parser.addOption(QCommandLineOption{QStringList{"p", "project"}, i18n("Open KDevelop and load the given project. can be either a .kdev4 file or a directory path."), QStringLiteral("project")}); parser.addOption(QCommandLineOption{QStringList{"d", "debug"}, i18n("Start debugging an application in KDevelop with the given debugger.\n" "The executable that should be debugged must follow - including arguments.\n" "Example: kdevelop --debug gdb myapp --foo bar"), QStringLiteral("debugger")}); // this is used by the 'kdevelop!' script to retrieve the pid of a KDEVELOP // instance. When this is called, then we should just print the PID on the // standard-output. If a session is specified through open-session, then // we should return the PID of that session. Otherwise, if only a single // session is running, then we should just return the PID of that session. // Otherwise, we should print a command-line session-chooser dialog ("--pss"), // which only shows the running sessions, and the user can pick one. parser.addOption(QCommandLineOption{QStringList{"pid"}}); parser.addPositionalArgument(QStringLiteral("files"), i18n( "Files to load, or directories to load as projects" ), QStringLiteral("[FILE[:line[:column]] | DIRECTORY]...")); // The session-controller needs to arguments to eventually pass them to newly opened sessions KDevelop::SessionController::setArguments(argc, argv); parser.process(app); aboutData.processCommandLine(&parser); if(parser.isSet(QStringLiteral("list-sessions"))) { QTextStream qout(stdout); qout << endl << ki18n("Available sessions (use '-s HASH' or '-s NAME' to open a specific one):").toString() << endl << endl; qout << QStringLiteral("%1").arg(ki18n("Hash").toString(), -38) << '\t' << ki18n("Name: Opened Projects").toString() << endl; foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos()) { if ( si.name.isEmpty() && si.projects.isEmpty() ) { continue; } qout << si.uuid.toString() << '\t' << si.description; if(KDevelop::SessionController::isSessionRunning(si.uuid.toString())) qout << " " << i18n("[running]"); qout << endl; } return 0; } // Handle extra arguments, which stand for files to open QVector initialFiles; QVector initialDirectories; foreach (const QString &file, parser.positionalArguments()) { const UrlInfo info(file); if (info.isDirectory()) { initialDirectories.append(info); } else { initialFiles.append(info); } } const auto availableSessionInfos = KDevelop::SessionController::availableSessionInfos(); if ((!initialFiles.isEmpty() || !initialDirectories.isEmpty()) && !parser.isSet(QStringLiteral("new-session"))) { #if KDEVELOP_SINGLE_APP if (app.isRunning()) { bool success = app.sendMessage(serializeOpenFilesMessage(initialFiles << initialDirectories)); if (success) { return 0; } } #else qint64 pid = -1; if (parser.isSet(QStringLiteral("open-session"))) { const QString session = findSessionId(availableSessionInfos, parser.value(QStringLiteral("open-session"))); if (session.isEmpty()) { return 1; } else if (KDevelop::SessionController::isSessionRunning(session)) { pid = findSessionPid(session); } } else { pid = getRunningSessionPid(); } if ( pid > 0 ) { return openFilesInRunningInstance(initialFiles, pid) + openProjectInRunningInstance(initialDirectories, pid); } // else there are no running sessions, and the generated list of files will be opened below. #endif } // if empty, restart kdevelop with last active session, see SessionController::defaultSessionId QString session; uint nRunningSessions = 0; foreach(const KDevelop::SessionInfo& si, availableSessionInfos) if(KDevelop::SessionController::isSessionRunning(si.uuid.toString())) ++nRunningSessions; // also show the picker dialog when a pid shall be retrieved and multiple // sessions are running. if(parser.isSet(QStringLiteral("pss")) || (parser.isSet(QStringLiteral("pid")) && !parser.isSet(QStringLiteral("open-session")) && !parser.isSet(QStringLiteral("ps")) && nRunningSessions > 1)) { QTextStream qerr(stderr); SessionInfos candidates; foreach(const KDevelop::SessionInfo& si, availableSessionInfos) if( (!si.name.isEmpty() || !si.projects.isEmpty() || parser.isSet(QStringLiteral("pid"))) && (!parser.isSet(QStringLiteral("pid")) || KDevelop::SessionController::isSessionRunning(si.uuid.toString()))) candidates << si; if(candidates.size() == 0) { qerr << "no session available" << endl; return 1; } if(candidates.size() == 1 && parser.isSet(QStringLiteral("pid"))) { session = candidates[0].uuid.toString(); }else{ for(int i = 0; i < candidates.size(); ++i) qerr << "[" << i << "]: " << candidates[i].description << endl; int chosen; std::cin >> chosen; if(std::cin.good() && (chosen >= 0 && chosen < candidates.size())) { session = candidates[chosen].uuid.toString(); }else{ qerr << "invalid selection" << endl; return 1; } } } if(parser.isSet(QStringLiteral("ps"))) { bool onlyRunning = parser.isSet(QStringLiteral("pid")); session = KDevelop::SessionController::showSessionChooserDialog(i18n("Select the session you would like to use"), onlyRunning); if(session.isEmpty()) return 1; } if ( parser.isSet(QStringLiteral("debug")) ) { if ( debugArgs.isEmpty() ) { QTextStream qerr(stderr); qerr << endl << i18nc("@info:shell", "Specify the executable you want to debug.") << endl; return 1; } QFileInfo executableFileInfo(debugArgs.first()); if (!executableFileInfo.exists()) { executableFileInfo = QStandardPaths::findExecutable(debugArgs.first()); if (!executableFileInfo.exists()) { QTextStream qerr(stderr); qerr << endl << i18nc("@info:shell", "Specified executable does not exist.") << endl; return 1; } } debugArgs.first() = executableFileInfo.absoluteFilePath(); debugeeName = i18n("Debug %1", executableFileInfo.fileName()); session = debugeeName; } else if ( parser.isSet(QStringLiteral("new-session")) ) { session = parser.value(QStringLiteral("new-session")); foreach(const KDevelop::SessionInfo& si, availableSessionInfos) { if ( session == si.name ) { QTextStream qerr(stderr); qerr << endl << i18n("A session with the name %1 exists already. Use the -s switch to open it.", session) << endl; return 1; } } // session doesn't exist, we can create it } else if ( parser.isSet(QStringLiteral("open-session")) ) { session = findSessionId(availableSessionInfos, parser.value(QStringLiteral("open-session"))); if (session.isEmpty()) { return 1; } } else if ( parser.isSet(QStringLiteral("remove-session")) ) { session = parser.value(QStringLiteral("remove-session")); auto si = findSessionInList(availableSessionInfos, session); if (!si) { QTextStream qerr(stderr); qerr << endl << i18n("No session with the name %1 exists.", session) << endl; return 1; } auto sessionLock = KDevelop::SessionController::tryLockSession(si->uuid.toString()); if (!sessionLock.lock) { QTextStream qerr(stderr); qerr << endl << i18n("Could not lock session %1 for deletion.", session) << endl; return 1; } KDevelop::SessionController::deleteSessionFromDisk(sessionLock.lock); QTextStream qout(stdout); qout << endl << i18n("Session with name %1 was successfully removed.", session) << endl; return 0; } if(parser.isSet(QStringLiteral("pid"))) { if (session.isEmpty()) { // just pick the first running session foreach(const KDevelop::SessionInfo& si, availableSessionInfos) if(KDevelop::SessionController::isSessionRunning(si.uuid.toString())) session = si.uuid.toString(); } const KDevelop::SessionInfo* sessionData = findSessionInList(availableSessionInfos, session); if( !sessionData ) { - qCritical() << "session not given or does not exist"; + qCritical(APP) << "session not given or does not exist"; return 5; } const auto pid = findSessionPid(sessionData->uuid.toString()); if (pid > 0) { // Print the PID and we're ready std::cout << pid << std::endl; return 0; } else { - qCritical() << sessionData->uuid.toString() << sessionData->name << "is not running"; + qCritical(APP) << sessionData->uuid.toString() << sessionData->name << "is not running"; return 5; } } if (parser.isSet("project")) { const auto project = parser.value(QStringLiteral("project")); QFileInfo info(project); QUrl projectUrl; if (info.suffix() == QLatin1String("kdev4")) { projectUrl = QUrl::fromLocalFile(info.absoluteFilePath()); } else if (info.isDir()) { QDir dir(info.absoluteFilePath()); const auto potentialProjectFiles = dir.entryList({QStringLiteral("*.kdev4")}, QDir::Files, QDir::Name); qDebug(APP) << "Found these potential project files:" << potentialProjectFiles; if (!potentialProjectFiles.isEmpty()) { projectUrl = QUrl::fromLocalFile(dir.absoluteFilePath(potentialProjectFiles.value(0))); } } else { QTextStream qerr(stderr); qerr << "Invalid project: " << project << " - should be either a path to a .kdev4 file or a directory containing a .kdev4 file"; return 1; } qDebug(APP) << "Attempting to find a suitable session for project" << projectUrl; const auto sessionInfos = findSessionsWithProject(availableSessionInfos, projectUrl); qDebug(APP) << "Found matching sessions:" << sessionInfos.size(); if (!sessionInfos.isEmpty()) { // TODO: If there's more than one match: Allow the user to select which session to open? qDebug(APP) << "Attempting to open session:" << sessionInfos.at(0).name; session = sessionInfos.at(0).uuid.toString(); } } KDevIDEExtension::init(); qDebug(APP) << "Attempting to initialize session:" << session; if(!Core::initialize(Core::Default, session)) return 5; // register a DBUS service for this process, so that we can open files in it from other invocations QDBusConnection::sessionBus().registerService(QStringLiteral("org.kdevelop.kdevelop-%1").arg(app.applicationPid())); Core* core = Core::self(); if (!QProcessEnvironment::systemEnvironment().contains(QStringLiteral("KDEV_DISABLE_WELCOMEPAGE"))) { core->pluginController()->loadPlugin(QStringLiteral("KDevWelcomePage")); } const auto fetchUrlStrings = parser.values(QStringLiteral("fetch")); for (const auto& fetchUrlString : fetchUrlStrings) { core->projectControllerInternal()->fetchProjectFromUrl(QUrl::fromUserInput(fetchUrlString)); } const QString debugStr = QStringLiteral("debug"); if ( parser.isSet(debugStr) ) { Q_ASSERT( !debugeeName.isEmpty() ); QString launchName = debugeeName; KDevelop::LaunchConfiguration* launch = nullptr; qCDebug(APP) << launchName; foreach (KDevelop::LaunchConfiguration *l, core->runControllerInternal()->launchConfigurationsInternal()) { qCDebug(APP) << l->name(); if (l->name() == launchName) { launch = l; } } KDevelop::LaunchConfigurationType *type = nullptr; foreach (KDevelop::LaunchConfigurationType *t, core->runController()->launchConfigurationTypes()) { qCDebug(APP) << t->id(); if (t->id() == QLatin1String("Native Application")) { type = t; break; } } if (!type) { QTextStream qerr(stderr); qerr << endl << i18n("Cannot find native launch configuration type") << endl; return 1; } if (launch && launch->type()->id() != QLatin1String("Native Application")) launch = nullptr; if (launch && launch->launcherForMode(debugStr) != parser.value(debugStr)) launch = nullptr; if (!launch) { qCDebug(APP) << launchName << "not found, creating a new one"; QPair launcher; launcher.first = debugStr; foreach (KDevelop::ILauncher *l, type->launchers()) { if (l->id() == parser.value(debugStr)) { if (l->supportedModes().contains(debugStr)) { launcher.second = l->id(); } } } if (launcher.second.isEmpty()) { QTextStream qerr(stderr); qerr << endl << i18n("Cannot find launcher %1", parser.value(debugStr)) << endl; return 1; } KDevelop::ILaunchConfiguration* ilaunch = core->runController()->createLaunchConfiguration(type, launcher, nullptr, launchName); launch = static_cast(ilaunch); } type->configureLaunchFromCmdLineArguments(launch->config(), debugArgs); launch->config().writeEntry("Break on Start", true); core->runControllerInternal()->setDefaultLaunch(launch); core->runControllerInternal()->execute(debugStr, launch); } else { openFiles(initialFiles); for(const auto &urlinfo: initialDirectories) core->projectController()->openProjectForUrl(urlinfo.url); } #if KDEVELOP_SINGLE_APP // Set up remote arguments. QObject::connect(&app, &SharedTools::QtSingleApplication::messageReceived, &app, &KDevelopApplication::remoteArguments); QObject::connect(&app, &SharedTools::QtSingleApplication::fileOpenRequest, &app, &KDevelopApplication::fileOpenRequested); #endif qCDebug(APP) << "Done startup" << "- took:" << timer.elapsed() << "ms"; timer.invalidate(); return app.exec(); } diff --git a/appimage/Dockerfile b/appimage/Dockerfile index 2beedbbef2..1fe8c9fd3e 100644 --- a/appimage/Dockerfile +++ b/appimage/Dockerfile @@ -1,21 +1,34 @@ FROM centos:6.8 RUN yum -y update && yum -y install wget && yum -y install centos-release-scl epel-release && yum -y update && yum -y install devtoolset-4-gcc devtoolset-4-gcc-c++ devtoolset-4-binutils wget tar bzip2 git libtool which fuse fuse-devel libpng-devel automake cppunit-devel cmake glibc-headers libstdc++-devel gcc-c++ freetype-devel fontconfig-devel libxml2-devel libstdc++-devel libXrender-devel patch xcb-util-keysyms-devel libXi-devel libudev-devel.x86_64 openssl-devel sqlite-devel.x86_64 gperftools.x86_64 gperf.x86_64 libicu-devel.x86_64 boost-devel.x86_64 libxslt-devel.x86_64 docbook-style-xsl.noarch python27.x86_64 cmake3.x86_64 ruby bison flex bison-devel ruby-devel flex-devel xz pcre-devel pcre2-devel pcre pcre2 mesa-libEGL-devel mesa-libGL-devel glib-devel gettext perl-URI.noarch bzip2-devel.x86_64 subversion-devel.x86_64 subversion.x86_64 sqlite2-devel.x86_64 hunspell-devel aspell-devel hspell-devel vim sudo unzip RUN cd /tmp && wget http://opensource.wandisco.com/rhel/6/svn-1.9/RPMS/x86_64/subversion-1.9.4-3.x86_64.rpm http://opensource.wandisco.com/rhel/6/svn-1.9/RPMS/x86_64/subversion-devel-1.9.4-3.x86_64.rpm http://opensource.wandisco.com/rhel/6/svn-1.9/RPMS/x86_64/serf-1.3.7-1.x86_64.rpm && yum -y install subversion* serf*; rm subversion* serf* RUN echo ". /opt/rh/devtoolset-4/enable && chmod +x /opt/rh/python27/enable && . /opt/rh/python27/enable" >> /root/.bashrc -ENV LC_ALL=en_US.UTF-8 LANG=en_us.UTF-8 QTVERSION=5.7.1 QVERSION_SHORT=5.7 LLVM_ROOT=/opt/llvm/ QTV=5.7.1 LD_LIBRARY_PATH=$QTDIR/lib/ +ENV LC_ALL=en_US.UTF-8 LANG=en_us.UTF-8 QTVERSION=5.9.1 QVERSION_SHORT=5.9 LLVM_VERSION=5.0.0 LLVM_ROOT=/opt/llvm/ LD_LIBRARY_PATH=$QTDIR/lib/ ENV QTDIR=/usr/local/Qt-${QTVERSION}/ -RUN bash -c "mkdir -p /qt && cd /qt && wget http://download.qt.io/archive/qt/${QVERSION_SHORT}/${QTVERSION}/single/qt-everywhere-opensource-src-${QTVERSION}.tar.xz && tar xvf qt-everywhere-opensource-src-${QTVERSION}.tar.xz && ln -sf /opt/rh/devtoolset-4/root/usr/bin/g++ /usr/bin/g++ && ln -sf /opt/rh/devtoolset-4/root/usr/bin/c++ /usr/bin/c++ && cd /qt/qt-everywhere-opensource-src-$QTV && ./configure -v -skip qt3d -skip qtgamepad -platform linux-g++ -qt-pcre -qt-xcb -qt-xkbcommon -xkb-config-root /usr/share/X11/xkb -no-pch -qt-sql-sqlite -qt-sql-sqlite2 -nomake tests -nomake examples -confirm-license -opensource && make -j$(nproc) || make -j 1 install; make -j$(nproc) install && rm -Rf /qt" +RUN bash -c "ln -sf /opt/rh/devtoolset-4/root/usr/bin/g++ /usr/bin/g++ && ln -sf /opt/rh/devtoolset-4/root/usr/bin/c++ /usr/bin/c++" -RUN bash -c "ln -sf /usr/local/Qt-$QTV/bin/qmake /usr/bin/qmake-qt5 && mkdir -p /qtwk && cd /qtwk && wget http://download.qt.io/community_releases/${QVERSION_SHORT}/${QTV}/qtwebkit-opensource-src-${QTV}.tar.xz && tar xvf qtwebkit-opensource-src-${QTV}.tar.xz && cd /qtwk/qtwebkit-opensource-src-${QTV} && $QTDIR/bin/qmake && make -j$(nproc) || make -j$(nproc) && make -j$(nproc) install && rm -Rf /qtwk" +# Build Qt5 +RUN bash -c "mkdir -p /qt && cd /qt && wget http://download.qt.io/archive/qt/${QVERSION_SHORT}/${QTVERSION}/single/qt-everywhere-opensource-src-${QTVERSION}.tar.xz && tar xvf qt-everywhere-opensource-src-${QTVERSION}.tar.xz" +RUN bash -c "export MAKEFLAGS=-j$(nproc) && cd /qt/qt-everywhere-opensource-src-${QTVERSION} && ./configure -v -skip qt3d -skip qtgamepad -platform linux-g++ -qt-pcre -qt-xcb -qt-xkbcommon -xkb-config-root /usr/share/X11/xkb -no-pch -nomake tests -nomake examples -confirm-license -opensource && make -j$(nproc) || make -j 1 install; make -j$(nproc) install && rm -Rf /qt" -RUN bash -c "mkdir -p /llvm && cd /llvm && wget http://llvm.org/releases/3.9.1/llvm-3.9.1.src.tar.xz && tar xvf llvm-3.9.1.src.tar.xz && cd llvm-3.9.1.src && cd tools && wget http://llvm.org/releases/3.9.1/cfe-3.9.1.src.tar.xz && tar xvf cfe-3.9.1.src.tar.xz && . /opt/rh/python27/enable && . /opt/rh/devtoolset-4/enable && python --version && cd /llvm/llvm-3.9.1.src && mkdir -p build && cd build && cmake3 .. -DCMAKE_INSTALL_PREFIX=/opt/llvm/ -DCMAKE_BUILD_TYPE=Release && make -j$(nproc) install && rm -Rf /llvm" +RUN ln -sf /usr/local/Qt-${QTVERSION}/bin/qmake /usr/bin/qmake-qt5 -RUN bash -c "mkdir -p /python && cd /python && wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz && tar xvf Python-3.6.0.tar.xz && cd /python/Python-3.6.0 && mkdir -p /usr/lib/pkgconfig && ./configure --prefix=/usr --enable-shared && make -j$(nproc) install && rm -Rf /python" +# Build qtwebkit +RUN bash -c "mkdir -p /qtwk && cd /qtwk && wget http://download.qt.io/archive/qt/${QVERSION_SHORT}/${QTVERSION}/submodules/qtwebkit-opensource-src-${QTVERSION}.tar.xz && tar xvf qtwebkit-opensource-src-${QTVERSION}.tar.xz" +RUN bash -c "cd /qtwk/qtwebkit-opensource-src-${QTVERSION} && $QTDIR/bin/qmake && make -j$(nproc) || make -j$(nproc) && make -j$(nproc) install && rm -Rf /qtwk" +# Install ninja RUN bash -c "yum install unzip && mkdir -p /tmp/deploy && cd /tmp/deploy && wget https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip && unzip ninja-linux.zip && mv -f ninja /usr/local/bin && cd .. && rm -Rf deploy" +# Build Clang/LLVM +RUN bash -c "mkdir -p /llvm && cd /llvm && wget http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz && tar xvf llvm-${LLVM_VERSION}.src.tar.xz && cd llvm-${LLVM_VERSION}.src && cd tools && wget http://llvm.org/releases/${LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.xz && tar xvf cfe-${LLVM_VERSION}.src.tar.xz" +RUN bash -c ". /opt/rh/python27/enable && . /opt/rh/devtoolset-4/enable && python --version && cd /llvm/llvm-${LLVM_VERSION}.src && mkdir -p build && cd build && cmake3 -G Ninja .. -DCMAKE_INSTALL_PREFIX=/opt/llvm/ -DCMAKE_BUILD_TYPE=Release && ninja install && rm -Rf /llvm" + +# Build Python +RUN bash -c "mkdir -p /python && cd /python && wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz && tar xvf Python-3.6.0.tar.xz && cd /python/Python-3.6.0 && mkdir -p /usr/lib/pkgconfig && ./configure --prefix=/usr --enable-shared && make -j$(nproc) install && rm -Rf /python" + + CMD /bin/bash diff --git a/appimage/kdevelop-recipe-centos6.sh b/appimage/kdevelop-recipe-centos6.sh index cd99681d32..50438951e3 100755 --- a/appimage/kdevelop-recipe-centos6.sh +++ b/appimage/kdevelop-recipe-centos6.sh @@ -1,513 +1,513 @@ #!/bin/bash # Halt on errors set -e # Be verbose set -x # Now we are inside CentOS 6 grep -r "CentOS release 6" /etc/redhat-release || exit 1 git_pull_rebase_helper() { git fetch git stash || true git rebase $(git rev-parse --abbrev-ref --symbolic-full-name @{u}) || true git stash pop || true } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -QTVERSION=5.7.1 -QVERSION_SHORT=5.7 +QTVERSION=5.9.1 +QVERSION_SHORT=5.9 QTDIR=/usr/local/Qt-${QTVERSION}/ if [ -z "$KDEVELOP_VERSION" ]; then KDEVELOP_VERSION=5.1 fi if [ -z "$KDEV_PG_QT_VERSION" ]; then KDEV_PG_QT_VERSION=2.0 fi KF5_VERSION=v5.37.0 KDE_PLASMA_VERSION=master # need libksysguard master (contains a0e69617442d720c76da5ebe3323e7a977929db4 -- patch which makes plasma dep optional) KDE_APPLICATION_VERSION=v16.12.3 GRANTLEE_VERSION=v5.1.0 export LLVM_ROOT=/opt/llvm/ export PATH=/opt/rh/python27/root/usr/bin/:$PATH export LD_LIBRARY_PATH=/opt/rh/python27/root/usr/lib64:$LD_LIBRARY_PATH # qjsonparser, used to add metadata to the plugins needs to work in a en_US.UTF-8 environment. That's # not always set correctly in CentOS 6.7 export LC_ALL=en_US.UTF-8 export LANG=en_us.UTF-8 # Determine which architecture should be built if [[ "$(arch)" = "i686" || "$(arch)" = "x86_64" ]] ; then ARCH=$(arch) else echo "Architecture could not be determined" exit 1 fi # Make sure we build from the /, parts of this script depends on that. We also need to run as root... cd / # Build AppImageKit #rm -Rf /AppImageKit if [ ! -d AppImageKit ] ; then git clone --depth 1 https://github.com/probonopd/AppImageKit.git /AppImageKit fi cd /AppImageKit/ git checkout stable/v1.0 git_pull_rebase_helper git reset --hard ./build.sh cd / # Use the new compiler . /opt/rh/devtoolset-4/enable # TODO: Use these vars more export FAKEROOT=/kdevelop.appdir export PREFIX=/kdevelop.appdir/usr/ export SRC=$HOME/src/ export BUILD=$HOME/build export CMAKE_PREFIX_PATH=$QTDIR:/kdevelop.appdir/share/llvm/ # if the library path doesn't point to our usr/lib, linking will be broken and we won't find all deps either export LD_LIBRARY_PATH=/usr/lib64/:/usr/lib:/kdevelop.appdir/usr/lib:$QTDIR/lib/:/opt/python3.6/lib/:$LD_LIBRARY_PATH # Workaround for: On CentOS 6, .pc files in /usr/lib/pkgconfig are not recognized # However, this is where .pc files get installed when bulding libraries... (FIXME) # I found this by comparing the output of librevenge's "make install" command # between Ubuntu and CentOS 6 ln -sf /usr/share/pkgconfig /usr/lib/pkgconfig # Prepare the install location if [ -z "$SKIP_PRUNE" ]; then rm -rf /kdevelop.appdir/ || true mkdir -p /kdevelop.appdir/usr # refresh ldconfig cache ldconfig # make sure lib and lib64 are the same thing mkdir -p /kdevelop.appdir/usr/lib cd /kdevelop.appdir/usr ln -s lib lib64 fi # start building the deps function build_project { ( PROJECT=$1 VERSION=$2 # clone if not there mkdir -p $SRC cd $SRC if ( test -d $PROJECT ) then echo "$PROJECT already cloned" cd $PROJECT git stash git reset --hard git fetch git fetch --tags cd .. else if [ -z "$CUSTOM_GIT_URL" ]; then git clone git://anongit.kde.org/$PROJECT else git clone $CUSTOM_GIT_URL fi fi cd $PROJECT git checkout $VERSION git rebase $(git rev-parse --abbrev-ref --symbolic-full-name @{u}) || true # git rebase will fail if a tag is checked out git stash pop || true cd .. if [ "$PROJECT" = "knotifications" ]; then cd $PROJECT echo "patching knotifications" git reset --hard cat > no_phonon.patch << EOF diff --git a/CMakeLists.txt b/CMakeLists.txt index b97425f..8f15f08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,10 +59,10 @@ find_package(KF5Config ${KF5_DEP_VERSION} REQUIRED) find_package(KF5Codecs ${KF5_DEP_VERSION} REQUIRED) find_package(KF5CoreAddons ${KF5_DEP_VERSION} REQUIRED) -find_package(Phonon4Qt5 4.6.60 REQUIRED NO_MODULE) +find_package(Phonon4Qt5 4.6.60 NO_MODULE) set_package_properties(Phonon4Qt5 PROPERTIES DESCRIPTION "Qt-based audio library" - TYPE REQUIRED + TYPE OPTIONAL PURPOSE "Required to build audio notification support") if (Phonon4Qt5_FOUND) add_definitions(-DHAVE_PHONON4QT5) EOF cat no_phonon.patch |patch -p1 cd .. fi # create build dir mkdir -p $BUILD/$PROJECT # go there cd $BUILD/$PROJECT # cmake it cmake3 $SRC/$PROJECT -G Ninja -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX $3 # make ninja # install ninja install ) } function build_framework { ( build_project $1 $KF5_VERSION $2 ) } # KDE Frameworks if [ -z "$SKIP_FRAMEWORKS" ]; then build_framework extra-cmake-modules build_framework kconfig build_framework kguiaddons build_framework ki18n build_framework kitemviews build_framework sonnet build_framework kwindowsystem build_framework kwidgetsaddons build_framework kcompletion build_framework kdbusaddons build_framework karchive build_framework kcoreaddons build_framework kjobwidgets build_framework kcrash build_framework kservice build_framework kcodecs build_framework kauth build_framework kconfigwidgets build_framework kiconthemes build_framework ktextwidgets build_framework kglobalaccel build_framework kxmlgui build_framework kbookmarks build_framework solid build_framework kio build_framework kparts build_framework kitemmodels build_framework threadweaver build_framework attica build_framework knewstuff build_framework syntax-highlighting build_framework ktexteditor build_framework kpackage build_framework kdeclarative build_framework kcmutils build_framework knotifications build_framework knotifyconfig build_framework kdoctools build_framework breeze-icons -DBINARY_ICONS_RESOURCE=1 build_framework kpty build_framework kinit fi # KDE Plasma build_project libksysguard $KDE_PLASMA_VERSION build_project kdecoration $KDE_PLASMA_VERSION # for breeze build_project breeze $KDE_PLASMA_VERSION # KDE Applications build_project libkomparediff2 $KDE_APPLICATION_VERSION build_project kate $KDE_APPLICATION_VERSION # for snippet plugin, see T3826 build_project konsole $KDE_APPLICATION_VERSION # Extra (CUSTOM_GIT_URL=https://github.com/steveire/grantlee.git build_project grantlee $GRANTLEE_VERSION) # KDevelop build_project kdevelop-pg-qt $KDEV_PG_QT_VERSION build_project kdevplatform $KDEVELOP_VERSION build_project kdevelop $KDEVELOP_VERSION build_project kdev-php $KDEVELOP_VERSION # Build kdev-python export LD_LIBRARY_PATH=$LD_LIBRARY_PATH/kdevelop.appdir/usr/lib/ build_project kdev-python $KDEVELOP_VERSION # Install some colorschemes cd $SRC $SCRIPT_DIR/install_colorschemes.sh cd /kdevelop.appdir # FIXME: How to find out which subset of plugins is really needed? I used strace when running the binary mkdir -p ./usr/lib/qt5/plugins/ if [ -e $(dirname $QTDIR/plugins/bearer) ] ; then PLUGINS=$(dirname $QTDIR/plugins/bearer) else PLUGINS=../../$QTVERSION_SHORT/gc*/plugins/ fi echo $PLUGINS # /usr/lib64/qt5/plugins if build system Qt is found cp -r $PLUGINS/bearer ./usr/lib/qt5/plugins/ cp -r $PLUGINS/generic ./usr/lib/qt5/plugins/ cp -r $PLUGINS/imageformats ./usr/lib/qt5/plugins/ cp -r $PLUGINS/platforms ./usr/lib/qt5/plugins/ cp -r $PLUGINS/iconengines ./usr/lib/qt5/plugins/ cp -r $PLUGINS/platforminputcontexts ./usr/lib/qt5/plugins/ # cp -r $PLUGINS/platformthemes ./usr/lib/qt5/plugins/ cp -r $PLUGINS/xcbglintegrations ./usr/lib/qt5/plugins/ cp -R /kdevelop.appdir/usr/lib/grantlee/ /kdevelop.appdir/usr/lib/qt5/plugins/ rm -Rf /kdevelop.appdir/usr/lib/grantlee cp -ru /usr/share/mime/* /kdevelop.appdir/usr/share/mime update-mime-database /kdevelop.appdir/usr/share/mime/ cp -R ./usr/lib/plugins/* ./usr/lib/qt5/plugins/ rm -Rf ./usr/lib/plugins/ cp $(ldconfig -p | grep libsasl2.so.2 | cut -d ">" -f 2 | xargs) ./usr/lib/ # Fedora 23 seemed to be missing SOMETHING from the Centos 6.7. The only message was: # This application failed to start because it could not find or load the Qt platform plugin "xcb". # Setting export QT_DEBUG_PLUGINS=1 revealed the cause. # QLibraryPrivate::loadPlugin failed on "/usr/lib64/qt5/plugins/platforms/libqxcb.so" : # "Cannot load library /usr/lib64/qt5/plugins/platforms/libqxcb.so: (/lib64/libEGL.so.1: undefined symbol: drmGetNodeTypeFromFd)" # Which means that we have to copy libEGL.so.1 in too cp $(ldconfig -p | grep libEGL.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # Otherwise F23 cannot load the Qt platform plugin "xcb" cp $(ldconfig -p | grep libxcb.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ cp $(ldconfig -p | grep libfreetype.so.6 | cut -d ">" -f 2 | xargs) ./usr/lib/ # For Fedora 20 ldd usr/bin/kdevelop | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true cp /usr/bin/cmake usr/bin/cmake ldd usr/bin/cmake | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true #ldd usr/lib64/kdevelop/*.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true #ldd usr/lib64/plugins/imageformats/*.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true ldd usr/lib/qt5/plugins/platforms/libqxcb.so | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' ./usr/lib || true # Copy in the indirect dependencies FILES=$(find . -type f -executable) for FILE in $FILES ; do echo "*** Processing:" $FILE ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -vu '{}' usr/lib || true done # The following are assumed to be part of the base system rm -f usr/lib/libcom_err.so.2 || true rm -f usr/lib/libcrypt.so.1 || true rm -f usr/lib/libdl.so.2 || true rm -f usr/lib/libexpat.so.1 || true #rm -f usr/lib/libfontconfig.so.1 || true rm -f usr/lib/libgcc_s.so.1 || true rm -f usr/lib/libglib-2.0.so.0 || true rm -f usr/lib/libgpg-error.so.0 || true rm -f usr/lib/libgssapi_krb5.so.2 || true rm -f usr/lib/libgssapi.so.3 || true rm -f usr/lib/libhcrypto.so.4 || true rm -f usr/lib/libheimbase.so.1 || true rm -f usr/lib/libheimntlm.so.0 || true rm -f usr/lib/libhx509.so.5 || true rm -f usr/lib/libICE.so.6 || true rm -f usr/lib/libidn.so.11 || true rm -f usr/lib/libk5crypto.so.3 || true rm -f usr/lib/libkeyutils.so.1 || true rm -f usr/lib/libkrb5.so.26 || true rm -f usr/lib/libkrb5.so.3 || true rm -f usr/lib/libkrb5support.so.0 || true # rm -f usr/lib/liblber-2.4.so.2 || true # needed for debian wheezy # rm -f usr/lib/libldap_r-2.4.so.2 || true # needed for debian wheezy rm -f usr/lib/libm.so.6 || true rm -f usr/lib/libp11-kit.so.0 || true rm -f usr/lib/libpcre.so.3 || true rm -f usr/lib/libpthread.so.0 || true rm -f usr/lib/libresolv.so.2 || true rm -f usr/lib/libroken.so.18 || true rm -f usr/lib/librt.so.1 || true rm -f usr/lib/libSM.so.6 || true rm -f usr/lib/libusb-1.0.so.0 || true rm -f usr/lib/libuuid.so.1 || true rm -f usr/lib/libwind.so.0 || true # Remove these libraries, we need to use the system versions; this means 11.04 is not supported (12.04 is our baseline) rm -f usr/lib/libGL.so.* || true rm -f usr/lib/libdrm.so.* || true #rm -f usr/lib/libz.so.1 || true # These seem to be available on most systems but not Ubuntu 11.04 # rm -f usr/lib/libffi.so.6 usr/lib/libGL.so.1 usr/lib/libglapi.so.0 usr/lib/libxcb.so.1 usr/lib/libxcb-glx.so.0 || true # Delete potentially dangerous libraries rm -f usr/lib/libstdc* usr/lib/libgobject* usr/lib/libc.so.* || true # Do NOT delete libX* because otherwise on Ubuntu 11.04: # loaded library "Xcursor" malloc.c:3096: sYSMALLOc: Assertion (...) Aborted # We don't bundle the developer stuff rm -rf usr/include || true rm -rf usr/lib/cmake || true rm -rf usr/lib/pkgconfig || true rm -rf usr/share/ECM/ || true rm -rf usr/share/gettext || true rm -rf usr/share/pkgconfig || true strip -g $(find usr) || true # We do not bundle this, so let's not search that inside the AppImage. # Fixes "Qt: Failed to create XKB context!" and lets us enter text #sed -i -e 's|././/share/X11/|/usr/share/X11/|g' ./usr/lib/qt5/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.so #sed -i -e 's|././/share/X11/|/usr/share/X11/|g' ./usr/lib/libQt5XcbQpa.so.5 # Workaround for: # D-Bus library appears to be incorrectly set up; # failed to read machine uuid: Failed to open # The file is more commonly in /etc/machine-id # sed -i -e 's|/var/lib/dbus/machine-id|//././././etc/machine-id|g' ./usr/lib/libdbus-1.so.3 # or rm -f ./usr/lib/libdbus-1.so.3 || true # Remove python rm -f ./usr/bin/python* rm -f ./usr/bin/pydoc* rm -f ./usr/bin/pyenv* # remove big execs rm -f ./usr/bin/verify-uselistorder rm -f ./usr/bin/obj2yaml ./usr/bin/yaml2obj rm -f ./usr/bin/kwrite ./usr/bin/kate cp /kdevelop.appdir/usr/lib/libexec/kf5/* /kdevelop.appdir/usr/bin/ cd / if [ ! -d appimage-exec-wrapper ]; then git clone git://anongit.kde.org/scratch/brauch/appimage-exec-wrapper fi; cd /appimage-exec-wrapper/ make clean make cd /kdevelop.appdir cp -v /appimage-exec-wrapper/exec.so exec_wrapper.so cat > AppRun << EOF #!/bin/bash DIR="\`dirname \"\$0\"\`" DIR="\`( cd \"\$DIR\" && pwd )\`" export APPDIR=\$DIR export LD_PRELOAD=\$DIR/exec_wrapper.so export APPIMAGE_ORIGINAL_QML2_IMPORT_PATH=\$QML2_IMPORT_PATH export APPIMAGE_ORIGINAL_LD_LIBRARY_PATH=\$LD_LIBRARY_PATH export APPIMAGE_ORIGINAL_QT_PLUGIN_PATH=\$QT_PLUGIN_PATH export APPIMAGE_ORIGINAL_XDG_DATA_DIRS=\$XDG_DATA_DIRS export APPIMAGE_ORIGINAL_PATH=\$PATH export APPIMAGE_ORIGINAL_PYTHONHOME=\$PYTHONHOME export QML2_IMPORT_PATH=\$DIR/usr/lib/qml:\$QML2_IMPORT_PATH export LD_LIBRARY_PATH=\$DIR/usr/lib/:\$LD_LIBRARY_PATH export QT_PLUGIN_PATH=\$DIR/usr/lib/qt5/plugins/ export XDG_DATA_DIRS=\$DIR/usr/share/:\$XDG_DATA_DIRS export PATH=\$DIR/usr/bin:\$PATH export KDE_FORK_SLAVES=1 export PYTHONHOME=\$DIR/usr/ export APPIMAGE_STARTUP_QML2_IMPORT_PATH=\$QML2_IMPORT_PATH export APPIMAGE_STARTUP_LD_LIBRARY_PATH=\$LD_LIBRARY_PATH export APPIMAGE_STARTUP_QT_PLUGIN_PATH=\$QT_PLUGIN_PATH export APPIMAGE_STARTUP_XDG_DATA_DIRS=\$XDG_DATA_DIRS export APPIMAGE_STARTUP_PATH=\$PATH export APPIMAGE_STARTUP_PYTHONHOME=\$PYTHONHOME export KDEV_DISABLE_PLUGINS=KDevWelcomePage cd \$HOME kdevelop \$@ EOF chmod +x AppRun cat > kdevelop.desktop << EOF [Desktop Entry] GenericName=Integrated development environment Name=KDevelop MimeType=text/plain; Exec=AppRun -b %U StartupNotify=true X-KDE-HasTempFileOption=true Icon=kdevelop X-DocPath=kdevelop/index.html Type=Application Terminal=false InitialPreference=9 Categories=Qt;KDE;Utility;TextEditor; EOF cp $SRC/kdevelop/app/icons/48-apps-kdevelop.png kdevelop.png cp -R /usr/lib/python3.6 /kdevelop.appdir/usr/lib/ rm -Rf /kdevelop.appdir/usr/lib/python3.6/{test,config-3.5m,__pycache__,site-packages,lib-dynload,distutils,idlelib,unittest,tkinter,ensurepip} mkdir -p /kdevelop.appdir/usr/share/kdevelop/ cp $BUILD/breeze-icons/icons/breeze-icons.rcc /kdevelop.appdir/usr/share/kdevelop/icontheme.rcc rm -Rf /kdevelop.appdir/usr/share/icons/breeze* # not needed because of the rcc rm -f /kdevelop.appdir/usr/bin/llvm* rm -f /kdevelop.appdir/usr/bin/clang* rm -f /kdevelop.appdir/usr/bin/opt rm -f /kdevelop.appdir/usr/bin/lli rm -f /kdevelop.appdir/usr/bin/sancov rm -f /kdevelop.appdir/usr/bin/cmake rm -f /kdevelop.appdir/usr/bin/python rm -Rf /kdevelop.appdir/usr/lib/pkgconfig rm -Rf /kdevelop.appdir/usr/share/man rm -Rf /kdevelop.appdir/usr/share/locale rm -Rf /kdevelop.appdir/usr/lib/libLTO.so #At first it seems like "we shouldn't ship X11", but actually we should; the X11 protocol is sort of guaranteed to stay compatible, #while these libraries are not. # rm -Rf /kdevelop.appdir/usr/lib/libxcb* # add that back in # cp /usr/lib64/libxcb-keysyms.so.1 /kdevelop.appdir/usr/lib/ # rm -Rf /kdevelop.appdir/usr/lib/{libX11.so.6,libXau.so.6,libXext.so.6,libXi.so.6,libXxf86vm.so.1,libX11-xcb.so.1,libXdamage.so.1,libXfixes.so.3,libXrender.so.1} rm -f /kdevelop.appdir/usr/bin/llc rm -f /kdevelop.appdir/usr/bin/bugpoint find /kdevelop.appdir -name '*.a' -exec rm {} \; cd / APP=KDevelop VERSION="git" if [[ "$ARCH" = "x86_64" ]] ; then APPIMAGE=$APP"-"$VERSION"-x86_64.AppImage" fi if [[ "$ARCH" = "i686" ]] ; then APPIMAGE=$APP"-"$VERSION"-i386.AppImage" fi echo $APPIMAGE mkdir -p /out rm -f /out/*.AppImage || true AppImageKit/AppImageAssistant.AppDir/package /kdevelop.appdir/ /out/$APPIMAGE chmod a+rwx /out/$APPIMAGE # So that we can edit the AppImage outside of the Docker container