- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
<macrodef name="foreach">
<attribute name="target"/>
<attribute name="file-property"/>
<element name="files"/>
<element name="args"/>
<sequential>
<local name="foreach.files"/>
<local name="foreach.target"/>
<local name="foreach.file-property"/>
<local name="foreach.args"/>
<property name="foreach.target" value="@{target}"/>
<property name="foreach.file-property" value="@{file-property}"/>
<pathconvert property="foreach.files">
<files/>
</pathconvert>
<propertyset id="foreach.args">
<args/>
</propertyset>
<property name="foreach.args" refid="foreach.args"/>
<property name="foreach.target" value="@{target}"/>
<!-- there is no better way to do this at the moment
property names and values should not contain comma-space and equals signs
-->
<script language="javascript"><![CDATA[
var files = project.getProperty("foreach.files").split(":"),
args = project.getProperty("foreach.args").split(", "),
task = project.createTask("antcall"), arg;
task.target = project.getProperty("foreach.target");
for (var a in args) {
arg = task.createParam();
arg.setName(a.split("=")[0]);
arg.setValue(String(a.split("=")[1]));
}
for (var f in files) {
arg = task.createParam();
arg.setName(project.getProperty("foreach.file-property"));
arg.setValue(String(files[f]));
task.perform();
}
]]></script>
</sequential>
</macrodef>
<!-- пример использования: -->
<target name="transcode-font-helper">
<property name="font.face.local" value="${font.face}"/>
<foreach target="transcode-font" file-property="font.raw.source">
<files>
<fileset dir="${basedir}/fonts">
<include name="*/${font.face.local}/*.otf"/>
<include name="*/${font.face.local}/*.ttf"/>
</fileset>
</files>
<args>
<propertyref name="font.face.local"/>
</args>
</foreach>
</target>
А ведь если подумать: собрали все самое лучше, что есть в современном программировании - Ява, ХМЛ и ж.скрипт. Потом выбросили условные операторы, итерацию и операции со строкам - потому что не нужны. И получилась замечательная система для сборки проектов.
мы уже про это говорили здесь.
потому что программисты думают только про программирование, и забывают про остальные фазы разработки (deployment, support). иногда даже про то что разница между release и debug может быть больше чем пара флагов компиляции.
поэтому почти у всех модерновых билд систем база такая слабая. просто тупо скопировать пачку файлов из одного места в другое часто становится неподъёмной проблемой. зато для компиляции вообще ничего писать не надо!!! магия.
Но это такая пытка это все расписывать. Плюс потом все равно очень легко ошибиться где чей ключ.
На сегодняшний день использование адобовского таска составляет доли процента от всей сборки, но чем дальше, тем сложнее это все поменять.
Не то, чтобы у них сейчас это хорошо получалось, но за полгода маленький прогресс все-таки есть. Переключиться на что-то другое: это мне обеспечит еще много ненависти и войны с ветряными мельницами...
Сам не так давно переписал довольно большой билд с анта на градл, доволен как слон. Напрягает только небыстрый запуск сборки.
Из плюсов - проекты для ИДЕ не нужно хранить в репе, нормальные ИДЕ могут генерить проекты прямо из gradle-файлов.
Драться ни с кем не пришлось, благо, работаю с очень умными и приятными людьми.
> это мне обеспечит еще много ненависти и войны с ветряными мельницами...
обязанность != ответственность.
возьми на себя *ответственность* что если они будут следовать твоим рекомендациям, то все будет работать. а если не будет работать - то ты пофиксишь. в конце концов, ты не можешь отвечать за то как у них это будет работать, если они не хотят твоим рекомендациям следовать.
другими словами, my way - or highway. только сформулировать надо помягче, что бы народ понял что не все на них висеть будет, но и ты какую-то часть ответственности перенимаешь.
по моему опыту, если клиент тебя уже знает, то им даже и проще ответственность на кого-то другого свалить. да, козёл отпущения, но такова селяви.
Опять оказалось, что тривиальный скрипт на Питоне лучше и проще.
Судя по стек трейсам, все программы написаные на Яве до 2014 годе участвовали в запуске этого кода, но все равно, ни одна из них не взяла на себя труд бросить исключение, (да что там бросить исключение, просто скопировать сообщение об ошибке в строку!). И вы на полном серьезе считаете это достижением инжинерной мысли?
Объясняется двумя словами: лень переписывать.
http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.Exec.html
Этот аргументы передает корректно, некорректно - встроенный Груви тип строг ГСтринг (Г уже должно было насторожить в названии... но думал по-английски может прокатит). "ls ${someDirectory}".execute() - если в someDirectory будут пробелы, амперсанды и т.п. То мы получим шелл-иньекцию, или хз. как это назвать.
http://stackoverflow.com/questions/786160/groovy-execute-with-parameters-containing-spaces
P.S. Какое-то ебанутое использование ООП, имхо. Какого хуя список и строка умеют запускать проги?!
Но что показательно, вот обычно читаешь документацию к библиотеке, и если людям хотелось попиарится, то могут туда бенчмарк вставить, или там цитату известного человека. Читаешь документацию Яваговна - что ни слово, то more powerful, more readable, more expressive и прочая ПР-хуйня вместо полезной информации.
Из документации Cisco.
Т.е. там нельзя делать свои сканеры зависимостей?
Насчет динамического вывода трабла есть - если система не знает имя выходного файла заранее, то она тупо не сможет трекать зависимости. Или я туплю? Вроде бы все эти системы работают по принципу выход-старше-входа-надо-пересобрать?
А что, если эти 50 тасков сгенерить циклом (как в http://govnokod.ru/17414#comment260826, только вместо exec запиливаем таски)? Тогда кеш должен заработать (но сканить каталог со входными файлами, походу, будет каждый раз, а как иначе, ведь они могли появиться/исчезнуть)...
http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html#N1029F
Ну в итоге я так и сделал. Жопа в том, что если мне такой же таск понадобится в другом месте для аналогичной задачи, то решение - только копипаста.
В идеале (и СКонс это умеет), можно было бы научить таск, что если он применяется к каждому файлу в отдельности, а не ко всем вместе, то и при изменении нужно только применять к изменившимся.
http://forums.gradle.org/gradle/topics/equivalent_for_ants_dirset
Эти люди очевидно про работу с файлами слышали только по телевизору.
Я сейчас вот это читать начал, вроде бы как раз то что надо: The other type of task is the enhanced task, where the behaviour is built into the task, and the task provides some properties which you can use to configure the behaviour.
https://gradle.org/docs/current/userguide/custom_tasks.html
И про динамическое создание тасков, походу, тоже. Нету метода, генерящего уникальные айдишки для подобных тасков.
Да там забавно... Если таск не кинул исключение - значит он выполнен. И похуй, что он описанные в outputs.files файлы не создал. Градл эту ситуацию всё равно закеширует. И больше этот таск никогда не запустится пока не изменится что-то в input'ах. После мейка непривычно, но логика в этом есть.
> Нет никакой возможности сделать чистый билд
Есть: --rerun-tasks заставляет его игнорить кеш. Ну или gradle clean сделай, если такой таск описан.
А это хз... вобщем, я конечно еще попытаюсь дочитать маны и посмотреть на проекты побольше, но пока что цель этого мне не понятна. Это настолько несущественно улучшает Ант, что помоему нет смысла.
И вообще, у меня есть странное ощущение, что люди, которые занимаются изучением языков программирования и люди которые создают языки программирования - два непересекающихся множества. Даже без каких-то выдающихся познаний в теории или истории изучения языков программирования, читая авторов практически всех языков созданных в 21м* веке, сразу же обнаруживаются и фактические и теоретические несоответствия.
Или, другой вариант: Одерский как бы теоретик и у него все с этим вроде как хорошо, но это не помогает ему принимать хорошие решения - вместо того, чтобы руководствоваться принципом "сделать как лучше", чаще всего получается "сделать как нравится большинству".
* Раст, Меркури и еще несколько - приятные исключения.
По поводу статьи: снова powerful, concise и flexible, semantic и features - матерого Ява-програмиста видно издалека.
Дважды пытался выучить окамл, дважды забил. Намешали всего, получили месиво фич, паршиво друг с другом сочетающихся. Система типов страдает от мутабельности. Многопоточности нет.
Их приятного только система модулей и, возможно, camlp4.
Уж лучше скалка.
Если кто-то всё же решил выучить этот камл, советую Real World Ocaml, занятное чтиво.
Если бы было время, то приоритеты были бы скорее всего такими: Shen, Mercury / Ciao, Loom, GP2, Rust. Но это не потому, что их где-то можно будет в обозримом будущем использовать, а потому, что интересно понять, как работает.
Gradle удобен там, где много жабоспецифики и есть иерархии жабопроектов.
Только если ради fun...
Вот то, что успел наговнокодить: http://pastebin.com/KAhNF8eM
P.S. Завтра попробую крестопроектик ради интереса портануть на gradle.
Чтобы сборка проекта шла менее нескольких минут.
Градл юзабелен, но уж больно тормозной.
> Вообще фейсбук не может ничего путного сжелать
да ты я смотрю иксперт
Это, походу из-за слишком честной проверки изменений?
Только вот магия имён порой бесит. У меня экзешник назывался storage, ну я и назвал компонент так же, и смотрел как баран на ошибку "свойство storage не найдено"... Вбил как в примерах hello и main - работает. Пришлось назвать компонент storageServer.
Входных файлов не нашлось, скорее всего, поэтому репак ни одного таска не сгенерил, а в нём самом экшенов нету.
и
Должен делать одно и то же... ну как бы так ведь задумано, и вообще логично преположить по аналогии, да? Но вот делает он что-то непонятное вместо.
Ну в теории то да, вызывает include на объекте fonts. Но принимает ли fileTree вторым аргументом Closure?
А ссылка на конкретную реалиазцию ведет вникуда. http://www.gradle.org/docs/current/groovydoc/org/gradle/api/Project.html#fileTree%28java.util.Map%29 . Т.е. нужно искать исходники и разбираться. Кстати об интерфейсах...
Так что можно было бы даже с большой долей уверенности предположить, что это должно работать - но тем не менее, хер.
А как только он начинает занимать 150 -- так сразу надо что-то править в консерватории