C++ Linux 到 Windows 交叉编译错误
Posted
技术标签:
【中文标题】C++ Linux 到 Windows 交叉编译错误【英文标题】:C++ Linux to Windows Cross-compilation error 【发布时间】:2016-10-21 19:46:51 【问题描述】:我正在尝试为 linux 中的 windows 编译一个 C++ 程序。该程序使用 SHGetKnownFolderPath 函数。每当我尝试编译它时,都会出现以下错误:
$ x86_64-w64-mingw32-g++ main.cpp main.h -mwindows -o main.exe
/tmp/cc7yIaVK.o:main.cpp:(.text+0x11c): undefined reference to `SHGetKnownFolderPath'
/tmp/cc7yIaVK.o:main.cpp:(.rdata$.refptr.FOLDERID_Startup[.refptr.FOLDERID_Startup]+0x0): undefined reference to `FOLDERID_Startup'
collect2: error: ld returned 1 exit status
这是我写的代码:
int WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
//get startup folder
if(SHGetKnownFolderPath(FOLDERID_Startup, 0, NULL, &startupFolder) != S_OK)
//error in getting startup folder
return -1;
/*
...
*/
我包含了正确的头文件并定义了 windows 版本:
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#include <shlobj.h>
编辑:根据 mingw.org 文档,我了解到我必须在编译中链接一个 lib 文件,大概是在源文件名之后使用 -l 标志。我不知道我需要的文件的名称是什么。
我不知道还能做什么。
【问题讨论】:
#include
s 和 #define
s 仅对编译时间感兴趣。您没有编译错误,但有链接器错误。所以你需要弄清楚你必须与你的东西链接什么,以便为链接器提供它需要的东西。 github.com/HandBrake/HandBrake/issues/112 有帮助吗?
@Alfe 我也在 google 上看到了该链接,但它不起作用。显然,这些网站现在受到 DDoS 攻击:pcworld.com/article/3133847/internet/…
SHChangeNotifyRegister with QT/MinGW 4.8 cannot link的可能重复
@krOoze 该帖子谈到了 Qt(我没有使用)和 Windows(我没有使用)(从答案中的 DOS 样式路径猜测)。该帖子提供的解决方案不适用于此处。
@Yapoz 很好。不过,该功能似乎在 shell32
中,需要以某种方式链接。
【参考方案1】:
快速查找/nm(具有识别 Windows 二进制文件的合适 nm)0 给出:
rich@dev:~/ellcc-release/libecc/mingw/x86_64-w64-mingw32$ find . -name "*.a" | xargs ~/ellcc/bin/ecc-nm -A | grep FOLDERID_Startup
/home/rich/ellcc/bin/ecc-nm: ./sys-root/mingw/lib/libruntimeobject.a: File format not recognized
./sys-root/mingw/lib/libuuid.a:lib64_libuuid_a-uuid.o:0000000000000000 r .rdata$FOLDERID_Startup
./sys-root/mingw/lib/libuuid.a:lib64_libuuid_a-uuid.o:0000000000000000 R FOLDERID_Startup
rich@dev:~/ellcc-release/libecc/mingw/x86_64-w64-mingw32$
看起来 -luuid 是您所需要的。
我做了一个小测试程序:
rich@dev:~$ cat win.c
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#include <shlobj.h>
int WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
const char *startupFolder;
//get startup folder
if(SHGetKnownFolderPath(&FOLDERID_Startup, 0, NULL, &startupFolder) != S_OK)
//error in getting startup folder
return -1;
/*
...
*/
rich@dev:~$ ~/ellcc/bin/ecc -target x86_64-w64-mingw32 win.c -luuid
win.c:7:57: warning: incompatible pointer types passing 'const char **' to
parameter of type 'PWSTR *' (aka 'unsigned short **')
[-Wincompatible-pointer-types]
if(SHGetKnownFolderPath(&FOLDERID_Startup, 0, NULL, &startupFolder) != S...
^~~~~~~~~~~~~~
/home/rich/ellcc/bin/../libecc/mingw/include/shlobj.h:746:92: note: passing
argument to parameter 'ppszPath' here
...(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
^
1 warning generated.
rich@dev:~$
【讨论】:
您好,感谢您的回答。 -luuid 似乎修复了 FOLDERID_Startup 问题,但在我的错误中我仍然得到对SHGetKnownFolderPath
的未定义引用。我原以为这将通过相同的解决方案来解决。它在这里抱怨它:/tmp/cc5KqFce.o:main.cpp:(.text+0x150)
而不是在 main.cpp 上写一行,所以我认为这是另一个链接器错误。
该符号在 libshell32.a 中定义。我的 clang/mingw 默认包含它,抱歉。添加 -lshell32 应该可以解决它。
不,同样的错误。 -lshell32 似乎没有做任何事情,而 -luuid 删除了 2 个错误中的 1 个,如果这有帮助的话。
这很奇怪,如果我从默认库列表中删除它,链接会失败,但这条线有效:~/ellcc/bin/ecc -target x86_64-w64-mingw32 win.c -luuid - lshell32
也许这与我使用 C++ 而不是 C 的事实有关?如果重要的话,这是我的线路(不起作用):x86_64-w64-mingw32-g++ main.cpp main.h -luuid -lshell32 -o main.exe
以上是关于C++ Linux 到 Windows 交叉编译错误的主要内容,如果未能解决你的问题,请参考以下文章
windows eclipse c++怎么交叉编译linux
从linux交叉编译到windows一个visual studio项目
在 Windows 7 中交叉编译 C 和 C++ 应用程序,在 linux 下使用 MinGW
在 linux 上用 Eclipse 交叉编译,在 windows 上用 eclipse 交叉编译?