Linux中“自己编译”思想的根源是什么?


11

我上大学时曾使用过Linux,并且对这些术语很熟悉。我会定期使用.NET语言进行开发,因此我不会识字。

就是说,我不能真的说我理解* nix圈子中存在的“自己编译” [CIY]心态。我知道它会消失,但仍会不时听到。作为一名开发人员,我知道设置编译器和必要的依赖关系是一件麻烦事,因此,我觉得CIY的工作流程已使* nix的可及性大大降低了。

哪些社会或技术因素导致CIY心态的兴起?


12
您是在Linux圈子中还是在UNIX圈子中听到的?这是个很大的差异。
terdon

2
Linux有许多不同的发行版,这并不奇怪。现在,一些发行版已经成为领先者,已经有了编译版本,但是它曾经是一个不实用的网络。
Centimane

8
记录下来,在Linux系统上“设置编译器和必要的依赖项”实际上并不难。有人甚至说容易。
Deathgrip

6
@Darren-相反,如今大多数OpenSource tarball遵循的是几年前不存在的标准。下载tarball,解压缩tarball,cd到目录,运行./configure <options>,然后进行安装。30年前,我在运行AT&T SysV Unix的AT&T 3B2服务器和运行UTX的Gould iron上咬牙切齿。那时的事情要艰难得多。有些是configure过程的开始,大多数是您必须makefile(s)为特定系统手动编辑的。
Deathgrip

1
@Deathgrip确实,您是否曾经尝试过为没有Visual Studio的系统编程设置Windows开发环境?我告诉你几乎不可能。

Answers:


27

很简单,在* nix的大部分历史中,没有其他选择。程序作为源tarball分发,而使用它们的唯一方法是从源代码进行编译。因此,与其说是必要的邪恶,不如说是一种心态。

就是说,有充分的理由自己编译东西,因为它们将随后专门针对您的硬件进行编译,您可以选择启用或不启用哪些选项,因此可以以自己喜欢的方式最终获得经过微调的可执行文件。但是,显然,这仅对专家用户有意义,而对于只希望工作的机器继续阅读其电子邮件的人而言,是没有意义的。

现在,在Linux世界中,主要发行版都已脱离了很多年前。除非您使用的是专门为像Gentoo这样的人设计的发行版,否则您现在很少需要自己编译任何东西。但是,对于绝大多数发行版,您的普通用户将不需要编译任何东西,因为他们所需的几乎所有内容都已经存在并在其发行版的存储库中进行了编译。

因此,您所说的CIY心态已基本消失。在UNIX世界中,它仍然可能还活着,并且没有什么经验,但是在Linux中,如果您使用的是带有良好存储库的流行发行版,则几乎不需要自己编译任何东西。


5
在Unix世界中,它将再次取决于操作系统。我的最后一个职位涉及大量Solaris(Sun Sparc平台)服务器,我在家中以台式机运行Solaris 10 x86已有几年。我不能代表HPUX或AIX,但是您必须在Solaris上做一些CIY。Sun确实分发了许多预打包用于Solaris的OpenSource实用程序。也有像opencsw.org和unixpackages.com这样的网站。但是我仍然从源代码压缩包中进行了大量编译。
Deathgrip

“在* nix的大部分历史中,别无选择。程序作为源tarball分发。” -但是那是因为 CIY的心态,对吗?
Woodrow Barlow

2
@woodrow不是真的。没有其他选择。不要忘记* nix很。而且,大多数程序都是在已经是专家的同事之间传递的,为什么您还要为其他8个使用您的代码的人烦恼发明与安装程序或软件包管理器一样复杂的东西?当发明了这样的工具时,* nix的人们开始像其他所有人一样使用它们。
terdon

@WoodrowBarlow不,您正在交换因果关系。程序作为源进行分发,因为周围有许多不同的平台(不同的硬件体系结构,不同的操作系统,不同的库集),因此程序作者将需要分发数百或数千个二进制文件来覆盖它们。对于运行“异国情调”平台的人来说,CIY仍然存在,但是绝大多数运行“主流”平台的人可以从发行版中轻松获得二进制文件。
吉尔斯(Gillles)“所以-别再邪恶了”

@terdon好吧,我明白了。我只想指出一点,那段话是重言式的。在某种程度上,OP询问“为什么* nix开发人员分发源代码而不是编译的二进制文件?” 您的第一段说“因为* nix开发人员分发源代码而不是编译的二进制文件”。是的,我意识到我正在简化,但是我认为,如果将注释中的参数添加到答案文本中,您的答案将会更清晰。
Woodrow Barlow

13

最终用户,分发维护者和代码供应商/开发人员/项目组有多种原因可能导致这种想法,并且每一个都是完全有效的。

开源方面

有些人喜欢知道他们正在使用Free软件,并选择从源代码进行编译来验证这一点。这就是Linux From Scratch项目/ howto / guide / book之类的地方。

优化和选项方面

是否要针对您的特定CPU架构编译具有特定优化的内容?也许有一个编译时选项(或创建补丁的补丁)来启用或禁用所需的特定功能。例如,修补后缀以具有管理配额的能力,或使用Gentoo之类的发行版,在该发行版中您可以选择不使用systemd,或者由于许可问题而专门选择支持ogg / theora / vorbis / whatever和not mp3管他呢。

CPU体系结构方面

您的工作场所是否使用高端非x86 / amd64机器?您需要/想要的软件包可能无法针对您的CPU体系结构进行预编译,更不用说您正在运行的发行版了。当然,大多数运行这种硬件的地方也在IBM等的支持下,不要随意安装/编译东西。但是,如果您从剩余的销售中拿出一个,挖出一个旧的带PPC处理器的iMac,该怎么办?

发行方面

发行“家庭”(即Debian w / Ubuntu,Mint等)和具有CentOS,Whitebox,Fedora等的RedHat都使用不同的软件包格式。每个版本附带不同的库版本,等等。即使对于简单的单个文件shell脚本,要设置正确的Debian .deb文件也需要花费时间和精力。如果您编写了一些软件来解决一些问题,并希望使其免费并发布到gitlab上,则您自己的网络服务器(无论如何),您宁愿仅发布通用的.tar.gz文件并附上构建说明,还是愿意打包了Debian的2个版本的版本(稳定和测试,也许是老式的),Redhat和Fedora的多个版本作为RPM,Slackware的TGZ,Gentoo的ebuild配置文件等等等。


1
另一个原因是,有时上游源修补了一项非严重错误,该错误在以前的版本中可用,但此后已被破坏。但是,要获得稳定发行版的软件包,可能要数周甚至数月才能更新该软件包。这就是普通用户可能想学习如何从源代码编译某些东西的原因之一。而且,即使在发行版中以尖端软件闻名的发行版(例如Arch)也将在某个时候落后。从源代码进行编译意味着我可以拥有您提到的所有内容,以及可能已经引入的任何新功能。

@ChronoKitsune非常正确;将Gentoo(CIY发行版)中的软件包版本与其他发行版进行比较。较新。制作编译指令比制作适用于每种架构的二进制包要容易上千倍。这意味着您将使用其他人暂时不会看到的很棒的新软件功能。
dogoncouch17年

9

正如@terdon所说,如今,编译内容的需求已经非常渺茫,尤其是对于家庭用户而言。

过去,在Unix世界中,我高度依赖于编译源,例如,当我管理Solaris,AIX,Ultrix,Digital Ultrix和HP / UX系统时,有时供应商不再维护它们,或者不实施这些实现。通用服务的数量远远落后于其他Unix,包括Linux。

当前仍然有真正的编译需求,或者是获得一些不在存储库中的晦涩或过时的软件,或者使用您没有兼容二进制文件的软件包的较新版本,或者如果您能够为其编写补丁程序或模块,则希望添加额外的功能或很少添加。

在重新设计系统以移植到Debian和/或Debian的新版本时,我也不得不手工编译软件,而Debian的新版本具有OS不再支持的框架。

例如,过去,我不得不手工编译DHCP守护进程,以支持(直到最近)Windows对协议的更改,或者支持在电信界进行配置的特定补丁程序。

我仍然将自己从dev git repo编译的FreeRadius版本的本地存储库中的debs保留在Debian中,因为在Debian中有一串具有严重错误的稳定版本,通常对于Debian / Ubuntu的.debs并没有足以满足我们的需求。

不用说,有时我们还必须运行/或编译自己编写的内容。

如今安装依赖项并不像过去那样困难,并且某些软件甚至为一些常见的Linux发行版自定义了规则文件,这些文件命名了要编译的依赖项,并通过内置的依赖项列表来完成创建软件包文件的繁重工作。从本地存储库安装此类软件包与从官方存储库安装相同软件包没有太大区别。


4

哪些社会或技术因素导致 CIY心态的兴起

根本原因显然是技术原因: 二进制可移植性比源可移植性难。在发行版软件包之外,大多数免费软件仍仅以源代码形式提供,因为这对于作者/维护者而言要方便得多。

在Linux发行版开始打包普通人想使用的大多数东西之前,您唯一的选择是获取源代码并针对您自己的系统进行编译。商业Unix供应商通常不包含几乎每个人都想要的东西(例如,像GNU bash或类似的不错的shell ),而只是他们自己的sh和/或实现csh,因此如果您(作为系统管理员)需要,则需要自己构建东西。为您的用户提供一个不错的Unix环境以进行交互使用。

现在的情况与大多数人是坐在桌面上的计算机的唯一管理员和唯一用户相比,这种情况与传统的Unix模型有很大的不同。 系统管理员将软件维护在中央系统以及每个人的桌面上。(通常是使人们的工作站仅安装在NFS上/opt/usr/local/从中央服务器安装,然后在其中安装东西。)


在诸如.NET和Java之类的东西之前,跨不同CPU体系结构实现真正的二进制可移植性是不可能的。出于这个原因,Unix文化演变为默认具有源可移植性,在最近的Linux之类的LSB努力之前,几乎没有任何努力甚至尝试启用二进制可移植性。例如,POSIX主要的Unix标准)只尝试标准化源的便携性,即使在最近的版本。

相关的文化因素:早期的商业化AT&T Unix带有源代码(在磁带上)。你没有必须从源代码编译系统,它只是有万一你想看看东西真的当文档还不够努力。

维基百科说

“ Unix的广泛在线文档政策以及(多年以来)随时可以访问所有系统源代码的政策提高了程序员的期望,并推动了1983年自由软件运动的启动。”

我不确定是什么原因促使了这一决定,因为这些天没有让客户访问商业软件的源代码了。在这个方向上显然有一些早期的文化偏见,但是也许是从Unix的根源发展出来的,因为它是一种主要用C(不是汇编语言)编写的便携式OS,可以针对不同的硬件进行编译。我认为许多早期的OS都在asm中为特定的CPU编写了更多代码,因此源代码级可移植性是Unix早期的优势之一。(对此我可能是错的;我不是早期Unix的专家,但是Unix和C是相关的。)


到目前为止,以源代码形式分发软件是使人们适应他们想要在其上运行的任何系统的最简单方法。(最终用户或将其打包为Linux发行版的人)。如果软件已经由分发包打包/用于分发,则最终用户可以使用它。

但是,期望大多数软件包的作者自己为每种可能的系统制作二进制文件实在是太过分了。一些主要项目为一些常见情况提供了二进制文件(尤其是x86 / windows,其中OS并未附带构建环境,并且OS供应商已将重点放在仅二进制安装程序的分发上)。

要使某款软件在与作者使用的软件不同的系统上运行,甚至可能需要进行一些小的更改,而这些更改对于source来说很容易。有人写过一个小小的一次性程序,以挠痒痒,可能从未在大多数晦涩的系统上进行过测试。有了来源,就可以进行此类更改。原始作者可能忽略了某些内容,或者有意编写了可移植性较低的代码,因为它节省了大量时间。即使像Info-ZIP这样的主要软件包也没有立即在每个平台上都配备测试人员,并且需要人们在发现问题后发送其可移植性补丁。

(还有其他类型的源代码级的便携性问题,只有发生的,因为在建ENV的差异,而不是这里的问题。随着Java风格的二进制可移植性,汽车修理工具(真正相关的autoconf/ auto-make),并像类似的事情cmake止跌我们不需要<netinet/in.h><arpa/inet.h>ntohl(3)某些系统要求包含而不是 for的东西(也许我们一开始就不需要ntohl()或任何其他字节顺序的东西!)


我会定期使用.NET语言进行开发,因此我不会识字。

一次编译,随处运行是.NET和Java的主要目标之一,因此可以说,已经发明了整个语言来解决此问题,而您的开发经验就是其中之一。使用.NET,您的二进制文件可以在可移植运行时环境(CLR)运行。Java将其运行时环境称为Java虚拟机。您只需要分发一个可以在任何系统上使用的二进制文件(至少在有人已经实现了JVM或CLR的任何系统上)。当然,您仍然会遇到可移植性问题,例如/vs \路径分隔符,如何打印或GUI布局细节。

许多软件是用完全编译成本机代码的语言编写的。没有.net或没有Java字节码,只是将要在其上运行的CPU的本机代码,以非便携式可执行文件格式存储。C和C ++是这种情况的主要示例,尤其是在Unix世界中。显然,这意味着必须为特定的CPU体系结构编译二进制文件。

库版本是另一个问题。在更改二进制级ABI时,库可以并且经常确实使源级API保持稳定。(请参阅API和ABI之间的区别。)例如,将另一个成员添加到不透明对象struct仍会更改其大小,并且对于为这种结构分配空间的任何代码,无论它是动态的(malloc),都需要使用新库版本的标头重新编译。 ),静态(全局)或自动(堆栈上的本地)。

操作系统也很重要。对于相同的CPU架构不同的风味的Unix可能有不同的二进制文件格式,不同的ABI制作系统调用,而不同的数值对于像常量fopen(3)O_RDONLYO_APPENDO_TRUNC

请注意,即使是动态链接的二进制文件也仍然具有某些特定于OS的启动代码,这些启动代码之前运行main()。在Windows上,这是crt0。Unix和Linux具有相同的功能,其中一些C运行时启动代码静态链接到每个二进制文件中。我想从理论上讲,您可以设计一个系统,在该系统中代码也可以动态链接,并且是libc或动态链接器本身的一部分,但这并不是我所知道的任何操作系统在实际中的工作方式。那只能解决系统调用的ABI问题,而不能解决标准库函数常数的数值问题。(通常,系统调用是通过libc包装函数进行的:使用的源代码的普通x86-64 Linux二进制文件mmap()将不包含syscall指令,仅包含call 相同名称的libc包装函数的指令。

这就是为什么您不能仅在i386-Linux上运行i386-FreeBSD二进制文件的部分原因。(有一阵子,Linux内核具有系统调用兼容性层。我认为至少一个BSD可以运行Linux二进制文件,并且具有类似的compat层,但是您当然需要Linux库。)


如果要分发二进制文件,则需要为CPU / OS-flavor + version / installed-library-versions的每种组合单独制作一个

上世纪80年代/ 90年代,Unix系统使用了许多不同类型的CPU(MIPS,SPARC,POWER,PA-RISC,m68k等),以及Unix的许多不同版本(IRIX,SunOS, Solaris,AIX,HP-UX,BSD等)。
那只是Unix系统。许多源代码包也可以在其他系统上编译和运行,例如VAX / VMS,MacOS(m68k和PPC),Amiga,PC / MS-DOS,Atari ST等。

尽管现在大多数台式机都运行三种主要操作系统之一,但x86仍具有许多CPU体系结构和操作系统。

因此,甚至在您开始考虑对第三方库的依赖关系(可能在不同系统上使用不同版本)之前,已经有不止一个的CPU / OS组合。(操作系统供应商未打包的所有内容都必须手动安装。)

编译为二进制文件的任何路径也是特定于系统的。(与启动时从配置文件读取它们相比,这节省了RAM和时间)。老式的Unix系统通常有很多手工定制的内容,因此您无法对何处进行任何有效的假设。

对于老式的Unix而言,分发二进制文件是完全不可行的,除了可以负担所有主要组合的构建和测试费用的大型商业项目

即使做的只是二进制文件i386-linux-gnuamd64-linux-gnu硬。为了使可移植的二进制文件成为可能,在Linux Standard Base之类的东西上花费了大量时间和精力。即使静态链接二进制文件也不能解决所有问题。(例如,在RedHat系统和Debian系统上应如何打印文字处理程序?安装程序应如何为守护程序添加用户或组,并安排其启动脚本在每次重新启动后运行?)例子,因为从源头重新编译不能解决它们。


除此之外,过去的记忆比现在更宝贵。 在编译时保留可选功能可以创建较小的二进制文件(较小的代码大小),从而也为它们的数据结构使用较少的内存。如果某个功能在某个对象的每个实例中都需要一个额外的成员classstruct要追踪某个东西,则禁用该功能会将对象缩小4个字节(例如),如果它是程序分配100k的对象,则很好。

如今,可选的编译时功能通常用于使其他库成为可选的。例如,您可以针对特定的视频/音频编码器,字幕处理等,使用,ffmpeg或不使用libx264,,和其他许多库进行编译。更常见的是,可以使用或不使用来编译很多东西:如果运行时可用,则生成的二进制文件将取决于库,并在从终端读取时提供精美的行编辑。如果不是,则该程序将使用一些后备支持以仅从标准输入中读取带有或的行。)libx265libvorbislibreadline./configurefgets()

出于性能原因,某些项目仍会使用可选功能来省略不需要的代码。例如,Linux内核本身可以在不支持SMP的情况下构建(例如,用于嵌入式系统或古老的台式机),在这种情况下,很多锁定操作都比较简单。或具有影响某些核心代码的许多其他可选功能,而不仅仅是遗漏了驱动程序或其他硬件功能。(尽管特定于arch的配置和特定于硬件的配置选项在总的源代码中占了很大比例。请参阅为什么Linux内核有超过1500万行代码?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.