LINUX.ORG.RU

Zig 0.8

 , ,


1

5

После 7 месяцев работы и 2711 коммитов вышла новая версия Zig: 0.8

Zig это:

  • Современный компилятор С

  • Современный компилятор С++

  • Компилятор языка Zig

  • Сборочная система для C, C++, языка Zig

  • (Планируется) Пакетный менеджер для С, C++, языка Zig

Zig разрабатывается под лицензией MIT: https://github.com/ziglang/zig/blob/master/LICENSE

Язык Zig – это язык общего назначения, который старается быть простым. Нет макросов, скрытых аллокаций, скрытого потока управления.

Небольшая заметка, которая пытается объяснить зачем нужен Zig, когда уже есть C++, D, и Rust: https://ziglang.org/learn/why_zig_rust_d_cpp/

Даже если вам не интересен язык Zig, возможно вам будет интересен Zig как кросскомпилятор С или С++.

#include <iostream>
int main() {
    std::cout << "Hello World!\n";
    return 0;
}
$ zig c++ -o hello hello.cpp -target riscv64-linux
$ qemu-riscv64 ./hello
Hello World!

Ещё про использование zig как кросскомпилятора: https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html

В новой версии:

  1. Обновление LLVM до LLVM 12.

  2. Поддержка arm64 macOS (aka the Apple Silicon) и также поддержка кросскомпиляции C, C++, и Zig в arm64 и x86_64 macOS.

  3. Zig также разрушает миф, что вам нужен Mac и Xcode для компиляции кода для Mac OS. Заголовочные С файлы Apple выложены под Apple Public Source License которая разрешительная.

Так что вы можете собирать бинарники для Apple из-под Linux/Windows/FreeBSD без XCode:

#include <iostream>

int main() {
   std::cout << "Hello World!\n";
}
$ zig c++ main.cpp -o test -target x86_64-macos
$ file test
test: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>

Подробнее: https://ziglang.org/download/0.8.0/release-notes.html#macOS-Support

и

https://github.com/ziglang/fetch-them-macos-headers

  1. Добавлена поддержка WASI libc

  2. Начальная поддержка Haiku

  3. Изменения в языке: https://ziglang.org/download/0.8.0/release-notes.html#Language-Changes

  4. Изменения в стандартной библиотеке: https://ziglang.org/download/0.8.0/release-notes.html#Standard-Library

  5. Zig поддерживает Position Independent Executables, даже когда компилируются статические бинарники

  6. Изменения в сборочной системе: https://ziglang.org/download/0.8.0/release-notes.html#Zig-Build-System

  7. Обновление musl до 1.2.2, mingw-w64 до 9.0.0, возможность нацеливания glibc 2.33

Полный список изменений: https://ziglang.org/download/0.8.0/release-notes.html

>>> Официальный сайт

★★★★★

Проверено: Satori ()

Ответ на: комментарий от aist1

Я, как человек работающий последние месяцы исключительно на расте могу сказать, что раст это просто нормальный язык, на котором приятно жить (ну не на всех задачах само собой, на тех, которые я решаю например да). Если бы его не было, ну можно было бы на окамле например писать, но было бы печально. Ну или на хаскеле прыгать по кочкам. Ну или тогда уползти на котлин к примеру. Ну может в задачах с компиляцией в васм лучше выбрать зиг, но стоит таки подождать его взросления

q0tw4 ★★★★ ()
Ответ на: комментарий от q0tw4

Ну чтоб макросы можно было нормально писать

Макросы не нужны. В D нет макросов. В Zig нет макросов. В C# нет макросов. В Java нет макросов. В Python нет макросов.

Он уже может в компилтайм коде генерировать новые структуры?

Функции могут возвращать типы. Посмотри как сделаны контейнеры в Zig, например PriorityQueue: https://github.com/ziglang/zig/blob/master/lib/std/priority_queue.zig

fsb4000 ★★★★★ ()

Тема начала иссякать, попробую её подогреть :)

Я посмотрел (еще раз) и Nim, и Zig, и имею что сказать по поводу дизайна языка.

В 90-х программы стали большими и пошла тема «программирования в большом». Появились модульность, пакетные менеджеры и метапрограммирования для генерации бойлерплейта. Java (как платформа) в этом плане очень хороша и свое дело делает. Обратная совместимость просто офигенная, и инженеры, которые это обеспечивают, свой хлеб ядят не зря: кодовая база способна расти. Что нельзя сказать про С++. Комитет по стандартизации делает всё, что может, чтобы сохранять обратную совместимость, но условия изначально гораздо более хдшие, чем в случае Java, которая создавалась изначально под «программирование в большом» так, как оно понималось в 90-е. Но я в них верю, что у них всё получится. С нашей помощью :)

В 2010-х появилось еще одно измерение программирования в большом — большая память/новые типы памяти, многоядерность, а теперь еще и гетерогенность (акселераторы). Если с многоядерностью всё более-менее решено уже давно, то с акселераторами и большой/другой памятью всё совсем-совсем кустарно. Пока что язык, который худо-бедно, но может вот в это всё здесь и сейчас — это С++. Со скрипом и матюгами, но тянет. Спасибо TMP.

Далее, кода становится так много, что код становится новыми данными. Постоянно возникает информационная потребность в исторической перспективе — «а как мы использовали вот этот интерфейс в различных версиях?». И тут у С++ всё на столько плохо, что я дже не знаю, что сказать. Вплоть до того, что некоторые (не будем показывать пальцем) насмерть стоят на том, чтобы не экспортировать AST из GCC для аналитики сторонними средствами. Сообщество С++, в целом очень, консервативно. Им нравиться продолжать жить в 90-х. Денюжка капает, зачем что-то менять?

Платформа программирования, нацеленная в будущее, должна уметь отвечать на все эти вызовы, которые я обозначил (и другие тоже), а основной язык этой платформы — уметь эти вызовы выражать.

И вот в этом разрезе я вижу Zig как идеальный язык для «программирования в малом». Это будет идеяльный язык для программиста, профессионально сформировавшегося в 90-х, и там, по сути, и оставшегося. Nim — то же самое, только в несколько другой парадигме. Nim будет лучше для казуального программирования, типа «как питон, только быстрый». Но тут Julia поджимает с другой стороны. Какоторая именно для казуального технического программирования и создается. Там батареек уже полно сразу, из коробки, а так же файберы есть.

Что бы я хотел видеть в языке, который я бы считал future-proof перед лицом возникающих вызовов.

  • Поддержка различных моделей памяти, а не только «куча» и «стек».
  • Поддержка различных моделей организации данных в памяти, а не только Array of Structures (объекты). (С++ может в это, хоть и с костылями).
  • Поддержка со стороны языка множества моделей управления памятью. Не «только ARC и арены» или «только GC, причем только один» (привет, JVM!), а различную комбинацию из этих технологий. (Nim — может, про Zig не знаю).
  • Сам язык должен быть достаточно выразительным, чтобы с его помощью можно было описывать код не только для CPU, но и для GPU, FPGA и даже ASIC (С++ может, но с расширениями). Хотелось бы, чтобы он был при этом компактным, как Nim или Julia.
  • Ориентация языка не только на код, как буквально все существующие языки, а еще и на структуры данных. Вспоминаем Роба Пайка. Нет, это не сводится к возможности описывать JSON или HTML прямо в тексте программы, хотя это и очень полезная вещь.
  • Поддержка различных профилей кода объединенных единой семантикой данных и операционной семантикой. Безопасный (без UB)/полный. Скриптовый/с явным control flow и т.д. Профиль определяет множество доступных фич языка для написания фрагмента программы.
  • Модульный рантайм. От полностью отсутствующего (Zig) до полноценной платформы со всеми батарейками из коробки (JVM). Не всем и не всегда нужны, например, файберы. Но их нужно иметь возможность включать, если это не ломает какой-то код (это определяется профилями).
  • Первоклассная поддержка для объектной модели кода всего проекта, дающая возможность создания инструментов для аналитики и трансформаций для быстрой и удобной обработки больших массивов кода. (Java — зачет, но с замечаниями). Clang-у горячий привет с их нестабильным AST и невозможностью пробрасывать нестандартные атрибуты в плагины.
  • Поддержка базовой платформой полного цикла разработки от интерктивного редактирования ресурсов для запуска/отладки и деплоймента через API (language server). Не обязательно at scale, хотя бы просто на локазхосте. Камон, на дворе уже третья декада 21-го века. Почему мы все еще через командную строку делаем?

Всё это можно добавить и в Nim, и в Zig, и в Rust. И даже в С++. Но то, что этого не декларируется в архитектуре, говорит о том, что эти языки не разрабатываются для программирования в большом изначально. В лучшем случае мы будем иметь premature optimization, как это получилось с числовыми обобщенными параметрами в Rust, которые не могли добавить несколько лет по причине большого объема работы (и сопротивления тех, кому это «не нужно»). Сейчас всю эту боль разруливания преждевременных оптимизаций проходит С++ на пути своего осовременивания.

aist1 ★★ ()
Ответ на: комментарий от fsb4000

Метафункции (возвращающие типы) не заменяют макросы. Макрос выполняется в конкретном месте AST, на вход он получает контекст выполнения и результатом его работы является фрагмент AST, а не тип.

Метафункции, возвращающие AST, тоже не заменяют макросы, так как требуют дополнительных операторов как захвата контекста вызова, так и внедрения результата. Это, как минимум, будет выглядеть синтаксически громоздко. Хотя и может быть обернуто синтаксическим сахаром. Но в поледнем случае такие метафункции становятся просто макросами — и всё.

aist1 ★★ ()
Ответ на: комментарий от aist1

Чтобы работать на удаленке в америке, надо иметь разрешение на работу в америке. Так ведь?

Или ты мне как босоногому фрилансеру предлагаешь за копейки танцевать перед хозяином?

anonymous ()
Ответ на: комментарий от anonymous

Чтобы работать на удаленке в америке, надо иметь разрешение на работу в америке. Так ведь?

Нет, конечно же. Разрешение нужно, чтобы работать, физически находясь в Америке.

Или ты мне как босоногому фрилансеру предлагаешь за копейки танцевать перед хозяином?

Зачем фриланс? Сдайся местным рекрутерам, ты не один такой желающий. Тут есть конторы, которые ремоут на поток поставили уже. Названий не скажу, реклама иногда мелькает.

aist1 ★★ ()
Ответ на: комментарий от fsb4000

В Zig нет макросов.

Ну вот же: https://ziglang.org/documentation/master/#Compile-Time-Expressions Разве не оно?

В Python нет макросов.

Для интерпретируемого языка наверное не совсем корректно говорить про макросы. Но там есть eval(), а также модуль ast с literal_eval().

В C# нет макросов.

Ну и здесь можно скомпилировать код из строки и запустить почти как в питоне.

Kogrom ()
Ответ на: комментарий от q0tw4

Если я хочу что-то красиво, для души или в психотерапевтических целях, я делаю пет-проджекты. Никто не висит над душей, никому не надо отчитываться, времени сколько угодно, всё можно обдумать. Можно всё сделать хорошо, а не «на продажу». Если надоело, можно бросить и ни перед кем не чувствовать себя виноватым.

А «работа-мечта» — это оксюморон)) Кто вообще будет мечтать о работе? Ну, собсно, кроме тех, у кого её нет.

aist1 ★★ ()
Ответ на: комментарий от aist1

Метафункции (возвращающие типы) не заменяют макросы.

Верно. Но для языка, в котором код должен явно отражать алгоритм, макросы противопоказаны. Метафункция — просто функция, возвращающая тип и используется как обычная функция. А сишный макрос позволяет написать

a.b = c.d

при том, что в структуре a нет поля b, а в структуре c нет поля d. И в результате ещё и произойдёт вывод строки на экран (или форматирование диска).

monk ★★★★★ ()
Ответ на: комментарий от monk

драйвера в ядро линукса на нём проблематично писать.

Проблематично, потому как инфраструктуры нет. Нужна поддержка рантайма. Если выбросить исключения и RTTI, то поддержка эта очень компактная и простая (я реализовывал на Cypress FX3). Плюс нужно втаскивать поддержку в загрузчик модулей. Плюс в инфраструктурных местах вполне себе встречаются имена переменных и структур типа class, которые очевидным образом конфликтуют с ЦПП). А вот для Embedded это вообще вкуснотень. Особенно проверки в компайл-тайме. У нас AV.io HD в один прекрасный момент практически дошёл до состояния «компилируется == работает» :)

hatred ()
Ответ на: комментарий от monk

try/catch

я могу в g++ сделать так, что с ними не соберётся.

new

да:

char *buf;

template<typename T>
struct wrapper
{
  T _val;  
};

void setup() {
  // put your setup code here, to run once:

  buf = new char[32]{0};

  wrapper<char> w;
  w._val = *buf;
}

void loop() {
  // put your main code here, to run repeatedly:

}
Скетч использует 440 байт (1%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
hatred ()
Ответ на: комментарий от X512

Тут главное разделять: операцию new и функцию operator new()

С т.з. зрения языка new в коде сначала вызывает operator new(), что бы выделить память (тут уже детали реализации откуда и как оно будет память возвращать), потом вызывается конструктор. Для new[], память выделяется тем же operator new() с небольшим запасом, в самое начало (это детали реализации, в реальности может и по другому быть) пишем число элементов, делаем сдвиг и вызываем конструкторы для каждого элемента, пользователю возвращаем уже сдвинутый указатель. Конда понимаешь такое детали, становится очевидным, почему new/delete и new[]/delete[] обязаны вызываться именно в такой паре :)

hatred ()
Ответ на: комментарий от hatred

Вот так:

extern "C" void* __dynamic_cast(
	const void* __src_ptr,
	const __cxxabiv1::__class_type_info* __src_type,
	const __cxxabiv1::__class_type_info* __dst_type,
	ptrdiff_t __src2dst
)
{
	const __cxxabiv1::__class_type_info *type = (*((*(__cxxabiv1::__class_type_info***)__src_ptr) - 1));
	while (type != NULL) {
		// WriteString(type->name()); WriteLn();
		if (type == __dst_type) return (void*)__src_ptr;
		if (typeid(*type) == typeid(__cxxabiv1::__si_class_type_info))
			type = ((__cxxabiv1::__si_class_type_info*)type)->__base_type;
		else if (typeid(*type) == typeid(__cxxabiv1::__class_type_info))
			type = NULL;
		else
			abort();
	}
	return NULL;
}

Множественное наследование пока не работает, но оно мне пока не потребовалось, при желании можно сделать.

X512 ★★ ()
Ответ на: комментарий от hatred

Если выбросить исключения и RTTI

Тогда не работает 90% того, что описано в стандарте языка.

Хотя с утверждением «g++ можно использовать для Embedded и компиляции модулей ядра» соглашусь.

monk ★★★★★ ()
Ответ на: комментарий от SR_team

Они с какой-то версии libstdc++ сказали, что больше не будут ломать ABI (ну, постараются). Те же std::string сейчас в двух вариантах есть. На новых инлайнится реализация из std::__cxx11 (или как-то так) неймспейса.

hatred ()
Ответ на: комментарий от monk

Тогда не работает 90% того, что описано в стандарте языка.

С какого перепугу? Тот же STL написан так, что он не вызывает напрямую thow, вызов делается через что-то вроде std::__throw_some_exception(), что является функцией, которая реализуется как часть минималистичного рантайма. В нашем embedded проекте там просто вызывалась panic(). На дебаг сборке гасились прерывания и мигал LED, на продакт - перезагрузка. Сходу: алгоритмы, вектора, списки, строки, всё прекрасно работало. Поэтому встречный вопрос: Вы утверждаете про 90%, а что именно не будет работать? И на основе каких знаний взята это цифра? Или так, лишь бы ляпнуть?

А что в рантайме/STL зависит от RTTI я даже навскидку не скажу. dynamic_cast, но он у конечного пользователя, в embedded точно можно обойтись. Там поведение более детерминированное. Да, я веду речь про Baremetall системы (без ОС или RTOS), жирный embedded с тем же Linux не в счёт. Там мало отличий от десктопа :)

ЗЫ Вот неполный список throw-функций:

namespace std {
void __throw_bad_alloc() throw();
void __throw_length_error(char const* msg);
void __throw_bad_function_call();
void __throw_out_of_range(char const* msg);
}

Ну и не совсем исключения:

extern "C" {
void __cxa_pure_virtual(void);
void __cxa_deleted_virtual(void);
}

Вообще, весь «рантайм» уместился в 36К исходников (повторюсь: исходников), большая часть которых: комментарии :)

hatred ()
Последнее исправление: hatred (всего исправлений: 1)
Ответ на: комментарий от monk

Они даже название ему дали - Wired. Но суть: ваш uno файл просто инклудится в преамбулу, в которой есть main() примерно такого содержимого:

int main()
{
  setup();
  while (true)
    loop();
}
hatred ()
Ответ на: комментарий от X512

Норм. Я тоже шёл по пути Торвальдса, реализовывал только то, что потребовалось в данный момент :)

Ради эксперимента, завернул треды от ThreadX под std::thread, но в интерфейсе последнего не хватает гибкости. Те же атрибуты можно задать только ПОСЛЕ создания объекта, передать в конструктор - низя (может в последних стандартах изменили, но у нас только C++11 был)

hatred ()
Ответ на: комментарий от hatred

Это сколько?

За текущую ситуацию не скажу, но в районе $30-60/h до налогов просить будет не зазорно. Можно и больше, но тут как получится. Тут «потолок» высокий и зависит от твоей наглости и от их жадности. А жадность здесь — основа-основ.

Дело в том, что всех осиляторов выгребает с рынка ФААНГ, чтобы другим не достались. А это — черная дыра. Вот и если надо человечка на тот же Rust, но бюджет не фаанговский, то будут рады рассматривать и удаленщиков.

aist1 ★★ ()
Ответ на: комментарий от hatred

У меня был случай, постучался рекрутер из какого-то банка с Wall Street. Им нужен был человек, умеющий семантические технологии (RDF, OWL) в продакшн заводить. А там проблема, что в большинстве случаев понадобится что-то очень кастомно-высокопроизводительное пилить. Вплоть до аппаратной акселерации на FPGA. А у меня кое-какой опыт завлен в этом деле.

Так вот, рекрутер сказал, что он во всем NYC и окрестностях нашел всего несколько человек, которые хотя бы просто заявляли семантику. И что кроме меня реальных кандидатур нет вообще. Пообщался я с тимлидом, оказался продвинутый чел, я был приятно удивлен (Wall Street славится не как очаг разума). Но в итоге не сошлись ценником, так как я такие скиллы продавать «за дешево» не намерен. Они мне кровью и потом достались.

Короче, ребята. Тут чуть что-то нестандартное нужно, и сразу людей на рынке трудла становится очень мало, если вообще есть. И нужно хантить, а не хайрить. А это уже совсем другие затраты.

aist1 ★★ ()
Ответ на: комментарий от fsb4000

Причём тут макрос?

Тут надо в терминологии разобраться. Часто под макросами понимают:

  1. Вычисление на этапе компиляции сложнее шаблона. Это есть в Zig.
  2. Программа, которая пишет программу. Это есть в Python и C#.

Отдельно можно рассмотреть реализацию printf в Zig: https://ziglang.org/documentation/master/#Case-Study-printf-in-Zig

Здесь во время компиляции форматирующая строка разделяется на токены и если формат неверный, то будет ошибка компиляции. Это и есть работа макроса.

А если придираться к особенностям реализации, то макросов не будет либо в Ниме с Растом, либо в Си.

Kogrom ()
Ответ на: комментарий от Kogrom

Здесь во время компиляции форматирующая строка разделяется на токены и если формат неверный, то будет ошибка компиляции. Это и есть работа макроса.

В С++20 точно также форматирующая строка разделяется на токены и если формат неверный, то будет ошибка компиляции.

Только используется для этого consteval.

consteval теперь макрос?

<source>:36:26: error: call to consteval function 'basic_format_string<char, char [18]>::basic_format_string<5>' is not a constant expression
  std::string s = format("{:d}", "I am not a number");
                         ^
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/format.h:1422:13: note: non-constexpr function 'on_error' cannot be used in a constant expression
    handler.on_error("invalid type specifier");

C++20 Defect Report: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html

Тут надо в терминологии разобраться

Да, это сложно. Я не знаю. У меня только есть вопрос, почему авторы языков применяют другие названия, например mixin, а не макрос?

https://dlang.org/articles/mixin.html

fsb4000 ★★★★★ ()
Последнее исправление: fsb4000 (всего исправлений: 4)
Ответ на: комментарий от hatred

Вы утверждаете про 90%, а что именно не будет работать? И на основе каких знаний взята это цифра?

На основе попытки сборки с -fno-rtti и -fno-exceptions без «36К исходников».

Ладно, если это чинится настолько малой кровью, тогда я неправ.

monk ★★★★★ ()
Ответ на: комментарий от fsb4000

А слово почему другое?

По чисто религиозным причинам, автор D когда был хайп рекламировал, что в нем нет ни препроцессора ни сишных макросов, кстати он вполе красиво вписал в язык всю нужную функциональность, включая условную сборку. Ну и поэтому текстовые миксины пришлось не называть макросами. Ему кстати предлагали нормальные ast макросы встроить, но он отказался.

anonymous ()
Ответ на: комментарий от anonymous

текстовые миксины пришлось не называть макросами

Ну это не совсем макросы. Макросы не любят за то что они игнорят неймспейсы, а миксинами такого нет.

Тут есть список различий - https://dlang.org/articles/mixin.html Но таки да, миксины закрывают ту же нишу, что и макросы

SR_team ★★★★ ()
Ответ на: комментарий от monk

Стандартная библиотека жирная, так как на все случаи, описанные в стандарте, расписана. Плюс в том, что легковесный рантайм делается достаточно просто, даже под конкретную задачу. Минус, что если нужно рациональное использование ресурсов, то его делать обязательно. Но тут уже на многое придётся смотреть под другим углом, да банально, на размеры vtable.

hatred ()
Ответ на: комментарий от anonymous

Ну для любимого раста и гошечки тоже нужно рантайм напильником хреначить, когда на код под жирную задачу у тебя 512кБ RAM и хоть что твори: нужно больше кода, ок, но будет меньше на динамические аллокации и DMA буфера. И наоборот.

hatred ()
Ответ на: комментарий от aist1

Дело в том, что всех осиляторов выгребает с рынка ФААНГ

Утверждение довольно спорное. К фаангу на интервью не попасть, если ты не в сша. И тут не от осиляторства зависит, а в принципе не попасть. Только амазон берет всех, но амазон это не фаанг, это галера за зп/2 от фаанга.

anonymous ()
Ответ на: комментарий от anonymous

К фаангу на интервью не попасть, если ты не в сша.

А я про США и говорил. Речь тут о том, стоит ли искать remote на Rust в США.

С местного рынка они всех осиляторов высасывают, медленно но методично.

Тут человек выше говорил, что и в России можно найти работу на Rust уже. Так что язык вполне себе практичный.

Мой поинт в том, что не стоит прям искать такую работу. Хочется попробовать на практике — pet project. Взлетело — ты уже специалист по Rust и можешь учить молодежь. Не взлетело/не понравилось — продолжаешь дальше на глобальной и надежной (в плане job security) Java.

aist1 ★★ ()
Ответ на: комментарий от fsb4000

Да, это сложно. Я не знаю. У меня только есть вопрос, почему авторы языков применяют другие названия, например mixin, а не макрос?

потому что макросы - это в лиспе

anonymous ()
Ответ на: комментарий от hatred

Ну для любимого раста и гошечки тоже нужно рантайм напильником хреначить

Для раста уже заранее все ошкуренно https://docs.rust-embedded.org/book/intro/no-std.html в с++ тоже очень бы не помешал аналог no_std.

anonymous ()