在 OSX 上打开 SDL 窗口时不要打开终端窗口。

3

打开SDL程序时,双击图标会弹出一个终端窗口。我们该如何避免这种情况发生?

我发现在Windows操作系统上,有一个编译选项-mwindows可以做到这一点,但在OSX上无法实现。

以下是我的代码:

#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;
}

这是我的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)

感谢您的提前帮助。PS:对于我的makefile格式,非常抱歉,我无法更改!

请展示一个最小、最简单的程序,以演示其效果,并说明如何编译/构建它。 - Mark Setchell
2个回答

3

我不知道是否有一种“适当”的方法来实现这一点,但是我使用以下命令将您的程序编译成一个二进制可执行文件:main

clang++ main.cpp $(pkg-config --cflags --libs sdl2) -o main

接着我使用了这里的appify工具,将其转化为常规的"应用程序"

appify main "Mark App"

当我双击我的漂亮新Mark App时,它会弹出一个SDL窗口而不是终端。


如果您启动Xcode并单击文件->新建项目,它将为您提供创建"命令行工具""Cocoa应用程序"的选项。我猜如果您这样做并创建了这两种类型的应用程序,则可以比较并查看生成的文件之间的区别,然后进行操作,但我自己不知道。


这个问题的答案提供了一些关于这个东西的见解和相关术语... https://dev59.com/qnVD5IYBdhLWcg3wVKEb - Mark Setchell
非常棒的技巧!我之前不知道。可惜,我在另一个项目(使用OpenGL)上测试了一下,但它并没有起作用。对我来说有趣的是它生成的模糊窗口(至少在我的电脑上)。我有时会遇到像那样模糊的窗口程序,这可能是一个解释。 - kipgon
如果您能提供一些在窗口中绘制图形的代码,我可以看看它是否会在我的iMac上变得模糊... - Mark Setchell
很好。实际上,我上面发布的代码在应用化时已经出现了模糊。使用OpenGL则不同,我使用了一个测试场景来绘制单个三角形,在这种情况下,窗口会显示出来(再次没有终端窗口!),但是三角形并不会出现。 - kipgon
制作应用程序包确实是“正确的方法”。要了解不正确的方法,请参阅我的答案。 - Brad Allred

3
这实际上非常容易做到,与SDL或您的构建系统无关。
首先是一个旁注:
正确的方法是生成一个“应用程序包”。有很多现有的问题/文档介绍如何生成。@Mark Setchell在他的答案中涵盖了其中一种方法。
如果出于某种原因您希望避免使用应用程序包,请继续阅读以下内容。
实际发生的情况是什么:
当您双击可执行文件或应用程序时,它实际上并没有执行。发生的情况是将路径传递给Launch Services,然后它将检查是否为“应用程序包”或其他内容。如果不是应用程序包,则LS会检查其数据库以查看应该使用哪个应用程序打开它。您可以通过在Finder中使用“获取信息”来查看,在独立二进制文件的情况下,它被设置为“打开方式”Terminal.app。这就是双击二进制文件时终端会打开的原因。
如何更改行为
您需要让启动服务相信您双击的是一个应用程序包。您需要做的唯一一件事就是将 .app 扩展名添加到您的二进制文件中。就是这样。
我刚在 10.13 上测试了一下,通过在 Xcode 中创建一个新的“命令行实用程序”,我只需为其添加一个 .app 扩展名,然后双击它,它就可以正常打开和运行。我不确定是否会遇到问题(除了明显的问题)使用某些使用 stdinstdout 的东西(stderr 似乎被路由到系统控制台)
您甚至可以通过 Xcode 直接将 Info.plist 文件嵌入二进制文件中(构建设置->打包->在二进制文件中创建 Info.plist 部分),如果需要或者只想要一个版本或者在 Finder 中显示一些东西。 限制 但是有一个注意事项,如果涉及到代码签名,您不能只拆开现有的应用程序包来尝试它。从现有的捆绑链接到框架的二进制文件的 @rpath 将需要更改。同样适用于任何捆绑资源。

如前所述,您实际上没有stdinstdout。SDL应用程序可能不关心,因为它将创建自己的UI;除了可能需要记录日志,应该将其定向到控制台。


OP提到的模糊问题有什么见解吗? - Mark Setchell
@MarkSetchell,我能想到他通过终端打开和我们两种方法的唯一区别是环境。你可以通过在“Info.plist”中输入来控制环境(以及许多其他事情)。我不知道具体控制它的环境变量是什么,但这是一个与 OP 相关的单独问题。 - Brad Allred
@BradAllred 我想不出比这更简单的解决方案了!非常感谢。 - kipgon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接