Pull to refresh

Паралелльная генерация plt файлов для Dialyzer (с депами и плюшками)

Reading time2 min
Views1.5K
Все, кто хоть раз занимался использованием dialyzer для своих приложений знает, что ему надо бы сперва подготовить plt файлы для основных аппликейшенов из поставки самого erlang'а.

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

Обновлено: добавлен патч (и отправлен пулл реквест, разумеется) к dialyzer добавляющий фичу мержа нескольких plt в один большой-и-толстый.

Итак, чтобы собрать один большой plt содержащий всё необходимое, нужно сперва пропатчить и пересобрать dialyzer.
Патч можно взять тут: github.com/datacompboy/otp/commit/bb5f53ed3e7bd28632fcf3d4a797d64c0e00f2c3
Так как я ленивый, я не делал полную пересборку всего-и-вся, я просто пересобрал тот, что и так лежит в системе:
mkdir dialyzer
cd dialyzer
cp -a /usr/lib/erlang/lib/dialyzer-2.4.3/* .
wget https://github.com/datacompboy/otp/commit/bb5f53ed3e7bd28632fcf3d4a797d64c0e00f2c3.patch
patch -p3 < bb5f53ed3e7bd28632fcf3d4a797d64c0e00f2c3.patch
echo '-define(VSN,"v2.4.3").' >> 	src/dialyzer.hrl
echo "{erl_opts, [debug_info]}." >> rebar.config
rebar compile && sudo cp ebin/dialyzer_* /usr/lib/erlang/lib/dialyzer-2.4.3/ebin/


И теперь собственно перейдём к многопоточному созданию plt файлов.

Создаём отдельную папочку (у меня это ~/work/erlang/plt), внутри создаём папку otp и файл Makefile с содержимым (отступы — табуляцией!):

OTP_LIB=/usr/lib/erlang/lib
APPS=$(shell perl -e "\$$a='$(patsubst -1%,,$(patsubst $(OTP_LIB)/%/ebin,%,$(wildcard $(OTP_LIB)/*/ebin)))';\$$a=~s!-[0-9.]+!!g;print \$$a;")
RELS=$(patsubst %,otp/%.plt,$(APPS))

all: all.plt

all.plt: $(RELS)
	dialyzer --merge_plts --output_plt $@ --plts $^

-include $(RELS:.plt=.deps)

IGNOREotp/%.plt:
	if [ -e $@ ]; then dialyzer --check_plt --plt $@ --output_plt $@ || rm $@; fi
	if [ ! -e $@ ]; then dialyzer --build_plt --output_plt $@ --apps $(patsubst otp/%.plt,%,$@); fi

otp/%.plt:
	dialyzer --build_plt --output_plt $@ --apps $(patsubst otp/%.plt,%,$@)

otp/%.deps: otp/%.plt
	dialyzer --plt_info --plt $< | (echo -n "$e:"; perl -ne 'print " $$1" if /^[[ ]"([^"]+)"/') > $@


После чего запускаем
make -j 8
и наблюдаем на генерацию по одному процессу на один app, 8 в параллель.

В финале получаем в папке otp/ файлы plt по одному на один application из otp поставки, и файл all.plt содержащий общий plt из всего-и-вся.

Если что-то вдруг поменяете (например, обновите erlang в системе) — просто запустите еще раз make и будут пересобраны только изменившиеся аппликейшены.

Если слово IGNORE перенести с первого случая во второй, то вместо перегенерации всего аппликейшена каждый раз, будет вызван --check для этой plt, что позволит обновить только изменившиеся beam файлы, но если в приложении появились новые файлы — они не будут автоматически обработаны, именно поэтому я и оставил такую схему регенерации выключенной.
Впрочем, отсюда вполне можно надёргать полезных фич к себе в проект для регенерации plt файлов к своему приложению.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 11: ↑11 and ↓0+11
Comments4

Articles