Search code examples
c++macosmakefilesdl

Don't open terminal window while opening SDL window on OSX


When opening a SDL program, double clicking on the icon, a terminal window pop up too. How can we avoid this ?

I saw that on Windows OS, there's a compilation option -mwindows which do this but it doesn't work on OSX.

Here is my code :

#include <iostream>
#include <SDL2/SDL.h>

int main(int argc, char *argv[])
{
    // SDL window
    SDL_Window* window(0);

    SDL_Event events;
    bool quit(false);

    // Initialize SDL
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "Initialization error : " << SDL_GetError() << std::endl;
        SDL_Quit();

        return -1;
    }

    // Create window
    window = SDL_CreateWindow("Windows", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    if(window == 0)
    {
        std::cout << "Creation error : " << SDL_GetError() << std::endl;
        SDL_Quit();

        return -1;
    }

    // Main loop
    while(!quit)
    {
        SDL_WaitEvent(&events);

        if(events.window.event == SDL_WINDOWEVENT_CLOSE)
            quit = true;
    }

    // Quit SDL
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

And here is my makefile :

# Makefile
.PHONY: clean, mrproper, run

NAME=Program

EXEC=$(NAME)
SRC_DIR=./Sources
HEA_DIR=./Headers
OBJ_DIR=./Objects
SRC=$(wildcard $(SRC_DIR)/*.cpp)
OBJ=$(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRC))

HEA=$(wildcard $(HEA_DIR)/*.h)

FRA_DIR=/Library/Frameworks/SDL2.framework/Headers/

CXX=g++
CXXFLAGS=-W -Wall -std=c++11 -I $(HEA_DIR) \
                             -I $(FRA_DIR)
LDFLAGS=-F/Library/Frameworks -framework SDL2

all: $(EXEC)

$(EXEC): $(OBJ)
    $(CXX) -o $@ $^ $(LDFLAGS)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEA)
    $(CXX) -o $@ -c $< $(CXXFLAGS)

clean:
    @rm -rf $(OBJ_DIR)/*.o

mrproper: clean
    @rm -rf $(EXEC)

run:
    @./$(EXEC)

Thanks in advance

PS : sorry for the format of my makefile I didn't manage to change that !


Solution

  • This is actually really easy to do and has nothing to do with SDL or your build system.

    First an aside

    The proper way to accomplish this is to produce an "app bundle". There are plenty of existing questions/documentation on how to produce one. @Mark Setchell covers one such method in his answer.

    If for some reason you wish to avoid an app bundle read on for how you can.

    What is actually happening

    When you double click an executable or an app it doesnt actually execute it. What happens is the path is passed off to Launch Services which will then check if something is an "app bundle" or something else. If it not an app bundle LS checks its database to see what application it should open it with. You can see (by using "Get Info" in Finder) in the case of a stand alone binary it is set to "Open with" Terminal.app. This is the reason Terminal opens when you double click your binary.

    How you change the behavior

    You need to convince Launch Services that what you are double clicking is an app bundle. The only thing you need to do is add the .app extension to your binary. That's it.

    I just tested this on 10.13 by creating a new "Command Line Utility" in Xcode. I simply added a .app extension to it and double clicked it and it opened and ran just fine. I'm not sure if you might run into issues (aside from the obvious) with something that uses stdin or stdout (stderr seems to be routed to the system console)

    You can even embed an Info.plist file directly into the binary via Xcode (Build Settings -> Packaging -> Create Info.plist Section in Binary) if you need one or just want a version or something to show in Finder.

    Restrictions

    There is a caveat however, if code signing is involved you cant just pull apart an existing app bundle to try it. The @rpath of a binary pulled out of an existing bundle linking to frameworks will need to be changed. Ditto any bundle resources.

    As mentioned before you really have no stdin or stdout. An SDL application likely doesn't care since it will create its own UI; except for maybe logging which should be directed at the console anyway.