#1
|
|||
|
|||
Makefile
Victor Sudakov написал(а) к All в May 18 08:37:32 по местному времени:
Dear All, Как правильно написать Makefile на тот случай, если программа генерирует одновременно два файла, чтобы при этом она не запускалась дважды даже при -j2 и больше? ============================================================== .MAKE.JOBS= 2 all: result foo bar: source touch foo bar result: foo bar cat foo bar > result clean: rm -f foo bar result ============================================================== Вышеприведенный пример запускает touch дважды. Читал https://www.gnu.org/savannah-checkou...e-Outputs.html но там настолько ужас-ужас, неужели проще никак? Хотелось бы в рамках BSD make. Victor Sudakov, VAS4-RIPE, VAS47-RIPN --- GoldED+/BSD 1.1.5-b20160322-b20160322 |
#2
|
|||
|
|||
Re: Makefile
Alex Korchmar написал(а) к Victor Sudakov в May 18 08:52:33 по местному времени:
From: Alex Korchmar <noreply@linux.e-moe.ru> Victor Sudakov <Victor.Sudakov@f49.n5005.z2.fidonet.org> wrote: VS> Как правильно написать Makefile на тот случай, если программа генерирует VS> одновременно два файла, чтобы при этом она не запускалась дважды То есть сперва мы специально запускаем дважды, потом пытаемся это сломать? VS> но там настолько ужас-ужас, неужели проще никак? То что ты хочешь - это какая-то заведомо вредная херня. Разумеется она не делается просто. Если файлы зависят друг от друга, это надо просто описать как зависимость. > Alex --- ifmail v.2.15dev5.4 |
#3
|
|||
|
|||
Re: Makefile
Eugene Grosbein написал(а) к Victor Sudakov в May 18 15:02:15 по местному времени:
11 мая 2018, пятница, в 06:37 NOVT, Victor Sudakov написал(а): VS> Как правильно написать Makefile на тот случай, если программа генерирует VS> одновременно два файла, чтобы при этом она не запускалась дважды даже при -j2 и VS> больше? VS> ============================================================== VS> .MAKE.JOBS= 2 VS> all: result VS> foo bar: source VS> touch foo bar VS> result: foo bar VS> cat foo bar > result VS> clean: VS> rm -f foo bar result VS> ============================================================== VS> Вышеприведенный пример запускает touch дважды. Решение зависит от того, почему именно мы не хотим запускать touch дважды, так как лекарство не должно быть хуже болезни. Например, такой вариант (не тестировал): .MAKE.JOBS?= 2 all: result foo: source .if ( ${.MAKE.JOBS} = 1 ) touch foo bar .else make -j1 foo bar .endif bar: foo [ -f $@ ] || make -j1 foo Eugene -- Choose no life --- slrn/1.0.2 (FreeBSD) |
#4
|
|||
|
|||
Makefile
Victor Sudakov написал(а) к Alex Korchmar в May 18 14:01:40 по местному времени:
Dear Alex, 11 May 18 08:52, Alex Korchmar wrote to me: VS>> Как правильно написать Makefile на тот случай, если программа VS>> генерирует одновременно два файла, чтобы при этом она не VS>> запускалась дважды AK> То есть сперва мы специально запускаем дважды, потом пытаемся это AK> сломать? Почему "специально запускаем дважды"? Просто программка такая, что результатом переработки исходника являются сразу и одновременно 2 файла, её дважды запускать вредно. VS>> но там настолько ужас-ужас, неужели проще никак? AK> То что ты хочешь - это какая-то заведомо вредная херня. AK> Разумеется она не делается просто. Видимо не настолько вредная, её периодически хотят, например в https://stackoverflow.com/questions/...-a-single-rule и в gmake даже есть изящный (хотя и ограниченный) способ: https://www.cmcrossroads.com/article...tputs-gnu-make AK> Если файлы зависят друг от друга, это надо просто описать как AK> зависимость. А они (файлы foo и bar) не зависят друг от друга, они зависят только от файла source. А вот result уже зависит от foo и от bar одновременно. Victor Sudakov, VAS4-RIPE, VAS47-RIPN --- GoldED+/BSD 1.1.5-b20160322-b20160322 |
#5
|
|||
|
|||
Makefile
Victor Sudakov написал(а) к Eugene Grosbein в May 18 14:25:56 по местному времени:
Dear Eugene, 11 May 18 15:02, you wrote to me: VS>> Как правильно написать Makefile на тот случай, если программа VS>> генерирует одновременно два файла, чтобы при этом она не VS>> запускалась дважды даже при -j2 и больше? VS>> ============================================================== VS>> .MAKE.JOBS= 2 VS>> all: result VS>> foo bar: source VS>> touch foo bar VS>> result: foo bar VS>> cat foo bar > result VS>> clean: VS>> rm -f foo bar result VS>> ============================================================== VS>> Вышеприведенный пример запускает touch дважды. EG> Решение зависит от того, почему именно мы не хотим запускать touch EG> дважды, так как лекарство не должно быть хуже болезни. "Unfortunately this Makefile does not describe a single rule with two outputs, but rather two distinct rules that each have a single output, and that happen to use the same series of commands. In a serial build this distinction is often irrelevant and sometimes even undetectable: although GNU Make will schedule both rules to run, the second rule will never do any work because its output file will already have been updated (by the first rule). But try running this build in parallel [...] the files are actually updated twice. In the best case, this just results in a little wasted work. In the worst case, the rules both try to update the output files at the same time, resulting in corrupted output." (это так объясняют в https://www.cmcrossroads.com/article...puts-gnu-make) т.е. от лишней траты вычислительных ресурсов до возможного повреждения файлов, если в них станут писать одновременно. В реальности ведь там не touch). EG> Например, такой вариант (не тестировал): EG> .MAKE.JOBS?= 2 EG> all: result EG> foo: source EG> .if ( ${.MAKE.JOBS} = 1 ) EG> touch foo bar EG> .else EG> make -j1 foo bar EG> .endif EG> bar: foo EG> [ -f $@ ] || make -j1 foo Вызов еще одного make изнутри Makefile мне в голову не приходил, это свежо. Но "bar: foo" конечно быть не должно, это не отражает реальной зависимости. Если например прога, обрабатывающая source, решит что foo в этот раз пересоздавать не надо, случится что-нибудь странное. Victor Sudakov, VAS4-RIPE, VAS47-RIPN --- GoldED+/BSD 1.1.5-b20160322-b20160322 |
#6
|
|||
|
|||
Re: Makefile
Alex Korchmar написал(а) к Victor Sudakov в May 18 11:50:08 по местному времени:
From: Alex Korchmar <noreply@linux.e-moe.ru> Victor Sudakov <Victor.Sudakov@f49.n5005.z2.fidonet.org> wrote: AK>> То есть сперва мы специально запускаем дважды, потом пытаемся это AK>> сломать? VS> Почему "специально запускаем дважды"? потому что ты зачем-то запускаешь с j2 VS> Видимо не настолько вредная, её периодически хотят, например в людей, ниасиливших make, в современном мире столько, что жуть берет. это не повод им уподобляться. VS> А они (файлы foo и bar) не зависят друг от друга, они зависят только от VS> файла source. значит этот source нельзя обрабатывать параллельным make вообще. Если он такой один - можно запустить вложенный, но скорее всего сегодня один, завтра будут тыщи, поэтому прощайся с параллельной сборкой такого уродца заранее, меньше потом возни. > Alex --- ifmail v.2.15dev5.4 |
#7
|
|||
|
|||
Makefile
Victor Sudakov написал(а) к Alex Korchmar в May 18 16:55:52 по местному времени:
Dear Alex, 11 May 18 11:50, Alex Korchmar wrote to me: AK>>> То есть сперва мы специально запускаем дважды, потом пытаемся AK>>> это сломать? VS>> Почему "специально запускаем дважды"? AK> потому что ты зачем-то запускаешь с j2 Я указываю -j2, чтобы другие цели параллельно выполнялись. А дважды одно и то же запускает дурак-make, а не я. VS>> Видимо не настолько вредная, её периодически хотят, например в AK> людей, ниасиливших make, в современном мире столько, что жуть берет. AK> это не повод им уподобляться. Как раз по приведенным ссылкам я вижу довольно серьезные попытки осилить make. Я бы сказал, даже изнасиловать. VS>> А они (файлы foo и bar) не зависят друг от друга, они зависят VS>> только от файла source. AK> значит этот source нельзя обрабатывать параллельным make вообще. То есть потребности в колбасе нет, понятно. Хотя на самом деле можно было бы добавить некий модификатор, который сообщал бы мейку, что все перечисленные на данной строчке цели мейкаются за одно действие и параллелить их не надо. Какой-нибудь .SINGLEPASS AK> Если он такой один - можно запустить вложенный, но скорее всего AK> сегодня один, завтра будут тыщи, поэтому прощайся с параллельной AK> сборкой такого уродца заранее, меньше потом возни. Уродец тут BSD make. Нигде не сказано, что программа, выдающая на выходе >1 файла зараз, не имеет права на существование. BTW даже при j1 такие программы make не умеет красиво собирать, например "make -n" будет странный. Victor Sudakov, VAS4-RIPE, VAS47-RIPN --- GoldED+/BSD 1.1.5-b20160322-b20160322 |
#8
|
|||
|
|||
Re: Makefile
Eugene Grosbein написал(а) к Victor Sudakov в May 18 20:37:42 по местному времени:
11 мая 2018, пятница, в 12:25 NOVT, Victor Sudakov написал(а): VS> (это так объясняют в VS> https://www.cmcrossroads.com/article...puts-gnu-make) VS> т.е. от лишней траты вычислительных ресурсов до возможного повреждения файлов, VS> если в них станут писать одновременно. В реальности ведь там не touch). Так что там в реальности-то? Если это нечто пишет в файл, не создавая собственных блокировок против параллельной записи другой своей копией, то эта проблема вообще не имеет отношения к make и решается стандартно, приписыванием lockf к вызову этого нечта. VS> Вызов еще одного make изнутри Makefile мне в голову не приходил, это свежо. Но VS> "bar: foo" конечно быть не должно, это не отражает реальной зависимости. Если VS> например прога, обрабатывающая source, решит что foo в этот раз пересоздавать не VS> надо, случится что-нибудь странное. foo bar: fileflag fileflag: sources lockf /tmp/touch.${.MAKE.PID} touch foo bar && echo -n > fileflag clean: rm -f fileflag ... Eugene --- slrn/1.0.2 (FreeBSD) |
#9
|
|||
|
|||
Makefile
Victor Sudakov написал(а) к Eugene Grosbein в May 18 09:36:22 по местному времени:
Dear Eugene, 11 May 18 20:37, you wrote to me: VS>> (это так объясняют в VS>> https://www.cmcrossroads.com/article...-outputs-gnu-m VS>> ake) т.е. от лишней траты вычислительных ресурсов до возможного VS>> повреждения файлов, если в них станут писать одновременно. В VS>> реальности ведь там не touch). EG> Так что там в реальности-то? Если это нечто пишет в файл, не создавая EG> собственных блокировок против параллельной записи другой своей копией, EG> то эта проблема вообще не имеет отношения к make и решается EG> стандартно, приписыванием lockf к вызову этого нечта. Приписывание lockf IMНO приведёт только к тому, что вторая ветка make дождется выполнения первого экземпляра нечта и таки запустит второй экземпляр. VS>> Вызов еще одного make изнутри Makefile мне в голову не приходил, VS>> это свежо. Но "bar: foo" конечно быть не должно, это не отражает VS>> реальной зависимости. Если например прога, обрабатывающая source, VS>> решит что foo в этот раз пересоздавать не надо, случится VS>> что-нибудь странное. EG> foo bar: fileflag EG> fileflag: sources EG> lockf /tmp/touch.${.MAKE.PID} touch foo bar && echo -n EG> > fileflag EG> clean: EG> rm -f fileflag ... Это некая вариация на тему "Dummy targets" из https://www.cmcrossroads.com/article...tputs-gnu-make "We can work around this by changing the generateparser rule so that it also creates a file on disk named "generate_parser"; then on an incremental build, make will see that the file "generate_parser" is newer than parser.i and will not rebuild. But this is messy: we'll have an extra file hanging around that serves no purpose other than to work around a deficiency* *in* *the* *build* *tool, and we need to remember to manage that file along with the other outputs of the build. It should be deleted by "make clean", for example. And if somebody does something like "touch generateoutput" in between builds, that make may not be able to correctly detect that parser.c and parser.h must be rebuilt. As with the previous solution, if you only do from-scratch full builds, this solution will work fine, but with incrementals you need to be careful." Victor Sudakov, VAS4-RIPE, VAS47-RIPN --- GoldED+/BSD 1.1.5-b20160322-b20160322 |
#10
|
|||
|
|||
Re: Makefile
Eugene Grosbein написал(а) к Victor Sudakov в May 18 17:56:18 по местному времени:
14 мая 2018, понедельник, в 07:36 NOVT, Victor Sudakov написал(а): EG>> Так что там в реальности-то? Если это нечто пишет в файл, не создавая ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ И в третий раз спрошу, а можно всё-таки услышать ответ? Потому как теоретически решение от него не зависит, но практически очень даже. EG>> собственных блокировок против параллельной записи другой своей копией, EG>> то эта проблема вообще не имеет отношения к make и решается EG>> стандартно, приписыванием lockf к вызову этого нечта. VS> Приписывание lockf IMНO приведёт только к тому, что вторая ветка make дождется VS> выполнения первого экземпляра нечта и таки запустит второй экземпляр. It depends. От того, возвращает ли "нечто" когда-нибуь код ошибки EX_TEMPFAIL (75) и нет. Если нет, то проблема решается через lockf -t0 ... && [ $? != 75 ] && while [ ! -s foo ]; do sleep 1 || break; done то есть если lockf вернул EX_TEMPFAIL из-за блокировки, то это не проблема и мы просто поспим до создания foo. EG>> foo bar: fileflag EG>> fileflag: sources EG>> lockf /tmp/touch.${.MAKE.PID} touch foo bar && echo -n fileflag EG>> clean: EG>> rm -f fileflag ... VS> Это некая вариация на тему "Dummy targets" из VS> https://www.cmcrossroads.com/article...tputs-gnu-make И она работает. VS> "We can work around this by changing the generate_parser rule so that it also VS> creates a file on disk named "generate_parser"; then on an incremental build, VS> make will see that the file "generate_parser" is newer than parser.i and will VS> not rebuild. But this is messy: we'll have an extra file hanging around that VS> serves no purpose other than to work around a deficiency* *in* *the* *build VS> tool, and we need to remember to manage that file along with the other outputs VS> of the build. It should be deleted by "make clean", for example. And if VS> somebody does something like "touch generate_output" in between builds, that VS> make may not be able to correctly detect that parser.c and parser.h must be VS> rebuilt. As with the previous solution, if you only do from-scratch full VS> builds, this solution will work fine, but with incrementals you need to be VS> careful." Я не вижу никаких практических препятствий к использованию этого метода. Более того, я активно использую его на практике и не только для сборки чего-нибудь. У меня есть централизованное хранилище конфигов для удалённых офисов, которые сисадмины центрального офиса могут править локально и потом используют команду upload, которая просто говорит cd dir && make upload и Makefile уже разбирается тупо по timestamps, на который сервер нужно влить копию которого локального конфига, создавая такие файл-флаги при успехе и вливая ssh-ем обновления на конкретный сервер именно при отсутствии файл-флага. И всё работает. Аргумент if somebody does something like "touch generate_output" просто смешон, а если самбоди с правами за запись в obj подменит сгенерированные файлы там и/или подставит им фейковые mtime? Eugene --- slrn/1.0.2 (FreeBSD) |