Собираем toolchain для С++ разработки под Linux (Ubuntu) на OSX

 
     
 

Crosstool-NG

Для начала нам необходимо crosstool-ng для сборки toolchain’а для компиляции под Linux на базе OSX.

Case Sensitive Volume

Для установки crosstool-ng и для сборки правильного toolchain’а необходим Case-Sensitive Volume. Для этого воспользуемся замечательным скриптом. Опционально надо поправить в нем ${HOME} на то, куда вы реально хотите сохранять образ - у меня например второй большой диск (HDD против SSD) для всякого такого, поэтому пришлось поправить это дело.

Заодно сделаем его, воспользовавшись скриптом

./casesafe.sh create
./casesafe.sh mount

После того как станет ненужным, не забудте сделать

./casesafe.sh unmount

Установка требуемых зависимостей через HomeBrew

brew install autoconf
brew install binutils
brew install gawk
brew install gmp
brew install gnu-sed
brew install help2man
brew install mpfr
brew install openssl
brew install pcre
brew install readline
brew install wget
brew install xz

Иногда brew может сказать что зависимость уже стоит, но устарела, тогда опционально можно сделать brew update …

Еще опционально просят поставить dupes/grep ввиду того, что libc результирующего toolchain’а будет неправильно сконфигурирована, ввиду отличия макового BSD grep от GNU grep. –with-default-names необходимо чтобы системный grep заменился новым, так как без этого параметры brew’шный grep поставиться как ggrep.

brew install grep --with-default-names

Установка собственно crosstool-ng

Я решил пойти по Hacker’s way и сделать все через исходники, а не через release tarballs. Поэтому первое что делаем - клонируем репу, нужен гит:

git clone https://github.com/crosstool-ng/crosstool-ng

Далее нам требуется выбрать конкретный релиз, релизы обозначены тегами, поэтому выгребем теги и зачекаутим нужный:

git fetch --all --tags --prune
git checkout tags/crosstool-ng-1.23.0 -b r1.23.0

Далее начинаем работу по сборке. Так как мы решили пойти Hacker’s Way, то будем запускать это дело из исходников (поэтому ./configure –enable-local).

./bootstrap
./configure --enable-local
make

Для проверки успешности сборки в текущей директории надо сделать

./ct-ng help

Должна вывестись инструкция.

Конфигурируем

./ct-ng menuconfig

Говорят, тем кто собирал линуксовые ядра все должно быть понятно, я просмотрел все опции и потыкал то, что мне надо.

А вообще можно сделать так

./ct-ng list-samples

И выбрать что-то из уже готовых настроек. И затем посмотреть конфигурацию так

./ct-ng show-x86_64-ubuntu16.04-linux-gnu

Выбираем preset

./ct-ng x86_64-ubuntu16.04-linux-gnu

И можно оттюнить с помощью menuconfig

Проблемы

Может случится так, что вы получите такую ошибку

/Volumes/OSXElCapitan/Users/mrdekk/casesafe/.build/src/gdb-7.12.1/gdb/doublest.c:258:19: error: use of undeclared identifier 'min'; did you mean 'fmin'?
[ERROR]    /Volumes/OSXElCapitan/Users/mrdekk/casesafe/.build/src/gdb-7.12.1/gdb/doublest.c:568:19: error: use of undeclared identifier 'min'; did you mean 'fmin'?
[ERROR]    /Volumes/OSXElCapitan/Users/mrdekk/casesafe/.build/src/gdb-7.12.1/gdb/doublest.c:912:25: error: use of undeclared identifier 'min'; did you mean 'fmin'?
[ERROR]    make[3]: *** [doublest.o] Error 1
[ERROR]    make[3]: *** Waiting for unfinished jobs....
[ERROR]    make[2]: *** [all-gdb] Error 2
[ERROR]    make[1]: *** [all] Error 2

Надо попробовать ветку master в crosstool-ng. Однако bash на OSX слишком старый для bootstrap, поэтому придется поставить bash из brew и поправить shell в bootstrap.

После однако начинаются проблемы с sha512sum, такие

/Volumes/OSXElCapitan/Users/mrdekk/Documents/Utils/crosstool-ng/scripts/functions: line 786: sha512sum: command not found

Для этого делаем так

brew install coreutils
ln -s /usr/local/bin/gsha512sum /usr/local/bin/sha512sum

Еще там не собирается glibc с binutils-2.29.1, есть патч, который позволяет так собираться

char *loc1 __attribute__ ((nocommon));
char *loc2 __attribute__ ((nocommon));
compat_symbol (libc, loc1, loc1, GLIBC_2_0);
compat_symbol (libc, loc2, loc2, GLIBC_2_0);

/* Although we do not support the use we define this variable as well.  */
char *locs __attribute__ ((nocommon));
compat_symbol (libc, locs, locs, GLIBC_2_0);

Еще появилась такая проблема

[ERROR]      ../sysdeps/ieee754/dbl-64/e_pow.c:469:13: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context]
[ERROR]      ../sysdeps/ieee754/dbl-64/e_pow.c:471:17: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context]
[ERROR]      ../sysdeps/ieee754/dbl-64/e_pow.c:477:9: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context]
[ERROR]      ../sysdeps/ieee754/dbl-64/e_pow.c:479:13: error: '<<' in boolean context, did you mean '<' ? [-Werror=int-in-bool-context]

Для ее решения есть такой патч

diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index 663fa39..bd758b5 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -466,15 +466,15 @@  checkint (double x)
     return (n & 1) ? -1 : 1;	/* odd or even */
   if (k > 20)
     {
-      if (n << (k - 20))
+      if (n << (k - 20) != 0)
 	return 0;		/* if not integer */
-      return (n << (k - 21)) ? -1 : 1;
+      return (n << (k - 21) != 0) ? -1 : 1;
     }
   if (n)
     return 0;			/*if  not integer */
   if (k == 20)
     return (m & 1) ? -1 : 1;
-  if (m << (k + 12))
+  if (m << (k + 12) != 0)
     return 0;
-  return (m << (k + 11)) ? -1 : 1;
+  return (m << (k + 11) != 0) ? -1 : 1;
 }

Далее опять проблемы

[ALL  ]      rpc_parse.c: In function 'get_prog_declaration':
[ERROR]      rpc_parse.c:543:23: error: '%d' directive writing between 1 and 10 bytes into a region of size 7 [-Werror=format-overflow=]
[ALL  ]           sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */
[ALL  ]                             ^~
[ALL  ]      rpc_parse.c:543:20: note: directive argument in the range [1, 2147483647]
[ALL  ]           sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */
[ALL  ]                          ^~~~~~
[ALL  ]      rpc_parse.c:543:5: note: 'sprintf' output between 5 and 14 bytes into a destination of size 10
[ALL  ]           sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */
[ALL  ]           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ALL  ]      cc1: all warnings being treated as errors
[ERROR]      make[3]: *** [/Volumes/OSXElCapitan/Users/mrdekk/casesafe/.build/x86_64-ubuntu16.04-linux-gnu/build/build-libc-final/multilib/sunrpc/rpc_parse.o] Error 1
[ERROR]      make[3]: *** Waiting for unfinished jobs....
[ERROR]      make[2]: *** [sunrpc/others] Error 2
[ERROR]      make[1]: *** [all] Error 2

Решение этой проблемы найти было сложнее, но кажется есть вот

+--- a/sunrpc/rpc_parse.c
++++ b/sunrpc/rpc_parse.c
+@@ -521,7 +521,7 @@ static void
+ get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
+ {
+   token tok;
+-  char name[10];		/* argument name */
++  char name[MAXLINESIZE];		/* argument name */
+ 
+   if (dkind == DEF_PROGRAM)
+     {

Дальше опять проблемы

nss_nisplus/nisplus-alias.c:300:12: error: argument 1 null where non-null expected [-Werror=nonnull]
[ERROR]      nss_nisplus/nisplus-alias.c:303:39: error: '%s' directive argument is null [-Werror=format-truncation=]
[ERROR]      make[3]: *** [/Volumes/OSXElCapitan/Users/mrdekk/casesafe/.build/x86_64-ubuntu16.04-linux-gnu/build/build-libc-final/multilib/nis/nisplus-alias.os] Error 1
[ERROR]      make[3]: *** Waiting for unfinished jobs....
[ERROR]      make[2]: *** [nis/others] Error 2
[ERROR]      make[1]: *** [all] Error 2

Лечаться так

diff --git a/nis/nss_nisplus/nisplus-alias.c b/nis/nss_nisplus/nisplus-alias.c
index 7f698b4e6d..509ace1f83 100644
--- a/nis/nss_nisplus/nisplus-alias.c
+++ b/nis/nss_nisplus/nisplus-alias.c
@@ -297,10 +297,10 @@  _nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias,
       return NSS_STATUS_UNAVAIL;
     }
 
-  char buf[strlen (name) + 9 + tablename_len];
+  char buf[tablename_len + 9];
   int olderr = errno;
 
-  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+  snprintf (buf, sizeof (buf), "[name=],%s", tablename_val);
 
   nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);

После этого toolchain собрался. После этого я попробовал собрать простой Hello, World с ним и запустить. На macOS не запустилось (zsh: exec format error: ./CrossWorld) - это хорошо. Собираем простейший контейнер на ubuntu 16.04 и запускаем - работает. Отлично!

Об Actor Model от автора

   

Хорошее видео про Actor Model от автора концепции. Правда, на английском, но если владеете и вам интересна модель акторов, то очень рекомендую посмотреть.

MySQL в Docker через supervisord

     

Крутится тут у меня небольшой контейнер с LAMP стэком (Apache, PHP, MySQL внутри одного контейнера вместе с supervisor). И в последнее время периодически стал вылетать MySQL (стал наедаться памяти). Помогала только ручная перезагрузка контейнера. Добавить памяти был не вариант (сама машинка ограниченная по ресурсам). Пробовал зашедулить в крон перезагрузку контейнера, но работало это плохо. Поэтому решил сделать что-нибудь чтоб жило само и без перезагрузок. Получилось так:

Проблема, как я уже сказал, ввиду ограниченных ресурсов виртуальной машинки - mysql хочет выделить блок памяти, но не может и поэтому падает совсем. Так как на диске место есть поколдуем так. Создадим специальный swap файлик:

dd if=/dev/zero of=/opt/swap.dat bs=1024 count=512k
mkswap /opt/swap.dat
swapon /opt/swap.dat
vim /etc/fstab

Файлик /etc/fstab отредактируем так, надо добавить в него такую строчку

/opt/swap.dat      none    swap    sw      0       0

Далее подредактируем конфиг mysql

vim /etc/mysql/my.cnf

Уменьшим размер буфера

innodb_buffer_pool_size=64M 

И далее пересоберем контейнер и перезапустим. 2 недели - полет нормальный. И да - эта инструкция как заставить работать на слабых конфигурациях. Может работать неоптимально с точки зрения производительности.

Шрифт Consolas в Ubuntu

 

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

Задача - установить шрифт consolas (моноширный шрифт для разработки, очень приятный на вид) в Ubuntu, для целей разработки. Он по-умолчанию есть в Windows, но в Ubuntu по понятным причинам его нет.

Делаем так

sudo apt-get install font-manager
sudo apt-get install cabextract

Далее создаем скрипт, который скачает и распакует шрифты

nano consolas.sh

Содержимое

#!/bin/sh
set -e
set -x
mkdir temp
cd temp
wget http://download.microsoft.com/download/E/6/7/E675FFFC-2A6D-4AB0-B3EB-27C9F8C8F696/PowerPointViewer.exe
cabextract -L -F ppviewer.cab PowerPointViewer.exe
cabextract ppviewer.cab

Выполняем

chmod +x consolas.sh
./consolas.sh

Устанавливаем шрифт Consolas

cd temp
font-manager

Шрифт Consolas содержится в таких файлах

  • CONSOLAB.TTF - Жирный (bold)
  • CONSOLAI.TTF - Курсив (italic)
  • CONSOLA.TTF - Обычный (regular)
  • CONSOLAZ.TTF - Жирный курсив (bold italic)

Полный Debug log сборки в Xcode

 
   

Иногда прям очень надо посмотреть что было не так во время сборки проекта Xcode’ом, оказывается есть полный debug log в DerivedData, достать можно так:

путь: ~/Library/Developer/Xcode/DerivedData/<YOURAPP>/Logs/Debug/

Вообще файлы .xcactivitylog - это просто gzip архивы, можно распаковать их так:

cd ~/Library/Developer/Xcode/DerivedData/<YOURAPP>/Logs/Debug/
EXT=".xcactivitylog"
for LOG in *.xcactivitylog; do
    NAME=`basename $LOG $EXT`
    gunzip -c -S $EXT "${NAME}${EXT}" > "${NAME}.log"
done

Кроме собственно Debug логов там есть и Build логи