Developer Blog - Inventic.eu
  • Skipper - The ORM Designer
  • VsBuilds - Parallel building
  • Pulpo - Free Skipper CLI

Tag: #deploy

Jenkinks and MacOS application signing

After re-installing our MacOS building machine which we're using for ORM Designer deploy, we started to getting following message:

./OrmDesigner2.app: User interaction is not allowed.<br />

After short searching on the internet I found it's required to click on **"Always Allow"** dialog.... which unfortunately we don't have on the console ;-).

The trick is in the keychain unlock. For this purpose we can use following command:

security unlock-keychain -pPASSWORD ~/Library/Keychains/login.keychain<br />

That's all. After this command I'm able to sign my application from Jenkinks command line again.

External links

23 Sep 2013

MacOS open file hander, app icon and other PLIST features

How to configure PLIST

This is how look ORM Designer plist file to correct setup file handler and application icon:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />
&lt;!DOCTYPE plist SYSTEM &quot;file://localhost/System/Library/DTDs/PropertyList.dtd&quot;&gt;<br />
&lt;plist version=&quot;1.0&quot;&gt;<br />
&lt;dict&gt;<br />
  &lt;key&gt;CFBundleVersion&lt;/key&gt;        &lt;string&gt;1.0&lt;/string&gt;<br />
  &lt;key&gt;CFBundlePackageType&lt;/key&gt;    &lt;string&gt;APPL&lt;/string&gt;<br />
  &lt;key&gt;CFBundleExecutable&lt;/key&gt;     &lt;string&gt;@EXECUTABLE@&lt;/string&gt;<br />
  &lt;key&gt;CFBundleIdentifier&lt;/key&gt;     &lt;string&gt;com.orm-designer.OrmDesigner2&lt;/string&gt;<br />
  &lt;key&gt;CFBundleSignature&lt;/key&gt;      &lt;string&gt;????&lt;/string&gt;<br />
  &lt;key&gt;CFBundleGetInfoString&lt;/key&gt;  &lt;string&gt;ORM Designer2, Copyright 2012 Inventic s.r.o.&lt;/string&gt;<br />
  &lt;key&gt;CFBundleIconFile&lt;/key&gt;       &lt;string&gt;@ICON@&lt;/string&gt;<br />
  &lt;key&gt;NOTE&lt;/key&gt;                   &lt;string&gt;ORM Designer2 by Inventic Corporation&lt;/string&gt;</p>
<p>  &lt;key&gt;CFBundleDocumentTypes&lt;/key&gt;<br />
  &lt;array&gt;<br />
    &lt;dict&gt;<br />
      &lt;key&gt;CFBundleTypeName&lt;/key&gt;         &lt;string&gt;ORM Designer project file&lt;/string&gt;<br />
      &lt;key&gt;CFBundleTypeRole&lt;/key&gt;         &lt;string&gt;Editor&lt;/string&gt;<br />
      &lt;key&gt;CFBundleTypeIconFile&lt;/key&gt;     &lt;string&gt;@ICON@&lt;/string&gt;<br />
      &lt;key&gt;LSHandlerRank&lt;/key&gt;            &lt;string&gt;Owner&lt;/string&gt;<br />
      &lt;key&gt;LSIsAppleDefaultForType&lt;/key&gt;  &lt;true/&gt;</p>
<p>      &lt;key&gt;CFBundleTypeExtensions&lt;/key&gt;<br />
      &lt;array&gt;<br />
        &lt;string&gt;ormdesigner&lt;/string&gt;<br />
        &lt;string&gt;ormdes&lt;/string&gt;<br />
        &lt;string&gt;ormdesigner2&lt;/string&gt;<br />
        &lt;string&gt;ormdes2&lt;/string&gt;<br />
      &lt;/array&gt;<br />
    &lt;/dict&gt;<br />
  &lt;/array&gt;<br />
&lt;/dict&gt;<br />
&lt;/plist&gt;<br />

Qt links:

Apple developer links:

Icon converting online tools

19 Sep 2012

Posted by: ludek.vodicka

Programming Mac OS #deploy #mac os

Very slow svn updates from Virtual Machines (VMWare)

I have a lot of virtual machines used for my everyday development. It's very frustrating the SVN update speed if you have several externals in your main SVN source.

Today when I wait for some compilation start searching if there is anything what could improve SVN speed. After searching a lot of articles about faster network, better server hdd,... I found article with mention how SVN client communicate with server (intensively ;-) ). But without any clue how to improve it.

So I start searching how SVN client communiacte from within VMWare machines to server. I noticed that VMWare default network settings is NAT: Used to share the host's IP address:

So I start trying other network methods and this is the result:

When I use "Custom: Specific virtual network" and choose "VMnet0 Bridged", my svn update is about ten times faster than on NAT settings!!. I also tried first option "Bridged:..." but this doesn't work for me.

30 Aug 2012

Posted by: ludek.vodicka

Linux Windows Mac OS #deploy #svn

QWidget: Must construct a QApplication before a QPaintDevice

Today I encounter this error after applying **macdeployqt** to my application. There is a lot of questions about this topic on google but not very answers.

The most important thing is setup following variable.

export DYLD_PRINT_LIBRARIES=1<br />

Using this you will se which libraries are loaded during execution of your application. The interesting thing is, that I see loading a libraries from their original directories instead of Application.app. But when I temporary moved these libraries from their location, libraries begin to load from then bundle location.

The reason for my "QWidget: Must construct a QApplication before a QPaintDevice" was executing an older version of QTitanRibbon from shared libraries path instead of the newest one compiled directly to /usr/lib.
The second reason for this issue was caused by another path in "export DYLD_LIBRARY_PATH". It seems that application search for libraries first in DYLD_LIBRARY_PATH and after in paths from their inner records.

To turn off this debug output, use:

unset DYLD_PRINT_LIBRARIES<br />

29 Aug 2012

Posted by: ludek.vodicka

Programming Qt Mac OS #Qt #MacOs #deploy

How to create .DEB package for Unix Debian-like systems

**This guide isn't complete. Create valid .DEB file is a much harder than I thought. So I will create .DEB file (and update this article) when I will have a more free time.**

This is how now looks lintian result ;-( :

[email protected]:~/dev/Applications/AtomixDevelopment/DeployInfo/Ubuntu$ lintian ormdesigner.deb<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/OrmDesigner2<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/OrmDesigner2<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libQtCore.so.4<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libQtGui.so.4<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_chrono.so<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_chrono.so<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_chrono.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_chrono.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_date_time.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_date_time.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_filesystem.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_filesystem.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_iostreams.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_iostreams.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_regex.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_regex.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_system.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_system.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libboost_thread.so.1.49.0<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libboost_thread.so.1.49.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libexslt.so.0<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libxml2.so.2<br />
E: orm-designer: embedded-library usr/share/orm-designer/libs/libxml2.so.2: libxml2<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libxslt.so.1<br />
E: orm-designer: arch-dependent-file-in-usr-share usr/share/orm-designer/libs/libyaml-cpp.so.0.2<br />
E: orm-designer: unstripped-binary-or-object usr/share/orm-designer/libs/libyaml-cpp.so.0.2<br />
W: orm-designer: unknown-control-file control~<br />
E: orm-designer: control-file-has-bad-permissions postinst 0775 != 0755<br />
E: orm-designer: control-file-has-bad-owner postinst dev/dev != root/root<br />
W: orm-designer: unknown-control-file postinst~<br />
E: orm-designer: control-file-has-bad-permissions postrm 0775 != 0755<br />
E: orm-designer: control-file-has-bad-owner postrm dev/dev != root/root<br />
W: orm-designer: unknown-control-file postrm~<br />
E: orm-designer: no-copyright-file<br />
W: orm-designer: extended-description-line-too-long<br />
W: orm-designer: package-relation-with-self breaks: orm-designer (&lt;&lt; 2.0.1)<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/ 1001/1001<br />
W: orm-designer: non-standard-dir-perm usr/ 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/ 1001/1001<br />
W: orm-designer: non-standard-dir-perm usr/share/ 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/ 1001/1001<br />
W: orm-designer: non-standard-dir-perm usr/share/orm-designer/ 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/OrmDesigner2 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/OrmDesigner2 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/ 1001/1001<br />
W: orm-designer: non-standard-dir-perm usr/share/orm-designer/libs/ 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libQtCore.so.4 1001/1001<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libQtGui.so.4 1001/1001<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_chrono.so 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_chrono.so 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_chrono.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_chrono.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_date_time.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_date_time.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_filesystem.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_filesystem.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_iostreams.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_iostreams.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_regex.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_regex.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_system.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_system.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libboost_thread.so.1.49.0 1001/1001<br />
W: orm-designer: non-standard-executable-perm usr/share/orm-designer/libs/libboost_thread.so.1.49.0 0775 != 0755<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libexslt.so.0 1001/1001<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libxml2.so.2 1001/1001<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libxslt.so.1 1001/1001<br />
E: orm-designer: wrong-file-owner-uid-or-gid usr/share/orm-designer/libs/libyaml-cpp.so.0.2 1001/1001<br />
W: orm-designer: maintainer-script-ignores-errors postinst<br />
W: orm-designer: maintainer-script-ignores-errors postrm~<br />
W: orm-designer: maintainer-script-ignores-errors postrm<br />
W: orm-designer: maintainer-script-ignores-errors postinst~<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_chrono.so 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_chrono.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_date_time.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_filesystem.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_iostreams.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_regex.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_system.so.1.49.0 0775<br />
E: orm-designer: shlib-with-executable-bit usr/share/orm-designer/libs/libboost_thread.so.1.49.0 0775<br />

Prerequisities

sudo apt-get install build-essential autoconf automake autotools-dev dh-make debhelper devscripts fakeroot xutils lintian pbuilder<br />

Commands

#creates .deb file<br />
dpkg -b ormdesigner-2.0.1 ormdesigner.deb</p>
<p>#validate .deb file<br />
lintian ormdesigner<br />

How to add screenshot to .DEB file

http://screenshots.debian.net/
http://stackoverflow.com/questions/4776624/how-to-create-deb-package-with-screenshot-for-ubuntu

Errors

E: orm-designer: wrong-file-owner-uid-or-gid usr/ 1001/1001<br />
...<br />

External links

http://www.ibm.com/developerworks/linux/library/l-debpkg/index.html
How to create DEB from source files
How to remove some litian errors

20 Aug 2012

Posted by: ludek.vodicka

Uncategorized Linux #Linux #deploy #ubuntu

How to create nice MacOS DMG installer

In this article I will show how to create DMG installer in reusable way. The most of things and ideas presented here are ideas from several articles mentioned on the end of this article.

1) As first step we need to create our DMG template with link to Applications.
2) Next we have to modify the visual representation of DMG file.
3) Next we store created DMG as template
4) Now mount copied template as directory, fill DMG with real files
5) Detach mounted DMG, pack DMG
6) Distribute app ;-)

More detailed info about all these steps you will find in articles mentioned below. Here is a short script I wrote for three-phase deploying (1) create template, 2) pack template, 3)fill template with real data and compress it)

#! /bin/bash</p>
<p>TEMPLATE_DMG=atomix-development-template.dmg<br />
VOLUME_NAME=&quot;Atomix Development&quot;<br />
APPLICATION_FILE_NAME=&quot;AtomixDevelopment.app&quot;</p>
<p>if [ &quot;$1&quot; = &quot;create-template&quot; ]<br />
then<br />
  echo Create DMG template<br />
  mkdir template<br />
  cd template<br />
  mkdir $APPLICATION_FILE_NAME<br />
  touch $APPLICATION_FILE_NAME/fake<br />
  ln -s /Applications/ Applications<br />
  cd ..<br />
  rm $TEMPLATE_DMG<br />
  rm $TEMPLATE_DMG.bz2<br />
  hdiutil create -fs HFSX -layout SPUD -size 100m &quot;$TEMPLATE_DMG&quot; -srcfolder template -format UDRW -volname &quot;$VOLUME_NAME&quot; -quiet<br />
  rm -rf template<br />
elif [ &quot;$1&quot; = &quot;zip-template&quot; ]<br />
then<br />
  echo Zipping DMG template<br />
  bzip2 &quot;$TEMPLATE_DMG&quot;<br />
elif [ &quot;$1&quot; = &quot;create-dmg&quot; ]<br />
then<br />
  echo Creating DMG file from template and data</p>
<p>  #unzip template<br />
  rm $TEMPLATE_DMG<br />
  bunzip2 -k $TEMPLATE_DMG.bz2</p>
<p>  #create pack path and attach DMG<br />
  PACK_PATH=`pwd`/dmg-pack<br />
  mkdir $PACK_PATH<br />
  hdiutil attach &quot;$TEMPLATE_DMG&quot; -noautoopen -quiet -mountpoint &quot;$PACK_PATH&quot;</p>
<p>  #copy new content to DMG<br />
  cp -r &quot;$2&quot; &quot;$PACK_PATH&quot;<br />
  rm $PACK_PATH/$APPLICATION_FILE_NAME/fake</p>
<p>  #detach DMG, remove mount path<br />
  hdiutil detach &quot;$PACK_PATH&quot; -force -quiet<br />
  rm -rf $PACK_PATH</p>
<p>  #compress DMG<br />
  hdiutil convert -format UDZO -o tmp-packer-output.dmg &quot;$TEMPLATE_DMG&quot; -imagekey zlib-level=9<br />
  rm ./$TEMPLATE_DMG<br />
  mv ./tmp-packer-output.dmg $TEMPLATE_DMG</p>
<p>  #rm $TEMPLATE_DMG<br />
else<br />
  echo Missing parameter<br />
  echo &quot;create-dmg [create|zip-template|create-dmg Path/Application.app]&quot;<br />
fi<br />

So, it looks like that DMG file for ORM Designer2 is ready ;-)

Another tools to create DMG package

External links

http://codevarium.gameka.com.br/how-to-create-your-own-beautiful-dmg-files/
http://el-tramo.be/guides/fancy-dmg/
http://stackoverflow.com/questions/96882/how-do-i-create-a-nice-looking-dmg-for-mac-os-x-using-command-line-tools
http://stackoverflow.com/questions/8680132/creating-nice-dmg-installer-for-mac-os-x
http://stackoverflow.com/questions/2104364/how-to-install-a-qt-application-on-a-customers-system

16 Aug 2012

Posted by: ludek.vodicka

Qt Mac OS #MacOs #deploy

How to deploy Qt application on MacOS - part II

In first part of this article I introduced a manual way how to deploy MacOS application. Because doing all these stuff manually was a lot of hand work, Qt introduced small tool called **macdeployqt**.

This utility looks very good, but also have some drawbacks. As first I will show you how utility works:

macdeployqt Application.app<br />

That's all ;-). This command should do all the hard work for you. But in some cases it didn't.

ERROR: no file at &quot;/usr/lib/libboost_iostreams.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_filesystem.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_system.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_thread.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_date_time.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_regex.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libboost_chrono.dylib&quot;<br />
ERROR: no file at &quot;/usr/lib/libyaml-cpp.0.2.dylib&quot;<br />

The problem is that libraries mentioned in the previous list doesn't has included absolute path. If you inspecit this library, you will se this:

otool -L libboost_regex.dylib<br />
libboost_regex.dylib:<br />
	libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)<br />
	/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)<br />
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)<br />

And this is the problem. Inner path in library is only filename without full path, so when we link library with our executable, our executable also has only relative path. And when macdeployqt try to find this library, automatically try to search in /usr/lib.

One possible solution is copy libraries to /usr/lib. Second solution is update paths in libraries to absolute paths. The third way is fix library linker to include full paths in libraries.

I found out that the simplies way how to fix it is call install_name_tool after library compilation and fix the path (don't forget to update library paths inside other library paths!)

  install_name_tool -id &quot;$SHL_PATH/boost/lib/libboost_chrono.dylib&quot; $SHL_PATH/boost/lib/libboost_chrono.dylib<br />
  install_name_tool -id &quot;$SHL_PATH/boost/lib/libboost_date_time.dylib&quot; $SHL_PATH/boost/lib/libboost_date_time.dylib<br />
  ...<br />
  install_name_tool -change &quot;libboost_system.dylib&quot; &quot;$SHL_PATH/boost/lib/libboost_system.dylib&quot; $SHL_PATH/boost/lib/libboost_chrono.dylib<br />
  install_name_tool -change &quot;libboost_system.dylib&quot; &quot;$SHL_PATH/boost/lib/libboost_system.dylib&quot; $SHL_PATH/boost/lib/libboost_filesystem.dylib<br />

So, now when we have updated all libraries, we can try to create application bundle again

macdeployqt AtomixDevelopment.app/<br />

And if we did everything correctly, now we should have a working app ;-).

Troubleshooting

In some cases you can get error "Permission defined", "Bad file descriptor" or other similar errors when using macdeployqt.

ERROR: &quot;install_name_tool: can't open input file: OrmDesigner2.app/Contents/Frameworks//libssl.1.0.0.dylib for writing (Permission denied)<br />
install_name_tool: can't lseek to offset: 0 in file: OrmDesigner2.app/Contents/Frameworks//libssl.1.0.0.dylib for writing (Bad file descriptor)<br />
install_name_tool: can't write new headers in file: OrmDesigner2.app/Contents/Frameworks//libssl.1.0.0.dylib (Bad file descriptor)<br />
install_name_tool: can't close written on input file: OrmDesigner2.app/Contents/Frameworks//libssl.1.0.0.dylib (Bad file descriptor)<br />

The reason is insufficient permissions for modifying copied libraries. Simple execute

sudo macdeployqt<br />

and everything should work ok. Another workaround for this issue is using newer version of Qt. I figured out that on MacOS I wrongly use Qt 4.7.4. When I correct this to version Qt 4.8.2 this issue was solved.

DMG file

If you want to create simply DMG file, simply call macdeployqt with param --dmg. But this dmg doesn't look so good:

This will need more investigation how to make DMG files nicer ;-).

Notes

  • Everytime you run macdeployqt run it on clean folder. The best way is to call rm -rf Application, compile app and than run macdeployqt

Notes to bug in macdeployqt

The problem is caused by invalid permissions. Copied libraries have the same permissions like in the source location. There are three different solutions:

  1. Use sudo and execute macdeployqt with root permissions
  2. Update external libraries permissions to rw, so also copies will have a correct permissions
  3. Update macdeployqt script. In file shared.cpp on line 91 is method copyFilePrintStatus. Here is a necessary to update copied files permissions to correct rw

In my case the problem was in file liblzma.5.dylib

Frameworks/liblzma.5.dylib is not writable (Permission denied)<br />

Orinal library is located in path:

/usr/local/Cellar/xz/5.0.4/lib<br />
16 Aug 2012

Posted by: ludek.vodicka

Qt Mac OS #Qt #MacOs #deploy

How to deploy Qt application on MacOS - part I

As I wrote yesterday, I found the way how to proceed deployment on the Linux system. Today I have to manage it the same on the MacOS systems.

Note: the simplest way is introduced in the second part of this article.

The first usefull command for tracking dependencies between your application and other shared libraries is otool:

#path to executable, not .App directory!<br />
otool -L Application.app/Contents/MacOS/AppExecutable<br />

Now we can see paths to our libraries. The bad news is that MacOS doesn't have any -RPATH and $ORIGIN. The good news is utility install_name_tool and variable @executable_path which works similar like $ORIGIN.
Note: For newer versions of MacOS there are more variables like @executable_path. On version 10.4 was introduced @loader_path and on version 10.5 apple introduce @rpath variable.

The step-by-step solution

As first step it's necessary to upload all dependent libraries directly to the Application.app/Contents/MacOS/. For list all required files use otool:

cd Application.app/Contents/MacOS<br />
otool -L AppExecutable<br />

When we have copied all libraries, we need to change paths **for** and **in** all libraries.

Here is example how to set libxml2 library. As first step we will check how is library referred.

$user otool -L AtomixDevelopment</p>
<p>AtomixDevelopment:<br />
	libboost_iostreams.dylib (compatibility version 0.0.0, current version 0.0.0)<br />
	libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0)<br />
	/Users/User/dev/SharedLibraries/libxml/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0)<br />
	/Users/User/dev/SharedLibraries/libxslt/lib/libxslt.1.dylib (compatibility version 3.0.0, current version 3.26.0)<br />
	/Users/User/dev/SharedLibraries/libxslt/lib/libexslt.0.dylib (compatibility version 9.0.0, current version 9.15.0)<br />

And Library:

User$ otool -L libxml2.2.dylib<br />
libxml2.2.dylib:<br />
	/Users/User/dev/SharedLibraries/libxml/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0)<br />
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)<br />
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)<br />
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)<br />

When we checked libxml2.2.dylib library with otool, we can see that library has hardocoded our development path. This isn't good ;-). So we now change this value to path relative to the executable and again verify this inner path.

install_name_tool -id &quot;@loader_path/libxml2.2.dylib&quot; libxml2.2.dylib<br />
otool -L libxml2.2.dylib<br />
libxml2.2.dylib:<br />
	@loader_path/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0)<br />
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)<br />
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)<br />
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)<br />

As you can see, now is path (first line) set up to reffer @loader_path/libxml2.2.dylib. It's correct now. As second step we have to update path in our executable, because also there is path hardcoded to our library repository.

install_name_tool -change &quot;/Users/User/dev/ExternalLibraries/../SharedLibraries/libxml/lib/libxml2.2.dylib&quot; &quot;@loader_path/libxml2.2.dylib&quot; AtomixDevelopment</p>
<p>otool -L AtomixDevelopment<br />
AtomixDevelopment:<br />
	libboost_iostreams.dylib (compatibility version 0.0.0, current version 0.0.0)<br />
	libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0)<br />
	@loader_path/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0)<br />
        ...<br />

So, now we have changed also path in our executable. And now we need to do all these steps for all libraries..... ;-).

 

Notes

To follow the MacOS application convention it's better to place libraries to folder Application.app/Contents/Frameworks. Here is a directory schema for Qt example application plugAndPaint.

External links

16 Aug 2012

Posted by: ludek.vodicka

Qt Mac OS #Qt #MacOs #deploy

Why is compiled Linux executable so large?

Today I encountered another issue when compiling my Qt application http://www.orm-designer.com/ under Linux. The size of final executable was about 400MB.
The first thought was that there is some static libraries compiled to application. But the problem was elsewhere.

Unlike to Windows compilation where linker creates .exe and .pdb file, linux linker creates only one final file. So this file includes also lot of additional symbols useful for debugging and post-mortem bugs finding. But it is not so usefull for distribution your application. To strip all these symbols, use following command

strip --strip-unneeded /path/to/application<br />

Strip command have a lot of switches, but after a short testing it seems that the results are the same. Maybe I'm doing something wrong or simply my executable doesn't contain any additional infos for stripping.

15 Aug 2012

Posted by: ludek.vodicka

Qt Linux #Linux #deploy