在Windows上使用Clang链接SDL2时出现错误 "LNK1561: 必须定义入口点"。

10
我正在尝试在Windows上使用clang编译和链接SDL2应用程序。这样做的原因是为了使我的开发环境与其他使用OSX和XCode(使用clang编译)的团队成员保持一致。由于Visual C++编译器比clang编译器宽松得多,我可能会提交无法在clang下编译的更改。我不想安装VS 2015来使用实验性的LLVM构建环境。我已经在Windows上安装了LLVM/clang工具(未从源代码构建,只是从这里下载了二进制文件),并成功地使用clang构建和运行了“hello world”控制台应用程序。我想要一个批处理文件,允许我定期使用clang进行构建和链接,以确保我的代码是安全的提交。当链接一个简单的单文件SDL2应用程序时,我收到以下链接器错误:
LINK : fatal error LNK1561: entry point must be defined
clang++.exe: error: linker command failed with exit code 1561 (use -v to see invocation)

这篇文章建议将链接子系统SDL2: LNK1561: entry point must be defined设置为CONSOLE,尽管我不确定在命令行编译时该如何操作。据我所知,如果没有指定,默认应该是CONSOLE。

根据Why SDL defines main macro?中的内容,我的主入口函数应该是int main(int argc, char* argv[])。

以下是我使用的批处理文件:

CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat"
clang++ -std=c++11 main.cpp -I./include/SDL2 -L./lib -lSDL2main -lSDL2

据我所知,包含目录和库目录都是正确的。链接器可以找到库文件,编译器也能看到包含的文件。

为了简单起见,我使用的测试编译器/链接器的代码直接来自lazy foo的介绍教程,可以在此处找到:http://lazyfoo.net/tutorials/SDL/01_hello_SDL/index2.php

/*This source code copyrighted by Lazy Foo' Productions (2004-2015)
and may not be redistributed without written permission.*/

//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main( int argc, char* args[] )
{
    //The window we'll be rendering to
    SDL_Window* window = NULL;

    //The surface contained by the window
    SDL_Surface* screenSurface = NULL;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
    }
    else
    {
        //Create window
        window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( window == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        }
        else
        {
            //Get window surface
            screenSurface = SDL_GetWindowSurface( window );

            //Fill the surface white
            SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );

            //Update the surface
            SDL_UpdateWindowSurface( window );

            //Wait two seconds
            SDL_Delay( 2000 );
        }
    }

    //Destroy window
    SDL_DestroyWindow( window );

    //Quit SDL subsystems
    SDL_Quit();

    return 0;
}

有没有人知道在Windows下使用clang链接SDL时为什么会收到这个链接器错误?

2个回答

8

MSVC链接器使用/subsystem:windows选项来设置GUI模式(并使用WinMain而不是main),因此你需要传递它:

clang++ -std=c++11 main.cpp -I./include/SDL2 -L./lib -lSDL2main -lSDL2 -Xlinker /subsystem:windows

请注意 -lSDL2main,在链接 SDL2 之前必须先链接 SDL2main - Ivan Rubinson
1
原问题中已经是“正确”的顺序了,但是只有使用GNU链接器才能生效。MSVC链接器不关心库的顺序。 - keltar
非常感谢keltar!问题已解决! 还要感谢Ivan,我一直在想这个问题,所以我从一个旧项目的先前工作的shell脚本中提取了命令顺序。 - radcore
当前版本出现sdl2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp_CommandLineToArgvW referenced in function main_getcmdline错误。已在他们的论坛上发布问题 - Denis Glotov
1
对于这个特定的例子,如果不链接-lShell32,我无法让它工作。 - not2qubit
@not2qubit 谢谢你,没有这个我也无法使用。我使用的是Windows 11,如果这有关的话。 - undefined

1

LINK : 致命错误 LNK1561:必须定义入口点 clang++.exe: 错误:链接器命令失败,退出码为1561(使用-v查看调用)

通常发生在没有 main(...) 函数的情况下。

SDL“窃取”了主函数,所以你的 int main(int, argc[]*) 实际上并不是入口点。

入口点在 SDL2main.lib 中定义。你必须告诉clang的链接器与它链接。(注意:必须先链接 SDL2main 再链接 SDL2。)

还要注意,无论你在哪里定义你的 main(...) 函数,你都必须 #include "SDL.h"


谢谢Ivan,我以前遇到过那些问题,但这次不是那样。我没有明确指定链接器要使用的子系统(请参见上面keltar的答案)。 - radcore

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