CIYメンタリティの上昇につながった社会的または技術的要因は何ですか?
根本的な原因は明らかに技術的な理由です。 バイナリの移植性は、ソースの移植性よりも困難です。ディストリビューションパッケージ以外では、ほとんどのフリーソフトウェアは、作成者/メンテナにとって非常に便利であるため、依然としてソース形式でのみ利用できます。
Linuxディストリビューションが平均的な人々が使用したいと思うであろうほとんどのもののパッケージ化を開始するまで、あなたの唯一の選択肢はソースを入手して自分のシステム用にコンパイルすることでした。商用のUnixベンダーは通常、ほとんどすべての人が望むもの(たとえば、GNU bash
などの素敵なシェル)を含まず、独自のsh
and / or 実装のみを使用しているため、csh
(システム管理者として)ユーザーにインタラクティブな使用のための素晴らしいUnix環境を提供するため。
現在、ほとんどの人が唯一の管理者であり、デスクトップに座っているマシンの唯一のユーザーであるという状況は、従来のUnixモデルとは大きく異なります。 システム管理者は、中央システムとすべてのユーザーのデスクトップでソフトウェアを維持していました。(多くの場合、人々のワークステーションにNFSマウント/opt
と/usr/local/
中央サーバーからのマウントを行い、そこにものをインストールします。)
.NETやJavaなどの以前は、異なるCPUアーキテクチャ間での真のバイナリ移植性は不可能でした。Unixカルチャーは、このため、デフォルトでソースの移植性を備えて進化しました。LSBのような最近のLinuxの取り組みまで、バイナリの移植性を有効にしようとする努力さえほとんどありませんでした。例えば、POSIX(主要なUnixの標準)のみであっても最近のバージョンでは、ソース移植を標準化しようと試みます。
関連する文化的要因:初期の商用AT&T Unixには、ソースコード(テープ上)が付属していました。あなたはしていない持っているあなたは何かがどのように見てみたかった場合にはそれだけであった、ソースからシステムを構築するために、本当にドキュメントが十分でなかったときに働きました。
ウィキペディアは言う:
「広範なオンラインドキュメントと(長年にわたって)すべてのシステムソースコードにいつでもアクセスできるというUnixポリシーは、プログラマーの期待を高め、1983年のフリーソフトウェア運動の立ち上げに貢献しました。」
顧客が商用ソフトウェアのソースコードにアクセスできるようにすることは最近では前例がないため、この決定の動機が何であるかはわかりません。この方向には明らかに初期の文化的偏見がいくつかありますが、おそらくそれはUnixのルーツから、さまざまなハードウェア用にコンパイルできる(アセンブリ言語ではなく)ほとんどがCで書かれたポータブルOSとして生まれたのでしょう。以前の多くのOSでは、特定のCPU用にasmで記述されたコードが多かったため、ソースレベルの移植性は、初期のUnixの強みの1つでした。(私はこれについて間違っているかもしれません。私は初期のUnixの専門家ではありませんが、UnixとCは関連しています。)
ソフトウェアをソース形式で配布することは、ソフトウェアを実行したいシステムにそれを適応させる最も簡単な方法です。(エンドユーザーまたはLinuxディストリビューション用にパッケージ化した人)。ソフトウェアが配布によってパッケージ化されている場合、エンドユーザーはそれを使用できます。
しかし、ほとんどのパッケージの作成者がすべての可能なシステム自体にバイナリを作成することを期待するのは、あまりにも多すぎます。いくつかの主要なプロジェクトは、いくつかの一般的なケース(特に、OSにビルド環境が付属しておらず、OSベンダーがバイナリのみのインストーラーの配布に重点を置いているx86 / windows)のバイナリを提供します。
作者が使用したシステムとは別のシステムでソフトウェアを実行するには、いくつかの小さな変更が必要になる場合もあり、これはソースを使用すると簡単です。誰かが自分のかゆみを掻くために書いた小さな1回限りのプログラムは、ほとんどのあいまいなシステムではテストされていません。ソースがあれば、そのような変更を行うことができます。元の作成者が何かを見落としたか、多くの時間を節約したため、移植性の低いコードを意図的に作成した可能性があります。Info-ZIPのような主要なパッケージでさえ、すぐにすべてのプラットフォームにテスターがいるわけではなく、問題が発見されたときに、移植パッチを送る必要がありました。
(そこだけのためのビルドENVの違いにより起こる、ソースレベルでの移植性の問題の他の種類があり、ここでの問題には本当に関係ありません。とJavaスタイルのバイナリポータビリティ、自動ツール(autoconf
/ auto-make
)など同様のことcmake
wouldn 一部のシステム<netinet/in.h>
では<arpa/inet.h>
for の代わりにを含める必要ntohl(3)
があるようなものはありません(そして、そもそもntohl()
やその他のバイト順のものはないでしょう!)
私は.NET言語で定期的に開発しているので、私はコンピュータの読み書きができません。
どこでもコンパイル、どこでも実行は.NETとJavaの主要な目標の1つなので、この問題を解決するために言語全体が発明されたと言っても過言ではありません。開発経験はそのうちの1つです。.NETでは、バイナリはポータブルランタイム環境(CLR)で実行されます。Javaは、そのランタイム環境をJava仮想マシンと呼びます。任意のシステム(少なくとも誰かがすでにJVMまたはCLRを実装しているシステム)で動作する1つのバイナリを配布するだけで済みます。あなたはまだ、のような移植性の問題を持つことができる/
対\
パス区切り、またはどのように印刷するか、GUIはもちろん、細部をレイアウト。
多くのソフトウェアは、完全にネイティブコードにコンパイルされた言語で記述されています。ない、.net
またはJavaバイトコードではなく、実行可能なCPUのネイティブマシンコードのみが、移植性のない実行可能ファイル形式で保存されます。特にUnixの世界では、CとC ++がこの主要な例です。これは明らかに、特定のCPUアーキテクチャ用にバイナリをコンパイルする必要があることを意味します。
ライブラリバージョンも別の問題です。ライブラリは、バイナリレベルのABIを変更している間、ソースレベルのAPIを安定させることができます。(APIとABIの違いを参照してください。)たとえば、不透明に別のメンバーを追加struct
すると、そのサイズは変更され、動的な(malloc)かどうかにかかわらず、そのような構造体にスペースを割り当てるコードには、新しいライブラリバージョンのヘッダーを使用して再コンパイルする必要があります。 )、静的(グローバル)、または自動(スタック上のローカル)。
オペレーティングシステムも重要です。同じCPUアーキテクチャ用のUnixの異なる味が異なるバイナリファイル形式を持っているかもしれない、などの定数のためのシステムコール、および異なる数値を作るための異なるABI fopen(3)
s「はO_RDONLY
、O_APPEND
、O_TRUNC
。
動的にリンクされたバイナリであっても、以前に実行されるOS固有の起動コードがまだあることに注意してくださいmain()
。Windowsでは、これはcrt0
です。UnixとLinuxには同じものがあり、Cランタイムスタートアップコードがすべてのバイナリに静的にリンクされています。理論的には、そのコードが動的にリンクされたシステム、およびlibcの一部または動的リンカー自体を設計することもできると思いますが、これは私が知っているOSで実際に機能する方法ではありません。これは、システムコールのABI問題のみを解決し、標準ライブラリ関数の定数の数値の問題は解決しません。(通常、システムコールはlibcラッパー関数を介して行われます。使用mmap()
するソース用の通常のx86-64 Linuxバイナリには、syscall
命令は含まれません。call
同名のlibcラッパー関数への命令。
これは、i386-Linuxでi386-FreeBSDバイナリを実行できない理由の一部です。(しばらくの間、Linuxカーネルにはシステムコール互換性レイヤーがありました。BSDの少なくとも1つは、同様の互換性レイヤーで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などの他のシステムでもコンパイルおよび動作します。
現在でも多くのCPUアーキテクチャとOSがありますが、デスクトップの大多数は3つの主要なOSの1つを実行しているx86です。
そのため、異なるシステムの異なるバージョンにある可能性のあるサードパーティのライブラリへの依存について考え始める前であっても、あなたが棒を振るよりも多くのCPU / OSの組み合わせがすでにあります。(OSベンダーによってパッケージ化されていないものはすべて手動でインストールする必要があります。)
バイナリにコンパイルされるパスもシステム固有です。(これにより、起動時に構成ファイルから読み取るよりもRAMと時間が節約されます)。古い学校のUnixシステムには通常、多くの手作業でカスタマイズされたものがあり、何がどこにあるかについて有効な仮定を立てることはできません。
バイナリを配布することは、すべての主要な組み合わせでビルドおよびテストする余裕のある主要な商用プロジェクトを除いて、昔ながらのUnixでは完全に実行不可能でした。
バイナリを作ることさえも、i386-linux-gnu
そしてamd64-linux-gnu
難しいです。ポータブルバイナリを可能にするために、Linux Standard Baseなどに多くの時間と労力が費やされています。バイナリを静的にリンクしても、すべてが解決されるわけではありません。(たとえば、RedHatシステムとDebianシステムでワードプロセッシングプログラムをどのように印刷する必要がありますか?インストールでデーモンのユーザーまたはグループを追加し、再起動するたびに起動スクリプトを実行するように調整するにはどうすればよいですか?)ソースからの再コンパイルはそれらを解決しないので、例。
それだけでなく、当時の記憶は今よりも貴重でした。 コンパイル時にオプション機能を省略すると、データ構造に使用するメモリが少なくなる小さなバイナリ(コードサイズが小さい)を作成できます。機能が特定のすべてのインスタンスで追加のメンバーを必要とする場合、class
またはstruct
何かを追跡するために、その機能を無効にすると、オブジェクトが4バイト縮小されます(たとえば)。
最近のオプションのコンパイル時機能は、追加のライブラリをオプションにするために最もよく使用されます。例えば、あなたがコンパイルできるffmpeg
の有無にかかわらずlibx264
、libx265
、libvorbis
より一般的には、物事の多くはの有無にかかわらずコンパイルすることができるなどなど、特定のビデオ/オーディオエンコーダ、字幕処理のための、および他の多くの図書館libreadline
:それは利用可能だ場合は、実行すると./configure
、結果のバイナリーはライブラリーに依存し、端末から読み取るときに豪華な行編集を提供します。そうでない場合、プログラムはフォールバックサポートを使用して、stdinからの行を読み取りfgets()
ます。
一部のプロジェクトでは、オプションの機能を使用して、パフォーマンス上の理由から不要なコードを除外しています。たとえば、Linuxカーネル自体をSMPサポートなしで構築できます(たとえば、組み込みシステムや古代のデスクトップ用)。この場合、多くのロックがより簡単になります。または、ドライバーやその他のハードウェア機能を除外するだけでなく、コアコードの一部に影響を与える他の多くのオプション機能を使用します。(アーキテクチャ固有およびハードウェア固有の構成オプションは、ソースコード全体の多くを占めています。Linuxカーネルが15百万行以上のコードである理由を参照してください。)