Qt and Google breakpad Windows/Linux/MacOS

Integration of Google breakpad on any platform is really challenge. I didn’t figure out how to do it by using recommended ways. So I did it my way 😉

Create your own Qt project

As first thing I did when integrating Qt and Breakpad is creation of my own .pri file. I manually add all required files from Breakpad one-by-one, starting with src/platform/exception_handler continuing with all files included in previous ones. The complete .pri file you will find at end of this post.

After that I created simple CCrashHandler (inspired by qt-breakpad project) class which register exception handler. It’s necessary to implement this handler for each platform separately because each platform have different parameters in google_breakpad::ExceptionHandler() constructor. CrashHandler source code you can find also at end of this post.

Using Breakpad on Linux:

Article about Linux integration.

Notes Linux

  • GCC 4.6.3
  • Ubuntu 12.04.1 32/64bit

Get and Compile Breakpad

#get breakpad latest version
svn checkout http://google-breakpad.googlecode.com/svn/trunk/ google-breakpad-read-only

#compile all breakpad tools for extracting symbol files
./configure
make
sudo make install

#when compilation is ready, you should have installed file dump_syms from original directory /src/tools/linux/dump_syms in your /usr/bin
dump_syms

Generate symbol file and test debug info

Now how to generate and use symbol file:

#generate .sym file
dump_syms ./Application > Application.sym

#store sym file in the correct location
#this step is necessary. Without that minidump_stackwalk tool doesn't work

head -n1 Application.sym
#Result: MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 Application

mkdir -p ./symbols/Application/6EDC6ACDB282125843FD59DA9C81BD830
mv Application.sym ./symbols/Application/6EDC6ACDB282125843FD59DA9C81BD830

#show stack with using minidump_stackwalk tool
minidump_stackwalk ./crash.dmp ./symbols

Result of minidump_stackwalk tool can look like this:

Use additional tools

There is script written by Mozzila corp which simplifies extracting and storing .sym file:
http://mxr.mozilla.org/mozilla-central/source/toolkit/crashreporter/tools/symbolstore.py?raw=1

Now with this script, you can do only one step instead of all described above.

python /path/to/script/symbolstore.py /usr/local/bin/dump_syms ./symbol-storage ./Application

This command correctly creates folder Application/uuid in path symbol-storage and copy generated .sym file inside.

Using Breakpad on MacOS:

To integrate Breakpad and Qt on MacOS I used the same article as for Linux because I’m using gcc and linux-like development toolchain. For native XCode integration you have to probably use this article.

Notes MacOS

  • GCC 4.6.3
  • Qt creator toolchain
  • Mac OS 10.7.3 64bit
  • Don’t using any of XCode tool chaing

Do almost all steps like on Linux integration. There is one exception, because you can’t compile Breakpad tools using linux-like configure&make. You have to build these tools with XCode.

Compile google_breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj with XCode

Before I managed to successfully compile dump_syms in XCode, I have to update Architectures Debug/Release to 64-bit Intel and BaseSDK to “Latest Mac OS X”. I also fix all issues displayed in the left part of XCode window.

Next step is change compilation type from Debug to Release. After a short searching I found a way in “Schema->Edit schema->Build configuration”.

To be honest, I was not sure what I did, but it worked ;-). Maybe there is some easier way how to compile dump_syms in xcode, but I don’t know how. This was my first contact with XCode ;-).

The application is compiled to path “/Users/User/Library/Developer/Xcode/DerivedData/dump_syms-bjvr/Build/Products/Release/dump_syms”. Now copy dump_syms to safe location from where you will use it.

The rest steps are same like in the Linux.

Using Breakpad on Windows

Notes Windows

Article about Windows integration.

  • Compile with Visual Studio 2010
  • Post-mortem debugging is done also via VS2010
  • Google breakpad under windows generates common .dmp files which can by simply load directly to VS

Generate symbol files and test debug info

You have to choices for Windows. First option is use standard .PDB and .DMP files mechanism in VS. Second is use the same way how you can did it for Linux and Mac.

First way: Let compiler generate .PDB file. Store this files and use them later in VS together with your crash dump.

Second way: Use dump_sys.exe. This file is located in the google breakpad directory tree: google-breakpad\src\tools\windows\binaries\dump_syms.exe .

dump_syms.exe AtomixDevelopment.exe >AtomixDevelopment.sym

And also like under Linux, you can use Python script symbolstore.py to extract symbols to correct directory:

python.exe symbolstore.py binaries\dump_syms.exe .\Symbols AtomixDevelopment.exe

Minidump stackwalk for windows:
http://code.google.com/p/pcxfirefox/source/browse/trunk/betterpgo/talos/talos/breakpad/win32/minidump_stackwalk.exe?r=19

The best thing at end

The most amazing thing I found about dump_syms is their platform independence. If you correctly extract symbol file on each platform and store it in one location, you can analyze any crashdump on one location. No matter what is source platform, you will analyze .dmp file by using minidump_stackwalk ./crash.dmp ./symbols.

How to include CrashHandler directly to your project

This is what I get when I follow all includes from .h and .cpp files starting with exception_handler.h for all platforms. With small modification you can include it to your project and your application will be fully breakpad-able ;-).

# ---------- HEADER -----------------------------------------------------------
OTHERS   += $$PWD/axCrashHandler.pri
HEADERS += $$PWD/CrashHandler.h
SOURCES += $$PWD/CrashHandler.cpp

BREAKPAD_PATH=$$EXTERNAL_LIBRARIES_PATH/breakpad-qt
INCLUDEPATH += $$BREAKPAD_PATH/src

OSMAC {
  HEADERS += $$BREAKPAD_PATH/src/client/mac/handler/exception_handler.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/crash_generation/crash_generation_client.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/crash_generation/crash_generation_server.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/crash_generation/client_info.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/handler/minidump_generator.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/handler/dynamic_images.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/handler/breakpad_nlist_64.h
  HEADERS += $$BREAKPAD_PATH/src/client/mac/handler/mach_vm_compat.h
  HEADERS += $$BREAKPAD_PATH/src/client/minidump_file_writer.h
  HEADERS += $$BREAKPAD_PATH/src/client/minidump_file_writer-inl.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/macho_utilities.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/byteswap.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/MachIPC.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/scoped_task_suspend-inl.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/file_id.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/macho_id.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/macho_walker.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/macho_utilities.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/bootstrap_compat.h
  HEADERS += $$BREAKPAD_PATH/src/common/mac/string_utilities.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/linux_libc_support.h
  HEADERS += $$BREAKPAD_PATH/src/common/string_conversion.h
  HEADERS += $$BREAKPAD_PATH/src/common/md5.h
  HEADERS += $$BREAKPAD_PATH/src/common/memory.h
  HEADERS += $$BREAKPAD_PATH/src/common/using_std_string.h
  HEADERS += $$BREAKPAD_PATH/src/common/convert_UTF.h
  HEADERS += $$BREAKPAD_PATH/src/processor/scoped_ptr.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_exception_mac.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/breakpad_types.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_format.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_size.h
  HEADERS += $$BREAKPAD_PATH/src/third_party/lss/linux_syscall_support.h

  SOURCES += $$BREAKPAD_PATH/src/client/mac/handler/exception_handler.cc
  SOURCES += $$BREAKPAD_PATH/src/client/mac/crash_generation/crash_generation_client.cc
  SOURCES += $$BREAKPAD_PATH/src/client/mac/crash_generation/crash_generation_server.cc
  SOURCES += $$BREAKPAD_PATH/src/client/mac/handler/minidump_generator.cc
  SOURCES += $$BREAKPAD_PATH/src/client/mac/handler/dynamic_images.cc
  SOURCES += $$BREAKPAD_PATH/src/client/mac/handler/breakpad_nlist_64.cc
  SOURCES += $$BREAKPAD_PATH/src/client/minidump_file_writer.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/macho_id.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/macho_walker.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/macho_utilities.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/string_utilities.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/file_id.cc
  SOURCES += $$BREAKPAD_PATH/src/common/mac/MachIPC.mm
  SOURCES += $$BREAKPAD_PATH/src/common/mac/bootstrap_compat.cc
  SOURCES += $$BREAKPAD_PATH/src/common/md5.cc
  SOURCES += $$BREAKPAD_PATH/src/common/string_conversion.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/linux_libc_support.cc
  SOURCES += $$BREAKPAD_PATH/src/common/convert_UTF.c
  LIBS += /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
  LIBS += /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
  #breakpad app need debug info inside binaries
  QMAKE_CXXFLAGS+=-g
}

OSLIN {
  HEADERS += $$BREAKPAD_PATH/src/client/linux/handler/exception_handler.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/crash_generation/crash_generation_client.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/handler/minidump_descriptor.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/minidump_writer/minidump_writer.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/minidump_writer/line_reader.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/minidump_writer/linux_dumper.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/minidump_writer/linux_ptrace_dumper.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/minidump_writer/directory_reader.h
  HEADERS += $$BREAKPAD_PATH/src/client/linux/log/log.h
  HEADERS += $$BREAKPAD_PATH/src/client/minidump_file_writer-inl.h
  HEADERS += $$BREAKPAD_PATH/src/client/minidump_file_writer.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/linux_libc_support.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/eintr_wrapper.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/ignore_ret.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/file_id.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/memory_mapped_file.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/safe_readlink.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/guid_creator.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/elfutils.h
  HEADERS += $$BREAKPAD_PATH/src/common/linux/elfutils-inl.h
  HEADERS += $$BREAKPAD_PATH/src/common/using_std_string.h
  HEADERS += $$BREAKPAD_PATH/src/common/memory.h
  HEADERS += $$BREAKPAD_PATH/src/common/basictypes.h
  HEADERS += $$BREAKPAD_PATH/src/common/memory_range.h
  HEADERS += $$BREAKPAD_PATH/src/common/string_conversion.h
  HEADERS += $$BREAKPAD_PATH/src/common/convert_UTF.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_format.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_size.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/breakpad_types.h
  HEADERS += $$BREAKPAD_PATH/src/processor/scoped_ptr.h
  HEADERS += $$BREAKPAD_PATH/src/third_party/lss/linux_syscall_support.h
  SOURCES += $$BREAKPAD_PATH/src/client/linux/crash_generation/crash_generation_client.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/handler/exception_handler.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/handler/minidump_descriptor.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/minidump_writer/minidump_writer.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/minidump_writer/linux_dumper.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
  SOURCES += $$BREAKPAD_PATH/src/client/linux/log/log.cc
  SOURCES += $$BREAKPAD_PATH/src/client/minidump_file_writer.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/linux_libc_support.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/file_id.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/memory_mapped_file.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/safe_readlink.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/guid_creator.cc
  SOURCES += $$BREAKPAD_PATH/src/common/linux/elfutils.cc
  SOURCES += $$BREAKPAD_PATH/src/common/string_conversion.cc
  SOURCES += $$BREAKPAD_PATH/src/common/convert_UTF.c
  #breakpad app need debug info inside binaries
  QMAKE_CXXFLAGS+=-g
}

OSWIN {
  BREAKPAD_PATH=q:/Applications/breakpad-qt/third-party/latest-breakpad
  INCLUDEPATH += $$BREAKPAD_PATH/src
  HEADERS += $$BREAKPAD_PATH/src/common/windows/string_utils-inl.h
  HEADERS += $$BREAKPAD_PATH/src/common/windows/guid_string.h
  HEADERS += $$BREAKPAD_PATH/src/client/windows/handler/exception_handler.h
  HEADERS += $$BREAKPAD_PATH/src/client/windows/common/ipc_protocol.h
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/minidump_format.h 
  HEADERS += $$BREAKPAD_PATH/src/google_breakpad/common/breakpad_types.h 
  HEADERS += $$BREAKPAD_PATH/src/client/windows/crash_generation/crash_generation_client.h 
  HEADERS += $$BREAKPAD_PATH/src/processor/scoped_ptr.h 

  SOURCES += $$BREAKPAD_PATH/src/client/windows/handler/exception_handler.cc
  SOURCES += $$BREAKPAD_PATH/src/common/windows/string_utils.cc
  SOURCES += $$BREAKPAD_PATH/src/common/windows/guid_string.cc
  SOURCES += $$BREAKPAD_PATH/src/client/windows/crash_generation/crash_generation_client.cc 
}

And this is the minimal implementation of your new CrashHandler. My ownd crash handler is much more sophisticate to perform reporting, sending crash dump etc. But for purposes of this article this is what you need (And also I don’t want to share my whole know-how here ;-)))

CrashHandler.h

#pragma once
#include <QtCore/QString>

namespace Atomix
{
	class CrashHandlerPrivate;
	class CrashHandler
	{
	public:
		static CrashHandler* instance();
    void Init(const QString&  reportPath);

		void setReportCrashesToSystem(bool report);
		bool writeMinidump();

	private:
		CrashHandler();
		~CrashHandler();
		Q_DISABLE_COPY(CrashHandler)
		CrashHandlerPrivate* d;
	};
}

CrashHandler.cpp

#include "CrashHandler.h"
#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QCoreApplication>
#include <QString>

#if defined(Q_OS_MAC)
#include "client/mac/handler/exception_handler.h"
#elif defined(Q_OS_LINUX)
#include "client/linux/handler/exception_handler.h"
#elif defined(Q_OS_WIN32)
#include "client/windows/handler/exception_handler.h"
#endif

namespace Atomix
{
	/************************************************************************/
	/* CrashHandlerPrivate                                                  */
	/************************************************************************/
	class CrashHandlerPrivate
	{
	public:
		CrashHandlerPrivate()
		{
			pHandler = NULL;
		}

		~CrashHandlerPrivate()
		{
			delete pHandler;
		}

		void InitCrashHandler(const QString& dumpPath);
		static google_breakpad::ExceptionHandler* pHandler;
		static bool bReportCrashesToSystem;
	};

	google_breakpad::ExceptionHandler* CrashHandlerPrivate::pHandler = NULL;
	bool CrashHandlerPrivate::bReportCrashesToSystem = false;

	/************************************************************************/
	/* DumpCallback                                                         */
	/************************************************************************/
#if defined(Q_OS_WIN32)
	bool DumpCallback(const wchar_t* _dump_dir,const wchar_t* _minidump_id,void* context,EXCEPTION_POINTERS* exinfo,MDRawAssertionInfo* assertion,bool success)
#elif defined(Q_OS_LINUX)
	bool DumpCallback(const google_breakpad::MinidumpDescriptor &md,void *context, bool success)
#elif defined(Q_OS_MAC)
	bool DumpCallback(const char* _dump_dir,const char* _minidump_id,void *context, bool success)
#endif
	{
		Q_UNUSED(context);
#if defined(Q_OS_WIN32)
		Q_UNUSED(_dump_dir);
		Q_UNUSED(_minidump_id);
		Q_UNUSED(assertion);
		Q_UNUSED(exinfo);
#endif
		qDebug("BreakpadQt crash");

		/*
		NO STACK USE, NO HEAP USE THERE !!!
		Creating QString's, using qDebug, etc. - everything is crash-unfriendly.
		*/
		return CrashHandlerPrivate::bReportCrashesToSystem ? success : true;
	}

	void CrashHandlerPrivate::InitCrashHandler(const QString& dumpPath)
	{
		if ( pHandler != NULL )
			return;

#if defined(Q_OS_WIN32)
		std::wstring pathAsStr = (const wchar_t*)dumpPath.utf16();
		pHandler = new google_breakpad::ExceptionHandler(
			pathAsStr,
			/*FilterCallback*/ 0,
			DumpCallback,
			/*context*/
			0,
			true
			);
#elif defined(Q_OS_LINUX)
		std::string pathAsStr = dumpPath.toStdString();
		google_breakpad::MinidumpDescriptor md(pathAsStr);
		pHandler = new google_breakpad::ExceptionHandler(
			md,
			/*FilterCallback*/ 0,
			DumpCallback,
			/*context*/ 0,
			true,
			-1
			);
#elif defined(Q_OS_MAC)
		std::string pathAsStr = dumpPath.toStdString();
		pHandler = new google_breakpad::ExceptionHandler(
			pathAsStr,
			/*FilterCallback*/ 0,
			DumpCallback,
			/*context*/
			0,
			true,
			NULL
			);
#endif
	}

	/************************************************************************/
	/* CrashHandler                                                         */
	/************************************************************************/
	CrashHandler* CrashHandler::instance()
	{
		static CrashHandler globalHandler;
		return &globalHandler;
	}

	CrashHandler::CrashHandler()
	{
		d = new CrashHandlerPrivate();
	}

	CrashHandler::~CrashHandler()
	{
		delete d;
	}

	void CrashHandler::setReportCrashesToSystem(bool report)
	{
		d->bReportCrashesToSystem = report;
	}

	bool CrashHandler::writeMinidump()
	{
		bool res = d->pHandler->WriteMinidump();
		if (res) {
			qDebug("BreakpadQt: writeMinidump() successed.");
		} else {
			qWarning("BreakpadQt: writeMinidump() failed.");
		}
		return res;
	}

	void CrashHandler::Init( const QString& reportPath )
	{
		d->InitCrashHandler(reportPath);
	}
}

Main.cpp

And here is how to use it:

#include "axCore/axCrashHandler/CrashHandler.h"
#include <QDebug>
#include <QCoreApplication>
#include <iostream>

int buggyFunc()
{
	delete reinterpret_cast<QString*>(0xFEE1DEAD);
	return 0;
}

int main(int argc, char * argv[])
{
	qDebug() << "App start";
	QCoreApplication app(argc, argv);

#if defined(Q_OS_WIN32)
	Atomix::CrashHandler::instance()->Init("c:\\dump");
#elif defined(Q_OS_LINUX)
	Atomix::CrashHandler::instance()->Init("/Users/dev/dump");
#elif defined(Q_OS_MAC)
	Atomix::CrashHandler::instance()->Init("/Users/User/dump");
#endif
	
	qDebug() << "CrashHandlerSet";
	buggyFunc();
	return 0;
}

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.

How to instal JRE 7 in Ubuntu 12

First step is clean all openjdk from system

sudo apt-get purge openjdk*

Now download latest JRE version from here http://www.oracle.com/technetwork/java/javase/downloads/jre-7u13-download-1501631.html. Download package: jre-7u13-linux-i586.tar.gz.

Download package to ~/Downloads and execute following commands

tar -xvf ~/Downloads/jre-7u13-linux-i586.tar.gz
sudo mkdir -p /usr/lib/jvm/jre1.7.0
sudo mv jre1.7.0_13/* /usr/lib/jvm/jre1.7.0/
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jre1.7.0/bin/java 0

External links

http://www.liberiangeek.net/2012/04/install-oracle-java-runtime-jre-7-in-ubuntu-12-04-precise-pangolin/

How to share Ubuntu drive

Today I need to share some testing data (deployment package) from one Ubuntu to another. Probably the simplest way is to install samba-server to Ubuntu and access it from the second one.

How to install samba server in Ubuntu

To install samba server, use:

sudo apt-get install samba
sudo smbpasswd [user-name]

When asked, enter new samba access password for selected user. Now you need to install gnome-install-tools to be able use shares-admin command to view all shared folders

sudo apt-get install gnome-system-tools
shares-admin

Now setup folder sharing and close dialog. From now, you can use

\\computer\shared

to access your samba-shared folder.

How to access samba sharing from Ubuntu

If you want to access samba share from ubuntu using GUI-way, follow next steps:

1) Open Places->Connect to Server
2) Choose Type: Windows Share
3) To “Server” field enter IP of your server (or computer-name)
4) To “Share” enter path of your shared folder
5) “Folder” keep as is “/”
6) Enter user details based on previous samba server settings

Now click “Connect” and your shared folder should be connected.

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 ;-( :

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

Prerequisities

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

Commands

#creates .deb file
dpkg -b ormdesigner-2.0.1 ormdesigner.deb

#validate .deb file
lintian ormdesigner

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
...

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

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

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.

The most easiest way how to deploy Qt linux Application

I found solution also for the problem with executing application form in-app directory!!, Look to text bellow.
Warning: This solution has one big disadvantage ;-(. It’s necessary to execute application only from app-dir. In other cases system doesn’t find required libraries.
The solution could be run patchelf on the client computer with final installation path

Today I start working on deploying my http://www.orm-designer.com/ Qt application on linux platform.

I read a lot of articles about deploying applications but all of the suggested methods was impractical, too complex or unusable. Here is a list of them:

  • Using qt.conf in Qt resource or application dir. Usefull for Qt libraries, but not third party libraries
  • Installing Qt and third-party libraries in one of the system library path. This method need root permission for app users
  • Using startup script for setting correct LD_LIBRARY_PATH. Really? It’s too complicated for maintenance and users
  • Using -rpath to specify predetermined path. This method requires the users have this directory and have the full access to this directory

Another solution, the simplest one

I’m not sure why this solution isn’t mentioned in Qt forums or anywhere else. Maybe this solution isn’t so clean and perfect for Linux gurus, but it’s perfect for me.

The solution is in simply changing the search path in already compiled application to “.” (current directory) current application location by using $ORIGIN variable, so application will search all libraries in application directory first. It’s simple, it’s clean. All libraries distributed with application will be isolated in application directory and app-loader will not load any other library by mistake.

Updated: The keyword $ORIGIN do the trick, that you can run application from anywhere on your computer. $ORIGIN is absolute path to your executable.

And how to do this change? As first, you need to download small utility called PatchELF. With this application you can change -rpath in app to anything you need.

patchelf --set-rpath '$ORIGIN' ./ApplicationExecutable

And it is. Now you can copy all required libraries to directory with your application and everything will works correctly.

Installation

Download Ubuntu 32/64bit package from site http://hydra.nixos.org/release/patchelf/patchelf-0.6

Note

Maybe there is a way how to set rpath directly in the linking proces by using -rpath linker param. But I didn’t manage it to work.

If you want to display list of shared libraries used by your application, use this command:

ldd ./ApplicationExecutable

External links

Linux find usage


#syntax
#find [SETTINGS] PATH [EXPR]

#write all files
find

#write all files in specified diretory
find /usr/dev

#write files with extension .pro
find /usr/dev -name "*.pro"

#write "file"
find /usr/dev -name "*.pro" | echo file

#wite file followed by all files in ONE row
find /usr/dev -name "*.pro" | xargs echo file

#write found file to specified position in echo command (char $ can be raplaced by anything else, for examle {} )
find /usr/dev -name "*.pro" | xargs -I $ echo file: $

#change date time in all *.pro files 
find /usr/dev -name "*.pro" | xargs -I $ touch -t 201208131010 $

#find specified texts in files
grep "text" *.pro

#find texts and write also a file name
grep -H "text" *

#write only file names (really don't know how it works ;-) )
grep -h "text" * | cut -d: -f1

#change privileges for files with content
grep -h "text" * | cut -d: -f1 | xargs -I $ chmod 777 $

Linux c++ linker – “ld terminated with signal 9”

The linker error “ld terminated with signal 9” is caused by low amount of memory for link process. There are two ways how to fix it.

  • First way is increase computer / virtual machine memory.
  • Second way is by increasing swap file size.

How to increase swap file size

#create new swap file 512x1M size filled with zeros
sudo dd if=/dev/zero of=/extraswap bs=1M count=512

#setup file as a swap file
sudo mkswap /extraswap

#enable created swapfile
sudo swapon /extraswap

If you want to use this swap file also after your computer reboot, you have to do also following steps:

#edit fstab
sudo nano /etc/fstab

#add following line to /etc/fstab
/extraswap           swap                    swap    defaults        0 0

[/sourcecode]

Additional swap-file commands

Here is a list of additional commands which can be useful when working with swap file


#show memory information in KB
free -k

#show existing swap file sizes in KB
swapon -s

External articles about this subject:

http://www.thegeekstuff.com/2010/08/how-to-add-swap-space/

https://www.linux.com/learn/tutorials/442430-increase-your-available-swap-space-with-a-swap-file

http://www.saicharan.in/blog/2009/06/30/ld-terminated-with-signal-9/