• Introduction
  • Why?
    • Speed
    • Cost
    • Containers + k8s
  • Rejected Strategies
    • Using x86_64-pc-windows-gnu
    • Using wine to run the MSVC toolchain
  • How?
    • Prerequisites
    • 1. Setup toolchain(s)
    • 2. Acquire Rust std lib
    • 3. Acquire CRT and Windows 10 SDK
    • 4. Override cc defaults
    • 5. Profit
  • Bonus: Headless testing
    • 1. Install
    • 2. Specify runner
    • 3. Test
  • Final image definition
  • Common issues
    • CMake
    • MASM
    • Compiler Target Confusion
  • Conclusion

Introduction

Last November I added a new job to our CI to cross compile our project for x86_64-pc-windows-msvc from an x86_64-unknown-linux-gnu host. I had wanted to blog about that at the time but never got around to it, but after making some changes and improvements last month to this, in addition to writing a new utility, I figured now was as good of a time as any to share some knowledge in this area for those who might be interested.

Why?

Before we get started with the How, I want to talk about why one might want to do this in the first place, as natively targeting Windows is a "known quantity" with the least amount of surprise. While there are reasons beyond the following, my primary use case for why I want to do cross compilation to Windows is our Continuous Delivery pipeline for my main project at Embark.

Speed

It's fairly common knowledge that, generally speaking, Linux is faster than Windows on equivalent hardware. From faster file I/O to better utilization of high core count machines, and faster process and thread creation, many operations done in a typical CI job such as compilation and linking tend to be faster on Linux. And since I am lazy, I'll let another blog post about cross compiling Firefox from Linux to Windows actually present some numbers in defense of this assertion.

Cost

Though we're now running a Windows VM in our on-premise data center for our normal Windows CD jobs, we actually used to run it in GCP. It was 1 VM with a modest 32 CPU count, but the licensing costs (Windows Server is licensed by core) alone accounted for >20% of our total costs for this particular GCP project.

While this single VM is not a huge deal relative to the total costs of our project, it's still a budget item that provides no substantive value, and on principle I'd rather have more/better CPUs, RAM, disk, or GPUs, that provide immediate concrete value in our CI, or just for local development.

Containers + k8s

This one is probably the most subjective, so strap in!

While fast CI is a high priority, it really doesn't matter how fast it is if it gives unreliable results. Since I am the (mostly) sole maintainer, (which yes, we're trying to fix) for our CD pipeline in a team of almost 40 people, my goal early on was to get it into a reliably working state that I could easily maintain with a minimal amount of my time, since I have other, more fun, things to do.

The primary way I did this was to build buildkite-jobify (we use Buildkite as our CI provider). This is just a small service that spawns Kubernetes (k8s) jobs for each of the CI jobs we run on Linux, based on configuration from the repo itself.

This has a few advantages and disadvantages over a more typical VM approach, which we use for x86_64-pc-windows-msvc (for now?), x86_64-apple-darwin, and aarch64-apple-darwin.

Pros

  • Consistency - Every job run from the same container image has the exact same starting environment.
  • Versioned - The image definitions are part of our monorepo, as well as the k8s job descriptions, so we get atomic updates of the environment CI jobs execute in with the code itself. This also makes rollbacks trivial if needed.
  • Scalability - Scaling a k8s cluster up or down is fairly easily (especially in eg GKE, because $) as long as you have the compute resources. k8s also makes it easy to specify resource requests so that individual jobs can dynamically spin up on the most appropriate node at the time based on the other workloads currently running on the cluster.
  • Movability - Since k8s is just running containers, it's trivial to move build jobs between different clusters, for example in our case, from GKE to our on-premise cluster.

Cons

  • Clean builds - Clean builds are quite slow compared to incremental builds, however we mitigate this by using cargo-fetcher for faster crate fetching and sccache for compiler output caching.
  • Startup times - Changing the image used for a build job means that every k8s node that runs an image it doesn't have needs to pull it before running. For example, the pull can take up to almost 2m for our aarch64-linux-android which is by far our largest image at almost 3GiB (the Android NDK/SDK are incredibly bloated). However, this is generally a one time cost per image per node and we don't update images so often that it is actually a problem in practice.

Rejected Strategies

Before we get into the how I just wanted to show two other strategies that could be used for cross compilation that you might want to consider if your needs are different than ours.

Using x86_64-pc-windows-gnu

To be honest, I rejected this one pretty much immediately simply because the gnu environment is not the "native" msvc environment for Windows. Targeting x86_64-pc-windows-gnu would not be representative for actual builds used by users, and it would be different from the local builds built by developers on Windows, which made it an unappealing option. That being said, generally speaking, Rust crates tend to support x86_64-pc-windows-gnu fairly well, which as we'll see later is a good thing due to my chosen strategy.

Using wine to run the MSVC toolchain

I briefly considered using wine to run the various components of the MSVC compiler toolchain, as that would be the most accurate way to match the native compilation for x86_64-pc-windows-msvc. However, we already use LLD when linking on Windows since it is vastly faster than the MSVC linker, so why not just replace the rest of the toolchain while we're at it?

Cross compiling Windows binaries from Linux相关推荐

  1. linux dhcp 4.3编译,关于在嵌入式Linux下编译dhcp报错“cannot check for file existence when cross compiling”的初步研究...

    前言.写这篇文章的由来 最近在学习韦东山嵌入式培训视频(3期项目实战之USB摄像头监控)时,在对dhcp源代码configure时,报错:cannot check for file existence ...

  2. 关于在嵌入式Linux下编译dhcp报错“cannot check for file existence when cross compiling”的初步研究...

    前言.写这篇文章的由来 最近在学习韦东山嵌入式培训视频(3期项目实战之USB摄像头监控)时,在对dhcp源代码configure时,报错:cannot check for file existence ...

  3. checksum命令 linux,Windows相当于linux cksum命令

    I am looking for a way to compute crc checksum cross platform. cksum works on Linux, AIX, HP-UX Itan ...

  4. Windows Subsystem for Linux (WSL2) - WSL 的基本命令

    Windows Subsystem for Linux (WSL2) - WSL 的基本命令 Windows Subsystem for Linux Documentation https://lea ...

  5. Windows Subsystem for Linux安装与使用

    WSL: Windows Subsystem for Linux(简称WSL)是一个在Windows 10上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层.它是由微软与Canonical ...

  6. Windows下ARM Linux应用程序开发环境搭建说明

    这是因为工作写的一个文档,主要是我们开发人员都不会Linux不会vi也不会命令行,于是研究了一下Windows系统调试ARM Linux程序的办法,在这共享一下. 1. 概述 嵌入式Linux系统的应 ...

  7. Socket程序从windows移植到linux下需要注意的

    )头文件 windows下winsock.h或winsock2.h linux下netinet/in.h(大部分都在这儿),unistd.h(close函数在这儿),sys/socket.h(在in. ...

  8. windows远程桌面linux系统,Windows远程桌面控制Linux图文详解

    随着互联网的高速发展以及Linux企业应用的成熟,Linux被广泛应用于服务器领域,如何实现Linux的远程管理成为网络管理员的首要任务. 我们经常见到的几种最为常用的windows下远程管理Linu ...

  9. windows 连Linux,Windows下访问Linux资源

    Windows下访问Linux资源 在Red Hat Linux中,借助Samba服务在Windows下访问Linux的资源也是很容易的,依次单击"主菜单" "系统设置& ...

最新文章

  1. TensorFlow用法
  2. php源码之计算两个文件的相对路径
  3. Windows从命令行创建文本文件的两种方式
  4. javaweb k8s_阿里云部署K8Sweb项目
  5. 公式冒号是什么意思_三角学中,这么一堆公式其实就说了2个事而已
  6. sap 供应商表_财务人员学习SAP的路线图
  7. 作者:张家琳(1983-),女,中国科学院计算技术研究所副研究员。
  8. scipy.stats.norm
  9. 11 绑定方法与非绑定方法
  10. java编程手册_Java编程手册
  11. 将手机浏览器下载的.ts格式的视频片段合并的方法
  12. 复数计算器(c++实训)
  13. 华为OD 社招(Java后端)一面
  14. mail,at,batch,sleep小练习
  15. 微信小程序仿打卡小程序
  16. 文墨绘学书法教育领导品牌
  17. frl啥意思_FRL是什么意思
  18. 几分钟黑掉阿里,被马云500万年薪收编的黑客,现在混得咋样了?
  19. PTA 病毒感染检测 (15分)
  20. 用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

热门文章

  1. java ceph_后台开发高级工程师必备技能-分布式存储ceph介绍
  2. 博途中用的是c吗_S7-1500系列博途中使用SCL语言编程方法简介
  3. opengl 坐标的理解
  4. 不合格高校教师的自我总结(学生评价和思考反省)
  5. 面向气象灾害预警信息的5G网络切片技术研究
  6. 加餐3 | 考博和读博
  7. 使用html2canvas.min.js将网页生成图片并打印(笔记记录)
  8. 批量插入模拟数据入库
  9. BUUCTF [INSHack2018]Tricky-Part2
  10. 自定义函数(创建函数)