4

I'd like to build my application such that debug mode is a console application and release mode is a Win32 application. According to the documentation I need to add WIN32 to add_executable depending on whether I want a console application or not.

Because I'm using Visual Studio, I can't use CMAKE_BUILD_TYPE (the generated project contains multiple configurations). How can I tell CMAKE to use WIN32 for release builds and omit it for debug builds?

Liviu
  • 1,859
  • 2
  • 22
  • 48
Gili
  • 86,244
  • 97
  • 390
  • 689

2 Answers2

7

Quoting http://www.cmake.org/Wiki/VSConfigSpecificSettings

if(WIN32)
   set_target_properties(WindowApplicationExample PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
   set_target_properties(WindowApplicationExample PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
   set_target_properties(WindowApplicationExample PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
   set_target_properties(WindowApplicationExample PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE")
   set_target_properties(WindowApplicationExample PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:windows")
   set_target_properties(WindowApplicationExample PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:windows")
endif(WIN32)

UPDATE: This feature is broken in recent versions due to a bug. One workaround I've found is to specify "/SUBSYSTEM:windows" instead of "/SUBSYSTEM:WINDOWS". That seems to work for some reason.

Gili
  • 86,244
  • 97
  • 390
  • 689
  • I have the same problem, but this solution does not work with VC++ 2010. – fbafelipe Jul 02 '12 at 04:17
  • @fbafelipe, I was using VC++ 2010 when I wrote this answer so unless something changed (in VC++ or CMake) it should work. Did you apply the workaround mentioned at the bottom? – Gili Jul 02 '12 at 19:07
  • 1
    Yes I did, stil doesn't work. I forgot to mention, it's VC++ 2010 express I use to open the project (although CMake generate VC++ 2010 project, and I don't thing it make any difference). I tryed many things, I tryed to change the LINK_FLAGS to all configurations, and it does not change to WINDOWS subsystem. The only way I could get to use windows subsystem was ADD_EXECUTABLE(name WIN32 sources), but that way I can't make debug with console and release with windows. – fbafelipe Jul 03 '12 at 03:16
  • 1
    @fbafelipe, I suggest bringing this up in the CMake mailing list and asking the CMake authors to finally fix this bug. – Gili Jul 03 '12 at 04:40
  • You should change the example code to use `windows` with small letters instead... – Joakim Nov 19 '14 at 12:33
  • @Gili I don't think this is a CMake issue but rather a Visual Studio issue. I mean CMake simply passes the linker flag as it is to Visual Studio, and it seems visual studio makes a difference between `windows` and `WINDOWS`. No? – Joakim Nov 19 '14 at 12:34
  • @Joakim, no. The bug has to do with the fact that CMake generates invalid manifest files for uppercase WINDOWS. Visual Studio doesn't care about the case-sensitivity of SUBSYSTEM. The bug has to do with the contents of the manifest file (which doesn't even contain the SUBSYSTEM flag). – Gili Nov 19 '14 at 20:04
5

Dunno if this bug has been fixed in CMake yet. I'm using VC++ 2010 express and CMake v2.8.10.1 (which is currently the latest release) and I'm still having the exact same problem.

A working solution was provided here: modify your source code (e.g. main.cpp/main.c) by adding:

#ifndef NDEBUG
#pragma comment(linker, "/SUBSYSTEM:CONSOLE")
#endif

Alternatively, you could add the linker flag "/SUBSYSTEM:WINDOWS" to the release-mode build. I'm using this definition which seems to work:

#ifdef _MSC_VER
#    ifdef NDEBUG
#        pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#    else
#        pragma comment(linker, "/SUBSYSTEM:CONSOLE")
#    endif
#endif

Use the entry-point setting in order to avoid linker errors in case you've defined:

int main(int argc, char* argv[]) { ... }
Sigi Schwartz
  • 111
  • 1
  • 7