I think this question has been asked a lot of times but I could not find a solution that works for me.
I have a CMake project for a desktop application, written in C , that uses some libraries (Qt and OpenCV). I developed the project under Windows, but I want to build it for MacOS. To do that, I installed the necessary libraries using brew and I use them in my project using the find_package
cmake command.
Everything works fine, but my problem is that I couldn't manage to successfully run my project on another MacOS computer because the libraries are missing (.dylib).
On Windows, I use windeployqt
and then I copy the remaining opencv into the executable folder by hand and this works. On MacOS, from what I understood, this is not the case and you have to use install_name_tool
to edit the executable with the correct paths.
I tried using macdeployqt
that authomatically copies all the necessary libraries into the app bundle (*.app
folder) and edits the executable libraries paths.
One problem I encountered is that the OpenCV libraries that are copied into the bundle are linked to the system installed ones. To solve this problem, I wrote a script that runs install_name_tool
on every OpenCV library, this solved the issue, but I'm not sure this is the best way of doing it.
Unfortunately, I had another problem I couldn't solve: macdeployqt
didn't deploy all the necessary frameworks, and, for some reason, the Qt QDBus framework is missing.
Maybe I am taking the wrong path? I've never used MacOS before, and I'm not sure this is the correct way of building desktop applications. Is there any example project I can use as a reference?
P.s. I'm not using XCode, I just build my project in the terminal using the cmake tool.
Edit
This is an example project I use.
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.20)
project(example LANGUAGES CXX)
# find libraries
find_package(OpenCV REQUIRED)
find_package(Qt6 COMPONENTS Widgets Gui OpenGL OpenGLWidgets Multimedia MultimediaWidgets PrintSupport Charts REQUIRED)
add_executable(some_executable)
target_sources(some_executable PRIVATE "main.cpp")
# tel CMake to create a bundle
# see https://doc.qt.io/qt-6/macos-deployment.html
set_target_properties(some_executable PROPERTIES MACOSX_BUNDLE TRUE)
# link libraries
# some opencv libs I use
target_link_libraries(some_executable PRIVATE opencv_core opencv_xfeatures2d opencv_videoio opencv_highgui opencv_video)
# some Qt libs I use
target_link_libraries(some_executable PRIVATE Qt6::Widgets Qt6::Multimedia Qt6::MultimediaWidgets Qt6::PrintSupport Qt6::Charts)
main.cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char** argv) {
QApplication app(argc, argv);
QLabel hello;
hello.setText("Hello There!");
hello.show();
return app.exec();
}
deploy.sh
echo Deploying MacOS bundle...
# use this to see the linked libraries
# otool -l some_executable.app/Contents/MacOS/some_executable
# use macreployqt to deploy the necessary libraries and frameworks
macdeployqt some_executable.app
FRAMEWORKS_PATH=some_executable.app/Contents/Frameworks
# wrong: OPENCV_LIB_PATH=/usr/local/Cellar/opencv/4.5.5_2/lib
OPENCV_LIB_PATH=@rpath
OPENCV_VER=405 # <- change this to match the opecv version
echo editing opencv paths...
OPENCV_LIBS=(
"libopencv_calib3d"
"libopencv_core"
"libopencv_dnn"
"libopencv_features2d"
"libopencv_flann"
"libopencv_highgui"
"libopencv_imgcodecs"
"libopencv_imgproc"
"libopencv_ml"
"libopencv_shape"
"libopencv_video"
"libopencv_videoio"
"libopencv_xfeatures2d"
)
replace_opencv_lib_path() {
# the library to patch
LIB=$1
# the linked library
TO_REPLACE=$2
install_name_tool -change ${OPENCV_LIB_PATH}/${TO_REPLACE}.${OPENCV_VER}.dylib @executable_path/../Frameworks/${TO_REPLACE}.${OPENCV_VER}.dylib $FRAMEWORKS_PATH/$LIB.${OPENCV_VER}.dylib
}
for lib in ${OPENCV_LIBS[@]}; do
for lib2 in ${OPENCV_LIBS[@]}; do
replace_opencv_lib_path $lib $lib2
done
done
An then I run these commands:
# configure the project
cmake .
# build the project
cmake --build .
# deploy
sudo /bin/sh deploy.sh
# create a DMG file we can test on another computer
sudo macdeployqt some_executable.app -dmg
CodePudding user response:
I just figured that macdeployqt
was not deploying the Qt D-Bus framework. To solve the problem, explicitly add the dependency in the CMake file.
So, the solution is to use the code I posted, but link Qt::DBus
in the CMakeLists.txt
:
...
find_package(Qt6 COMPONENTS ... DBus REQUIRED)
...
target_link_libraries(some_executable PRIVATE Qt6::DBus)
Then everything works fine.