QT iOS app plugins not found issue?
-
I have a QT app that runs smoothly on windows and macOS.
I am currently trying to test and deploy this app via TestFlight for iOS. The app is built using cmake and the great QTIosCMake macro by OlivierLDff.
Building and uploading works fine, but when calling the app I get an empty screen.
When testing via Xcode I get the following error output
2023-12-31 02:58:49.756283-0800 DCT[747:129511] Metal GPU Frame Capture Enabled 2023-12-31 02:58:49.756514-0800 DCT[747:129511] Metal API Validation Enabled 2023-12-31 02:58:49.831099-0800 DCT[747:129511] This plugin does not support setting window masks 2023-12-31 02:58:51.158800-0800 DCT[747:129511] QQmlApplicationEngine failed to load component 2023-12-31 02:58:51.158930-0800 DCT[747:129511] qrc:/assets/alpha/Main.qml:1:1: module "QtQuick" plugin "qtquick2plugin" not found
I know that, contrary to the macOS version, the libraries have to be integrated statically. This is done in the CMakeList.txt using the following construct
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") qt6_import_plugins(DCT INCLUDE Qt6::QMinimalIntegrationPlugin INCLUDE Qt6::Core INCLUDE Qt6::Qml INCLUDE Qt6::Widgets INCLUDE Qt6::Network INCLUDE Qt6::Quick INCLUDE Qt6::Concurrent INCLUDE Qt6::Core5Compat INCLUDE Qt6::QuickControls2 INCLUDE Common INCLUDE_BY_TYPE platforms )
This was not included in the first attempts where I get the same error. It seems that inserted import_plugins part that has no effect.
Any idea where I can start troubleshooting?
Thanks in advanced
-
@astoffregen
Looks like iOS still tries to load the plugin dynamically. Probably because it's not statically linked.That can be done in CMake like that (where
$plugin_targets
) is a list of all plugin targets. You can of course replace the variable with the hard coded name, in case you have only one plugin.if(QT6_IS_SHARED_LIBS_BUILD) add_dependencies(yourApp ${plugin_targets}) else() target_link_libraries(yourApp PRIVATE ${plugin_targets}) endif()
-
@Axel-Spoerl
Hello Axel thanks for your response. Does this mean that my call of the qt6_import_plugins macro as listed above is not the correct way? I found this way in the qt6 documentation for static libraries -
@astoffregen
It is definitively correct.
You just have to make sure to link your plugins statically, if you want to deploy to iOS/watchOS.
You can look at the documentviewer example and it's CMake files. -
@Axel-Spoerl
Thanks for the link but in the CMakeList of the viewer I don't see how this should help me. I don't see any of the commands for static embedding there. I have to admit that I am not specialized in QT projects, I am trying to implement a pipeline based on Jenkins and am less concerned with QT project itselfs. That comes from another placeI have checked the prerequisites again and the qt_import_plugin macro should be available via this section.
find_package(Qt6 REQUIRED COMPONENTS core Qml Widgets network Quick Concurrent LinguistTools Core5Compat QuickControls2 )
And then this section for iOS including the plugin with the iOS CMake macro from OlivierLDff
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") qt6_import_plugins(ABC INCLUDE Qt6::QMinimalIntegrationPlugin INCLUDE Qt6::Core INCLUDE Qt6::Qml INCLUDE Qt6::Widgets INCLUDE Qt6::Network INCLUDE Qt6::Quick INCLUDE Qt6::Concurrent INCLUDE Qt6::Core5Compat INCLUDE Qt6::QuickControls2 INCLUDE Common INCLUDE_BY_TYPE platforms ) macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) endmacro (set_xcode_property) set(CMAKE_SYSTEM_PROCESSOR aarch64) set_target_properties(DCT PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") set_target_properties(DCT PROPERTIES QT_IOS_LAUNCH_SCREEN "${CMAKE_CURRENT_SOURCE_DIR}/Launch.storyboard") include(build-tools/xyz/ios/AddQtIosApp.cmake) add_qt_ios_app(ABC NAME "ABC" BUNDLE_IDENTIFIER ${APPLE_BUNDLE_IDENTIFIER} VERSION ${APPLE_SHORT_VERSION} SHORT_VERSION ${APPLE_SHORT_VERSION} LONG_VERSION ${APPLE_LONG_VERSION} CUSTOM_PLIST ${APPLE_CUSTOM_PLIST} ASSET_DIR ${APPLE_ASSET_DIR} TEAM_ID ${APPLE_TEAM_ID} CODE_SIGN_IDENTITY ${APPLE_CODE_SIGN_IDENTITY} PROVISIONING_PROFILE_SPECIFIER ${APPLE_PROVISIONING_PROFILE_SPECIFIER} IPA )
That should be enough to statically integrate the required libraries, right? However, I still get the error as described above.
Would it help if I provided the complete CMakeList?
-
@astoffregen
Yes, please provide the full CMakeLists.txt. -
@Axel-Spoerl
Thanks for the support, can I send you the file by email? -
@astoffregen
Hello Axel,
please find attached the complete Cmaketext file. Since five different platforms and two company versions are supported, the whole thing is somewhat largercmake_minimum_required(VERSION 3.21.1) include(FetchContent) project(MyProject) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(QT_DEFAULT_MAJOR_VERSION 6) find_package(Qt6 REQUIRED COMPONENTS Core Qml Widgets Network Quick Concurrent LinguistTools Core5Compat QuickControls2 ) ################## ext libs ################## FetchContent_Declare( COMMON_LIB_BUILD SVN_REPOSITORY http://111.222.333.444/svn/MyProject/libraries/common/trunk SVN_USERNAME svnuser SVN_PASSWORD svnpass ) ################## sets variables for libs ################## set(COMPANY "MyCompany") set(BUNDLE_NAME "MyApp") set(BUNDLE_NAME_DISPLAY "MyApp") set(BUNDLE_NAME_SHORT "MyApp") ################## builds the libs ################## FetchContent_MakeAvailable(COMMON_LIB_BUILD) ################## alias for lib sources ################## set(common_src ${common_lib_build_SOURCE_DIR}/src) ################## includes for ide ################## include_directories( src ${common_src} ) set(HEADERS src/logic_layer/alphastringmanager.h src/logic_layer/productlistmodel.h src/logic_layer/alphastrings.h src/logic_layer/alpha.h src/logic_layer/permissionmanager.h src/logic_layer/permission.h src/logic_layer/translator.h src/logic_layer/bundlemanager.h src/logic_layer/productmanager.h src/logic_layer/product.h src/logic_layer/messagefilterproxymodel.h src/logic_layer/messagelistmodel.h src/logic_layer/httprequesthandler.h src/logic_layer/replytimeout.h src/logic_layer/jsonhelper.h src/logic_layer/languagelistmodel.h src/presentation_layer/alphasplashscreen.h ${common_src}/logic_layer/xevents.h ${common_src}/logic_layer/iplugin.h ${common_src}/logic_layer/commonstrings.h ${common_src}/themes/colors.h ${common_src}/themes/theme.h ${common_src}/themes/company.h ) set(SOURCES src/logic_layer/alphastringmanager.cpp src/logic_layer/productlistmodel.cpp src/logic_layer/alpha.cpp src/logic_layer/permissionmanager.cpp src/logic_layer/permission.cpp src/logic_layer/translator.cpp src/logic_layer/bundlemanager.cpp src/logic_layer/productmanager.cpp src/logic_layer/product.cpp src/logic_layer/messagefilterproxymodel.cpp src/logic_layer/messagelistmodel.cpp src/logic_layer/httprequesthandler.cpp src/logic_layer/replytimeout.cpp src/presentation_layer/alphasplashscreen.cpp src/logic_layer/jsonhelper.cpp src/logic_layer/languagelistmodel.cpp ) if("${COMPANY}" STREQUAL "MyCompany") option(MYCOMP2 "Flag that indicates if this is build for MyCompany2" OFF) elseif("${COMPANY}" STREQUAL "MyCompany2") option(MYCOMP2 "Flag that indicates if this is build for MyCompany2" ON) endif() ################## Translation files ################## if(${CREATE_TRANSLATION}) set(TS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/presentation_layer/assets/translations) set(TS_FILES "${TS_DIR}/myapp_de.ts" "${TS_DIR}/myapp_en.ts" "${TS_DIR}/myapp_cn.ts" "${TS_DIR}/myapp_fr.ts" "${TS_DIR}/myapp_pl.ts" "${TS_DIR}/myapp_ru.ts" "${TS_DIR}/myapp_it.ts" "${TS_DIR}/myapp_nl.ts" "${TS_DIR}/myapp_es.ts" "${TS_DIR}/myapp_pt.ts" ) set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${TS_DIR}) find_program(LUPDATE_EXECUTABLE lupdate) foreach(_ts_file ${TS_FILES}) execute_process(COMMAND ${LUPDATE_EXECUTABLE} -recursive -noobsolete ${CMAKE_SOURCE_DIR} -ts ${_ts_file}) endforeach() endif() ################## Translation files end ################## qt_add_resources(RESOURCES src/presentation_layer/alpha_controls.qrc # src/presentation_layer/translation.qrc src/presentation_layer/assets/licenses/${COMPANY}/licenses.qrc src/presentation_layer/codes.qrc ) # Define the version components set(VER_MAJOR ${BUNDLE_VERSION_MAJOR}) set(VER_MINOR ${BUNDLE_VERSION_MINOR}) set(VER_PATCH ${BUNDLE_VERSION_REV}) set(VER_BUILD ${APPLICATION_BUILD_NUMBER}) if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") add_executable(MyAPP MACOSX_BUNDLE #for creating the archive ${common_src}/logic_layer/shareutils.h src/main.cpp ${HEADERS} ${SOURCES} ${RESOURCES} ) elseif(APPLE) # The MACOSX_BUNDLE_ICON_FILE variable is added to the Info.plist # generated by CMake. This variable contains the .icns file name, # without the path. set(MACOSX_BUNDLE_ICON_FILE app.icns) # And the following tells CMake where to find and install the file itself. if("${COMPANY}" STREQUAL "MyCompany") set(app_icon_macos "${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/appicons/macOS/app.icns") elseif("${COMPANY}" STREQUAL "MyCompany2") set(app_icon_macos "${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/${BUNDLE_APP_ID}/appicons/macOS/app.icns") endif() set_source_files_properties(${app_icon_macos} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") qt_add_executable(MyAPP MACOSX_BUNDLE #for creating the archive src/main.cpp ${HEADERS} ${SOURCES} ${RESOURCES} ${app_icon_macos} ) elseif(ANDROID) add_library(MyAPP SHARED src/main.cpp ${HEADERS} ${SOURCES} ${RESOURCES} ) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "MyType") qt_add_executable(MyAPP src/main.cpp ${HEADERS} ${SOURCES} ${RESOURCES} ) else() # Combine the version components to form FILEVERSION set(FILE_VERSION "${VER_MAJOR},${VER_MINOR},${VER_PATCH},${VER_BUILD}") if("${COMPANY}" STREQUAL "MyCompany") set(ICON_PATH "build-tools/${COMPANY}/appicons/windows/app.ico") set(COMPANY_FULL_NAME "MyCompany full name") set(ORIG_FILE_NAME "${BUNDLE_NAME_SHORT}.exe") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build-tools/version.rc.in ${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/version.rc @ONLY) set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/version.rc") elseif("${COMPANY}" STREQUAL "MyCompany2") set(ICON_PATH "build-tools/${COMPANY}/${BUNDLE_APP_ID}/appicons/windows/app.ico") set(COMPANY_FULL_NAME "MyCompany2 full name") set(ORIG_FILE_NAME "${BUNDLE_NAME_SHORT}.exe") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build-tools/version.rc.in ${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/${BUNDLE_APP_ID}/version.rc @ONLY) set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/build-tools/${COMPANY}/${BUNDLE_APP_ID}/version.rc") endif() add_executable(MyAPP WIN32 src/main.cpp ${HEADERS} ${SOURCES} ${RESOURCES} ${APP_ICON_RESOURCE_WINDOWS} ) endif () configure_file(AlphaConfig.h.in AlphaConfig.h) target_include_directories(MyAPP PUBLIC ${common_src} "${PROJECT_BINARY_DIR}" ) target_link_libraries(MyAPP PRIVATE Qt6::Core Qt6::Qml Qt6::Widgets Qt6::Network Qt6::Quick Qt6::Concurrent Qt6::Core5Compat Qt6::QuickControls2 Common ) if (APPLE) target_link_libraries(MyAPP PRIVATE "-framework CoreFoundation" #macos "-framework IOkit" #macos ) set_target_properties(MyAPP PROPERTIES LINK_OPTIONS "-Wl,-F/Library/Frameworks") #macos set_target_properties(MyAPP PROPERTIES MACOSX_BUNDLE TRUE) endif () if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") qt6_import_plugins(MyAPP INCLUDE Qt6::QMinimalIntegrationPlugin INCLUDE Qt6::Core INCLUDE Qt6::Qml INCLUDE Qt6::Widgets INCLUDE Qt6::Network INCLUDE Qt6::Quick INCLUDE Qt6::Concurrent INCLUDE Qt6::Core5Compat INCLUDE Qt6::QuickControls2 INCLUDE Common INCLUDE_BY_TYPE platforms ) macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) endmacro (set_xcode_property) set(CMAKE_SYSTEM_PROCESSOR aarch64) set_target_properties(MyAPP PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") set_target_properties(MyAPP PROPERTIES QT_IOS_LAUNCH_SCREEN "${CMAKE_CURRENT_SOURCE_DIR}/Launch.storyboard") include(build-tools/mycompany/ios/AddQtIosApp.cmake) add_qt_ios_app(MyAPP NAME "MyAPP" BUNDLE_IDENTIFIER ${APPLE_BUNDLE_IDENTIFIER} VERSION ${APPLE_SHORT_VERSION} SHORT_VERSION ${APPLE_SHORT_VERSION} LONG_VERSION ${APPLE_LONG_VERSION} CUSTOM_PLIST ${APPLE_CUSTOM_PLIST} ASSET_DIR ${APPLE_ASSET_DIR} TEAM_ID ${APPLE_TEAM_ID} CODE_SIGN_IDENTITY ${APPLE_CODE_SIGN_IDENTITY} PROVISIONING_PROFILE_SPECIFIER ${APPLE_PROVISIONING_PROFILE_SPECIFIER} IPA ) #https://github.com/OlivierLDff/QtIosCMake elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") set_target_properties(MyAPP PROPERTIES BUNDLE True BUNDLE_IDENTIFIER de.mycompany.macos.myapp MACOSX_BUNDLE_GUI_IDENTIFIER de.mycompany.macos.myapp MACOSX_BUNDLE_BUNDLE_NAME MyAPP MACOSX_BUNDLE_BUNDLE_VERSION "2.0.4" MACOSX_BUNDLE_SHORT_VERSION_STRING "2.0.4" #MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/build-tools/mycompany/Info.plist.in ) elseif (ANDROID) include(build-tools/mycompany/android/AddQtAndroidApk.cmake) # https://github.com/LaurentGomila/qt-android-cmake/tree/master add_qt_android_apk(Alpha_apk MyAPP NAME "MyAPP" PACKAGE_SOURCES ${ANDROID_PACKAGE_SOURCE} PACKAGE_NAME ${ANDROID_PACKAGE_NAME} VERSION_CODE ${ANDROID_VERSION_CODE} KEYSTORE ${ANDROID_KEYSTORE_FILE} KEYSTORE_PASSWORD ${ANDROID_KEYSTORE_PASSWORD} KEY_ALIAS ${ANDROID_KEY_ALIAS} KEY_PASSWORD ${ANDROID_KEY_PASSWORD} ) elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Emscripten") target_link_options(MyAPP PRIVATE "SHELL:-s FULL_ES2=1" "SHELL:-s FULL_ES3=1") endif () set_target_properties(MyAPP PROPERTIES IMPORTED_LOCATION external_libs/ftd2xx.dll )
-
Good morning @astoffregen,
thanks for sharing. In a static build,
qtquick2plugin
has to be linked explicitly. If your app is using any quick layouts, you'll also need to link the respective plugin.Adding this will probably solve the problem (untested ;-)
if(NOT QT6_IS_SHARED_LIBS_BUILD) target_link_libraries(MyApp PRIVATE Qt6::qtquick2plugin Qt6::qquicklayoutsplugin ) endif()
-
@Axel-Spoerl
Good morning Axel,
we are on the right track thanks for your support.
After adding the plugins, the app starts and tries to open the Main.qml.
However, further errors occur here.2024-01-15 12:50:04.929169-0800 MyApp[445:14608] This plugin does not support setting window masks 2024-01-15 12:50:06.063795-0800 MyApp[445:14608] QQmlApplicationEngine failed to load component 2024-01-15 12:50:06.063928-0800 MyApp[445:14608] qrc:/assets/alpha/Main.qml:5:1: module "Qt5Compat.GraphicalEffects" is not installed 2024-01-15 12:50:06.063990-0800 MyApp[445:14608] qrc:/assets/alpha/Main.qml:4:1: module "QtQuick.Dialogs" is not installed 2024-01-15 12:50:06.064032-0800 MyApp[445:14608] qrc:/assets/alpha/Main.qml:3:1: module "QtQuick.Window" is not installed 2024-01-15 12:50:06.064072-0800 MyApp[445:14608] qrc:/assets/alpha/Main.qml: module "QtQuick.Controls.Basic" is not installed
But the components should already be available via the includes or not?
-
@astoffregen said in QT iOS app plugins not found issue?:
module "Qt5Compat.GraphicalEffects" is not installed
Good morning,
all of those modules need to be found and linked in the CMake file, e.g.find_package(Qt6 COMPONENTS Core5Compat Quick REQUIRED) target_link_libraries(MyApp PUBLIC Qt6::Core5Compat Qt6::Quick )
Greetings from a cold, stormy winter in Oslo,
Axel -
@Axel-Spoerl
Hello Axel,
thanks for so soon response. Yes it's also very cold here in Hamburg. As you can find in attached CMakeText file we included this already ?target_link_libraries(MyAPP PRIVATE Qt6::Core Qt6::Qml Qt6::Widgets Qt6::Network Qt6::Quick Qt6::Concurrent Qt6::Core5Compat Qt6::QuickControls2 Common )
-
we included this already
Oh, my bad, I overlooked that. Furthermore, "not installed" points more at deployment being the issue.
What I don't find explicitly in the CMake file, is
main.qml
.
So I guess it is sort of implicitly added as a resource andmain.cpp
knows how to find it.=> Is a
qmldir
directory in the resource tree?
Something along the lines of this might help:install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir DESTINATION "${INSTALL_DIR}"