Building a Windows application for Console subsystem

I have noticed that JUCE doesn't support building for the Console subsystem by default anymore. Is that an intentional change?

Our product can be built in a few different ways, one way is the usual way with GUI, but another way is as a command line application. It still runs the event loop for timers and such, but it needs to work as a console application (i.e. it displays stdout and stderr on the console and it usually doesn't display a GUI).

The reason why it doesn't build is that if you build a console application, the linker expects int main(int, char**) rather than WinMain(....) as your entry point (as on the UNIX platforms).

I got it working by changing the preprocessor checks in juce_Initialisation.h:95 and juce_ApplicationBase.cpp:141 to check if _CONSOLE is not defined:

 #if JUCE_WINDOWS && !defined(_CONSOLE)

and to add

#ifdef _CONSOLE
const char* const* juce_argv = nullptr;
int juce_argc = 0;

somewhere in the native windows code (I put it in juce_win32_Files.cpp for consistency).


Have a look here:

[Haven't checked it on the *very* latest Introjuce, but OK last week]

Yes - I was under the impression that this was already working fine without any changes needed?

It will work if we write the main() function ourself for the console builds, and use the START_JUCE_APPLICATION for the other builds, but I thought it'd be nice if the START_JUCE_APPLICATION macro also works in console builds.


In that case, how is what you're doing different from just writing a normal app and invoking it from the command line?

We have

// This macro creates the application's main() function..

in our main.cpp file, rather than

int main(int argc, char *argv[])
    // code goes here....

The former will always generate a WinMain() function on Windows, even if building for the console subsystem.

I saw the Introjucer will just put the latter into your main.cpp file if you generate a console app, which will build correctly. But it won't work on Windows if you make a build for the Windows subsystem.

I guess since we make builds for both the console and windows subsystems from the same source tree, we are a bit of a corner case here.


Sorry, my question wasn't very clear - I meant: if you need an event loop, then what exactly is wrong with just building a normal Windows app and then invoking it from the command-line? I do that all the time (e.g. the introjucer itself can be run as a command-line app with arguments) and AFAIK the only difference is that you write your main function differently.

Sorry, to jump into the discussion, but I wrote that particular mode. The reason why we want to use the CONSOLE sub-system is because it is supposed to behave like a terminal application. I.e. if you start it from the command line, it will block the command line and key presses can be read via stdin/cin and stdout/stderr/cout/cerr go to the terminal. It also allows us to hook up sigints to catch the CTRL-C event etc.. All these things are not possible in the normal WINDOWS sub-system.

I hope that explains it.




Ok, well I've no objections to making it handle the _CONSOLE flag as described in the original post. I'll make those changes shortly - let me know if it's enough to get you running!

Not yet, you also need to change the START_JUCE_APPLICATION macro in juce_Initialisation.h (line 95). After that change it will work.


Ah yes, missed that one.. Done now, thanks!

A bit late to the party, but I need to have a console in my Windows code as well. Using the _CONSOLE preprocessor flag works, but only if I also change the linker SubSystem to Console in the Visual Studio project. This adds


to the *.vcxproj file for the selected build. This change is overwritten by Introjucer, however, so my question is: is there a way to add this to the Introjucer? If so, where and how? If not, what is the best workaround?

I believe I did this by adding the text below in the [size=16]Extra linker flags[/size] section of the Visual Studio configuration.

[font=Consolas][size=20]/SUBSYSTEM:CONSOLE [/size][/font]

The introjucer will set this stuff for you if you set your project type to "Application (Non-GUI)"

Cool, setting it in the Introjucer works fine. Missed that one.