Problem with Qt compilation under Windows 64-bit

This short post will show you how to resolve following error during Qt compilation on 64-bit windows:

Creating library ..\..\..\..\lib\QtWebKitd4.lib and object ..\..\..\..\lib\Qt
WebKitd4.exp
PluginViewWin.obj : error LNK2019: unresolved external symbol _HBeginPaint refer
enced in function "private: static struct HDC__ * __cdecl WebCore::PluginView::h
ookedBeginPaint(struct HWND__ *,struct tagPAINTSTRUCT *)" ([email protected]
[email protected]@@[email protected]@[email protected]@PEAUtagP [email protected]@@Z)
PluginViewWin.obj : error LNK2019: unresolved external symbol _HEndPaint referen
ced in function "private: static int __cdecl WebCore::PluginView::hookedEndPaint
(struct HWND__ *,struct tagPAINTSTRUCT const *)" ([email protected]@Web
[email protected]@[email protected]@[email protected]@@Z)
..\..\..\..\lib\QtWebKitd4.dll : fatal error LNK1120: 2 unresolved externals
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 9.0\
VC\BIN\x86_amd64\link.EXE"' : return code '0x460'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 9.0\
VC\BIN\nmake.exe"' : return code '0x2'

This error is caused by bug in QMAKE_HOST variable used in WebCore.pro file. This variable is tested to determine destination platform (x86 or x64).
This variable contains x86 value also on 64-bit builds instead of x86_64 value. This value is tested on the following line in a WebCore.pro file:

win32:!win32-g++*:contains(QMAKE_HOST.arch, x86_64):{

If you want to fix this error, simply replace QMAKE_HOST by QMAKE_TARGET variable. Updated line should look like this:

win32:!win32-g++*:contains(QMAKE_TARGET.arch, x86_64):{

After this update all required asm defines are correctly included and build of WebKit will be successful.

Update for this error

In newer versions of Qt there is already applied fix the error with QMAKE_HOST / QMAKE_TARGET, but also there is a new problem ;-(.

The Problem is in the following “if” definition:

   if(win32-msvc2005|win32-msvc2008):equals(TEMPLATE_PREFIX, "vc") {
        SOURCES += \
            plugins/win/PaintHooks.asm
    }

When you compile your project for MSVC 2010, .asm file isn’t included. It’s necessary to add win32-msvc2010 to this definition. So updated WebCore.pro for Qt 4.8 will look like this:

 if(win32-msvc2005|win32-msvc2008|win32-msvc2010):equals(TEMPLATE_PREFIX, "vc") {
        SOURCES += \
            plugins/win/PaintHooks.asm
    }

Next problem solution

Next problem which I found during compilation is wrongly set QMAKE_TARGET.arg. For unspecified reason, when I compile 64bit library in 64bit system in 64bit VS command line, this variable has value x86 instead of x86_64.
The problem is in the qmake project.cpp file. QMAKE trying to determine 64/32 bit version based on the %PATH% configuration. Qmake search for VS-PATH\bin\amd64 of \bin\x86_amd64 string. Unfortunately there is a bug in concating searched string. This is how looks original project.cpp file at line 3177:

QString vcBin64 = qgetenv("VCINSTALLDIR").append("\\bin\\amd64");
QString vcBinX86_64 = qgetenv("VCINSTALLDIR").append("\\bin\\x86_amd64");

The problem is, that VCINSTALLDIR contains \ at the end of the string, and then we append \ again. So, result is:

QString vcBin64 = qgetenv("VCINSTALLDIR");
if ( vcBin64.at( vcBin64.size()-1 ) != '\\' )
  vcBin64.append("\\");
vcBin64.append("bin\\amd64");

QString vcBinX86_64 = qgetenv("VCINSTALLDIR");
if ( vcBinX86_64.at( vcBinX86_64.size()-1 ) != '\\' )
  vcBinX86_64.append("\\");
vcBinX86_64.append("bin\\x86_amd64");

Now, QMake correctly determine 32/64 bit compilation and then correctly include PaintHooks.asm and your Qt WebCore will be sucesfully compiled.

Collection of links about ORM, Datamapper and design patterns

Domain model

http://www.slideshare.net/weierophinney/architecting-your-models

ORM design patterns

http://martinfowler.com/eaaCatalog/mapper.html
http://martinfowler.com/eaaCatalog/dataMapper.html

DataMapper

http://stackoverflow.com/questions/207758/data-mapper-pattern
http://stackoverflow.com/questions/762252/fowler-data-mapper-object-creation
http://stackoverflow.com/questions/4658340/should-data-mapper-reference-domain-model
http://stackoverflow.com/questions/1977684/should-a-finder-method-be-part-of-the-data-mapper-or-part-of-the-domain-class
http://stackoverflow.com/questions/3738687/using-the-data-mapper-pattern-should-the-entities-domain-objects-know-about-th

Anemic domain model

http://www.martinfowler.com/bliki/AnemicDomainModel.html (Anemic domain model – why huge service layer  is bad)
http://stackoverflow.com/questions/258534/anemic-domain-model-pros-cons

Data Mapper best practices

http://stackoverflow.com/questions/4465237/doctrine2-best-practice-should-entities-use-services
http://stackoverflow.com/questions/4108291/using-entitymanager-inside-doctrine-2-0-entities/4109458#4109458

Doctrine2 articles

http://www.doctrine-project.org/docs/orm/2.0/en/cookbook/aggregate-fields.html

Qt programming tips

How to configure mkspec for paralel builds on Windows

Edit qmake.conf file in Qt\mkspecs\win32-msvcXXXX. Add -MP2 / -MP4 to the following defines:

QMAKE_CFLAGS_RELEASE    = -O2 -MD -MP4
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MD -Zi -MP4
QMAKE_CFLAGS_DEBUG      = -Zi -MDd -MP4

How to deploy Qt application on MacOs

Missing dylib libraries

If your application using some externals dynamic libraries (called .dylib in MacOs system), you have to provide all these libraries. The simplest way is to provide these libraries into the Application.app directory.

Find out which libraries are used

Qt provide really useful tool called “otool” which serves to lots of purpose. One of them is to detect which shared libraries are required by our application. For this purpose otool has parameter -L. The usage is following:

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

Output could looks like this:

./Test1:
        libboost_iostreams.dylib (compatibility version 0.0.0, current version 0.0.0)
        libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0)
        libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
        libboost_thread.dylib (compatibility version 0.0.0, current version 0.0.0)
        libboost_date_time.dylib (compatibility version 0.0.0, current version 0.0.0)
        libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)
        /Users/dev/dev/SharedLibraries/libiconv/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.0.0)
        /Users/dev/dev/ExternalLibraries/../SharedLibraries/libxml/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.8.0)
        /Users/dev/dev/ExternalLibraries/../SharedLibraries/libxslt/lib/libxslt.1.dylib (compatibility version 3.0.0, current version 3.26.0)
        /Users/dev/dev/ExternalLibraries/../SharedLibraries/libxslt/lib/libexslt.0.dylib (compatibility version 9.0.0, current version 9.15.0)
        /Users/dev/dev/ExternalLibraries/yaml-cpp-0.2.5/build/libyaml-cpp.0.2.dylib (compatibility version 0.2.0, current version 0.2.5)
        QtGui.framework/Versions/4/QtGui (compatibility version 4.7.0, current version 4.7.0)
        QtCore.framework/Versions/4/QtCore (compatibility version 4.7.0, current version 4.7.0)
        /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 625.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Output from “otool” is simmilar to linux tool “ldd”.

The Mac Deployment Tool

Because manual copying and configuring all shared libraries to our application could be difficult, Qt have deployment tool which do all work for us. Tool is called “macdeployqt” and can be found in /Developer/Tools/Qt/macdeployqt.

 /Developer/Tools/Qt/macdeployqt ./GeneratedFilesMacOs/Debug/Test1.app

Note: Every time when you call macdeployqt tool, project have to be build from scratch. But is sufficient when whole result directory is removed and linked again:

rm -rf ./GeneratedFilesMacOs/Debug/Test1.app/
make

g++ template method problem

Quick post about problem which I already solved, but think that could be handy for someone else.

I have following code:

template<class T>
struct Test
{
	T val;
	template <class T2>
	void DoSomething( T2 &obj )
	{
		obj.FindByType<int>();
	}
};

When compiling under Visual studio, everything is ok. But when try the same code snippet under g++, have following error:

test.cpp: In member function ‘void Test<T>::DoSomething(T2&)’:
test.cpp:48: error: expected primary-expression before ‘int’
test.cpp:48: error: expected ‘;’ before ‘int’

This is because compiler doesn’t known FindByType method, because T2 is templated argument. The solution which I found is in adding keyword template before FindByType method name. So updated source code will look like this:

template<class T>
struct Test
{
	T val;
	template <class T2>
	void DoSomething( T2 &obj )
	{
		obj.template FindByType<int>();
	}
};

After this update, code will be compiled correctly under both compilers.

Git tips

Show files status

git status #show all files
git statis -u -s #show untracked in short listing

Commit with message

git commit -m"text"

Recursive add files by mask to git

git add *.mask -A

Linux-recursive remove some files

find -iname '*mask' | xargs rm

How to create global .gitignore file

git config --global core.excludesfile /file-path/.gitignore-global

TENG – c++ templating engine

Project site: http://teng.sourceforge.net/?page=home

External project documentation: http://teng.olmik.net/

Latest TENG source code: http://teng.cvs.sourceforge.net/teng/ (Note: Source code referenced from main site isn’t latest! )

How to compile TENG on windows

Compilation under Windows is possible only using MinGW and with few modifications in TENG code (because there is few glitch which didn’t meet c++ standards). If you want more information or updated TENG version, please let me know.

How to install and configure git with ssh key

  • Download git client depends on your OS platform
  • Open your .ppk key in PuTTY Key generator and export key to OpenSSH key:
  • Content of this OpenSSH key store to file ~/.ssh/id_dsa (copy exported key to ~/.ssh folder and rename it to id_dsa)
  • Now change security permissions on this file to 400 (chmod 400 ~/.ssh/id_dsa)
  • Now cal ssh-add to load id_dsa key

And it’s done. Now you can use your git. For example clone some repository:

git clone ssh://[email protected]/~/repository/example.git

Automatic ssh-key loading during startup:

TODO

List of usefull links for Visual Studio

How to customize autoexp.dat in Visual Studio 2005

http://mariusbancila.ro/blog/?p=26
http://www.virtualdub.org/blog/pivot/entry.php?id=120

Example visualizator for XString

String::CStringSmart<String::malloc_string_trait<String::string_trait<char> > >{
  preview([$c.m_pszData,s])
  stringview([$c.m_pszData,sb])
}

String::CStringSmart<String::malloc_string_trait<String::string_trait<wchar_t> > >{
  preview([$c.m_pszData,su])
  stringview([$c.m_pszData,sub])
}

How to configure STEP-INTO for Visual Studio 2005

External links:
Google group
www.cprogramming.com

http://blogs.msdn.com/b/andypennell/archive/2004/02/06/69004.aspx

Example how to setup ingoring step-into for MFC CString for VS2005

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\NativeDE\StepOver]
"\"20\""="\\scope:CString.*\\:\\:.*=NoStepInto"
"\"21\""="\\scope:CSmartObjPtr.*\\:\\:.*=NoStepInto"

Example how to setup ingoring step-into for MFC CString for VS2010 on 64bit system

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\NativeDE\StepOver]
"22"=".*CStringSmart.*=NoStepInto"

Mac OS problem with samba mount

Sometime after some time or when MacOS system is waked-up samba mounts stop working.

Instead of  mounting a drive reporting following error:

mount_smbfs: could not find mount point /mnt/disk_d: Socket is not connected</div>
mount_smbfs: could not find mount point /mnt/disk_e: Socket is not connected</div>
mount_smbfs: mount error: /mnt/disk_p: Socket is not connected</div>

After a little search I found following tip. It could help:

1. Click Start, and then click Run. 
2. Type regedit, and then click OK. 
3. Navigate to the following key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters 
4. In the right pane, double-click the IRPStackSize value.

NOTE: If the IRPStackSize value does not already exist, use the following procedure to create it:a. In the Parameters folder of the registry, right-click the right pane. 
b. Point to New, and then click DWord Value. 
c. Type IRPStackSize.

IMPORTANT: Type "IRPStackSize" exactly as it is displayed because the value name is case-sensitive. 

5. Change the Base to decimal. 
6. In the Value Data box, type a value that is larger than the value that is listed. 

If you created the IRPStackSize value using the procedure described in step 4, the default value is 15. It is recommended that you increase the value by 3. Therefore, if the previous value was 11, type 14, and then click OK. 
7. Close the Registry Editor. 
8. Restart the computer.

Simple iconv (libiconv) example

Here is a simple example how to use the iconv library.

#include <iostream>
#include <fstream>
#include <iconv.h>

int main(int argc, char *argv[])
{
	char src[] = "abcčde";
	char dst[100];
	size_t srclen = 6;
	size_t dstlen = 12;

	fprintf(stderr,"in: %s\n",src);

	char * pIn = src;
	char * pOut = ( char*)dst;

	iconv_t conv = iconv_open("UTF-8","CP1250");
	iconv(conv, &pIn, &srclen, &pOut, &dstlen);
	iconv_close(conv);

	fprintf(stderr,"out: %s\n",dst);
}

During my attempts with libiconv library I encountered two different problems:

Converting function returns 0, but pOut is empty

This is because iconv function modify pOut ptr during string processing. When you need to access output buffer after iconv() function finish its work, you have to access it via different pointer than one passed to this function. In my code I’m using *dst and pOut ptrs;

Conversion between different character sets returns strange results

Check if have correct order of parameters in your iconv_open() and iconv() function. Function iconv_open() has as its first parameter OUTPUT encoding, and as second parameter INPUT encoding. While iconv() function has as first parameters INPUT variables, and as second parameters OUTPUT variables. This inconsistency is really confusing.

Notes

Official libiconv site: http://www.gnu.org/software/libiconv/

Official libiconv documentation: http://www.gnu.org/software/libiconv/documentation/libiconv-1.13/