Комментарии 17
После такой статьи становится очевидно, что Cosmopolitan - это больше игрушка для фанатов, чем реальный инструмент для продакшена.
На каждом шагу заложены грабли и неочевидные предположения об ОС или о самом коде, и когда оно где-то там взорвётся, отлаживать это (без детального знания кучи низкоуровневых вещей, которое, очевидно, есть у мизерного процента разработчиков) будет то ещё веселье...
Нет, это реальный инструмент для продакшена, но в области системного программирования, а не прикладного.
но в области системного программирования
это не оправдание использованию грязных трюков.
разовое использование их где-нибудь в бутлоадере, обложенное кучей документации с описанием того как оно работает и почему сделано именно так, ещё можно представить, но вот использовать это на каждом шагу и делать вид, что всё нормально — увольте
Cosmopolitan превращает Cи в язык для однократной сборки и запуска в любом месте, аналогичный языку Java, за исключением того, что он не требует интерпретаторов или виртуальных машин, установленых заранее. Он обеспечивает те же преимущества портативности, что и языки высокого уровня, такие как Go и Rust, но не изобретая нового языка, и вам не нужно будет настраивать CI/CD для создания отдельных бинарников для каждой операционной системы.
Cosmopolitan нацелен на исправление C, отделив его от платформ (один бинарник для Windows и Linux - это ли не достижение?), чтобы его было приятно использовать для написания небольших unix-программ, которые легко распространяются среди широкой аудитории.
Ваша программа также будет загружаться на «голом железе». Другими словами, вы написали обычную программу из учебника на C, и благодаря волшебству низкоуровневого компоновщика Cosmopolitan, вы фактически создали свою собственную операционную систему, которая также работает на всех существующих.
Это то, что никто не делал раньше.
По мне так в этом очень много духа старой школы, духа UNIX. Нужно иметь некоторый уровень гениальности чтобы придумать это, а для использования достаточно просто подключить нужные библиотеки.
gcc -g -Os -static -fno-pie -no-pie -nostdlib -nostdinc -gdwarf-4 \
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs \
-o hello.com.dbg hello.c -Wl,--gc-sections -fuse-ld=bfd -Wl,--gc-sections \
-Wl,-T,ape.lds -include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
objcopy -S -O binary hello.com.dbg hello.com
Тот кто это придумал - настоящий хакер, в старом значении этого слова
"Будет приятно узнать, что любая обычная программа для ПК, которую мы напишем, будет «просто работать» на Raspberry Pi и Apple ARM."
Нужно иметь некоторый уровень гениальности чтобы придумать это,
тут соглашусь
а для использования достаточно просто
… не трогать это.
все эти трюки хороши для разминки ума, а в прод лучше пускать скучный код.
В данном случае ваша программа поддерживает SSSE3, только если пользователь установит флаг компиляции
-mssse3
. Лучше пользоваться макросомX86_HAVE()
, так как он делает то же, что иX86_REQUIRE(SSSE3)
, за исключением проверки во время выполнения. По умолчанию, если вы не передали никаких флагов микроархитектуры GCC или Clang, обе ветви войдут в двоичный файл.
if (X86_HAVE(SSSE3)) {
// делаем несколько диких хаков ssse3 на ассемблере
} else {
// возвращаемся к медленному коду ansi c
}
Вот тут либо с переводом что-то не то, либо я чего-то не понимаю. X86_HAVE
по коду дает нам ветвление и мертвый код во время исполнения с проверкой, а пример с X86_REQUIRE
нет. А по тексту все наоборот.
Хотя на практике такое ветвление само по себе не шик и в первой попытке оптимизировать под SSE достаточно флага, чтобы сгенерировать две разные библиотеки с SSE и без нее, выбирая какую загружать в процессе работы или при установке приложения. Тут достаточно ifdef чтобы оба варианта не хранили друг дуга, а Cosmopolitan такое все же допускает. Опять же не забываем про оптимизирующие компиляторы.
Лучше пользоваться макросом X86_HAVE(), так как он делает то же, что и X86_REQUIRE(SSSE3), за исключением проверки во время выполнения.
А потом даётся пояснение:
По умолчанию, если вы не передали никаких флагов микроархитектуры GCC или Clang, обе ветви войдут в двоичный файл.
Т.е. X86_HAVE() лучше, хоть и имеет недостаток.
Если заглянуть в оригинал, то можно увидеть, что там оформление отличается: оно поясняет сказанное, в отличие от перевода. И asm-листинги там читаемые.
P.S. Хотя, я перечитал, и уже не совсем уверен.
P.P.S. Нет же, всё норм. Смысл как раз в том, что если использовать X86_REQUIRE, то нужно обязательно передавать флаг -mssse3 (если нужна поддержка SSSE3); если же использовать X86_HAVE(), то флаг передавать не обязательно, но можно: с флагом оптимизатор уберёт ненужный код, без флага этот код останется.
Как я уже сказал выше, проще сделать два отдельных кода и выкинуть из тела программы условие навсегда.
А по поводу проще/правильнее: в статье неоднократно используется слово «магия» в том или ином виде. КМК, статья именно о ней. Возможно, был бы уместен соответствующий тэг.
еще вариант - вынести платформенный код в разные библиотеки\плагины и после проверки возможностей процессора на старте - подключать нужную (libNoSSSE3 / libSSSE3).
Соглашусь с emaxx: это для фокусов с кодом и никак не для продакшена.
saboteur_kiev: какое (...) системное программирование? Тут под одну операционку пишешь драйвер, потом меняется версия ядра и (вуаля!) количество аргументов в функции поменялось. В пределах одной операционной системы, Карл!
Особенно позабавило перекрытие функции. Этим бы поиграться и забыть как страшный сон. А тут предлагается этим целенаправленно пользоваться. Ужас-ужас-ужас.
Только за одну КДПВ уже поставил плюсик.
Текст совершенно невозможно читать. Такое ощущение, что писала нейросеть. Например:
Однако, если захочется распечатать результат, возникает вторая проблема.
Здесь имеется в виду «вывести результат на экран», а не «распечатать». Однако подобные смысловые нестыковки переводчика по какой-то причине не смутили.
Шестнадцатеричные редакторы хороши, когда вы ищете что-то конкретное, но о форме и виде двоичного кода из них мы узнаём немного.
Думаю, имелась в виду не форма, а формат.
Фокусы оптимизации размера исполняемых файлов ELF. Поддержка 4 ОС в 400 байт единственного бинарника