Які соціальні чи технічні фактори призвели до підняття ментальності CIY?
Першопричиною, очевидно, є технічна причина: переносність бінарних файлів важче, ніж переносність джерела . Поза пакетами дистрибуції більшість безкоштовного програмного забезпечення все ще доступне лише у вихідному вигляді, оскільки це набагато зручніше для автора (ів) / обслуговуючого персоналу.
Поки дистрибутиви Linux не почали пакувати більшість речей, якими хотіли б користуватися пересічні люди, вашим єдиним варіантом було отримати джерело та скласти його для вашої власної системи. Комерційні постачальники Unix, як правило, не включають речі, які хотіли майже всі (наприклад, приємна оболонка на зразок GNU bash
чи подібних), а лише їх власна реалізація sh
та / або csh
, тому вам потрібно було самостійно створювати речі, якщо ви (як sys-admin) хотіли щоб забезпечити своїм користувачам приємне середовище Unix для інтерактивного використання.
Зараз ситуація, коли більшість людей є єдиним адміністратором і єдиним користувачем машини, що сидить на робочому столі, сильно відрізняється від традиційної моделі Unix. Sysadmin підтримував програмне забезпечення в центральній системі та на робочому столі кожного. (Часто за допомогою робочих станцій людей просто встановити NFS /opt
і /usr/local/
з центрального сервера та встановити там речі.)
До таких речей, як .NET та Java, справжня бінарність через різні архітектури процесора була неможливою. З цієї причини культура Unix розвивалася з переносимістю джерел як за замовчуванням, з невеликими зусиллями навіть намагаючись увімкнути бінарну портативність до останніх зусиль Linux, як LSB. Наприклад, POSIX ( основний стандарт Unix) тільки намагається стандартизувати вихідну портативність, навіть в останніх версії.
Суміжний культурний фактор: Ранній комерційний AT&T Unix поставився із вихідним кодом (на стрічках). Вам не потрібно було будувати систему з джерела, вона була просто на випадок, якщо ви хочете побачити, як щось насправді працює, коли документів не вистачає.
У Вікіпедії сказано :
"Політика Unix щодо великої он-лайн документації та (протягом багатьох років) готового доступу до всіх вихідних кодів системи підняла очікування програмістів і сприяла запуску руху вільного програмного забезпечення в 1983 році".
Я не впевнений, що мотивувало це рішення, оскільки надання клієнтам доступу до вихідного коду комерційного програмного забезпечення сьогодні не чує. Очевидно, що в цьому напрямку є ранні культурні ухили, але, можливо, це виросло з коренів Unix як портативна ОС, написана здебільшого на C (а не на мові збірки), яку можна було скласти для різних апаратних засобів. Я думаю, що багато ранніх ОС мали більше свого коду, написаного у ASM для певного процесора, тому портативність на рівні джерела була однією з сильних сторін Unix. (Я можу помилятися з цього приводу; я не є експертом з раннього Unix, але Unix і C пов'язані.)
Поширення програмного забезпечення у вихідному вигляді - це найпростіший спосіб дозволити людям адаптувати його до будь-якої системи, на якій вони хочуть працювати. (Або кінцеві користувачі, або люди, які упаковують його для дистрибутива Linux). Якщо програмне забезпечення вже було розфасовано / для розповсюдження, кінцеві користувачі можуть просто використовувати це.
Але очікувати від авторів більшості пакунків набагато надто багато, щоб зробити бінарні файли для кожної можливої системи. Деякі великі проекти надають бінарні файли для декількох поширених випадків (особливо x86 / windows, де ОС не має середовища побудови, а постачальник ОС зробив основний акцент на розповсюдженні встановлень, призначених лише для двійкових файлів).
Отримання програмного забезпечення для роботи в іншій системі, ніж та, яку використовував автор, може вимагати навіть невеликих змін, які є простими з джерелом . Невелика разова програма, яку хтось написав, щоб подряпати власний свербіж, ймовірно, ніколи не перевірявся на більшості незрозумілих систем. Наявність джерела дозволяє вносити такі зміни. Оригінальний автор, можливо, щось пропустив або навмисно написав менш портативний код, оскільки це заощадило багато часу. Навіть такі великі пакети, як Info-ZIP , не мали одразу тестерів на кожній платформі, і потрібні були люди, щоб надсилати свої патчі для перенесення, оскільки проблеми були виявлені.
(Існують і інші види проблем з перенесенням вихідного рівня , які тільки відбуваються з - за відмінностей в збірки окр, і які на насправді не належать до проблеми тут. З Java-стиль двоичная портативності, авто ( autoconf
/ auto-make
) і тому подібні речі , як cmake
Wouldn «т бути необхідні. І ми не мали б такі речі , як деякі системи вимагають включення <netinet/in.h>
замість<arpa/inet.h>
дляntohl(3)
. (А може бути , ми не мали б ntohl()
або будь-який інший матеріал , байт-порядок в першу чергу!)
Я регулярно розвиваюся мовами .NET, тому я не комп'ютерний неграмотний.
Одноразово компілюйте, запускайте будь-де - одна з головних цілей .NET, а також Java, тому справедливо сказати, що цілі мови були винайдені, щоб вирішити цю проблему , і ваш досвід розробників - одна з них. За допомогою .NET ваш двійковий файл працює на портативному середовищі виконання (CLR) . Java називає це віртуальним середовищем Java Virtual Machine . Потрібно розподілити лише один двійковий файл, який буде працювати в будь-якій системі (принаймні, будь-якій системі, де хтось уже реалізував JVM або CLR). Ви можете все ще є проблеми з перенесенням , як, /
проти \
роздільників шляху, або , як друкувати, або GUI макет деталі, звичайно.
Багато програмного забезпечення написано мовами, повністю скомпільованими в рідний код . .net
Байт-коду немає або java, просто власний машинний код для процесора, на якому він буде працювати, зберігається у непереносному файлі, що виконується. C і C ++ - основні приклади цього, особливо у світі Unix. Очевидно, це означає, що двійковий файл повинен бути складений для конкретної архітектури процесора.
Бібліотечні версії - ще одна проблема . Бібліотеки можуть і часто підтримують API рівня джерела стабільним, змінюючи ABI бінарного рівня. (Див. Різниця між API та ABI .) Наприклад, додавання іншого члена до непрозорого struct
все ще змінює його розмір і вимагає перекомпіляції із заголовками для нової версії бібліотеки для будь-якого коду, який виділяє простір для такої структури, будь то динамічний (malloc ), статичні (глобальні) або автоматичні (локальні в стеку).
Операційні системи також важливі . Інший смак Unix для тих же архітектур процесора може мати різні бінарні формати файлів, різний ABI для створення системних викликів, а також різних числових значень констант , таких як fopen(3)
«з O_RDONLY
, O_APPEND
,O_TRUNC
.
Зауважте, що навіть динамічно пов’язаний двійковий файл все ще має певний ОС, який запускається раніше main()
. У Windows це так crt0
. У Unix та Linux є одне і те ж, де деякий код запуску C-Runtime статично пов'язаний з кожним бінарним файлом. Я думаю, що теоретично ви могли б створити систему, де цей код теж був динамічно пов'язаний, і частина libc або сам динамічний лінкер, але це не так, як все працює на практиці в будь-якій ОС, про яку я знаю. Це вирішило б лише проблему ABI системного виклику, а не задачу числових значень констант для стандартних функцій бібліотеки. (Зазвичай системні виклики здійснюються за допомогою функції оболонки libc: звичайний бінарний файл x86-64 для джерела, який використовує mmap()
, не включає syscall
інструкцію, а лишеcall
інструкція до однойменної функції обгортки libc.
Це частина того, чому ви не можете просто запустити бінарні файли i386-FreeBSD на i386-Linux. (Якийсь час у ядрі Linux був шар сумісності системних викликів. Я думаю, що принаймні один із BSD може запускати бінарні файли Linux із подібним шаром compat, але вам, звичайно, потрібні бібліотеки Linux.)
Якщо ви хочете поширювати бінарні файли, вам потрібно буде зробити окремий для кожної комбінації CPU / OS-аромат + версія / встановлена-бібліотека-версії .
Ще в 80-х / 90-х було багато різних типів процесора, загальноприйнятих для систем Unix (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 / OS, ніж ви можете потиснути палицю, навіть перш ніж починати думати про залежності від сторонніх бібліотек, які можуть бути в різних версіях для різних систем. (Все, що не упаковано постачальником ОС, потрібно було б встановити вручну.)
Будь-які шляхи, складені у двійковий, також є специфічними для системи. (Це економить оперативну пам’ять та час порівняно з читанням їх із конфігураційного файлу при запуску). У системах Unix для старих шкіл зазвичай було багато ручно налаштованих речей, тому немає жодного способу зробити будь-які обґрунтовані припущення щодо того, що де.
Розповсюдження бінарних файлів було цілком нездійсненним для старої школи Unix, за винятком великих комерційних проектів, які можуть дозволити будувати та перевіряти всі основні комбінації .
Навіть робити бінарні файли просто i386-linux-gnu
і amd64-linux-gnu
важко. Багато часу і сил було витрачено на такі речі, як стандартна база Linux, щоб зробити портативними файли файлів можливими . Навіть статичне посилання бінарних файлів не вирішує все. . приклади, оскільки перекомпіляція з джерела не вирішує їх.
Окрім усього цього, пам'ять у той час була ціннішою, ніж зараз. Якщо не залишати додаткових функцій під час компіляції, можна створити менші бінарні файли (менший розмір коду), які також використовують менше пам'яті для своїх структур даних. Якщо функція вимагає додаткового учасника у кожному екземплярі певного class
або struct
відстежувати щось, відключення цієї функції зменшить об'єкт на 4 байти (наприклад), що добре, якщо це об'єкт, якому програма виділяє 100 к.
Необов’язкові функції компіляції в ці дні найчастіше використовуються для надання додаткових бібліотек. Наприклад , ви можете скомпілювати ffmpeg
з або без libx264
, libx265
, libvorbis
і багатьма іншими бібліотеками для конкретного відео / аудіо кодерів, обробки субтитрів і т.д. і т.п. Найчастіше всього , багато речей , які можуть бути зібраний з або без libreadline
: якщо він доступний при запуску ./configure
, то отриманий бінарний файл залежатиме від бібліотеки та забезпечить фантазійне редагування рядків під час читання з терміналу. Якщо це не так, програма використовуватиме деяку резервну підтримку, щоб просто прочитати рядки з stdin з fgets()
чи іншим.)
Деякі проекти все ще використовують додаткові функції, щоб залишити непотрібний код з міркувань продуктивності. наприклад, саме ядро Linux може бути побудовано без підтримки SMP (наприклад, для вбудованої системи або стародавнього робочого столу), в цьому випадку багато блокування простіше. Або з багатьма іншими додатковими функціями, які впливають на деякі основні коди, а не лише залишаючи драйвери чи інші апаратні функції. (Незважаючи на те, що для архівних та апаратних параметрів конфігурації припадає велика кількість загального вихідного коду. Див. Чому для ядра Linux 15+ мільйонів рядків коду? )