Wednesday, October 10, 2007

Windres problem and solution

A very technical post as first post on my blog. I publish the solution to a problem that we encountered yesterday, in the hope that it will help others.

Windres is an utility part of mingw or cygwin, that one uses on Windows to compile and add resources to an executable. An example of resources are the application icon, or the version information. There are more types but this is usually the one we are concerned about.

Our windres generation line part of our cmake build process is here:
ADD_CUSTOM_COMMAND( 
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qyzis_ico.obj
COMMAND windres.exe
-I${CMAKE_CURRENT_SOURCE_DIR}
-o ${CMAKE_CURRENT_BINARY_DIR}/qyzis_ico.obj
-i${CMAKE_CURRENT_SOURCE_DIR}/qyzis_ico.rc
)


The problem we had was with path containing spaces. On windows, those are common beast. If you do a checkout on the desktop, the actual path of your checkout is C:\Document and vSettings\[User Name]\Desktop which contain spaces. If you run windres on a file in such a path, you get an error about gcc not finding the file. Why gcc while we are talking windres. The man page of windres gives the hint:

--preprocessor program
When windres reads an rc file, it runs it through the C
preprocessor first. This option may be used to specify the
preprocessor to use, including any leading arguments. The default
preprocessor argument is gcc -E -xc-header -DRC_INVOKED.


Oh, windres runs the rc files through the gcc preprocessor. But it does not quote them properly so gcc gets confused. We tried several combination of adding quotes and backslash to solve the problem, but it did not work. windres expects the filename unquoted and pass it like that to gcc.

Luckily, there is a way out of this. Two ways actually.

First solution :


There is a bug reported in the mingw bug tracker (I can find the reference now though) about this problem and a proposed fix. The bug has been closed and a fix is included in the mingw CVS. So, for the brave, you can recompile mingw and probably get rid or the problem.


Second solution :


The fix was quite trivial:
ADD_CUSTOM_COMMAND( 
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qyzis_ico.obj
COMMAND windres.exe
-I${CMAKE_CURRENT_SOURCE_DIR}
-o ${CMAKE_CURRENT_BINARY_DIR}/qyzis_ico.obj
< ${CMAKE_CURRENT_SOURCE_DIR}/qyzis_ico.rc
)

Instead of specifying a file path to windres, we just pipe the file through its standard input. Works like a charm. You can thank orzel for that solution.

No comments: