Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use CMake to build plugin + fetch dependencies automatically #34

Merged
merged 11 commits into from
Nov 16, 2022

Conversation

gikari
Copy link
Collaborator

@gikari gikari commented Nov 5, 2022

Summary

This change ports the QMake build to CMake - a recommended way to build plugins according to the Qt Documentation:
https://doc.qt.io/qtcreator-extending/first-plugin.html#cmake-project

This also adds a number of useful features, for example, an ability to fetch neovim-qt and qtcreator automatically.

Neovim-qt is downloaded and built with the Message Pack using FetchContent CMake feature. In case of QtCreator only the precompiled binaries are downloaded to save time.

Test Plan

  1. Ensure Neovim is installed and in the PATH
  2. Open the CMake project in QtCreator (any version).
  3. Once successfully configured, set in run configuration the following:
    • Executable: %{buildDir}\_deps\qtcreator-src\bin\qtcreator.exe
    • Command line arguments: -pluginpath %{buildDir}\lib\qtcreator\plugins
  4. Build the project and run. This will launch a Qt Creator of compatible version.
  5. Open a file and test that the plugin is working. Make sure you have FakeVim disabled.

Configurations tested:

  • Windows, building the project using MinGW (Qt 5.15.11 from installer)
  • Windows, building the project using MSVC (Qt 5.15.11 from installer)
  • Linux (PopOS 22.04 with Qt 5.15.3 from apt)
  • macOS (Cannot test, as I do not have a Mac)

CC #32

This change ports the QMake build to CMake - a recommended way to
build plugins according to the Qt Documentation:
https://doc.qt.io/qtcreator-extending/first-plugin.html#cmake-project

This also adds a number of useful features, for example, an ability
to fetch neovim-qt and qtcreator automatically.

Neovim-qt is downloaded and built with the Message Pack using
FetchContent CMake feature. In case of QtCreator only the
precompiled binaries are downloaded to save time.
@gikari gikari force-pushed the feature/cmake-port branch from 4f19da6 to 7ca5307 Compare November 6, 2022 15:14
@gikari gikari requested a review from sassanh November 6, 2022 15:17
@sassanh
Copy link
Owner

sassanh commented Nov 6, 2022

Thanks! I'm getting errors like these in macOS:

.../qnvim/src/qnvimplugin.cpp:165:31: error: no member named 'hasBlockSelection' in 'TextEditor::TextEditorWidget'
    auto cursor = textEditor->hasBlockSelection() ? textEditor->blockSelection() : textEditor->textCursor();
                  ~~~~~~~~~~  ^
.../qnvim/src/qnvimplugin.cpp:165:65: error: no member named 'blockSelection' in 'TextEditor::TextEditorWidget'
    auto cursor = textEditor->hasBlockSelection() ? textEditor->blockSelection() : textEditor->textCursor();
                                                    ~~~~~~~~~~  ^
.../qnvim/src/qnvimplugin.cpp:172:21: error: no member named 'hasBlockSelection' in 'TextEditor::TextEditorWidget'
    if (textEditor->hasBlockSelection()) {
        ~~~~~~~~~~  ^
.../qnvim/src/qnvimplugin.cpp:289:21: error: no member named 'setBlockSelection' in 'TextEditor::TextEditorWidget'
        textEditor->setBlockSelection(cursor);
        ~~~~~~~~~~  ^
.../qnvim/src/qnvimplugin.cpp:810:69: error: no viable conversion from 'QString' to 'const Utils::FilePath'
                    if (mEditors[buffer]->document()->save(nullptr, filename)) {
                                                                    ^~~~~~~~
.../Qt/Qt Creator.app/Contents/Resources/Headers/qtcreator/src/libs/utils/filepath.h:66:30: note: candidate constructor (t
he implicit copy constructor) not viable: no known conversion from 'QString' to 'const Utils::FilePath &' for 1st argument
class QTCREATOR_UTILS_EXPORT FilePath

Do you know anything about it?

@gikari
Copy link
Collaborator Author

gikari commented Nov 6, 2022

I've got similar errors when building against Qt Creator of later versions because of changed APIs. Perhaps CMake is linking to incorrect version of Qt Creator libs (the ones installed in the system, not the fetched ones).

I took a look at the contetns of archive that is downloaded for macOS and it's quite different layout from Windows and Linux archives (CMAKE_PREFIX_PATH expects (at least on WIndows and Linux) the path to have lib and include directories, but macOS archive have additional QtCreator.app/Contents/{Resources,Frameworks} prefixes).

It seems like for macOS we need to set CMAKE_APPBUNDLE_PATH and CMAKE_FRAMEWORK_PATH in addition to CMAKE_PREFIX_PATH.

@sassanh
Copy link
Owner

sassanh commented Nov 6, 2022

I'm a bit confused, are you using an older version of QtCreator compiled with Qt 5 to be able to compile and use this plugin? Because now I remember this plugin is not compatible with Qt Creator built with Qt 6, right?

If that's the case I need to install an older version of Qt Creator, do you know what's the latest version using Qt 5?

@gikari
Copy link
Collaborator Author

gikari commented Nov 6, 2022

You don't have to install Qt Creator with this patch - it is downloaded for you with the specific hardcoded version. In this case it's 4.15.2 (It is old, but requires small amount of fixes in plugin source code). After it is downloaded, the plugin is built against it. After successful but you can launch an instance of it with the enabled plugin to test it.

But in your case (on macOS) something went wrong and now the plugin build system tries to use some other Qt Creator, not the automatically downloaded one, hence the errors above.

@sassanh
Copy link
Owner

sassanh commented Nov 6, 2022

I see, that should be it then. I'm getting this error (even with your latest commit):

CMake Error at CMakeLists.txt:29 (find_package):
  By not providing "FindQtCreator.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "QtCreator", but CMake did not find one.

  Could not find a package configuration file provided by "QtCreator" with
  any of the following names:

    QtCreatorConfig.cmake
    qtcreator-config.cmake

  Add the installation prefix of "QtCreator" to CMAKE_PREFIX_PATH or set
  "QtCreator_DIR" to a directory containing one of the above files.  If
  "QtCreator" provides a separate development package or SDK, be sure it has
  been installed.

I was setting QtCreator_DIR to a Qt Creator 6 directory as suggested in the error message.

@gikari
Copy link
Collaborator Author

gikari commented Nov 6, 2022

You should not need to add it. Could you try a clean build with the commit I just added?

@sassanh
Copy link
Owner

sassanh commented Nov 6, 2022

FetchContent_Declare(
  qtcreator
  URL "${QTC_URL}"
  URL_HASH MD5=${QTC_MD5}
)

This is extracting qtcreator-macOS-1029797214.7z directly into build/_deps/qtcreator-src (creating build/_deps/qtcreator-src/Contents) while this:

  file(ARCHIVE_EXTRACT INPUT "${PROJECT_BINARY_DIR}/downloads/qtc_dev.7z" DESTINATION "${qtcreator_SOURCE_DIR}")

is extracting qtcreator-Linux-1029797214_dev.7z into build/_deps/qtcreator-src/Qt Creator.app, the result is this:

$ ls build/_deps/qtcreator-src/
Contents/       Qt Creator.app/

Either Contents/ should be inside Qt Creator.app/ or the contents of Qt Creator.app/ should be directly extracted next to Contents/ (I prefer the first one, cause I think it will make things easier with CMAKE_APPBUNDLE_PATH)

@gikari
Copy link
Collaborator Author

gikari commented Nov 8, 2022

I fixed the directory structure bug, so you are welcome to test it.

@sassanh
Copy link
Owner

sassanh commented Nov 9, 2022

Thanks!
Now I need to apply this diff:

diff --git a/cmake/FetchQtCreator.cmake b/cmake/FetchQtCreator.cmake
index 7a6ffae..9939cf7 100644
--- a/cmake/FetchQtCreator.cmake
+++ b/cmake/FetchQtCreator.cmake
@@ -51,7 +51,11 @@ if(NOT qtcreator_POPULATED)
   # Add dev files into the same directory
   file(DOWNLOAD "${QTC_DEV_URL}" "${qtcreator_SOURCE_DIR}/qtc_dev.7z" EXPECTED_MD5 ${QTC_DEV_MD5})
   file(ARCHIVE_EXTRACT INPUT "${qtcreator_SOURCE_DIR}/qtc_dev.7z" DESTINATION "${qtcreator_BINARY_DIR}")
+endif()
 
-  # Let the CMake Find scripts find Qt Creator files
+# Let the CMake Find scripts find Qt Creator files
+if(APPLE) # macOS
+  list(APPEND CMAKE_PREFIX_PATH "${qtcreator_BINARY_DIR}/Qt Creator.app/Contents/Resources/lib/cmake/QtCreator")
+else()
   list(APPEND CMAKE_PREFIX_PATH "${qtcreator_BINARY_DIR}")
 endif()

so that cmake finds Qt Creator.

And I'm getting this error:

CMake Error at build/_deps/qtcreator-build/Qt Creator.app/Contents/Resources/lib/cmake/QtCreator/QtCreatorAPIInternal.cmake:302 (target_link_libraries)
:
  Target "QNVim" links to:

    Qt6::Widgets

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

Call Stack (most recent call first):
  build/_deps/qtcreator-build/Qt Creator.app/Contents/Resources/lib/cmake/QtCreator/QtCreatorAPIInternal.cmake:475 (add_qtc_depends)
  build/_deps/qtcreator-build/Qt Creator.app/Contents/Resources/lib/cmake/QtCreator/QtCreatorAPI.cmake:460 (extend_qtc_target)
  CMakeLists.txt:33 (add_qtc_plugin)

@sassanh
Copy link
Owner

sassanh commented Nov 11, 2022

Considering we are building for a Qt 5 version of Qt Creator, do we need Qt 6 in the build process?
I was able to build the plugin by applying this diff (I don't know much about cmake, please check it):

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b51aa78..9ba1ba7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,8 +27,7 @@ if (MSVC)
 endif()
 
 find_package(QtCreator REQUIRED COMPONENTS Core)
-find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network REQUIRED)
-set(QtX Qt${QT_VERSION_MAJOR})
+find_package(Qt5 COMPONENTS Widgets Network REQUIRED)
 
 add_qtc_plugin(QNVim
   PLUGIN_DEPENDS
@@ -36,7 +35,7 @@ add_qtc_plugin(QNVim
     QtCreator::TextEditor
     QtCreator::ProjectExplorer
   DEPENDS
-    ${QtX}::Widgets
+    Qt5::Widgets
     QtCreator::ExtensionSystem
     QtCreator::Utils
     neovim-qt

But now Qt Creator (the one in build/_deps/qtcreator-build) crashes when I add the plugin and restart it. doesn't show any informative error:
image

@gikari
Copy link
Collaborator Author

gikari commented Nov 11, 2022

No we don't need Qt6 for now. Indeed we can remove the Qt6 from dependencies.

As for crash: this is strange. Did you try to run it with the debugger?

@gikari
Copy link
Collaborator Author

gikari commented Nov 11, 2022

I applied a Qt version patch and tried to fix the find_package for macOS by removing the space in the bundle name. I'm still not sure if it will work, since CMake docs do not list the path you added explicitly in their locations for search in macOS.

Could you test if it works? If not, maybe the subdirectories of a bundle could be added to CMAKE_PREFIX_PATH.

@sassanh
Copy link
Owner

sassanh commented Nov 12, 2022

Unfortunately it didn't work, still getting this error:

CMake Error at CMakeLists.txt:29 (find_package):
  By not providing "FindQtCreator.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "QtCreator", but CMake did not find one.

  Could not find a package configuration file provided by "QtCreator" with
  any of the following names:

    QtCreatorConfig.cmake
    qtcreator-config.cmake

  Add the installation prefix of "QtCreator" to CMAKE_PREFIX_PATH or set
  "QtCreator_DIR" to a directory containing one of the above files.  If
  "QtCreator" provides a separate development package or SDK, be sure it has
  been installed.

It works by adding the subdirectories of the bundle to CMAKE_PREFIX_PATH, you can see it in the diff snippet I provided here

@sassanh
Copy link
Owner

sassanh commented Nov 12, 2022

Latest commit is good. I try to find some time to see why it is crashing in macOS.

.gitignore Show resolved Hide resolved
@sassanh
Copy link
Owner

sassanh commented Nov 14, 2022

The problem was a misconfiguration on my machine living from old versions.
All is good now, thanks!

@gikari gikari merged commit 06be8fb into sassanh:master Nov 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants