rewrite buildsystem with make

This commit is contained in:
Sebastian Hugentobler 2015-11-30 18:26:30 +01:00
parent 0b9103b9f6
commit 1115a3fc34
54 changed files with 362 additions and 182 deletions

8
.gitignore vendored
View File

@ -1,7 +1,7 @@
*.pdf
*~
*.*~
out/*
pdf/*
revision.tex
out/
pdf/
midi/
music/
.DS_Store

99
Makefile Normal file
View File

@ -0,0 +1,99 @@
SHELL = /bin/sh
MIDITEMPO = 120
LILYPOND = lilypond
LUALATEX = lualatex
MAKEINDEX = makeindex
TIMIDITY = timidity
OPUSENC = opusenc
PDF2PS = pdf2ps
PSBOOK = psbook
PSTOPS = pstops
PSNUP = psnup
PS2PDF = ps2pdf
SED = sed
RM = rm
MKDIR = mkdir
CD = cd
CP = cp
SRCDIR = src
OUTDIR = out
PDFDIR = pdf
MIDIDIR = midi
OPUSDIR = music
SCORESDIR = $(SRCDIR)/scores
LYRICSDIR = $(SRCDIR)/lyrics
OUTPUTFILE = $(OUTDIR)/singalongs.tex
SCORES = $(wildcard $(SCORESDIR)/*.ly)
PDFS = $(patsubst %.ly,$(PDFDIR)/%.pdf,$(notdir $(SCORES)))
MIDIS = $(patsubst %.ly,$(MIDIDIR)/%.midi,$(notdir $(SCORES)))
OPUSFILES = $(patsubst %.ly,$(OPUSDIR)/%.opus,$(notdir $(SCORES)))
LILYPONDSUBST = $(foreach score,$(SCORES), \\\\chapter {$(shell grep title "$(score)" | awk -F '"|"' '{print $$2}')} \\\\includely[staffsize=18]{$(abspath $(score))} ~\\\\\\\\ ~\\\\\\\\ \\\\input{$(abspath $(LYRICSDIR)/$(notdir $(basename $(score)))).tex})
BOOKPDF = $(PDFDIR)/book.pdf
BOOKLETPDF = $(PDFDIR)/booklet.pdf
all: pdfs midis opus book booklet
pdfs: $(PDFS)
midis: pdfs $(MIDIS)
opus: midis $(OPUSFILES)
book: $(BOOKPDF)
booklet: $(BOOKLETPDF)
$(BOOKPDF): | $(PDFDIR) $(OUTDIR)
@$(CP) $(SRCDIR)/*.tex $(OUTDIR)/
@$(CP) -r lib/* $(OUTDIR)/
@$(CP) -r $(SRCDIR)/images $(OUTDIR)/images
@$(SED) "s;\musicbooklet;$(LILYPONDSUBST);g" $(SRCDIR)/singalongs.tex > $(OUTPUTFILE)
@$(SED) -i '' 's;\input{revision.tex};\newcommand{\\revision}{ $(shell git log -1 --format="%h") };g' $(OUTPUTFILE)
@$(CD) $(OUTDIR); \
$(LUALATEX) -shell-escape singalongs.tex; \
$(MAKEINDEX) singalongs.tex; \
$(LUALATEX) -shell-escape singalongs.tex
@$(CP) $(OUTDIR)/singalongs.pdf $(PDFDIR)/$(@F)
$(BOOKLETPDF): $(BOOKPDF)
$(PDF2PS) $(BOOKPDF) - | $(PSBOOK) | $(PSTOPS) -pa4 '1:0@1.0(-1.25cm,0cm)' | $(PSNUP) -2 | $(PS2PDF) - $(PDFDIR)/$(@F)
$(PDFDIR)/%.pdf: $(SCORESDIR)/%.ly | $(PDFDIR) $(OUTDIR)
@$(SED) 's/%title/title/g' $< > $(OUTDIR)/$(notdir $<)
@$(SED) -i '' 's/\header {/\paper{indent=0\\mm} \\header { tagline=""/g' $(OUTDIR)/$(notdir $<)
@$(LILYPOND) --output=$(PDFDIR)/$(basename $(@F)) $(OUTDIR)/$(notdir $<)
$(MIDIDIR)/%.midi: $(SCORESDIR)/%.ly | $(MIDIDIR) $(OUTDIR)
@$(SED) 's/\layout { }/\midi{ \\tempo 4 = $(MIDITEMPO) }/g' $< > $(OUTDIR)/$(notdir $<)
@$(SED) -i '' 's/\header/\include "articulate.ly" \\header/g' $(OUTDIR)/$(notdir $<)
@$(SED) -i '' 's/<</\\articulate \\unfoldRepeats <</g' $(OUTDIR)/$(notdir $<)
@$(LILYPOND) --output=$(MIDIDIR)/$(basename $(@F)) $(OUTDIR)/$(notdir $<)
$(OPUSDIR)/%.opus: $(MIDIDIR)/%.midi | $(OPUSDIR)
@$(TIMIDITY) $< -Ow -o - | $(OPUSENC) - $(OPUSDIR)/$(@F)
.PHONY: clean
clean:
@$(RM) -rf $(PDFDIR) $(MIDIDIR) $(OPUSDIR) $(OUTDIR)
$(PDFDIR):
@$(MKDIR) -p $(PDFDIR)
$(MIDIDIR):
@$(MKDIR) -p $(MIDIDIR)
$(OPUSDIR):
@$(MKDIR) -p $(OPUSDIR)
$(OUTDIR):
@$(MKDIR) -p $(OUTDIR)

View File

@ -1,13 +1,6 @@
Sing Alongs
===========
[![Build Status](https://build.vanwa.ch/job/Music%20Booklet/badge/icon)](https://build.vanwa.ch/job/Music%20Booklet/)
The latest versions can be found here:
- [Booklet](https://build.vanwa.ch/job/Music%20Booklet/lastSuccessfulBuild/artifact/pdf/singalongs.pdf)
- [Booklet for direct, double sided printing](https://build.vanwa.ch/job/Music%20Booklet/lastSuccessfulBuild/artifact/pdf/singalongs_booklet.pdf)
Motivation
----------

186
lib/lyluatex.lua Normal file
View File

@ -0,0 +1,186 @@
local err, warn, info, log = luatexbase.provides_module({
name = "lyluatex",
version = '0',
greinternalversion = internalversion,
date = "2015/07/14",
description = "Module lyluatex.",
author = "The Gregorio Project (see CONTRIBUTORS.md)",
copyright = "2008-2015 - The Gregorio Project",
license = "MIT",
})
local md5 = require 'md5'
LILYPOND = 'lilypond'
TMP = 'tmp_ly'
N = 0
function ly_definir_programme(lilypond)
if lilypond then LILYPOND = lilypond end
end
function contenuIntegral(contenu)
local content =""
for i, Line in ipairs(contenu:explode('\n')) do
if Line:find("^%s*[^%%]*\\include") then
local i = io.open(Line:gsub('%s*\\include%s*"(.*)"%s*$', "%1"), 'r')
if i then
content = content .. contenuIntegral(i:read('*a'))
else
content = content .. Line .. "\n"
end
else
content = content .. Line .. "\n"
end
end
return content
end
function direct_ly(ly, largeur, facteur)
N = N + 1
facteur = calcul_facteur(facteur)
ly = ly:gsub('\\par ', '\n')
local sortie = TMP..'/'..string.gsub(md5.sumhexa(contenuIntegral(ly))..'-'..facteur..'-'..largeur, '%.', '-')
if not lfs.isfile(sortie..'-systems.tex') then
compiler_ly(entete_lilypond(facteur, largeur - 10)..'\n'..ly, sortie)
end
retour_tex(sortie)
end
function inclure_ly(entree, currfiledir, largeur, facteur)
facteur = calcul_facteur(facteur)
nom = splitext(entree, 'ly')
entree = currfiledir..nom..'.ly'
if not lfs.isfile(entree) then entree = kpse.find_file(nom..'.ly') end
if not lfs.isfile(entree) then err("Le fichier %s.ly n'existe pas.", nom) end
local i = io.open(entree, 'r')
ly = i:read('*a')
i:close()
local sortie = TMP..'/' ..string.gsub(md5.sumhexa(contenuIntegral(ly))..'-'..facteur..'-'..largeur, '%.', '-')
if not lfs.isfile(sortie..'-systems.tex') then
compiler_ly(entete_lilypond(facteur, largeur - 10)..'\n'..ly, sortie, dirname(entree))
end
retour_tex(sortie)
end
function compiler_ly(ly, sortie, include)
mkdirs(dirname(sortie))
local commande = LILYPOND.." "..
"-dno-point-and-click "..
"-dbackend=eps "..
"-djob-count=2 "..
"-ddelete-intermediate-files "
if include then commande = commande.."-I "..lfs.currentdir()..'/'..include.." " end
commande = commande.."-o "..sortie.." -"
local p = io.popen(commande, 'w')
p:write(ly)
p:close()
end
function entete_lilypond(facteur, largeur)
return string.format(
[[%%En-tête
\version "2.18.2"
#(define default-toplevel-book-handler
print-book-with-defaults-as-systems )
#(define toplevel-book-handler
(lambda ( . rest)
(set! output-empty-score-list #f)
(apply print-book-with-defaults rest)))
#(define toplevel-music-handler
(lambda ( . rest)
(apply collect-music-for-book rest)))
#(define toplevel-score-handler
(lambda ( . rest)
(apply collect-scores-for-book rest)))
#(define toplevel-text-handler
(lambda ( . rest)
(apply collect-scores-for-book rest)))
#(set-global-staff-size %s)
%%Paramètres de la partition
\paper{
indent = 0\mm
line-width = %s\pt
}
%%Partition originale
]],
facteur,
largeur
)
end
function calcul_facteur(facteur)
if facteur == 0 then facteur = fontinfo(font.current()).size/39321.6 end
return facteur
end
function retour_tex(sortie)
local i = io.open(sortie..'-systems.tex', 'r')
contenu = i:read("*all")
i:close()
texoutput, _ = string.gsub(
contenu,
[[includegraphics{]], [[includegraphics{]]..dirname(sortie)
)
tex.print(([[\noindent]]..texoutput):explode('\n'))
end
function dirname(str)
if str:match(".-/.-") then
local name = string.gsub(str, "(.*/)(.*)", "%1")
return name
else
return ''
end
end
function splitext(str, ext)
if str:match(".-%..-") then
local name = string.gsub(str, "(.*)(%." .. ext .. ")", "%1")
return name
else
return str
end
end
function mkdirs(str)
path = '.'
for dir in string.gmatch(str, '([^%/]+)') do
path = path .. '/' .. dir
lfs.mkdir(path)
end
end
local fontdata = fonts.hashes.identifiers
function fontinfo(id)
local f = fontdata[id]
if f then
return f
end
return font.fonts[id]
end
mkdirs(TMP)

69
lib/lyluatex.sty Normal file
View File

@ -0,0 +1,69 @@
\ProvidesPackage{lyluatex}
% Dépendances
\RequirePackage{kvoptions}
\RequirePackage{graphicx}
\RequirePackage{keycommand}
\RequirePackage{environ}
\RequirePackage{currfile}
% Options
\DeclareStringOption[lilypond]{program}[lilypond]
\ProcessKeyvalOptions*
% Script lua
\directlua{dofile(kpse.find_file("lyluatex.lua"))}
\directlua{ly_definir_programme('\lyluatex@program')}
% Une tricherie un peu sale pour récupérer la largeur de ligne
\let\bs\textbackslash
{\catcode`p=12 \catcode`t=12 \gdef\un#1pt{#1}}
\newcommand*{\largeur}{\expandafter\un\the\linewidth}
% Taille des partitions
% Si la valeur est 0, elle sera automatiquement calculée
% à partir de la taille de police.
\def\staffsize{0}
\let\localstaffsize\staffsize
% Commandes principales
% Inclusion d'un fichier ly
\newkeycommand*\includely[staffsize=\staffsize][autres][1]{%
\directlua{%
inclure_ly(
"\luatexluaescapestring{#1}",
"\luatexluaescapestring{\currfiledir}",
\luatexluaescapestring{\largeur},
\luatexluaescapestring{\commandkey{staffsize}}
)%
}%
}
% Inclusion d'un fragment intégré au document (environnement de base)
\NewEnviron{compilerly}{%
\directlua{%
direct_ly(
"\luatexluaescapestring{\unexpanded\expandafter{\BODY}}",
\luatexluaescapestring{\largeur},
\luatexluaescapestring{\localstaffsize}
)%
}%
}
% Commande et environnement avec paramètres
\newkeycommand{\lily}[staffsize=\staffsize][autres][1]{%
\def\localstaffsize{\commandkey{staffsize}}%
\begin{compilerly}%
#1
\end{compilerly}%
}
\newkeyenvironment{ly}[staffsize=\staffsize][autres]{%
\def\localstaffsize{\commandkey{staffsize}}%
\compilerly%
}{
\endcompilerly%
}
% Commandes pour la compatibilité avec lilypond-book
\let\lilypondfile\includely
\let\lilypond\ly
\let\endlilypond\endly

View File

@ -1,11 +0,0 @@
#(set-global-staff-size 18)
\paper {
myStaffSize = #18
#(define fonts
(make-pango-font-tree "Iwona Condensed"
"Nimbus Sans"
"Luxi Mono"
(/ myStaffSize 18)))
}

156
make.py
View File

@ -1,156 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
import shutil
import subprocess
import sys
OUTDIR = 'out'
PDFDIR = 'pdf'
IMG_OUTDIR = os.path.join(OUTDIR, 'images')
PDFFILE = 'singalongs.pdf'
PDFBOOKLETFILE = 'singalongs_booklet.pdf'
PSFILE = 'singalongs.ps'
TEXFILE = 'singalongs.tex'
LYTEXFILE = os.path.join(OUTDIR, 'singalongs.lytex')
GITFILE = 'revision.tex'
def build():
make_paths()
assemble()
git_info()
copy()
build_book()
build_booklet()
def make_paths():
if not os.path.exists(OUTDIR):
os.makedirs(OUTDIR)
if not os.path.exists(PDFDIR):
os.makedirs(PDFDIR)
def assemble():
lilyfiles = find_ly_files()
songmap = build_songmap(lilyfiles)
lytex_source = build_lytex('singalongs.tex', songmap)
with open(LYTEXFILE, 'w') as f:
f.write(lytex_source)
def git_info():
latest_rev = subprocess.check_output('git log -1 --format="%h"', shell=True)
latest = '\\newcommand{\\revision}{' + latest_rev.decode('utf-8').strip() + '}'
with open(GITFILE, 'w') as f:
f.write(latest)
def copy():
shutil.copy('lilysettings.ly', OUTDIR)
shutil.copy('headfoot.tex', OUTDIR)
shutil.copy('settings.tex', OUTDIR)
shutil.copy(GITFILE, OUTDIR)
if os.path.exists(IMG_OUTDIR):
shutil.rmtree(IMG_OUTDIR)
shutil.copytree('images', IMG_OUTDIR)
def build_book():
lilycmd = 'lilypond-book --latex-program=lualatex --process="lilypond -dinclude-settings=lilysettings.ly" --pdf -o {0} {1}'.format(OUTDIR, LYTEXFILE)
pdfcmd = 'lualatex {}'.format(TEXFILE)
indexcmd = 'makeindex {}'.format(TEXFILE)
subprocess.call(lilycmd, shell=True)
subprocess.call(pdfcmd, shell=True, cwd=OUTDIR)
subprocess.call(indexcmd, shell=True, cwd=OUTDIR)
subprocess.call(pdfcmd, shell=True, cwd=OUTDIR)
shutil.copy(os.path.join(OUTDIR, PDFFILE), os.path.join(PDFDIR, PDFFILE))
os.remove(GITFILE)
def build_booklet():
pdf2pscmd = 'pdf2ps {0} {1}'.format(os.path.join(OUTDIR, PDFFILE), os.path.join(OUTDIR, PSFILE))
psbookcmd = 'psbook {0} {1}'.format(os.path.join(OUTDIR, PSFILE), os.path.join(OUTDIR, 'booklet_tmp.ps'))
pstopscmd = "pstops -pa4 '1:0@1.0(0cm,0cm)' {0} {1}".format(os.path.join(OUTDIR, 'booklet_tmp.ps'), os.path.join(OUTDIR, 'booklet_tmp00.ps'))
psnupcmd = 'psnup -2 {0} {1}'.format(os.path.join(OUTDIR, 'booklet_tmp00.ps'), os.path.join(OUTDIR, 'booklet.ps'))
ps2pdfcmd = 'ps2pdf {0} {1}'.format(os.path.join(OUTDIR, 'booklet.ps'), os.path.join(PDFDIR, PDFBOOKLETFILE))
subprocess.call(pdf2pscmd, shell=True)
subprocess.call(psbookcmd, shell=True)
subprocess.call(pstopscmd, shell=True)
subprocess.call(psnupcmd, shell=True)
subprocess.call(ps2pdfcmd, shell=True)
def clean():
shutil.rmtree(OUTDIR)
lily_template = """
\chapter {[[title]]}
\lilypondfile{[[scorefile]]}
~\\ ~\\
\input{[[lyricfile]]}
"""
def find_ly_files(path='./scores'):
lilyfiles = []
for found_file in os.listdir(path):
if found_file.endswith(".ly"):
filepath = os.path.join(path, found_file)
lilyfiles.append(filepath)
return lilyfiles
def build_songmap(lilyfiles, lyric_folder='./lyrics'):
songmap = []
for scorefile in lilyfiles:
filename_with_ext = os.path.basename(scorefile)
filename = os.path.splitext(filename_with_ext)[0]
lyricfile = os.path.join(lyric_folder, "{0}.tex".format(filename))
title = find_title(scorefile)
# for windows systems
scorefile = scorefile.replace('\\', '/')
lyricfile = lyricfile.replace('\\', '/')
songmap.append({'scorefile': scorefile, 'lyricfile': lyricfile, 'title': title })
return songmap
def find_title(scorefile):
with open(scorefile) as opened_file:
score = opened_file.read()
title = re.findall('title = "(.*)"', score)
return title[0]
def build_lytex(base_template, songmap):
lilychapters = []
for song in sorted(songmap, key=lambda k: k['scorefile']):
lilychapter = lily_template.replace('[[title]]', song['title'])
lilychapter = lilychapter.replace('[[scorefile]]', song['scorefile'])
lilychapter = lilychapter.replace('[[lyricfile]]', song['lyricfile'])
lilychapters.append(lilychapter)
lilychapters_string = create_lilychapter_string(lilychapters)
with open(base_template) as opened_file:
template = opened_file.read()
template = template.replace('\\musicbooklet', lilychapters_string)
return template
def create_lilychapter_string(lilychapters):
lilychapter_string = ''
for lilychapter in lilychapters:
lilychapter_string += '{0}\n'.format(lilychapter)
return lilychapter_string
if __name__ == "__main__":
action = sys.argv[1] if len(sys.argv) > 1 else 'build'
globals()[action]()

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -8,6 +8,7 @@
\usepackage{geometry}
\usepackage[unicode]{hyperref}
\usepackage{multicol}
\usepackage{lyluatex}
\input{revision.tex}
\input{settings.tex}
@ -45,4 +46,3 @@
\musicbooklet
\end{document}

View File

@ -10,7 +10,7 @@
\begin{minipage}{0.5\textwidth}
\begin{flushleft} \large
\emph{Project Website:} \\
\href{https://code.vanwa.ch/shu/sing-alongs}{code.vanwa.ch/shu/sing-alongs} \\
\href{https://code.vanwa.ch/sing-alongs}{code.vanwa.ch/sing-alongs} \\
\end{flushleft}
\end{minipage}
\begin{minipage}{0.4\textwidth}