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.

5 Responses to “Windres problem and solution”

  1. keeney Says:

    Thanks, it works!

  2. orzel Says:

    Nice to hear the blog has been useful for someone :-)

  3. Joshua Says:

    I had a similar problem, except I didn’t have any spaces in the path. Instead, windres wasn’t seeing the backslashes being passed to it. The problem turned out to be that codeblocks wasn’t calling MinGW’s windres — it was calling the first windres.exe found in my path — which happened to be Cygwin’s. I renamed cygwin’s windres.exe to something else and the problem was solved. A better “solution” is to place MinGW ahead of Cygwin in my path.

  4. admin Says:

    When using mingw, you should get rid or cygwin as much as you can. Usually, I simply discard cygwin and work in a dos shell. That’s really annoying in terms of shell capabilities but at the same time, it avoids tons of problems.

  5. AgiceRuidge Says:

    I don’t even know,fellow!) continued to write in the same vein, it is interesting people!

Leave a Reply