web-dev-qa-db-ja.com

Linuxの「自分でコンパイルする」という考え方の源は何ですか

私は大学でLinuxを少し使用しましたが、用語に精通しています。私は.NET言語で定期的に開発しているので、私はコンピュータの読み書きができません。

とは言っても、* nixサークルに存在する「自分でコンパイルする」[CIY]考え方を理解しているとは本当に言えません。私はそれがなくなることを知っていますが、それでも時々それを聞きます。開発者として、コンパイラーと必要な依存関係のセットアップはお尻の痛みであることを知っているので、CIYワークフローが* nixのアクセス性を大幅に低下させるのに役立ったと感じています。

CIYメンタリティの上昇につながった社会的または技術的要因は何ですか?

11
Sidney

非常に簡単に言うと、* nixの歴史の多くにとって、他に選択肢はありませんでした。プログラムはソースtarballとして配布され、ソースを使用してコンパイルする方法しかありませんでした。だから、必要な悪というほどの考え方ではありません。

とは言っても、ハードウェア専用にコンパイルされるので、自分でコンパイルすることには非常に十分な理由があります。有効にするオプションと無効にするオプションを選択できるため、細かく調整された実行可能ファイルを好みの方法で作成できます。 。ただし、それは明らかに、エキスパートユーザーにとっては理にかなったことであり、稼働中のマシンにメールを読んでもらいたいだけの人にとっては意味がありません。

現在、Linuxの世界では、主要なディストリビューションはすべて、何年も前にこれから遠ざかっています。 Gentooのようにこれを行うのが好きな人のために特別に設計されたディストリビューションを使用しているのでない限り、ごくまれに、最近自分で何かをコンパイルする必要はありません。ただし、ほとんどのディストリビューションでは、平均的なユーザーは何もコンパイルする必要はありません。ディストリビューションのリポジトリに必要なものがほとんどすべて存在し、コンパイルされているためです。

したがって、このCIYの考え方は、あなたが言うように本質的に消えています。それはまだ生きていてUNIXの世界でキックしているかもしれませんが、私はそこでの経験はありませんが、Linuxでは、まともなリポジトリを備えた人気のあるディストリビューションを使用している場合は、自分でコンパイルする必要はほとんどありません。

27
terdon

エンドユーザー、ディストリビューションメンテナー、コードサプライヤー/開発者/プロジェクトグループなど、その考え方にはいくつかの原因があり、それらのすべてが完全に有効です。

オープンソースの側面

フリーソフトウェアを使用していることを知り、ソースからコンパイルすることを選択して検証する人もいます。ここから、Linux From Scratchプロジェクト/ howto/guide/bookなどが登場します。

最適化とオプションの側面

特定のCPUアーキテクチャ向けに特定の最適化を行ってコンパイルしたいですか?おそらく、必要な特定の機能を有効または無効にするためのコンパイル時オプション(またはパッチを作成するためのパッチ)があるでしょう。この例として、postfixにパッチを適用してクォータを管理する機能や、Gentooのようなディストリビューションを使用してsystemdを使用しないように選択したり、ライセンスの問題によりogg/theora/vorbis/whateverやmp3をサポートしないように特別に選択したりすることができます。または何でも。

CPUアーキテクチャの側面

あなたの職場はハイエンドの非x86/AMD64マシンを使用していますか?必要なパッケージは、CPUアーキテクチャ用にプリコンパイルされていない可能性があり、実行しているディストリビューションがはるかに少ない場合があります。確かに、この種のハードウェアを実行しているほとんどの場所は、IBMなどからのサポートも受けているため、物事をインストールしたりコンパイルしたりすることはありません。しかし、もしあなたが余剰セールからそれを手に入れたら、古いiMac w/PPCプロセッサーなどを掘り出しますか?

配布の側面

ディストリビューション「ファミリー」-つまり、Ubuntu、MintなどのDebian、およびCentOS、Whitebox、FedoraなどのRedHatは、すべて異なるパッケージ形式を使用しています。また、各バージョンには異なるライブラリバージョンが付属しています。単純な単一ファイルのシェルスクリプトであっても、適切なDebian .debファイルを設定するには時間と労力がかかります。かゆみをひっくり返すソフトウェアを作成し、それを無料にしてgitlabに投稿したい場合は、独自のWebサーバーなど、ビルドの手順を記載したソースの一般的な.tar.gzファイルを投稿するか、むしろDebianの2つのバージョンのバージョンをパッケージ化します(安定版とテスト版、場合によっては旧版版)、RedhatとFedoraの複数のバージョンをRPM、SlackwareのTGZ、Gentooのebuildプロファイルなどとしてパッケージ化します。

13
ivanivan

@terdonが言うように、今日、特にホームユーザーにとって、物事をコンパイルする必要性はかなりスリムです。

以前は、Unixの世界では、たとえば、ベンダーによってメンテナンスされなくなったSolaris、AIX、Ultrix、Digital UltrixおよびHP/UXシステムを管理していたため、ソースのコンパイルに大きく依存していました。一般的なサービスの数は、Linuxを含む他のUnixで一般的に使用されていたものよりもはるかに遅れていました。

リポジトリに存在しないソフトウェアの不明瞭または古くなった部分を入手するため、または互換性のあるバイナリがないパッケージのより新しいバージョンを使用するため、またはパッチやモジュールを作成できる場合は、追加の機能を追加するか、まれに追加する必要があります。

また、Debianに移植するためのシステムのリエンジニアリングや、OSでサポートされなくなったフレームワークを備えたDebianの新しいバージョン、あるいはその両方を行うときに、ソフトウェアを手動でコンパイルする必要がありました。

たとえば、以前はプロトコルへのWindowsの変更をサポートするために(または最近まで)、DHCPデーモンを手動でコンパイルするか、テレコムの世界でプロビジョニングするための特定のパッチをサポートする必要がありました。

Debianに(深刻な)バグがある一連の安定したバージョンがあり、通常、Debian/Ubuntuの対応する.debsがなかったため、私は自分の開発したgitリポジトリからFreeRadiusバージョンのローカルリポジトリdebsを保持しています。私たちのニーズに十分です。

そして言うまでもないことですが、自分で書いたものを実行したりコンパイルしたりする必要があることもあります。

今日の依存関係のインストールは以前ほど難しくはありません。一部のソフトウェアでは、コンパイルする依存関係に名前を付け、組み込みの依存関係のリストを含むパッケージファイルを作成するという重労働を行ういくつかの一般的なLinuxディストリビューション用にカスタマイズされたルールファイルを使用しています。このようなパッケージをローカルリポジトリからインストールすることは、公式リポジトリから同じパッケージをインストールすることと大差ありません。

9
Rui F Ribeiro

CIYの考え方の社会的または技術的な要素上昇の原因

根本的な原因は明らかに技術的な理由です:バイナリの移植性はソースの移植性よりも難しい。ディストリビューションパッケージ以外では、ほとんどのフリーソフトウェアはソース形式でのみ利用できます。これは、作者/メンテナにとって非常に便利だからです。

Linuxディストリビューションが平均的な人々が使用したいと思うであろうほとんどのもののパッケージ化を開始するまで、あなたの唯一の選択肢はソースを入手して自分のシステム用にコンパイルすることでした。商用Unixベンダーは通常、ほとんどの人が望んでいたもの(たとえば、GNU bashなど)のナイスシェル)を含まず、shcshの独自の実装のみを使用しているため、ビルドする必要がありました。 (sys-adminとして)インタラクティブな使用のためにユーザーに素敵なUnix環境を提供したい場合は、自分自身を用意してください。

現在、ほとんどの人が唯一の管理者であり、デスクトップに座っているマシンの唯一のユーザーであるという状況は、従来のUnixモデルとは大きく異なります。システム管理者は、中央システム上でソフトウェアを維持し、みんなのデスクトップ。 (多くの場合、人々のワークステーションに中央サーバーから/opt/usr/local/をNFSマウントし、そこにものをインストールするだけです。)


.NETやJavaなどの以前は、異なるCPUアーキテクチャ間での真のバイナリ移植性は不可能でした。 Unixカルチャーは、この理由から、ソースの移植性をデフォルトとして進化しました。LSBのような最近のLinuxの取り組みまで、バイナリの移植性を有効にしようとする努力さえほとんどありませんでした。たとえば、 [〜#〜] posix [〜#〜]theMajor Unix standard)は、最近でもソースの移植性を標準化しようとするだけですバージョン。

関連する文化的要因:初期の商用AT&T Unixには、ソースコードが(テープで)付属していました。ソースからシステムを構築するhaveしませんでした。何かが実際にどのように動作するかを確認したい場合に備えて、そこにありましたドキュメントが十分ではなかったとき。

ウィキペディアは言う

「広範なオンラインドキュメントと(長年にわたって)すべてのシステムソースコードにいつでもアクセスできるというUnixポリシーは、プログラマーの期待を高め、1983年のフリーソフトウェア運動の立ち上げに貢献しました。」

商用ソフトウェアのソースコードへのアクセスを顧客に提供することは最近では前例がないため、この決定の動機が何であるかはわかりません。この方向には明らかにいくつかの初期の文化的偏見がありますが、おそらくそれはUnixのルーツから、ほとんどがC(アセンブリ言語ではなく)で記述され、さまざまなハードウェア用にコンパイルできるポータブルOSとして生まれました。以前の多くのOSでは、特定のCPU向けにコードがasmで記述されていたため、ソースレベルの移植性は、初期のUnixの強みの1つでした。 (私はこれについて間違っているかもしれません。私は初期のUnixの専門家ではありませんが、UnixとCは関連しています。)


ソフトウェアをソース形式で配布することは、ソフトウェアを実行したいシステムにそれを適応させる最も簡単な方法です。 (エンドユーザーまたはLinuxディストリビューション用にパッケージ化した人)。ソフトウェアが配布によってパッケージ化されている場合、エンドユーザーはそれを使用できます。

しかし、ほとんどのパッケージの作成者がすべての可能なシステム自体のバイナリを作成することを期待するのは、あまりにも多すぎます。いくつかの主要なプロジェクトは、いくつかの一般的なケース(特に、OSにビルド環境が付属しておらず、OSベンダーがバイナリのみのインストーラーの配布に重点を置いているx86/windows)のバイナリを提供しています。

作成者が使用したシステムとは異なるシステムでソフトウェアを実行するには、いくつかの小さな変更が必要な場合さえあり、ソースを使用すると簡単です。誰かが自分のかゆみを掻くために書いた小さな1回限りのプログラムは、ほとんどのあいまいなシステムではテストされていません。ソースがあれば、そのような変更を行うことができます。元の作成者が何かを見落としたか、多くの時間を節約したため、移植性の低いコードを意図的に作成した可能性があります。 Info-Zip のような主要なパッケージでさえ、すぐにすべてのプラットフォームにテスターがいなかったため、問題が発見されたときに移植パッチを送信する必要がありました。

(他にも、ビルド環境の違いが原因で発生するソースレベルの移植性の問題があり、ここでの問題には実際には関係ありません。Javaスタイルのバイナリ移植性では、自動ツール( autoconf =/auto-make)およびcmakeのような同様のものは必要ありません。そして 一部のシステムでは、<netinet/in.h>の代わりに<arpa/inet.h>を含める必要があります。 ntohl(3) 。(そして、そもそもntohl()やその他のバイト順のものはないかもしれません!)


私は.NET言語で定期的に開発しているので、コンピューターの知識がないわけではありません。

コンパイル、どこでも実行は.NETとJavaの主要な目標の1つなので、この問題を解決するために言語全体が発明されました、そしてあなたの開発経験そのうちの1つです。 .NETでは、バイナリは ポータブルランタイム環境(CLR) で実行されます。 Javaはそのランタイム環境を Java Virtual Machine)と呼びます 。任意のシステム(少なくとも、誰かがすでに実装しているシステム)で機能する1つのバイナリを配布するだけJVMまたはCLR)もちろん、/\のパス区切り文字、印刷方法、またはGUIレイアウトの詳細などの移植性の問題が発生する可能性があります。

多くのソフトウェアは 完全にネイティブコードにコンパイル の言語で記述されています。 .netまたはJavaバイトコードはありません。実行されるCPUのネイティブマシンコードであり、移植性のない実行可能ファイル形式で保存されます。CとC++は特にこの例ですUnixの世界では、明らかにこれはバイナリは特定のCPUアーキテクチャ用にコンパイルする必要があります。

ライブラリのバージョンは別の問題です。ライブラリは、バイナリレベルのABIを変更している間、ソースレベルのAPIを安定させることができます。 ( APIとABIの違い を参照してください。)たとえば、不透明なstructに別のメンバーを追加すると、そのサイズは変わりますが、そのためのスペースを割り当てるコードには、新しいライブラリバージョンのヘッダーを使用して再コンパイルする必要があります。構造体(動的(malloc)、静的(グローバル)、または自動(スタックのローカル))。

オペレーティングシステムも重要です。同じCPUアーキテクチャのUnixの種類によって、バイナリファイル形式が異なり、システムコールを作成するためのABIが異なり、定数の数値が fopen(3) 's O_RDONLYO_APPENDO_TRUNC のように異なる場合があります。 =。

動的にリンクされたバイナリでも、main()の前に実行されるOS固有の起動コードがまだあることに注意してください。 Windowsでは、これは crt0 です。 UnixとLinuxには同じものがあり、Cランタイムスタートアップコードの一部がすべてのバイナリに静的にリンクされています。理論的には、そのコードが動的にリンクされたシステム、およびlibcの一部または動的リンカー自体を設計することもできると思いますが、これは私が知っているOSで実際に機能する方法ではありません。これは、システムコールのABI問題のみを解決し、標準ライブラリ関数の定数の数値の問題は解決しません。 (通常、システムコールはlibcラッパー関数を介して行われます:mmap()を使用するソースの通常のx86-64 Linuxバイナリには、syscall命令は含まれず、同じのlibcラッパー関数へのcall命令のみが含まれます名前。

これは、i386-Linuxでi386-FreeBSDバイナリを実行できない理由の一部です。 (しばらくの間、Linuxカーネルにはシステムコール互換性レイヤーがありました。少なくとも1つのBSDは、同様の互換性レイヤーでLinuxバイナリを実行できると思いますが、もちろんLinuxライブラリが必要です。)


バイナリを配布したい場合は、CPU/OS-flavour + version/installed-library-versionsのすべての組み合わせに対して個別に作成する必要があります

80年代/ 90年代には、Unixシステム(MIPS、SPARC、POWER、PA-RISC、m68kなど)で一般的に使用されているさまざまな種類のCPUと、さまざまな種類のUnix(IRIX、SunOS、 Solaris、AIX、HP-UX、BSDなど)。
そして、それだけUnixシステムです。多くのソースパッケージは、VAX/VMS、MacOS(m68kおよびPPC)、Amiga、PC/MS-DOS、Atari STなどのotherシステムでもコンパイルおよび動作します。

現在でも多くのCPUアーキテクチャとOSがありますが、デスクトップの大多数は3つの主要なOSの1つを実行しているx86です。

そのため、異なるシステムの異なるバージョンにある可能性のあるサードパーティライブラリへの依存関係について考える前であっても、CPU/OSの組み合わせは、スティックを振ることができるよりも多くあります。 (OSベンダーによってパッケージ化されていないものはすべて手動でインストールする必要があります。)

バイナリにコンパイルされるパスもシステム固有です。 (これにより、RAMおよび起動時に構成ファイルから読み取るのに比べて時間を節約できます。)古い学校のUnixシステムには、通常ロットの手がありました。 -カスタマイズされたものなので、どこにあるかについて有効な仮定を行う方法はありません。

バイナリを配布することは、すべての主要な組み合わせでビルドおよびテストする余裕のある主要な商用プロジェクトを除いて、昔ながらのUnixではまったく実行不可能でした

i386-linux-gnuAMD64-linux-gnuだけのバイナリを作成することも困難です。 Linux Standard Base のようなものに多くの時間と労力が費やされ、ポータブルバイナリが可能になります。バイナリを静的にリンクしても、すべてが解決されるわけではありません。 (たとえば、RedHatシステムとDebianシステムでワードプロセッシングプログラムをどのように印刷する必要がありますか?インストールでデーモンのユーザーまたはグループを追加し、再起動するたびに起動スクリプトを実行するように調整するにはどうすればよいですか?)これらは素晴らしいものではありません。ソースからの再コンパイルはそれらを解決しないので、例。


それに加えて、当時の記憶は今よりも貴重でした。 コンパイル時にオプション機能を除外するは、データ構造により少ないメモリを使用する、より小さなバイナリ(より少ないコードサイズ)を作成できます。機能が何かを追跡するために特定のclassまたはstructのすべてのインスタンスで追加のメンバーを必要とする場合、その機能を無効にすると、オブジェクトが4バイト縮小されます(たとえば)。

最近のオプションのコンパイル時機能は、追加のライブラリをオプションにするために最もよく使用されます。例えばffmpegは、libx264libx265libvorbis、および特定のビデオ/オーディオエンコーダー、字幕処理などの他の多くのライブラリを使用して、または使用せずにコンパイルできます。より一般的には、libreadlineを使用しても使用しなくても、多くのものがコンパイルできます。 ./configureを実行すると、結果のバイナリーはライブラリーに依存し、端末から読み取るときに豪華な行編集を提供します。そうでない場合、プログラムはフォールバックサポートを使用して、fgets()または何かでstdinから行を読み取るだけです。)

一部のプロジェクトでは、パフォーマンス上の理由から、オプションの機能を使用して不要なコードを除外しています。例えばLinuxカーネル自体は、SMPサポートなしで(たとえば、組み込みシステムや古いデスクトップ用に)構築できます。その場合、ロックの多くはより簡単です。または、manyドライバーやその他のハードウェア機能を除外するだけでなく、コアコードの一部に影響を与えるその他のオプション機能を使用します。 (Arch固有およびハードウェア固有の構成オプションは、ソースコード全体のlotを占めますが、 なぜLinuxカーネルは1500万行以上のコードなのですか?)

4
Peter Cordes