Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Make, zpracování souborů vytvořených až při kompilaci

Dělám generátor statických stránek (Static Site Generator) pomocí make

V podstatě čtu .RST soubory a vytvářím .HTML soubory, což je lehké:


TARGETS_R = $(shell find . -name '*.rst')
TARGETS_H = $(TARGETS_R:.rst=.html)
regular_files: $(TARGETS_H)
    @echo "Generating HTML files and tag files..."
%.html: %.rst
    @./compile.py $< $@ # create also tags/<tag_name>.tag files as side-effect

Problém je, že vstupní soubory obsahují tagy, takže seznam tagů zjistím teprve až je všechny nějak zpracuju. Tagy se mi objeví jako tags/*.tag soubory, s tím, že jejich jména předem neznám (protože jsou uvnitř těch vstupních souborů, odkud se dají relativně snadno vyparsovat).

Takhle nějak bych si to naivně představoval - akorát, že to nechodí jak má, ale při prvním spuštění to vygeneruje ty *.tag soubory (ale žádné *.nav), teprve po druhém spuštění to z už existujících souborů .tag udělá všechny potřebné .nav (tady je zjednodušené řešení, protože nejde o obsah, ale o existenci souborů)


TARGETS_R = $(shell find . -name '*.rst')
TARGETS_H = $(TARGETS_R:.rst=.html)
regular_files: $(TARGETS_H)
    @echo "Generating HTML files and tag files..."
%.html: %.rst
    @./compile.py $< $@ @# create also tags/<tag_name>.tag files as side-effect

# ----------- tohle bych chtěl, aby se vyhodnotilo až když je vršek hotový
TAGS = $(shell find . -name '*.tag')
NAVS = $(TAGS:.tag=.nav)
navigation.nav: $(NAVS)
    echo $^ >$@ # some magic here
%.nav: %.tag
    echo $^ >$@ # some magic here

.PHONY: all regular_files

all: regular_files navigation.nav

No a navíc bych to rád spouštěl paralelně s argumentem "-j24", abych využil všechna jádra.

Myslím, že na to musí být nějaký trik, jak to dělat, protože něco podobného už muselo řešit asi bambilión lidí přede mnou, ale nějak jsem nepřišel na to, co hledat, na co se ptát, takže jsem nenašel nic k tématu.
Zkoušel jsem to jak s googlem (vždycky mi vypsal mraky věcí, které s tím nesouvisely), tak jsem to zkusil s chatGPT (a ten zase vůbec nepochopil, o co mi jde na navrhoval samé nefunkční kraviny)

Takže jestli někdo zná řešení, nebo aspoň na co se ptát, tak bych byl velice rád.

Předmět Autor Datum
makefile jsem nikdy nevyráběl, ale pokud všechno selže, můžeš použít nástroje bashe, ne? edit: troc…
touchwood 10.04.2023 19:47
touchwood
Jo, jasně, že můžu, akorát pak přijdu o dost šikovné funkcionality právě toho make (řešení závislost…
gilhad 11.04.2023 02:50
gilhad
a nemůžeš si v makeskriptu udělat několik metod a ty pak postupně spouštět ve třetí? Co se tak pamat…
touchwood 11.04.2023 05:37
touchwood
Pokud "metodama" myslíš věci, jako klasické "install", "compile", "clean" a podobně, tak se nazývají…
nepřihlášený gilhad 12.04.2023 21:03
nepřihlášený gilhad
Zatím jsem to obešel tím, že při startu make prostě projdu všechny RST, vytahám z nich všechny tagy… poslední
gilhad 13.04.2023 03:35
gilhad
Tak jsem na to kouknul a zjevně nestačí - https://stackoverflow.com/questions/26694249/makefiles-usi…
gilhad 11.04.2023 05:25
gilhad

Jo, jasně, že můžu, akorát pak přijdu o dost šikovné funkcionality právě toho make (řešení závislostí, paralelní běh s -j24 a jiné hezké výmysly a krátké výstižné zápisy).
Ono to make je právě dělané (a velmi dlouho laděné) na tyhle problémy.
Takže pokud to nepůjde po dobrém, tak popřemýšlím o nějakém shellskriptu, co by ten make pospouštěl opakovaně, nebo tak něco.
Kdyby bylo úplně nejhůř, tak si to můžu postupně všechno napsat a odladit skoro v čemkoli, co mě napadne (abych řekl v čemkoli, na to znám až moc esoterických jazyků ). Jenže to by bylo zoufale dlouhé, pracné a neefektivní.
Takže mnohem raději bych byl, kdyby to šlo nějak nativně.

Dokonce si myslím, že jsem o něčem takovém četl na nějakém anglickém internetu, ale nedaří se mi to dohledat (a ani nevím, jestli to šlo úplně normálně, nebo nějakým fikaným trikem).

Co se TAGS a find týče, tak tam bude různých podivností víc.

Já to tak nějak řeším za pochodu, protože zároveň píšu ten program na RST -> HTML s různýma speciálníma vychytávkama - např. pokud je v adresáři u RST souboru taky symlink, nazvaný %root%, tak se jak v tom RST, tak v templatech, tak i leckde jinde nahradí všechny řetězce %root% obsahem toho symlinku převedeným na relativní adresu. Takže tam pak kdekoliv funguje třeba %root%/logos/favicon.ico, což se hodí, protože plánuju používat košaté a hluboké adresářové struktury (což jsem stejně dělal vždycky, jen to spousta generátorů a jiných softwarů moc nepodporovala a já se s nima o to musel dost prát). Takře teď se starám, abych se prát nemusel. Navíc takhle pojmenované symlinky jsou fajn, že jsou názorné a pokud je používám v tom zdrojové RST, tak mi editor nativně doplňuje věci přez ně dostupné. A po jejich překladu na relativní cesty to bude fungovat stejně na webu, jako na lokálním disku při ladění, nebo když si to někdo postahuje k sobě - furt bude všechno jak má být :-)

No a podobných vychytávek tam mám mraky, ale do tohohle zadání jsem je nedal, protože by to všechno jen komplikovaly, zatímco mě jde jen o to správně uchopit tu myšlenku ...

No a zároveň teda dělám k tomu i templaty v Jinja2 a snažím se vychytat vlastnorušně psané CSS pro to a snažím se to aspoň nějak dokumentovat už přímo na těch nových stránkách ... prostě dělám toho moc naráz, tak to zatím dělám jen jako proof-of-concept a časem to snad i poladím a učešu. Až to bude spolehlivě fungovat a budu tak schopný při refaktorování snadno hledat regrese.

No a aby toho snad nebylo málo, [strike]spřáhnul se s pankáčema ]:)[/strike], tak se na tom učím používat chatGPT, kdy na něj hážu nápady a kousky kódu a žádosti o běžné obraty a tak a on na mě háže něco, co občas nefunguje vůbec, občas to dělá něco úplně jiného a občas to dělá "něco, co se téměř úplně, ale ne zcela naprosto nepodobá čaji". Takže z toho vytahám, co se nezdá být na první pohled zcela špatně, něco z toho splácám a když to i dělá to, co má, tak už se v tom nevrtám, ale jdu honem dál řešit jiné věci, s tím, že detaily vylepším, až bude celek funkční a stabilní.

a nemůžeš si v makeskriptu udělat několik metod a ty pak postupně spouštět ve třetí? Co se tak pamatuju, tak "make install" běžně spustí i kompilaci, pokud není hotova.

Jinak makefile je poměrně čitelný, kdysi jsem celkem obstojně zvládal m4 (skriptovací nástroj sendmailu) a dokonce i jeho "kompiláty."

Pokud "metodama" myslíš věci, jako klasické "install", "compile", "clean" a podobně, tak se nazývají "cíle" a já je používám :-)

Problém je v tom, že "make" si nejdřív přečte "Makefile", pak ho projde a vyhodnotí přiřazení do proměných a jejich expanze a tak, pak teprve začne vyhodnocovat jednotlivé cíle a pravidla, a pak je teprve začne provádět. Jenže když je provádí, tak už nevyhodnocuje ty proměnné znovu, takže pokud se objeví nové soubory, o kterých nevěděl a nepočítal s nima, tak už je neuvažuje. Až při dalším spuštění.

Můžu jako důsledek nějakého pravidla volat další make se stejným či jiným souborem, můžu v klasickém shell-skriptu volat make několikrát po sobě, můžu to prostě spouštem dvakrát po sobě sám, ale to všechno se mi zdá nějaké neohrabané a myslím si, že by to přece mělo jít nějak líp. Navíc si myslím, že jsem kdysi něco takového někde na internetu viděl a že nemůžu být jediný, kdo řeší podobný problém.
Ale hledání a dotazy zatím nikam nevedou. No, pokud nic nenajdu, tak to holt udělám neelegantně a taky to bude fungovat ... akorád raději dělám věci správně, no ...

Kdysi (možná 2004, nebo dřív) jsem si taky napsal generátor stránek pomocí make a m4 a v podstatě funguje dodnes, jen ho už nepoužívám. Ale ten generoval php, ve kterém se vlastně řešil ten druhý krok. Ale já teď chci ty stránky statické. A ačkoli můj jazyk byl výrazně lepší, než HTML (už jen proto, že v něm nebylo možné křížit tagy a jednotlivé tagy, nebo funkční bloky se psaly jako funkce, například _a(https://pc.poradna.net/questions/3186563-make-zpracovani-souboru-vytvorenych-az-pri-kompilaci, můj dotaz) by vedlo sem :-) ), tak takový reStructuredText je vlastně na podobné věci pohodlnější, i když umí míň.

Zatím jsem to obešel tím, že při startu make prostě projdu všechny RST, vytahám z nich všechny tagy a autory a pokud nemají příslušné soubory, tak je aspoň udělám, i když nenaplňuju.
Takže make pak už má všechna jména souborů a může s nima machrovat (i když jsou třeba zatím prázdné) - a díky závislostem se ty soubory i naplní.
A při dalším spuštění make už ty soubory mají správné hodnoty a pohoda.
Akorát to počáteční projití mi teď sežere něco jako 0.1sec a to na té pokusné sitě mám jen nějakých 32 souborů s mizernými 1.200 řádky textu ... no zatím to jde, můžu aspoň dopsat další chybějící věci a k tomuhle se vrátit později, až mě to začne tlačit víc ...

Je to v podstatě oneliner, teda dva stejné, jeden pro tagy a druhý pro autory. A i když se to nezdá, tak ten sort -u uprostřed to urychluje asi 5x :-)


mkdir -p build/.tags
mkdir -p input/.tags
mkdir -p build/.authors
mkdir -p input/.authors
find input -type f -name "*.rst" -exec grep -h "^:tags:" {} \; | sed "s/^:tags:\s*//; s/\s*,\s*/,/g" | tr "," "\n" | sort -u | sed "s@^.*@( [ ! -e 'build/.tags/\0.tag' ] \&\& touch 'build/.tags/\0.tag' ;  [ ! -e 'input/.tags/\0.rst' ] \&\& sed < .theme/defaults/tag.rst >'input/.tags/\0.rst' 's/%TAG_NAME%/\0/g')@" |sh
find input -type f -name "*.rst" -exec grep -h "^:authors:" {} \; | sed "s/^:authors:\s*//; s/\s*,\s*/,/g" | tr "," "\n" | sort -u | sed "s@^.*@( [ ! -e 'build/.authors/\0.author' ] \&\& touch 'build/.authors/\0.author' ;  [ ! -e 'input/.authors/\0.rst' ] \&\& sed < .theme/defaults/author.rst >'input/.authors/\0.rst' 's/%TAG_NAME%/\0/g')@" |sh

Tak jsem na to kouknul a zjevně nestačí - https://stackoverflow.com/questions/26694249/makefiles-using-wildcard-vs-find-for-specifying-source-files
A když jsem si na to napsal pár příkladů, tak to taky nefungovalo
A chatGPT mi tvrdí, že to funguje a po dotazu na odkaz na https://www.gnu.org/ (protože kde už jinde by to měli vědět, když ne u zdroje?) vrátil rovnou dva - a ani jeden nevedl na stránku, kde by to bylo ...

takže zůstanu u toho, že zavolám find jako externí příkaz ...

Zpět do poradny Odpovědět na původní otázku Nahoru