Clang C++交叉编译器-从Mac OS X生成Windows可执行文件
Clang C++ Cross Compiler - Generating Windows Executable from Mac OS X
我使用Clang编译器在Mac上使用Xcode创建了一个C++应用程序。
我想编译我的源文件来创建一个可以在windows机器上运行的可执行文件,但我无法让Clang为我生成一个可执行文件。
以下是我尝试过的:
clang++ -std=c++11 -stdlib=libc++ -arch x86_64 class1.cpp class2.cpp... -o executable.exe
这创建了一个可执行文件,但它不能运行(Windows给我一个错误,因为应用程序是16位的-不理解这一点-不能在64位上运行)
clang++ -std=c++11 -stdlib=libc++ -target i386-pc-win32 class1.cpp class2.cpp
出于某种原因,每当我使用-target
标志时,我都会收到一个错误,说明编译器找不到<iostream>
标头,但在其他任何时候它都不会抱怨
我试过使用-Ipath/to/iostreamfolder/
,但这并没有产生任何更好的结果
任何建议都很好!谢谢
我也尝试过'-triple x86-pc-win32'
标志,但我收到了这个警告clang: warning: argument unused during compilation: '-triple x86-pc-win32'
以下是在Mac OS X上使用llvm/clang构建Hello World.exe的分步说明。
在Mac OS X上使用Clang/LLVM交叉编译Hello World for Windows
用自制软件安装llvm。这将包括clang和llvm链接器。
brew install llvm
您需要访问Visual Studio C++库和标头,这些库和标头可通过Visual Studio 2017在Windows 10虚拟机(VM)或Windows 10计算机上获得。在Window上安装Visual Studio,并通过Visual Studio安装程序包括以下"单个组件":
- Windows通用CRT SDK
- Windows通用C运行时
- 用于UWP:C的Windows 10 SDK(X.X.X.X)++
- VC++2017 vXXX工具集(x86、x64)
- Visual C++2017 Redistributable Update
- C++/CLI支持
从Mac上访问MSVC库和头文件。
- (选项1)使用Windows虚拟机并在主机和来宾之间创建共享文件夹
- (选项2)在Windows计算机上创建远程共享,并从Mac连接到它
- (选项3)按照任何许可条款将库和标头复制到您的Mac
在llvm+MSVC安装中查找与以下内容相对应的特定目录:
// LLVM:
INCLUDES: /usr/local/Cellar/llvm/5.0.0/include
// MSVC:
INCLUDES: "C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.11.25503include"
LIBS: "C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.11.25503libx86"
// C Runtime Library (CRT):
INCLUDES: "C:Program Files (x86)Windows Kits10Include10.0.15063.0ucrt"
LIBS: "C:Program Files (x86)Windows Kits10Include10.0.15063.0ucrt"
// User-Mode Library (UM):
INCLUDES: "C:Program Files (x86)Windows Kits10Include10.0.15063.0um"
LIBS: "C:Program Files (x86)Windows Kits10Lib10.0.15063.0umx86"
// 'Shared' includes:
INCLUDES: "C:Program Files (x86)Windows Kits10Include10.0.15063.0shared"
// WinRT includes:
INCLUDES: "C:Program Files (x86)Windows Kits10Include10.0.15063.0winrt"
// Figure out your MSC 'version', e.g.
Visual C++ 2012 (11.0) --> MSC_VER=1700
Visual C++ 2013 (12.0) --> MSC_VER=1800
Visual C++ 2015 (14.0) --> MSC_VER=1900
Visual C++ 2017 (15.0) --> MSC_VER=1910
创建你的Hello World src:
// hello.cc
#include <cstdio>
int main(int argc, char* argv[]) {
printf("Hello, World!n");
return 0;
}
用clang编译:
clang -target i686-pc-win32
-fms-compatibility-version=19
-fms-extensions
-fdelayed-template-parsing
-fexceptions
-mthread-model posix
-fno-threadsafe-statics
-Wno-msvc-not-found
-DWIN32
-D_WIN32
-D_MT
-D_DLL
-Xclang -disable-llvm-verifier
-Xclang '--dependent-lib=msvcrt'
-Xclang '--dependent-lib=ucrt'
-Xclang '--dependent-lib=oldnames'
-Xclang '--dependent-lib=vcruntime'
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
-U__GNUC__
-U__gnu_linux__
-U__GNUC_MINOR__
-U__GNUC_PATCHLEVEL__
-U__GNUC_STDC_INLINE__
-I/usr/local/Cellar/llvm/5.0.0/include
-I/c/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/include
-I/c/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt
-I/c/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared
-I/c/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt
-c hello.cc -o hello.o
链接lld链接器,由clang:驱动
clang -fuse-ld=lld -target i686-pc-win32 -Wl,-machine:x86 -fmsc-version=1900
-o hello.exe hello.o
-L/external/code8-cc/cc/msvctoolchain/x86/lib/msvc
-L/external/code8-cc/cc/msvctoolchain/x86/lib/um
-L/code8-cc/cc/msvctoolchain/x86/lib/ucrt
-nostdlib -lmsvcrt -Wno-msvc-not-found
将hello.exe复制到您的Windows计算机或Windows虚拟机并在PowerShell中运行:
.hello.exe
若要生成64位版本,请更改为"-target x86_64-pc-win32"、"-Wl,-machine:x64",然后链接到x64库。
Clang原则上可以用作交叉编译器:与大多数编译器不同,Clang/LLVM在同一二进制文件中包含不同平台的组件(如代码生成程序、汇编程序和链接器)。
然而,在生产能力中尝试使用它时会遇到许多问题:
-
您需要平台库和标头。要生成可在Windows上运行的可执行文件,您需要链接到的Windows标头和Windows库,如果您正在动态链接,请导入库,或者导入静态库进行静态链接。您应该能够从Visual Studio的安装中获得这些。
-
许多C++功能,如名称篡改和RTTI支持,在Windows上并不完整。使用Clang在Windows上编译Windows时也会遇到同样的问题Windows C++的支持现在已经基本完成了。 -
LLVM项目包括lld链接器,它显然已经足够长了,可以在x86 Windows上自托管,因此可以作为跨平台链接器使用,但是lld还不是clang发行版的标准部分。默认情况下,OS X上的Clang仍然使用OS X平台链接器
ld
,Windows上的Clag也是如此(link.exe
)。您需要获取lld并弄清楚如何与它链接,或者找到其他跨平台链接器。 -
clang驱动程序不是作为跨平台编译器驱动程序编写的。要运行跨平台编译,您可能需要做更多的实际操作。看看
clang -###
的输出:clang驱动程序为您构造该命令,但您可能需要手动执行与clang驱动相同的许多工作。由于clang在跨平台编译中得到的测试要少得多,您可能会遇到更多的错误。 -
Xcode对你没有任何帮助。它可以将clang配置为OS X或iOS版本,但您必须手动将跨平台版本配置为Windows版本。
我相对有信心,可以拼凑出一个基于LLVM的环境,在OS X或Linux上构建一个C"Hello,World"Windows exe,但Xcode还没有准备好在可能的目标平台列表中添加"Windows"项目。
如果你不是一个编译器开发人员,你最好把源代码复制到Windows机器上,然后用Visual Studio进行构建。如果你是或想成为一名编译器开发人员,那么一定要帮助Clang的交叉编译能力向前发展。我认为Clang通用驱动程序项目是令人兴奋的,我真的希望看到进展继续下去。
我已经成功地完成了相反的交叉编译:在Windows上编译一个Mac OS X可执行文件。这在小程序上很容易手动完成,即直接编译.cpp文件。
首先,Mac OS X开发工具附带"SDK",其中包含特定操作系统的所有系统库和头文件。这里最大的挑战是弄清楚如何将SDK转移到Windows,同时保留SDK中的所有符号链接。(出于某种原因,在Windows上创建符号链接需要更高的权限,所以在OS X上生成带有符号链接的tar.gz后,我不得不作为管理员在Windows上运行7zip来正确扩展存档。)
一旦SDK在Windows上可用,就有一个单独的标志来告诉clang在哪里获取所有的系统依赖项:-isysroot
。这与-target
标志相结合,就是我需要告诉clang如何为OS X生成完整的对象文件的全部内容。
对于链接,我手动使用了lld,因为编译器驱动程序似乎不支持使用lld的交叉链接。lld支持用于确定目标系统库的类似标志。
最后一步是简单地将生成的可执行文件复制到OS X机器上,启用执行权限(Windows不支持相同的文件权限,因此在构建时不会设置执行位)并运行结果。
考虑在Mac OS X上使用MinGW编译Windows二进制文件。以下是有关如何在Linux上执行此操作的说明:http://www.blogcompiler.com/2010/07/11/compile-for-windows-on-linux/
你必须将它们适应Mac OS X,你可能必须自己编译MinGW。
http://www.mingw.org
多亏了xwin项目,现在可以很容易地在Mac或Linux等其他平台上获得Windows头文件和库:
- 使用xwin安装头文件和库:
export WINSDK_PATH="$HOME/winsdk" ./xwin --accept-license splat --preserve-ms-arch-notation --output "$WINSDK_PATH"
- 安装clang、clang-cl、lld,如果需要,还可以为OpenMP安装libomp。在Mac上,
brew install llvm
应该可以工作,在Debian/Ubuuntusudo apt install clang lld libomp-13-dev clang-tools
上。它也可以与conda:conda install clang llvm-openmp
一起安装 - 使用clang-cl编译代码。Clang cl可以像Microsoft编译器cl.exe一样使用。C运行时库可以使用选项
/MT
静态链接(默认),也可以使用/MD
动态链接(可能更适合大多数使用):# Create a program from C++ code clang-cl --target=x86_64-pc-windows-msvc -fuse-ld=lld /winsdkdir "$WINSDK_PATH/sdk" /vctoolsdir "$WINSDK_PATH/crt" /MD hello.cpp -o hello.exe # Create a DLL from C code and use OpenMP, AVX2 and LTO ("/openmp", "/arch:avx2", "-flto") clang-cl --target=x86_64-pc-windows-msvc -fuse-ld=lld /openmp /arch:avx2 -flto /LD /winsdkdir "$WINSDK_PATH/sdk" /vctoolsdir "$WINSDK_PATH/crt" /MD dll_test.c # The same without clang-cl clang -o dll_test.dll -target x86_64-pc-windows-msvc -isystem "$WINSDK_PATH/crt/include" -isystem "$WINSDK_PATH/sdk/Include/ucrt" -isystem "$WINSDK_PATH/sdk/Include/shared" -isystem "$WINSDK_PATH/sdk/Include/um" -Xclang --dependent-lib=msvcrt -fuse-ld=lld "-L$WINSDK_PATH/crt/lib/x64" "-L$WINSDK_PATH/sdk/Lib/ucrt/x64" "-L$WINSDK_PATH/sdk/Lib/um/x64" -flto -shared -march=x86-64-v3 c_test.c
当使用clang而不是clang-cl时,添加-Xclang --dependent-lib=msvcrt
会创建一个动态链接的二进制文件,如/MD
。
- 我在c++代码中生成了一个运行时#3异常
- Cppcheck生成xml转储文件
- 如何使用CMake编译.proto文件来生成.grpcp.pb.cc和.grpc.pb.h文件
- 如何在C++中使用结构生成映射
- 使用 C/C++ 宏生成函数签名
- "unknown ca"自生成的 CA、证书和客户端/服务器
- 如何从具有移动语义的类对象中生成共享指针
- 生成文件不对文件使用隐式规则
- boost::asio如何生成多个协同程序,然后加入它们
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- 生成MRPT库时cmake配置失败
- 如何处理使用.ui文件生成的.h文件
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 如何将我的应用程序生成的标准 Mac OS X 日志输出重定向到文件
- Qt生成按键(键盘)到系统(OS)的跨平台方式
- 如何在OS X上编译Google的protobuf编译器生成的C++文件
- Clang C++交叉编译器-从Mac OS X生成Windows可执行文件