JoelOnSoftware

Joel on Software

Please Sir May I Have a Linker

先生我能要个编译器么

by Joel Spolsky Wednesday, January 28, 2004


For some reason, Microsoft's brilliant and cutting-edge .NET development environment left out one crucial tool... a tool that has been common in software development environments since, oh, about 1950, and taken so much for granted that it's incredibly strange that nobody noticed that .NET doesn't really have one.

出于某种原因,微软的最尖端的革新工具.NET开发平台漏掉一个至关重要的工具…一个自从1950年开始就已经是软件开发环境很常见的工具,并且人们总是默认的工具, 居然没有人发现.NET没有附带这种工具实在是很奇怪。

The tool in question? A linker. Here's what a linker does. It combines the compiled version of your program with the compiled versions of all the library functions that your program uses. Then, it removes any library functions that your program does not use. Finally, it produces a single executable binary program which people can run on their computers.

缺失的那个工具是什么呢? 连接器。 连接器的工作是这样的。 它会把你的程序的已编译部分和程序使用到的库的已编译部分组合起来。 然后它会移除那些你的程序没有用到的库代码, 最后它会产生出一个每个人都可以运行在他们的个人计算机上的可执行程序。

Instead, .NET has this idea of a "runtime" ... a big 22 MB steaming heap of code that is linked dynamically and which everybody has to have on their computers before they can use .NET applications.

而.NET的想法则是“运行时”… 一个巨大的22MB的通过动态链接的冒着热气的堆代码,每个人在他们的电脑上运行.NET应用程序之前都得先安装这个运行时环境。

Runtimes are a problem, much like DLLs, because you can get into trouble when application version 1 was designed to work with runtime version 1, and then runtime version 2 comes out, and suddenly application version 1 doesn't work right for some unpredictable reason. For example right now for some reason our internal company control panel is rounding sales figures to four decimal points, as a result of upgrading from 1.0 to 1.1 of the runtime. Usually the incompatibilities are worse.

运行时环境是个问题,就像DLL那样,因为当你的程序版本1是为运行时环境版本1设计的,然后运行环境版本2发布了, 然后程序版本1因为某些无法预测的原因就无法工作了。 比如说,出于某种原因,我们把运行时环境从1.0升级到1.1之后,现在我们的内部公司控制面板会将销售额数字舍入到小数点后4位。 通常这种不兼容性要糟的多。

In fact .NET includes an extensive technology system called "manifests" which are manifestly complicated and intended to insure that somehow only the right runtime will be used with a given application, but nobody I know can figure out how to use them.

实际上 .NET包含了一种扩展性的技术系统,称为 “程序清单”。这种清单技术显然很复杂,他被用来确保对于给定的应用程序会使用正确的运行时环境版本。 但是没人能搞清楚如何使用这种技术。

This calls for a story. At the Fog Creek New Year's Eve party, we wanted a bunch of computer screens in the main room to display a countdown until midnight. Michael wrote an application to do this in C# with WinForms in about 60 seconds. It's a great development environment.

这个引出了一个故事,在FogCreek新年前夕的晚会上, 我们想让主会场的所有电脑屏幕上都显示出倒计时移植到午夜。 迈克花了大概60秒用C#的WinForm来实现这一目标。 这真是个伟大的编程环境。

My job was getting countdown.exe to run on three computers. Sounds easy.

我的工作就是让这个倒计时.EXE运行在三台电脑上,听起来很简单。

Nope. Double click the EXE, and I got a ridiculously user-hostile error message about mscoree.dll or something, followed by a gratuitous dump of my path. No mention of the fact that the problem was simply that the .NET runtime was not installed. Luckily I'm a programmer and I figured that must be the problem.

不是的。 双击EXE,我得到的却是一个可笑的,对用户充满了敌意的错误信息,这个错误信息是关于MSCOREE.DLL或者其他什么东西的,然后附带着我的运行路径信息, 却没有提到问题的原因只是因为我没有安装.NET运行时环境。幸运的是我是个程序员,我觉得肯定是这个问题。

How do you install the runtime? The "easiest" way is through Windows Update. But Windows Update really wanted me to get all the critical updates first before I installed the runtime. That's reasonable, right? Two of the "critical" updates were a Windows service pack and a new version of Internet Explorer, both of which required a reboot.

你怎么安装运行时环境呢? 最简单的方式就是通过Windows自动更新。 但是Windows自动更新很显然在我安装CLR运行时环境之前会让我安装其他的重要的安装包。 这听起来不是很合理么? 这两个关键的升级包分别是:Windows服务包和新版本的IE,两个安装都需要重新启动。

All told, for each computer I needed to run this little .NET application on, I had to download something like 70 or 80 MB (good thing we have a fast net connection) and reboot three or four times. And this is at a software company! I know how long it took, because the first time it started downloading, I put Office Space on the big screen TV, and by the time the movie was over, the installation process was almostfinished. Every ten minutes during the movie I had to jump up, go to each computer, and hit OK to some stupid dialog box.

到最后,为了在计算机上运行这个小小的.NET应用程序我们得下载大约70到80MD的的东西(好事是我们有快速的网络连接 )然后重新启动3到4次。

This is frustrating enough for our in-house apps. But think about our product CityDesk. Almost all of our users download a free trial versionbefore buying the product. The download is around 9 MB and has no additional requirements. Almost none of these users has the .NET runtime yet.

哪怕是内部工具,这也太让人难受了。 但是想想我们的产品CityDesk吧, 几乎我们所有的用户在正式购买之前都会下载一个免费试用版本。 下载大概9MB文件然后没有其他要求了。 但是这些用户几乎没有人有什么.NET运行时环境。

If we asked our trial users, usually small organizations and home users, to go through a movie-length installation hell just to try our app, I think we'd probably lose 95% of them. These are not customers yet, they're prospects, and I can't afford to give up 95% of my prospects just to use a nicer development environment.

如果我让我们的试用用户,通常是小企业或者家庭用户,通过一个见鬼似的有一部电影那么长的时间来安装试用我们的软件,我想我大概得失去95%的用户。 这些还不是用户, 他们只是潜在用户, 我可不会因为什么好的漂亮的开发环境放弃我95%的潜在用户。

"But Joel," people say, "eventually enough people will have the runtime and this problem will go away."

“但是Joel”人们会说, “最后,人们都会有运行时环境,到时候就没这个问题了。”

I thought that too, then I realized that every six or twelve months Microsoft ships a new version of the runtime, and the gradually increasing number of people that have it deflates again to zero. And I'll be damned if I'm going to struggle to test my app on three different versions of the runtime just so I can get the benefit of the 1.2% of the installed base that has one of the three.

我也这么觉得, 然后我意识到每隔6到12个月,微软就会发布运行时环境的新版本, 这样慢慢的实际上拥有运行时环境的人又降成了0。 如果我要挣扎着为我的产品同时测试3个运行时环境 那就太操蛋了,而这只能为那些安装了这三个版本的1.2%客户带来好处。

I just want to link everything I need in a single static EXE that runs without any installation prerequisites. I don't mind if it's a bit bigger. All I would need is the functions that I actually use, the byte code interpreter, and little bit of runtime stuff. I don't need the entire C# compiler which is a part of the runtime. I promise CityDesk doesn't need to compile any C# source code. I don't need all 22 MB. What I need is probably five or six MB, at most.

我只想要把我运行时所需要的东西全部连接成一个可执行文件,这样它就能不需要任何前提的情况下运行。 我不在乎如果它有点儿大。 所有我在乎的只是我运行时候实际试用的函数,那些字节码,解释器 和一点儿运行时环境之类的东西。 我并不需要运行时环境里的C#编译器。 我承诺CityDesk绝对不需要编译什么c#代码。 我不需要所有的22MB。 我最多可能也就需要5到6兆。

I know of companies that have the technology to do this, but they can't do it without permission from Microsoft to redistribute bits and pieces of the runtime like the byte code interpreter. So Microsoft, wake up, get us some nice 1950s-era linker technology, and let me make a single EXE that runs on any computer with Win 98 or later and no other external dependencies. Otherwise .NET is fatally flawed for consumer, downloaded software.

我知道有些公司有技术能够实现这一点, 但是除非微软授权给他们重新发布那些运行时环境的片片段段,像字节码解释器否则他们不能这么做。 所以,微软,醒醒吧, 给我们一个1950年的连接器一样的技术吧, 让我能够生成一个能够运行在Win98或者后续版本但是不需要任何其他外部以来的可执行程序吧。 否则.NET对于客户来说有是一个着致命的缺陷下载软件。