【问题标题】:Don't open terminal window while opening SDL window on OSX在 OSX 上打开 SDL 窗口时不要打开终端窗口
【发布时间】:2019-02-17 23:45:06
【问题描述】:

打开 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
.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 格式我没能改变它!

【问题讨论】:

  • 请展示最小、最简单的程序来演示效果,并说明您如何编译/构建它。

标签: c++ macos makefile sdl


【解决方案1】:

这实际上很容易做到,与 SDL 或您的构建系统无关。

先放一边

实现此目的的正确方法是生成“应用程序包”。有很多关于如何制作的现有问题/文档。 @Mark Setchell 在他的回答中涵盖了一种这样的方法。

如果出于某种原因您希望避免使用应用程序包,请继续阅读如何做。

实际情况

当您双击可执行文件或应用程序时,它实际上并没有执行它。发生的情况是路径被传递给Launch Services,然后它将检查某个东西是“应用程序包”还是其他东西。如果它不是一个应用程序包,LS 检查它的数据库以查看它应该用什么应用程序打开它。您可以看到(通过在 Finder 中使用“获取信息”)在独立二进制文件的情况下,它被设置为“打开方式”Terminal.app。这就是双击二进制文件时终端打开的原因。

你如何改变行为

您需要让 Launch Services 相信您双击的是一个 app bundle。您唯一需要做的就是将.app 扩展添加到您的二进制文件中。就是这样。

我刚刚通过在 Xcode 中创建一个新的“命令行实用程序”在 10.13 上对此进行了测试。我只是添加了一个.app 扩展名并双击它,它打开并运行得很好。我不确定您是否会遇到使用 stdinstdout 的问题(除了显而易见的问题)(stderr 似乎被路由到系统控制台)

如果您需要一个或只是想在 Finder 中显示一个版本或其他内容,您甚至可以通过 Xcode(构建设置 -> 打包 -> 在二进制中创建 Info.plist 部分)将Info.plist 文件直接嵌入到二进制文件中。

限制

但有一点需要注意,如果涉及代码签名,您不能只是拆开现有的应用程序包来尝试它。需要更改从链接到框架的现有捆绑包中提取的二进制文件的@rpath。同上任何捆绑资源。

如前所述,您确实没有stdinstdout。 SDL 应用程序可能并不关心,因为它会创建自己的 UI;除了可能应该直接在控制台上的日志记录。

【讨论】:

  • 对 OP 提到的模糊性有何见解?
  • @MarkSetchell 我能想到的他通过终端打开和我们的任何一种方法之间的唯一区别是环境。您可以通过Info.plist 中的条目来控制它(以及许多其他事情)。我不知道具体是什么环境变量可以控制它,但对于 OP 来说,这是一个单独的问题。
  • @BradAllred 我无法想象更简单的解决方案!非常感谢
【解决方案2】:

我不知道是否有 "正确" 方法可以做到这一点,但我将您的程序编译成一个名为 main 的二进制可执行文件:

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

然后我使用here中的appify,将其变成了一个普通的“app”

appify main "Mark App"

当我双击我闪亮的新 Mark App 时,它会弹出一个 SDL 窗口并且没有终端。


如果您启动Xcode 并单击File->New Project,它将为您提供创建“命令行工具”“可可应用程序”的选项时间>。我想如果您这样做并创建了两种类型的应用程序,您可以比较并查看生成的文件有什么区别并执行此操作,但我自己不知道。

【讨论】:

  • 这个问题的答案让我们对这些东西有了一些了解,以及相关的术语......stackoverflow.com/q/12332/2836621
  • 非常好的技巧!我不知道。可悲的是,我在另一个项目(使用 OpenGL)上对其进行了测试,但它不适用于这个项目。对我来说有趣的是它生成的模糊窗口(至少在我的计算机上)。我有时会遇到窗口像这样模糊的程序,这可能是解释。
  • 如果你愿意提供一些在窗口中绘制东西的代码,我可以看看它是否在我的 iMac 上变得模糊......
  • 很好。实际上,我上面发布的代码在我应用它时已经显得模糊了。使用 OpenGL 就不同了,我使用了一个绘制单个三角形的测试场景,在这种情况下,窗口显示(模糊且再次没有终端窗口!)但三角形没有出现。
  • 制作应用程序包确实是“正确的方式”。有关完成此操作的不正确方法,请参阅我的答案。
猜你喜欢
  • 2020-08-15
  • 1970-01-01
  • 2014-07-20
  • 2010-12-20
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
相关资源
最近更新 更多