Mac OS QT application packaging

1, Introduction

The graphical interface packaged on MacOS must be created from the Bundle. This Bundle is like Apk, which contains code, libraries, resource files and so on.

If you create a QT project by yourself and use a. pro file, this file will have the Bundle attribute. To be safe, you can also add the following:

CONFIG+=app_bundle

If there is no Bundle, the. app to be used later will not be compiled. To use CMakeLists.txt, you need to configure the Bundle yourself:  

add_executable(example
        # The important thing is the following line
        MACOSX_BUNDLE
        ${SRC_LIST}
        ${SRC_COMMON_LIST}
        ${SRC_TEST_LIST}
        ${QRC_FILES}
        main.cpp
    )
# These are version numbers and names
set_target_properties(example PROPERTIES
    BUNDLE True
    MACOSX_BUNDLE_GUI_IDENTIFIER example
    MACOSX_BUNDLE_BUNDLE_NAME "example"
    MACOSX_BUNDLE_BUNDLE_VERSION "0.1"
    MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1"
    # This plist.in is extracted from QT, mainly for macos application configuration. I also copied it below
    MACOSX_BUNDLE_INFO_PLIST ./MacOSXBundleInfo.plist.in
)

MacOSXBundleInfo.plist.in :  

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
	<key>CFBundleGetInfoString</key>
	<string>${MACOSX_BUNDLE_INFO_STRING}</string>
	<key>CFBundleIconFile</key>
	<string>${MACOSX_BUNDLE_ICON_FILE}</string>
	<key>CFBundleIdentifier</key>
	<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleLongVersionString</key>
	<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
	<key>CFBundleName</key>
	<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
	<key>CSResourcesFileMapped</key>
	<true/>
	<key>NSHumanReadableCopyright</key>
	<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
</dict>
</plist>

2, Pack

First select the Release version in QT, compile it, and then enter the build directory. Normally, you will see an example.app file in the build directory. If not, there is only one executable file, that is, the Bundle is not set.

First:

~/Qt/5.15.2/clang_64/bin/macdeployqt example.app

This project will copy the resource files and three-party libraries used by example to example.app/Contents /, and then the three-party libraries will be placed under example.app/Contents/Frameworks /.

Specific to our application, it will copy some third-party libraries to Frameworks:

Then the important thing is to adjust the dependency structure of the library. Use "otool -L" to see the dependency of the program or other libraries:
For example, look at the example:  

otool -L example.app/Contents/MacOS/example

  The paths of its dependent libraries will be listed. If some third-party libraries, such as libopus.dylib, point to / usr/lib /, they must be manually changed. Otherwise, when running, they will go to the system directory and find problems in other people's environment. If they are public libraries, such as libc++.1.dylib, there will be no problem.

The above figure shows the library dependency of example. It is still relatively perfect after the implementation of macdeployqt. There is no problem with the path and there is no need to change it.

However, if you package directly in this way, you may still report an error after running dmg:

This problem has been perplexed for a long time. It is clear that the paths listed above are correct, but they always go to the system path to find the solution. Later, I read the document that otool can also see the library dependencies, and then listed libavformat.58.dylib in the figure:

otool -L example.app/Contents/Frameworks/libavformat.58.dylib

I found that some of the paths here are systematic, so I have to change them one by one  

install_name_tool -change "/usr/local/Cellar/ffmpeg/4.4_1/lib/libswresample.3.dylib" "@executable_path/../Frameworks/libswresample.3.dylib" example.app/Contents/Frameworks/libavformat.58.dylib 

This install_name_tool is specially used by MacOS to change the dependency library.
Many other libraries are like this. They have to be changed back and repackaged after the change:

~/Qt/5.15.2/clang_64/bin/macdeployqt example.app -dmg

In this way, the typed package can be used in other MAC computers.

Keywords: C++ Qt macOS Virtual Machine

Added by sonehs on Wed, 22 Sep 2021 03:09:24 +0300