Re: Identify included files
On 09/06/2020 15:57, Fr. Samuel Springuel wrote: On 9 Jun, 2020, at 5:54 AM, Matt Wallis wrote: I found https://lists.gnu.org/archive/html/lilypond-user/2020-05/msg00148.html very interesting. It describes how to get lilypond to print out dependencies. Have you looked into this? That’s from the start of this thread and I’m making use of it in the with-deps.ly file (and in parse-only.ly on the GNUmake_dependencies branch). I don’t use it exactly as it was originally presented in that message because the format wasn’t make-freindly, but ly:source-files is the starting point for generating the list of prerequisites. Sorry - I should have read more carefully! Be clear about the difference between = and :=. You are using = when := would work fine. That’s a good point. I’m carrying over some bad practices from the original Makefile example in the documentation and should clean that up as much as possible. Put everything that moves (!) into a variable. For example, I'd have PDF_DIR := PDF/ Include the backslash when you define a directory (as above). This is a habit I've got into and now rely on. It helps me. Can you elaborate on this? Why would this be better than what I’ve got? Good question. I've been doing this out of habit for so long, I had to think hard to remember why! I've come up with two reasons: 1. The trailing slash in foo/ forces it to be a directory. For example, even when foo does not exist you can't treat foo/ as a regular file: $ cat > foo/ bash: foo/: Is a directory 2. An accidental extra slash causes no problems, but an accidental missing slash changes the meaning: foo//bar is the same as foo/bar, but foobar is not the same as foo/bar Matt
Re: Identify included files
> On 9 Jun, 2020, at 5:54 AM, Matt Wallis wrote: > > I found > https://lists.gnu.org/archive/html/lilypond-user/2020-05/msg00148.html very > interesting. > It describes how to get lilypond to print out dependencies. Have you looked > into this? That’s from the start of this thread and I’m making use of it in the with-deps.ly file (and in parse-only.ly on the GNUmake_dependencies branch). I don’t use it exactly as it was originally presented in that message because the format wasn’t make-freindly, but ly:source-files is the starting point for generating the list of prerequisites. > Be clear about the difference between = and :=. You are using = when := would > work fine. That’s a good point. I’m carrying over some bad practices from the original Makefile example in the documentation and should clean that up as much as possible. > Put everything that moves (!) into a variable. For example, I'd have > > PDF_DIR := PDF/ > > Include the backslash when you define a directory (as above). This is a habit > I've got into and now rely on. It helps me. Can you elaborate on this? Why would this be better than what I’ve got? ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On 09/06/2020 10:54, Matt Wallis wrote: Include the backslash when you define a directory (as above). s/backslash/slash/
Re: Identify included files
On 06/06/2020 16:34, Fr. Samuel Springuel wrote: I have now updated the repository I posted earlier (https://github.com/rpspringuel/lilypond_make) to contain two additional branches: GNUmake_dependencies: Implements dependency generation as described in the GNUmake manual mad-scientist_dependencies: Implements dependency generation as described in the article that Matt linked. Right now I’ve used a simple sed script in the recipe to add the midi file to the targets of the dly file generated by LilyPond, but I haven’t given up on a more general solution. Comments from anyone willing to look these over and play around with them are greatly appreciated. Hi Samuel, Great work! I have not had a play, but I have had a quick look through https://github.com/rpspringuel/lilypond_make/blob/mad-scientist_dependencies/Makefile Just a few comments, mostly general things about makefiles, practices that I usually follow. Be clear about the difference between = and :=. You are using = when := would work fine. Put everything that moves (!) into a variable. For example, I'd have PDF_DIR := PDF/ Include the backslash when you define a directory (as above). This is a habit I've got into and now rely on. It helps me. Use `mkdir -p` to create dirs because it doesn't fail if the directory exists. Having said that, this goes against another principle I often try to follow: Write software according to Dijkstra's weakest preconditions, by making it as fragile as possible (but no more fragile!). That way the program will break if the implementation does not follow the design, making it easier for bugs to become apparent. With the `mkdir -p` example, it could be argued that because these directory targets only come into play via order-only prerequisites, they should never be called upon unless the directory does not exist... I found https://lists.gnu.org/archive/html/lilypond-user/2020-05/msg00148.html very interesting. It describes how to get lilypond to print out dependencies. Have you looked into this? Best regards, Matt
Re: Identify included files
I have now updated the repository I posted earlier (https://github.com/rpspringuel/lilypond_make) to contain two additional branches: GNUmake_dependencies: Implements dependency generation as described in the GNUmake manual mad-scientist_dependencies: Implements dependency generation as described in the article that Matt linked. Right now I’ve used a simple sed script in the recipe to add the midi file to the targets of the dly file generated by LilyPond, but I haven’t given up on a more general solution. Comments from anyone willing to look these over and play around with them are greatly appreciated. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
> On 26 May, 2020, at 6:13 PM, David Wright wrote: > > Because of the inability to collate multiple MIDI files, I've always > renamed them. I tee the log into a nonce file, which I grep for their > names in a postprocessing script. (I then trash the log unless there > was an error code, in which case I leave it, renaming it foo.error.) I’m beginning to think that this may be the way to go. The article that Matt linked makes some good points about when dependency files actually need to be updated. I hadn’t considered those points before and they lead to something different from what the GNUMake manual suggests as far as building the dependency files. Implementing those ideas will require me to rework some of what I’ve been doing, but also would open up the possibility to do things like analyze the stderr from the compilation for messages which clearly identify the output. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On Tue 26 May 2020 at 13:06:50 (-0400), Fr. Samuel Springuel wrote: > > On 26 May, 2020, at 12:09 PM, Timothy Lanfear wrote: > > > > Maybe this code can give some hints on how to decide if midi is being > > produced. > > That’s the first code I’ve seen that’s been able to definitively show when a > midi file is being produced. Thank you. > > Now, there is the issue of it being inside the book block, which makes it > harder to incorporate into something like parse-only.ly (which generally > operates either before or after all input is read), but at least it gives me > a starting point for something to play with. Because of the inability to collate multiple MIDI files, I've always renamed them. I tee the log into a nonce file, which I grep for their names in a postprocessing script. (I then trash the log unless there was an error code, in which case I leave it, renaming it foo.error.) End of main script: "$Youngestlily" "$Pointclick" --include="$HOME"/LilyLib/… … "$Sourcefilename" 2>&1 | tee "$Unique"; [ $PIPESTATUS -ne 0 ] && Lilyerror="ERROR"; midirename "$Unique"; if [ -z "$Lilyerror" ]; then rm -f "${Sourcefilename/%.ly/.error}"; else printf '\n%s\n\n' "$Lilyerror"; mv "$Unique" "${Sourcefilename/%.ly/.error}"; return 2; fi ) } Fragment of midirename script: grep -e '^MIDI output to `' "$1" | sed -e 's/^[^`]*.//;s/.\.\.\.$//' >> "$Unique" PDFs show up in the same way, but not PNGs (which aren't in my own workflow). Cheers, David.
Re: Identify included files
> On 26 May, 2020, at 12:09 PM, Timothy Lanfear wrote: > > Maybe this code can give some hints on how to decide if midi is being > produced. That’s the first code I’ve seen that’s been able to definitively show when a midi file is being produced. Thank you. Now, there is the issue of it being inside the book block, which makes it harder to incorporate into something like parse-only.ly (which generally operates either before or after all input is read), but at least it gives me a starting point for something to play with. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On 26/05/2020 16:15, Fr. Samuel Springuel wrote: I’ve already accounted for this in my most recent version of parse-only.ly. It’s not as straight forward as ly:source-files but by looking at (ly:get-option 'backend), (ly:get-option 'aux-files), (ly:parser-output-name) and (ly:output-formats), it is possible to determine which output files lilypond is going to produce (except for the midi, I have yet to find any option or function which will indicate that a midi is being produced). The applicable code is: Maybe this code can give some hints on how to decide if midi is being produced. \version "2.20.0" #(define (outputdeftype def) (cond ((ly:output-def-lookup def 'is-layout #f) (display "\nlayout")) ((ly:output-def-lookup def 'is-midi #f) (display "\nmidi" \book { \score { { c'1 } \layout{} \midi{} } #(for-each (lambda (score) (for-each outputdeftype (ly:score-output-defs score))) (ly:book-scores $current-book)) } -- Timothy Lanfear, Bristol, UK.
Re: Identify included files
> On 26 May, 2020, at 6:18 AM, Matt Wallis wrote: > > For C/C++, there is an excellent discussion of the issues about automatically > producing dependencies and dealing with them in make: > > http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ > > I think much of this is relevant to lilypond too. There's even a section > entitled "Dependencies for non C files". > > With regard to wanting to avoid typesetting when you want to produce only the > dependencies, this section discusses how to set up a makefile to use > dependency information that is created as a side-effect of compilation: > > http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#combine > > I know I would find it useful if some of the dependency generation flags > (-MMD, -MF, -MP, -MF , see > https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html) available on > C/C++ preprocessor were implemented in lilypond. The work discussed in this > thread might be paving a path towards that. I hadn’t seen that article before, but I’ve started reading it and can definitely see that there are some possibilities there. I’m going to take the time to pursue this and see how I can adapt my process. > Lilypond can produce multiple output files: > > One difference between C/C++ compilers and lilypond is that where a C > compiler produces exactly one .o file for each .c file, lilypond can generate > several output files e.g. .pdf and .midi, but there are other examples too - > I sometimes produce a separate .png for each page of a score. And I expect > that the set of output files may depend on the lilypond command line options, > and not just on the .ly file on which it is being run. > > Is there a way to get lilypond to output this list of targets, analogous to > the ly:source-files capability? > > I think in most cases, the issues around multiple targets can be ignored but > there may be some cases where a full solution would need to handle them ... > more thought required. I’ve already accounted for this in my most recent version of parse-only.ly. It’s not as straight forward as ly:source-files but by looking at (ly:get-option 'backend), (ly:get-option 'aux-files), (ly:parser-output-name) and (ly:output-formats), it is possible to determine which output files lilypond is going to produce (except for the midi, I have yet to find any option or function which will indicate that a midi is being produced). The applicable code is: % Construct list of target extensions % We look at which backend is being used and what formats have been requested to determine this list % Since some backends cause the list of formats to be ignored, we check that first, only looking at the % formats if the backend would allow that. #(define target-extensions (cond ((equal? (ly:get-option 'backend) 'svg) (list "svg")) ((equal? (ly:get-option 'backend) 'scm) (list "scm")) ((equal? (ly:get-option 'backend) 'ps) (uniq-list (sort-list (ly:output-formats) string
Re: Identify included files
> Le 15 mai 2020 à 18:03, Fr. Samuel Springuel a écrit : > >> On 15 May, 2020, at 3:43 AM, Valentin Villenave wrote: >> >> On 5/15/20, Fr. Samuel Springuel wrote: >>> Before I start writing a script to do this, is there an existing tool which >>> will identify all the `\include` files that a LilyPond file depends on? >>> Even better, one that will work in a recursive fashion? >> >> Since 2.19.39, you can simply use this: >> >> #(display (ly:source-files)) That's good! I didn't know you could do that. >> > > I’m hoping for something that doesn’t require actually typesetting the > document. My end goal is a script which will somewhat intelligently > determine which files in a project have changed and re-typeset them as > needed. Having to typeset the document in order to determine which files it > depends on means I’ve already done the typesetting. Is there a way to pass > that and \set Score.skipTypesetting = ##t at the command line? Elsewhere in this thread, there are useful comparisons between C/C++ source and Lilypond source. Also there's the suggestion of using 'make' to express dependencies. For C/C++, there is an excellent discussion of the issues about automatically producing dependencies and dealing with them in make: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ I think much of this is relevant to lilypond too. There's even a section entitled "Dependencies for non C files". With regard to wanting to avoid typesetting when you want to produce only the dependencies, this section discusses how to set up a makefile to use dependency information that is created as a side-effect of compilation: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#combine I know I would find it useful if some of the dependency generation flags (-MMD, -MF, -MP, -MF , see https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html) available on C/C++ preprocessor were implemented in lilypond. The work discussed in this thread might be paving a path towards that. Lilypond can produce multiple output files: One difference between C/C++ compilers and lilypond is that where a C compiler produces exactly one .o file for each .c file, lilypond can generate several output files e.g. .pdf and .midi, but there are other examples too - I sometimes produce a separate .png for each page of a score. And I expect that the set of output files may depend on the lilypond command line options, and not just on the .ly file on which it is being run. Is there a way to get lilypond to output this list of targets, analogous to the ly:source-files capability? I think in most cases, the issues around multiple targets can be ignored but there may be some cases where a full solution would need to handle them ... more thought required. Matt
Re: Identify included files
> On 25 May, 2020, at 3:12 PM, Wols Lists wrote: > > So. Am I correct in thinking that, if you change one .ily file, you need > to rebuild the entire makefile? WHY? > And it means if put a new include into > dynamics.ily, I just need to create/update the line for dynamics.ily, > and everything that depends on it will rebuild if I run the "make" command. Not the entire makefile, just the dly files (which are only partial makefiles) which depend on that ily file. This is necessary to take care of your later issue automatically. By making the dly files depend on the same files which the associate pdf file depends on make will automatically check for changes to the number of included files. > partTrombone.ly voiceTrombone.ily > : This is not a valid statement for make (even if coerced into the correct syntax). While partTrombone.ly may include voiceTrombone.ily, it does not actually depend on it. Dependency in make implies one thing is required to *create* the other, not that they cannot be used independently (which is what you appear to mean by “virtual object”). Each dly file looks like this: target.dly target.pdf : target.ly include_1.ily include_2.ily path/to/include_3.ily The separator (:) splits the targets (the files which can be built) from their prerequisites (the files needed to do the building). If make determines that any target doesn’t exist or is out-of-date, then it will rebuild the target. That’s all that’s in a single dly file, so it does not constitute a complete makefile. Instead it is read into the master makefile, which also contains the rules for building both dly files and pdf files. The master makefile looks like the one I posted earlier in this thread. It co ntains the rules for building dly files and pdf files. Both of these are pattern rules. This means that one rule tells make how to build all dly files from a ly (and parse-init.ly) file and another tells it how to build all pdf files from a ly file. Perhaps a working example will be more productive than a purely theoretical discussion. Here’s a repository that I built using code from the documentation: https://github.com/rpspringuel/lilypond_make Right now it just tries to actualize the example from http://lilypond.org/doc/v2.21/Documentation/usage/make-and-makefiles (using content taken from http://lilypond.org/doc/v2.21/Documentation/snippets/staff-notation#staff-notation-orchestra-choir-and-piano-template). I had to make a few changes to make it work on my system, but I tried to make those changes be as system-agnostic as possible. If you’ll accept that this is a working representation of the makefile example from the documentation, then I’ll go about showing how it gets modified to use the system that I’ve worked out. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On 25/05/20 19:25, Fr. Samuel Springuel wrote: > I think this is where you’ve missed something. When using DK’s code as the > init file (or my later version, which make the output more make-friendly), > LilyPond **does not actually typeset the music.** All it does is read > through the files to construct ly:source-files and then output that list to > stdout. It is the equivalent, in some sense, of the -M option for a CC > (which is where the whole analogy got started). cc -M sample.c does not > create sample.o, it outputs the list of files that sample.o depends on. > Likewise lilypond --init parse-only.ly sample.ly does not create sample.pdf, > it outputs the list of files that sample.pdf depends on. In both cases we’re > using the compiler’s (cc or lilypond) already existing knowledge of how to > read its source and find the mentioned includes, but instead of telling it to > use that knowledge to create the target (the object file or pdf), we’re > telling it to use that knowledge to create the dependency list. So. Am I correct in thinking that, if you change one .ily file, you need to rebuild the entire makefile? WHY? I don't know the exact make syntax but my makefile would be something like partTrombone.pdf partTrombone.ly lilypond partTrombone.ly partTrombone.ly voiceTrombone.ily : voiceTrombone.ily dynamics.ily : Here I'm assuming that ":" tells make that this is a virtual object - it can't be made but it's affected by changes to the file(s) that it depends on. So if I edit dynamics.ily, then do "make partTrombone.pdf", make will cascade that virtual dependency up, realise that partTrombone.pdf is out of date, and rebuild it. And it means if put a new include into dynamics.ily, I just need to create/update the line for dynamics.ily, and everything that depends on it will rebuild if I run the "make" command. Cheers, Wol
Re: Identify included files
On 25 May, 2020, at 12:46 PM, David Wright wrote: > But it seems to me that your OP had the makings of an A/B problem. > You originally asked for a script that worked in the forward > direction: a list of top-level file's dependencies, for constructing > DEP. Having got LP to perform that with DK's method, it turns out > your goal is something different: to discover all the top-level files > that need to be recompiled when you edit an arbitrary \include file. Not really an A/B problem in that I’m not changing the end goal. I needed (and asked) about A (constructing the list of dependencies) because solving A was the prerequisite for getting make to do B (figuring out which scores needed to be recompiled when I changed a source file). While I briefly toyed with the idea of doing B myself (and indeed, had a proof of concept bash script), Jacques pointing to make just made it clear to me that B was already solved by make, provided I solved A in a make-friendly way. > That means that, having edited a mid- to low-level source file in your > library, you have to search every DEP to see whether that file is > mentioned. This includes those of the "someone" who uses your library. > And all those DEPs must be kept up-to-date if the search is to be > performed correctly. That’s true, but this is something make can do automatically given a rule which defines how to create the DEPs. Since such a rule already exists for doing this with CC -M (and is in the gnumake manual: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites), it was fairly trivial for me to adapt that. > The idea behind my later script was: given "some simple rules in your > source layout" and the constituency of your LP sources, the backwards > search for reverse dependencies can be carried out any time any source > file is altered, without the need to keep DEP files up-to-date, > because it greps the active set of files. If I’m understanding you correctly, your point is that A doesn’t need to be solved at all, if you’re willing to solve B in a totally different fashion (i.e. not use make). And I would say that that is true. But it means ignoring the tools that are already at my disposal. While I’m all for learning new things, I hate spending time doing things that someone else has already done if I can use their work. > > Given a top-level .ly file and DK's code, I don't see how you > would avoid any of the recompilng required when you use DK's > output. The last line of the script says > >#(format #t "~{~a\n~^~}" (ly:source-files)) > > How do you use source files without recompiling them—that's what 's > perplexed me all along in this thread. All I've tried to do is give > an idea for finding a list of current top-level files that \include an > arbitrary, specific file. Anyone, with assistance from LP, can make > this as hard as they like for themselves. I think this is where you’ve missed something. When using DK’s code as the init file (or my later version, which make the output more make-friendly), LilyPond **does not actually typeset the music.** All it does is read through the files to construct ly:source-files and then output that list to stdout. It is the equivalent, in some sense, of the -M option for a CC (which is where the whole analogy got started). cc -M sample.c does not create sample.o, it outputs the list of files that sample.o depends on. Likewise lilypond --init parse-only.ly sample.ly does not create sample.pdf, it outputs the list of files that sample.pdf depends on. In both cases we’re using the compiler’s (cc or lilypond) already existing knowledge of how to read its source and find the mentioned includes, but instead of telling it to use that knowledge to create the target (the object file or pdf), we’re telling it to use that knowledge to create the dependency list. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On Sun 24 May 2020 at 16:28:53 (-0400), Fr. Samuel Springuel wrote: > > On 23 May, 2020, at 7:34 PM, David Wright wrote: > > > > If you follow some simple rules in your source layout, constructing > > such a list might be most straightforward to do in the shell, using > > grep. > > It’s not quite as straight-forward as you seem to think: That's why I pasted the sentence above from my previous suggestion. I didn't think it was worth your generalising your script to cover every possibility that LP offers, but that's in your hands. > 1) You haven’t accounted for the possibility of multiple folders with varying > levels of hierarchy. The changed file might be in ../ relative to one file, > ../../ relative to another, ../some/dir/levels relative to a third and other > possible variations. It might also be specified /with/an/absolute/path in > some files. All of that complicates the search string for grep. That's right. You can also flip back and forth between relative-to-top-level-file's-directory and relative-to-calling-file's-directory in the same file, which my grep will know nothing about. You can make it yet tougher: place different files named foo.ily in several directories, and then select different versions from different locations, guided entirely by the directories from which each \include originates. Again, grep will be blind to such tricks. With constructions baroque enough to match the music, a shell script would obviously be more work than it's worth, particularly compared with DK's method. You'd probably be better off concentrating on writing a script to deal with automating the DK method and using its results (as well as keeping track of all this complexity in the source, if it hasn't already caused insanity). > 2) You haven’t accounted for -I options when lilypond is called. Some of the > files included might not be in the same directory tree at all. You’ll need > access to the list of -I options with which lilypond is called in order to > properly identify all the possible top-of-tree/ folders. You might be able > to extract what -I flags a particular project has that are specific to it by > examining some file in the project folders, but what do you do if that > information is stored in a personal shell script or alias setup that catches > all lilypond calls and makes sure certain -I flags are added (as might be > common for someone using openLilyLib or with a personal library of formatting > snippets)? Now your shell script has to go analyze your personal shell > script or shell profile. Oh, come on, that's the easy bit. Whatever options you call LP with, you can make the same information available to the script when you use it as they're both at the level of the shell. As for catching all LP calls, do people actually type their LP commands, with all its options, directly into the shell each time they run it, rather than using scripts? BTW, bear in mind that you may need a fresh run of parse-only.ly to generate a new .dep file/Makefile ("DEP" to save typos) whenever you change your set of includes, else they're stale. > 3) What about the relative-includes option? If an included file includes > other files, where are these files located? Is the given path relative to > the current file or to the top-level file? Our grep search string is getting > even more complicated to account for this. Already treated under (1). > Sure, your ideas would probably catch most cases, and it would be possible to > write a shell script that accounted for these complications. But you’re > duplicating a whole lot of work that’s already been done. LilyPond itself > already knows how to deal with these factors to find the included files > (either because it’s built-in or because you’ve already told it what to do > when you configured your system). Why reinvent this wheel in a shell script > if LilyPond can be made to output what it already knows for you? I agree. there's no magic here. If you want to add complexity in one place, you have to match it in another. Just so long as you need it. (We haven't seen your use case.) > Another issue: How are you keeping track of which files have changed (and > thus should seed your script)? If you recompile frequently after only > changing a file or two, it’s fairly easy, but what if the change you’re > working on takes several days to (either due to complexity or restricted > time) or touches a whole bunch of files? Are you supposed to manually > remember all those changes? Or maybe you’re planning on querying your > version control system (you are using one, right?) for that information? As > a last resort, you might also look at modified times on the pdfs (if they > exist) and the source files. That's a question I might ask you: these are your files, your edits, your working methods, your problem area. > Of course, given a proper list of file dependencies, make will do all this > work for you. That’s what
Re: Identify included files
On 5/25/20, R. Padraic Springuel wrote: > It depends on the state of the relative-includes variable. If true, then > paths are relative to the file in which the include statement appears. If > false, the paths are relative to the main input file. Default behavior is > false. Careful, the default will be set to true from version 2.21.2 on: https://git.savannah.gnu.org/cgit/lilypond.git/commit/?id=16b5212f7c1745e14e29792fdcf7cb307bc23ad5 Cheers, -- V.
Re: Identify included files
> On May 25, 2020, at 2:58 AM, Wols Lists wrote: > > On 24/05/20 21:28, Fr. Samuel Springuel wrote: >> It’s not quite as straight-forward as you seem to think: >> >> 1) You haven’t accounted for the possibility of multiple folders with >> varying levels of hierarchy. The changed file might be in ../ relative to >> one file, ../../ relative to another, ../some/dir/levels relative to a third >> and other possible variations. It might also be specified >> /with/an/absolute/path in some files. All of that complicates the search >> string for grep. > > This is a real can of worms ... > > I THINK all paths are relative to where lilypond is running. So any > include file that itself contains relative includes is asking for > trouble - it's "random" whether those paths will be valid or not... > > Cheers, > Wol > It depends on the state of the relative-includes variable. If true, then paths are relative to the file in which the include statement appears. If false, the paths are relative to the main input file. Default behavior is false. It’s explained here: http://lilypond.org/doc/v2.21/Documentation/notation/including-lilypond-files
Re: Identify included files
On 24/05/20 21:28, Fr. Samuel Springuel wrote: > It’s not quite as straight-forward as you seem to think: > > 1) You haven’t accounted for the possibility of multiple folders with varying > levels of hierarchy. The changed file might be in ../ relative to one file, > ../../ relative to another, ../some/dir/levels relative to a third and other > possible variations. It might also be specified /with/an/absolute/path in > some files. All of that complicates the search string for grep. This is a real can of worms ... I THINK all paths are relative to where lilypond is running. So any include file that itself contains relative includes is asking for trouble - it's "random" whether those paths will be valid or not... Cheers, Wol
Re: Identify included files
> On 23 May, 2020, at 7:34 PM, David Wright wrote: > > If you follow some simple rules in your source layout, constructing > such a list might be most straightforward to do in the shell, using > grep. It’s not quite as straight-forward as you seem to think: 1) You haven’t accounted for the possibility of multiple folders with varying levels of hierarchy. The changed file might be in ../ relative to one file, ../../ relative to another, ../some/dir/levels relative to a third and other possible variations. It might also be specified /with/an/absolute/path in some files. All of that complicates the search string for grep. 2) You haven’t accounted for -I options when lilypond is called. Some of the files included might not be in the same directory tree at all. You’ll need access to the list of -I options with which lilypond is called in order to properly identify all the possible top-of-tree/ folders. You might be able to extract what -I flags a particular project has that are specific to it by examining some file in the project folders, but what do you do if that information is stored in a personal shell script or alias setup that catches all lilypond calls and makes sure certain -I flags are added (as might be common for someone using openLilyLib or with a personal library of formatting snippets)? Now your shell script has to go analyze your personal shell script or shell profile. 3) What about the relative-includes option? If an included file includes other files, where are these files located? Is the given path relative to the current file or to the top-level file? Our grep search string is getting even more complicated to account for this. Sure, your ideas would probably catch most cases, and it would be possible to write a shell script that accounted for these complications. But you’re duplicating a whole lot of work that’s already been done. LilyPond itself already knows how to deal with these factors to find the included files (either because it’s built-in or because you’ve already told it what to do when you configured your system). Why reinvent this wheel in a shell script if LilyPond can be made to output what it already knows for you? Another issue: How are you keeping track of which files have changed (and thus should seed your script)? If you recompile frequently after only changing a file or two, it’s fairly easy, but what if the change you’re working on takes several days to (either due to complexity or restricted time) or touches a whole bunch of files? Are you supposed to manually remember all those changes? Or maybe you’re planning on querying your version control system (you are using one, right?) for that information? As a last resort, you might also look at modified times on the pdfs (if they exist) and the source files. Of course, given a proper list of file dependencies, make will do all this work for you. That’s what it is for. Pair make with a LilyPond based tool which can determine dependencies automatically and it becomes even simpler because the system is self-updating. Now, I will grant you, that if LilyPond could not be convinced to output what it knows about file dependencies (and the Frescobaldi project hadn’t written python-ly which has the include_args() command in the ly.slexer module), then I probably would have written a shell script like you describe to get the dependencies information (or, more likely, to just do the recompiling itself and not bothered with make at all). However, once David K. showed that it was possible for LilyPond to output that information (and even better, without going through all the work necessary to produce a score at the same time) it makes the most logical sense to me to use that rather than start from scratch with a shell script (or start from include_args() in python-ly to write a Python script). ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On Thu 21 May 2020 at 13:10:40 (-0400), Fr. Samuel Springuel wrote: > > On 21 May, 2020, at 9:36 AM, David Kastrup wrote: > > antlists writes: > >> On 21/05/2020 01:49, David Wright wrote: > >>> I don't understand your equivalence between .ily and .h files. The > >>> .ily file(s) can contain just as much code as the .ly file(s), whereas > >>> .h files don't contain any code at all (in the sense of producing > >>> executable code for the next stage. > >> > >> a) just like .h files, .ily files can't be passed directly to a > >> compiler for compilation. > >> > >> b) who says .h files don't produce executable code? They often contain > >> code, sometimes entire functions. > > > > The point of .h files is that they are intended to be included by more > > than one compilation unit resulting in an executable. > > > > As such, they are limited with regard to the code they can contain. > > They can contain > > > > a) inline function definitions: those can occur in multiple compilation > > units as long as they are identical. > > b) static inline: do not even need to be identical, are per-unit. > > c) static data definitions, are per-unit. > > d) template function definitions > > > > I don't think that .ly/.ily is all that comparable here... > > The analogy is not perfect, but then no analogy is (otherwise it wouldn’t be > an analogy). Lilypond doesn’t enforce a distinction between .ly and .ily > files in the same way that C enforces the distinction between .h and .c > files. Further, .pdf files are stand alone in a way that .o files are not. > The linker level which combines .o files into an executable would have as its > closest approximation in the LilyPond world assembling several pdfs into some > kind of portfolio. And this is another point where the analogy breaks in > that an executable cannot contain incompatible .o files but a portfolio can > contain pdfs of scores with vastly different styles. The result may not be > as professional looking, but it’s possible. > > Here are the parts of the analogy that do work: > > 1) .ily files cannot produce scores. Sure, I can call LilyPond on them > directly, but regardless of the options I use, no score will ever result. > This may be purely by convention (as in, LilyPond itself doesn’t enforce > this, it really couldn’t care what the extension on its input files is), but > it’s a convention which I rigorously apply in the files I write. In this > respect, .ily files are like .h files which also cannot, by themselves, ever > produce a .o file. For .h files, at least a dummy.c file is needed to include > the .h file. My .ily files likewise need a .ly file to include them to > produce a score. As you say, these file extensions are just conventions. $ cat scale.ily \relative { c' d e f g \include "included.pdf" a b c } $ cat included.pdf { f e f g } $ ~/lilypond-2.21.0-1.linux-64/bin/lilypond scale.ily GNU LilyPond 2.21.0 Processing `scale.ily' Parsing... scale.ily:1: warning: no \version statement found, please add \version "2.21.0" for future compatibility Interpreting music... Preprocessing graphical objects... Finding the ideal number of pages... Fitting music on 1 page... Drawing systems... Layout output to `/tmp/lilypond-50Ds6o'... Converting to `scale.pdf'... Deleting `/tmp/lilypond-50Ds6o'... Success: compilation successfully completed $ Only the final .pdf (in scale.pdf) is unavoidable. > 2) .ly files do produce scores. If I call LilyPond on an .ly file, then I > expect a score to come out (in pdf format by default, but other formats are > possible too if I use the right options or flags). Again, this is primarily > a convention, as LilyPond won’t throw an error on a .ly file which doesn’t > produce a score (but has no other problems). However, it is a convention > that I strictly apply to my files. In this respect .ly files are like .c > files, which can be compiled to create .o files. > > 3) Further the relation between the .ly and .ily files is similar to the > relation between .c and .h files. .ly (.c) files do not, themselves, depend > on the .ily (.h) files that they include. There is no build process which > creates a .ly (.c) file from the included .ily (.h) files. However, if I > make a change to a .ily (.h) file, then the .pdf (.o) file which is produced > when LilyPond (GCC) compiles a .ly (.c) file which includes that changed file > is out of date and needs to be recompiled. In this regard the directed > acyclic graph (DAG) which illustrates these relationships is the same, just > with one less level (unless I make use of a pdf merge tool to replace the > linker level). > > > My goal is to inform make of these relationships so that when I tweak a > LilyPond source, only the scores affected by that source are recompiled. > This may be several pdfs, but it’s not all of them, even when I tweak an ily > file because not all ily files are included in all scores. Furthermore,
Re: Identify included files
On Fri 22 May 2020 at 12:12:17 (+0100), Wols Lists wrote: > On 22/05/20 02:08, David Wright wrote: > > On Thu 21 May 2020 at 17:54:38 (+0100), antlists wrote: > >> On 21/05/2020 16:36, David Wright wrote: > >>> On Thu 21 May 2020 at 13:57:00 (+0100), antlists wrote: > > >> I have tried accidentally > >> to do things like "lilypond voiceTrombone.ily" and it blew up quite > >> spectacularly. I would expect most of mine, and in truth most other > >> peoples', .ily files to blow up if fed straight to lilypond. > > > > Big deal. I won't ask what's in voiceTrombone.ily. > > A variable declaration. You know - EXACTLY THE SAME as C programmers > often stick in .h files ... Sure, but am I supposed to divine what's wrong with it from your statement that it "blows up". $ cat scale.ily scale = \relative { c' d e f g a b c } $ ~/lilypond-2.21.0-1.linux-64/bin/lilypond scale.ily GNU LilyPond 2.21.0 Processing `scale.ily' Parsing... scale.ily:1: warning: no \version statement found, please add \version "2.21.0" for future compatibility Success: compilation successfully completed $ > >> And if they do compile, the output probably isn't much use ... :-) > > >> Does bar.c contain a main{} definition? > > > > Why would it? > > Why WOULDN'T it? Because, in trying to understand the equivalences that were given, .ily -> .h .ly -> .c .pdf -> .o I'm not deliberately generating corner cases. > You said that bar.c contained a load of functionality that you wanted in > foo.c. How am I supposed to know whether bar.c is a program or a library? Because of the next paragraph. > >>> Now we can compile foo.c (which #includes bar.h) over and over while > >>> debugging it, all without ever recompiling bar.c. foo.c knows all it > >>> needs to know about bar.c because of bar.h's declarations. Main programs have to know about the libraries they call. That's what header lines were invented for. Then the header lines were put in a separate file so that the library source could include the header lines too (just as a confirmatory check). > >> Can you now link bar.o into foo? I honestly don't know - I don't know > >> how a linker will behave if fed two main{} functions ... ? > > > > This isn't too hard. As I wrote, bar.c has functions, and bar.h has > > declarations for those functions so that compiling foo.c can check > > the calls of those functions without ever seeing bar.c (ie without > > recompiling bar.c over and over). > > > >>> I now have a suite.ly that typesets my Suite for flute and piano. > >>> It \includes nine files: flute{I,II,III}.ily, piano{I,II,III}.ily > >>> (the notes), and flute-part.ily, piano-part.ily and complete-score.ily, > >>> (my \score templates). It also \includes {marks,dyns,fingers}.ily that > >>> contain LP code for my preferred styles of markings, dynamics and > >>> fingering. > >>> > >>> I have a file, suite.dep, which contains the information that suite.ly > >>> depends on these files to produce three targets, {flute,piano,suite}.pdf > >>> The same file might also indicate that I need just flute{I,II,III}.ily, > >>> flute-part.ily and {marks,dyns,fingers}.ily for just a flute.pdf. > >>> > >>> What do I write in a top-level theFlute.ly file to produce this > >>> flute.pdf and how does it benefit from the suite.sep information? > >>> How do I use this information profitably, in the way that bar.h did? > > I don't have a clue. Your workflow sounds completely weird and totally > incomprehensible to me. You know what? I don't give a monkeys - your > world view is what you choose to see. You see things different to me! It isn't my workflow. It's just an attempt to split a project into hypothetical .ly and .ily files in some manner suitable for matching the equivalences above. My turn to write a list of equivalences, with flute≡cello, piano≡horn: flute{I,II,III}.ilycello.ily piano{I,II,III}.ilyhorn.ily {marks,dyns,fingers}.ily figures.ily flute-part.ily symphony-cello.ly piano-part.ily symphony-horn.ly complete-score.ily symphony.ly theFlute.lysymphony-cello.ly and cello.ily for cello part → flute.pdf→ symphony-cello.pdf thePiano.lysymphony-horn.ly and horn.ily for horn part → piano.pdf→ symphony-horn.pdf theSuite.lysymphony.ly and all the above for full symphony → suite.pdf→ symphony.pdf That's not very different from the LP documentation (in the right hand column). My *hypothetical* workflow allowed for movement II to become outrageously popular, such that people would want to buy it separately :) When theFlute.ly is run, it \includes the appropriate .ily files, which LP finds without needing any suite.dep file to point out that theFlute.ly depends on flute-part.ily. Hence my question about the benefit it's meant to give me. > >>> ¹ I'm abbreviating with shell's "brace expansion" notation. > >>> > >> Now we get to the meat
Re: Identify included files
On 23/05/2020 06:06, Michael Gerdau wrote: Big deal. I won't ask what's in voiceTrombone.ily. A variable declaration. You know - EXACTLY THE SAME as C programmers often stick in .h files ... I don’t think that’s correct. For one according to my understanding LP has no variable declarations whatsoever, only definitions. I think I'm getting confused :-) no change there :-) For two LP allows for an arbitrary number of definitions of the same variable, the latest (as of the parser) overriding any previous. In C there’s just one definition and an arbitrary number of repetitions of the same declaration. int i = 1; enum something = { a = 1; b = 2; c = 3; } voiceTromboneI = \relative c { c d e f g a b c } Forgive my rusted solid C syntax - I can't remember it properly :-) The two languages may be different, but my mental view of the Computer Science behind them tells me to treat them the same. I declare them in an include file, and use them where I need them. (Whether the language treats them as such, the theory says they are global constants...) Cheers, Wol
Re: Identify included files
>> Big deal. I won't ask what's in voiceTrombone.ily. > > A variable declaration. You know - EXACTLY THE SAME as C programmers > often stick in .h files ... I don’t think that’s correct. For one according to my understanding LP has no variable declarations whatsoever, only definitions. For two LP allows for an arbitrary number of definitions of the same variable, the latest (as of the parser) overriding any previous. In C there’s just one definition and an arbitrary number of repetitions of the same declaration. Kind regards, Michael
Re: Identify included files
> On 21 May, 2020, at 9:08 PM, David Wright wrote: > > Look¹, I'm not the one making this analogy. I'm trying to make any > sense of it, and why this "dependency file" is being built. Well, perhaps it’s time to drop the analogy then and work with an example. For reference sake, let’s use the makefile example in the documentation: http://lilypond.org/doc/v2.21/Documentation/usage/make-and-makefiles In that file you’ve got the following section which lists file dependencies: # The dependencies of the movements. $(piece)I.pdf: $(piece)I.ly $(notes) $(piece)II.pdf: $(piece)II.ly $(notes) $(piece)III.pdf: $(piece)III.ly $(notes) $(piece)IV.pdf: $(piece)IV.ly $(notes) # The dependencies of the full score. $(piece).pdf: $(piece).ly $(notes) # The dependencies of the parts. $(piece)-cello.pdf: $(piece)-cello.ly cello.ily $(piece)-horn.pdf: $(piece)-horn.ly horn.ily $(piece)-oboes.pdf: $(piece)-oboes.ly oboe.ily $(piece)-viola.pdf: $(piece)-viola.ly viola.ily $(piece)-violinOne.pdf: $(piece)-violinOne.ly violinOne.ily $(piece)-violinTwo.pdf: $(piece)-violinTwo.ly violinTwo.ily As I see it, there are two problems with this section: 1) None of these dependencies mention symphonyDefs.ily. If I make any changes to it (say I change the paper size from A4 to Letter), then make will **not** know the pdfs are now out of date. 2) These lists are manually maintained. Each time I add another part I’ve got to add another line. If I add more dependencies (perhaps by pulling from a library of commonly used tweaks that I reuse from project to project), I have to make sure those are listed. If I decide to change the output format from pdf to eps, I’ve got to change everyone of these rules (as well as a couple of other things). Basically, any little change to the project structure requires me to edit the Makefile, sometimes in several places, and that introduces opportunities for error. The point of the dependency files that I’m trying to build is to fix these problems and do so automatically (so that once it is fixed, its fixed for all time). Under this idea (with parse-only.ly in the file structure alongside Makefile, latest version is attached) the above section of the makefile becomes: LY_all := $(wildcard Parts/*.ly) $(wildcard Scores/*.ly) include $(LY_all:.ly=.dly) %.dly: %.ly parse-only.ly @set -e; rm -f $@; \ $(LILY_CMD) --silent --init parse-only.ly $< > $@.; \ sed '1s,^,$@ ,' < $@. > $@; \ rm -f $@. You’ll note, this is fewer total lines and it doesn’t care how many parts or scores there are. Add a part or a score and make will notice and create the dependency list for that part/score automatically. Find a snippet that does something that you want to happen in one or more scores, simply add the necessary \include statements to the appropriate file(s) and make will notice and update accordingly. Want to switch from pdf to eps (by adding the -E flag to LILY_CMD)? Well, there are other parts of the Makefile which will need edits (because the Makefile was not written with this switch in mind), but as far as the dependencies are concerned no changes are necessary, you just need to clean out the existing dly files (which are written for the pdf targets) and make will create the new ones for the eps targets. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ parse-only.ly Description: Binary data
Re: Identify included files
On 22/05/20 02:08, David Wright wrote: > On Thu 21 May 2020 at 17:54:38 (+0100), antlists wrote: >> On 21/05/2020 16:36, David Wright wrote: >>> On Thu 21 May 2020 at 13:57:00 (+0100), antlists wrote: > >> I have tried accidentally >> to do things like "lilypond voiceTrombone.ily" and it blew up quite >> spectacularly. I would expect most of mine, and in truth most other >> peoples', .ily files to blow up if fed straight to lilypond. > > Big deal. I won't ask what's in voiceTrombone.ily. A variable declaration. You know - EXACTLY THE SAME as C programmers often stick in .h files ... > >> And if they do compile, the output probably isn't much use ... :-) > >> >> Does bar.c contain a main{} definition? > > Why would it? Why WOULDN'T it? You said that bar.c contained a load of functionality that you wanted in foo.c. How am I supposed to know whether bar.c is a program or a library? > >>> Now we can compile foo.c (which #includes bar.h) over and over while >>> debugging it, all without ever recompiling bar.c. foo.c knows all it >>> needs to know about bar.c because of bar.h's declarations. >> >> Can you now link bar.o into foo? I honestly don't know - I don't know >> how a linker will behave if fed two main{} functions ... ? > > This isn't too hard. As I wrote, bar.c has functions, and bar.h has > declarations for those functions so that compiling foo.c can check > the calls of those functions without ever seeing bar.c (ie without > recompiling bar.c over and over). > >>> I now have a suite.ly that typesets my Suite for flute and piano. >>> It \includes nine files: flute{I,II,III}.ily, piano{I,II,III}.ily >>> (the notes), and flute-part.ily, piano-part.ily and complete-score.ily, >>> (my \score templates). It also \includes {marks,dyns,fingers}.ily that >>> contain LP code for my preferred styles of markings, dynamics and fingering. >>> >>> I have a file, suite.dep, which contains the information that suite.ly >>> depends on these files to produce three targets, {flute,piano,suite}.pdf >>> The same file might also indicate that I need just flute{I,II,III}.ily, >>> flute-part.ily and {marks,dyns,fingers}.ily for just a flute.pdf. >>> >>> What do I write in a top-level theFlute.ly file to produce this >>> flute.pdf and how does it benefit from the suite.sep information? >>> How do I use this information profitably, in the way that bar.h did? I don't have a clue. Your workflow sounds completely weird and totally incomprehensible to me. You know what? I don't give a monkeys - your world view is what you choose to see. You see things different to me! >>> >>> ¹ I'm abbreviating with shell's "brace expansion" notation. >>> >> Now we get to the meat of the matter. You've put bar.c's >> *declarations* into bar.h. Does lilypond even have declarations? Also, >> it's perfectly normal practice to put *definitions* in .h files - >> static variables, macros, inline functions, etc etc. >> >> I put most of my lilypond variable *definitions* into .ily files. Yup, >> .h files *tend* to contain declarations not definitions, but as I say, >> I don't think lilypond syntax has declarations? >> >> So yes, am I right in thinking you view .ily files as closer to .o >> files? With lilypond closer to a linker than a compiler? > > No. Okay. > >> At the end of the day, I see it as .h files can contain declarations, >> .ily files contain declarations. .h files are included, .ily files are >> included. Some languages (like lilypond) are monolithic and don't >> really have the concept of libraries. So I find it extremely easy to >> view .ly/.ily as being similar to .c/.h. Not the same, because >> lilypond is not gcc ... :-) >> >> There's no one absolute view - you see things different to me, doesn't >> mean you (or me) is right. > > Look¹, I'm not the one making this analogy. I'm trying to make any > sense of it, and why this "dependency file" is being built. I didn't make it either! I just happen to totally agree with it. > > How do I use .ily files—almost all of them are definitions of > layouts, score structures, paper formats, variables' default values, > my abbreviations, and scheme code where it's wrapped in LP syntax. > They reside in a library directory that also has three subdirectories: > a collection of systematically named paper-margin files, a load of > boilerplate for exhaustively constructing MIDI file voice combinations, > and raw .scm files (like swing.scm). > > One or two .ily files consist of source that's been factorised out of > the .ly file(s) that calls them. So, for example, there are festal > hymns that have words for the different seasons, so most of the > seasonal versions can be factorised out into an .ily file and then > inserted at the appropriate points in the main .ly file. There's > no saving in volume of compilation, only duplication. WHICH IS EXACTLY A REASON FOR .h FILES! Removing duplication is a good way of removing errors (or making them easier to fix :-) > > I haven't used any
Re: Identify included files
On Thu 21 May 2020 at 17:54:38 (+0100), antlists wrote: > On 21/05/2020 16:36, David Wright wrote: > > On Thu 21 May 2020 at 13:57:00 (+0100), antlists wrote: > > > On 21/05/2020 01:49, David Wright wrote: > > > > I don't understand your equivalence between .ily and .h files. The > > > > .ily file(s) can contain just as much code as the .ly file(s), whereas > > > > .h files don't contain any code at all (in the sense of producing > > > > executable code for the next stage. > > > > > > a) just like .h files, .ily files can't be passed directly to a > > > compiler for compilation. > > > > Why do you say that? > > Because while it may not be globally true, It's not true at all. > I have tried accidentally > to do things like "lilypond voiceTrombone.ily" and it blew up quite > spectacularly. I would expect most of mine, and in truth most other > peoples', .ily files to blow up if fed straight to lilypond. Big deal. I won't ask what's in voiceTrombone.ily. > And if they do compile, the output probably isn't much use ... :-) That depends on what output you're expecting, and whether the file conforms to the expectations of the person compiling it. By that I mean that it's possible for anybody to name any file quz.h or quz.ily and then say "Gosh, look what happens when I compile it!". Here I am compiling clockchips.h from the linux kernel: $ gcc clockchips.h $ ls -lgG clockchips* -rw-r--r-- 17445 Apr 23 03:30 clockchips.h -rw-r- 1 1790384 May 21 20:01 clockchips.h.gch No output on the terminal is good news. I see that a pre-compiled header has been generated. Here I am compiling an .ily file pasted from the LM: $ ~/lilypond-2.21.0-1.linux-64/bin/lilypond definitions.ily GNU LilyPond 2.21.0 Processing `definitions.ily' Parsing... definitions.ily:1: warning: no \version statement found, please add \version "2.21.0" for future compatibility Success: compilation successfully completed $ ls -lgG definitions* -rw-r- 1 575 May 21 19:50 definitions.ily $ > > > b) who says .h files don't produce executable code? They often contain > > > code, sometimes entire functions. > > > > > > I understand the equivalence exactly - it's what you DO to the file. > > > > Good, that means I have a second source of edification as to what the > > intent of this analysis is. > > > > > You're thinking "what you *should* put in the file". Since when have > > > people done what they *should*? > > > > Letting that pass, let's say we have a source file foo.c and it needs > > an extraordinary quantity of functionality that's contained in bar.c. > > We put the latter's function declarations into bar.h and compile > > bar.{c,h}¹ into bar.o. > > Does bar.c contain a main{} definition? Why would it? > > Now we can compile foo.c (which #includes bar.h) over and over while > > debugging it, all without ever recompiling bar.c. foo.c knows all it > > needs to know about bar.c because of bar.h's declarations. > > Can you now link bar.o into foo? I honestly don't know - I don't know > how a linker will behave if fed two main{} functions ... ? This isn't too hard. As I wrote, bar.c has functions, and bar.h has declarations for those functions so that compiling foo.c can check the calls of those functions without ever seeing bar.c (ie without recompiling bar.c over and over). > > I now have a suite.ly that typesets my Suite for flute and piano. > > It \includes nine files: flute{I,II,III}.ily, piano{I,II,III}.ily > > (the notes), and flute-part.ily, piano-part.ily and complete-score.ily, > > (my \score templates). It also \includes {marks,dyns,fingers}.ily that > > contain LP code for my preferred styles of markings, dynamics and fingering. > > > > I have a file, suite.dep, which contains the information that suite.ly > > depends on these files to produce three targets, {flute,piano,suite}.pdf > > The same file might also indicate that I need just flute{I,II,III}.ily, > > flute-part.ily and {marks,dyns,fingers}.ily for just a flute.pdf. > > > > What do I write in a top-level theFlute.ly file to produce this > > flute.pdf and how does it benefit from the suite.sep information? > > How do I use this information profitably, in the way that bar.h did? > > > > ¹ I'm abbreviating with shell's "brace expansion" notation. > > > Now we get to the meat of the matter. You've put bar.c's > *declarations* into bar.h. Does lilypond even have declarations? Also, > it's perfectly normal practice to put *definitions* in .h files - > static variables, macros, inline functions, etc etc. > > I put most of my lilypond variable *definitions* into .ily files. Yup, > .h files *tend* to contain declarations not definitions, but as I say, > I don't think lilypond syntax has declarations? > > So yes, am I right in thinking you view .ily files as closer to .o > files? With lilypond closer to a linker than a compiler? No. > At the end of the day, I see it as .h files can contain declarations, > .ily files contain declarations. .h files
Re: Identify included files
On 21/05/2020 16:36, David Wright wrote: On Thu 21 May 2020 at 13:57:00 (+0100), antlists wrote: On 21/05/2020 01:49, David Wright wrote: I don't understand your equivalence between .ily and .h files. The .ily file(s) can contain just as much code as the .ly file(s), whereas .h files don't contain any code at all (in the sense of producing executable code for the next stage. a) just like .h files, .ily files can't be passed directly to a compiler for compilation. Why do you say that? Because while it may not be globally true, I have tried accidentally to do things like "lilypond voiceTrombone.ily" and it blew up quite spectacularly. I would expect most of mine, and in truth most other peoples', .ily files to blow up if fed straight to lilypond. And if they do compile, the output probably isn't much use ... :-) b) who says .h files don't produce executable code? They often contain code, sometimes entire functions. I understand the equivalence exactly - it's what you DO to the file. Good, that means I have a second source of edification as to what the intent of this analysis is. You're thinking "what you *should* put in the file". Since when have people done what they *should*? Letting that pass, let's say we have a source file foo.c and it needs an extraordinary quantity of functionality that's contained in bar.c. We put the latter's function declarations into bar.h and compile bar.{c,h}¹ into bar.o. Does bar.c contain a main{} definition? Now we can compile foo.c (which #includes bar.h) over and over while debugging it, all without ever recompiling bar.c. foo.c knows all it needs to know about bar.c because of bar.h's declarations. Can you now link bar.o into foo? I honestly don't know - I don't know how a linker will behave if fed two main{} functions ... ? I now have a suite.ly that typesets my Suite for flute and piano. It \includes nine files: flute{I,II,III}.ily, piano{I,II,III}.ily (the notes), and flute-part.ily, piano-part.ily and complete-score.ily, (my \score templates). It also \includes {marks,dyns,fingers}.ily that contain LP code for my preferred styles of markings, dynamics and fingering. I have a file, suite.dep, which contains the information that suite.ly depends on these files to produce three targets, {flute,piano,suite}.pdf The same file might also indicate that I need just flute{I,II,III}.ily, flute-part.ily and {marks,dyns,fingers}.ily for just a flute.pdf. What do I write in a top-level theFlute.ly file to produce this flute.pdf and how does it benefit from the suite.sep information? How do I use this information profitably, in the way that bar.h did? ¹ I'm abbreviating with shell's "brace expansion" notation. Cheers, David. Now we get to the meat of the matter. You've put bar.c's *declarations* into bar.h. Does lilypond even have declarations? Also, it's perfectly normal practice to put *definitions* in .h files - static variables, macros, inline functions, etc etc. I put most of my lilypond variable *definitions* into .ily files. Yup, .h files *tend* to contain declarations not definitions, but as I say, I don't think lilypond syntax has declarations? So yes, am I right in thinking you view .ily files as closer to .o files? With lilypond closer to a linker than a compiler? At the end of the day, I see it as .h files can contain declarations, .ily files contain declarations. .h files are included, .ily files are included. Some languages (like lilypond) are monolithic and don't really have the concept of libraries. So I find it extremely easy to view .ly/.ily as being similar to .c/.h. Not the same, because lilypond is not gcc ... :-) There's no one absolute view - you see things different to me, doesn't mean you (or me) is right. Cheers, Wol
Re: Identify included files
> On 21 May, 2020, at 9:36 AM, David Kastrup wrote: > > antlists writes: > >> On 21/05/2020 01:49, David Wright wrote: >>> I don't understand your equivalence between .ily and .h files. The >>> .ily file(s) can contain just as much code as the .ly file(s), whereas >>> .h files don't contain any code at all (in the sense of producing >>> executable code for the next stage. >> >> a) just like .h files, .ily files can't be passed directly to a >> compiler for compilation. >> >> b) who says .h files don't produce executable code? They often contain >> code, sometimes entire functions. > > The point of .h files is that they are intended to be included by more > than one compilation unit resulting in an executable. > > As such, they are limited with regard to the code they can contain. > They can contain > > a) inline function definitions: those can occur in multiple compilation > units as long as they are identical. > b) static inline: do not even need to be identical, are per-unit. > c) static data definitions, are per-unit. > d) template function definitions > > I don't think that .ly/.ily is all that comparable here... > > -- > David Kastrup > The analogy is not perfect, but then no analogy is (otherwise it wouldn’t be an analogy). Lilypond doesn’t enforce a distinction between .ly and .ily files in the same way that C enforces the distinction between .h and .c files. Further, .pdf files are stand alone in a way that .o files are not. The linker level which combines .o files into an executable would have as its closest approximation in the LilyPond world assembling several pdfs into some kind of portfolio. And this is another point where the analogy breaks in that an executable cannot contain incompatible .o files but a portfolio can contain pdfs of scores with vastly different styles. The result may not be as professional looking, but it’s possible. Here are the parts of the analogy that do work: 1) .ily files cannot produce scores. Sure, I can call LilyPond on them directly, but regardless of the options I use, no score will ever result. This may be purely by convention (as in, LilyPond itself doesn’t enforce this, it really couldn’t care what the extension on its input files is), but it’s a convention which I rigorously apply in the files I write. In this respect, .ily files are like .h files which also cannot, by themselves, ever produce a .o file. For .h files, at least a dummy.c file is needed to include the .h file. My .ily files likewise need a .ly file to include them to produce a score. 2) .ly files do produce scores. If I call LilyPond on an .ly file, then I expect a score to come out (in pdf format by default, but other formats are possible too if I use the right options or flags). Again, this is primarily a convention, as LilyPond won’t throw an error on a .ly file which doesn’t produce a score (but has no other problems). However, it is a convention that I strictly apply to my files. In this respect .ly files are like .c files, which can be compiled to create .o files. 3) Further the relation between the .ly and .ily files is similar to the relation between .c and .h files. .ly (.c) files do not, themselves, depend on the .ily (.h) files that they include. There is no build process which creates a .ly (.c) file from the included .ily (.h) files. However, if I make a change to a .ily (.h) file, then the .pdf (.o) file which is produced when LilyPond (GCC) compiles a .ly (.c) file which includes that changed file is out of date and needs to be recompiled. In this regard the directed acyclic graph (DAG) which illustrates these relationships is the same, just with one less level (unless I make use of a pdf merge tool to replace the linker level). My goal is to inform make of these relationships so that when I tweak a LilyPond source, only the scores affected by that source are recompiled. This may be several pdfs, but it’s not all of them, even when I tweak an ily file because not all ily files are included in all scores. Furthermore, the more I work on this project, the more I tend to split up the “formatting” file so that I actually have several, each of which is responsible for a single aspect of the formatting. This makes it easier for me to find code when I need to make adjustments to a particular aspect of the formatting. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On Thu 21 May 2020 at 13:57:00 (+0100), antlists wrote: > On 21/05/2020 01:49, David Wright wrote: > > I don't understand your equivalence between .ily and .h files. The > > .ily file(s) can contain just as much code as the .ly file(s), whereas > > .h files don't contain any code at all (in the sense of producing > > executable code for the next stage. > > a) just like .h files, .ily files can't be passed directly to a > compiler for compilation. Why do you say that? > b) who says .h files don't produce executable code? They often contain > code, sometimes entire functions. > > I understand the equivalence exactly - it's what you DO to the file. Good, that means I have a second source of edification as to what the intent of this analysis is. > You're thinking "what you *should* put in the file". Since when have > people done what they *should*? Letting that pass, let's say we have a source file foo.c and it needs an extraordinary quantity of functionality that's contained in bar.c. We put the latter's function declarations into bar.h and compile bar.{c,h}¹ into bar.o. Now we can compile foo.c (which #includes bar.h) over and over while debugging it, all without ever recompiling bar.c. foo.c knows all it needs to know about bar.c because of bar.h's declarations. I now have a suite.ly that typesets my Suite for flute and piano. It \includes nine files: flute{I,II,III}.ily, piano{I,II,III}.ily (the notes), and flute-part.ily, piano-part.ily and complete-score.ily, (my \score templates). It also \includes {marks,dyns,fingers}.ily that contain LP code for my preferred styles of markings, dynamics and fingering. I have a file, suite.dep, which contains the information that suite.ly depends on these files to produce three targets, {flute,piano,suite}.pdf The same file might also indicate that I need just flute{I,II,III}.ily, flute-part.ily and {marks,dyns,fingers}.ily for just a flute.pdf. What do I write in a top-level theFlute.ly file to produce this flute.pdf and how does it benefit from the suite.sep information? How do I use this information profitably, in the way that bar.h did? ¹ I'm abbreviating with shell's "brace expansion" notation. Cheers, David.
Re: Identify included files
On 21/05/2020 14:36, David Kastrup wrote: antlists writes: On 21/05/2020 01:49, David Wright wrote: I don't understand your equivalence between .ily and .h files. The .ily file(s) can contain just as much code as the .ly file(s), whereas .h files don't contain any code at all (in the sense of producing executable code for the next stage. a) just like .h files, .ily files can't be passed directly to a compiler for compilation. b) who says .h files don't produce executable code? They often contain code, sometimes entire functions. The point of .h files is that they are intended to be included by more than one compilation unit resulting in an executable. Which is exactly how I use .ily files ... As such, they are limited with regard to the code they can contain. They can contain a) inline function definitions: those can occur in multiple compilation units as long as they are identical. You're describing the way I define variables that contain all my notes. You're also describing how I define the musical structure. b) static inline: do not even need to be identical, are per-unit. c) static data definitions, are per-unit. d) template function definitions I redefine the header function - I've NEVER seen a header laid out the way lilypond does it, apart from parts produced by lilypond ... Plus I have my own dynamics definition file that extends lilypond's ones I don't think that .ly/.ily is all that comparable here... The way I use .ily files EXACTLY matches your definition of a .h file... how on earth do you use them? Cheers, Wol
Re: Identify included files
antlists writes: > On 21/05/2020 01:49, David Wright wrote: >> I don't understand your equivalence between .ily and .h files. The >> .ily file(s) can contain just as much code as the .ly file(s), whereas >> .h files don't contain any code at all (in the sense of producing >> executable code for the next stage. > > a) just like .h files, .ily files can't be passed directly to a > compiler for compilation. > > b) who says .h files don't produce executable code? They often contain > code, sometimes entire functions. The point of .h files is that they are intended to be included by more than one compilation unit resulting in an executable. As such, they are limited with regard to the code they can contain. They can contain a) inline function definitions: those can occur in multiple compilation units as long as they are identical. b) static inline: do not even need to be identical, are per-unit. c) static data definitions, are per-unit. d) template function definitions I don't think that .ly/.ily is all that comparable here... -- David Kastrup
Re: Identify included files
On 21/05/2020 01:49, David Wright wrote: I don't understand your equivalence between .ily and .h files. The .ily file(s) can contain just as much code as the .ly file(s), whereas .h files don't contain any code at all (in the sense of producing executable code for the next stage. a) just like .h files, .ily files can't be passed directly to a compiler for compilation. b) who says .h files don't produce executable code? They often contain code, sometimes entire functions. I understand the equivalence exactly - it's what you DO to the file. You're thinking "what you *should* put in the file". Since when have people done what they *should*? Cheers, Wol
Re: Identify included files
On Mon 18 May 2020 at 14:32:31 (-0400), Fr. Samuel Springuel wrote: > > On 18 May, 2020, at 11:30 AM, David Wright > > wrote: > > > > If you were compiling a C program foo.c into an executable, what you > > would be trying to avoid is recompiling fnbar.c into fnbar.o over > > and over again (and all of its similar companions). > > > > Can you explain which of your files are the equivalents of fnbar.o. > > (In python, for another example, they'd be your *.pyc files, and > > python looks after all this housekeeping itself.) > > As I see it, the filetype equivalencies roughly map as this: > > .ily -> .h > .ly -> .c > .pdf -> .o So the final output is constructed¹ from several PDF files, and these are what you don't want to recompile each time the constructing takes place. So what program(s) are you using to construct the final output? I don't understand your equivalence between .ily and .h files. The .ily file(s) can contain just as much code as the .ly file(s), whereas .h files don't contain any code at all (in the sense of producing executable code for the next stage. So I'm unable to see which files you avoid compiling, and in what form their compiled derivatives are stored between runs. > To this I would also add one more file type for storing dependency information > .dly -> .d ¹ I've avoided the word assemble for obvious reasons. Cheers, David.
Re: Identify included files
> On 20 May, 2020, at 12:05 PM, Fr. Samuel Springuel > wrote: > > Use of the -dbackend=eps (or setting the backend to eps in the file) also > causes the production of several other files (*-systems.tex, *-systems.texi, > *-systems.count, and the eps and pdf files for each system) while -E (or > --eps) does not. So far, however, I haven’t been to determine the difference > between these two situations. Is there some variable (or scheme function) > that can be used to figure out if these files are being produced (and how > many systems there are)? Okay, I found the answer to this one. The aux-files option (accessed with (ly:get-option 'aux-files)) indicates that these files are being created. It’s also occurred to me that the only way to determine the number of systems is to actually do the typesetting. Any attempt, therefore, to determine the targets and prerequisites automatically without typesetting the document cannot know exactly how many there are and has to be written from that perspective. This part of the question was akin to asking someone how many apples are in a bag while keeping the bag hidden from them. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
As an exercise in Scheme programming (and because I’m something of a perfectionist), I’m working on improving the output when using parse-only.ly by having it account for `--format` flags and the various backends when constructing the target portion of the make rule (the version I previously posted always assumes the target is pdf). To that end I’ve been exploring some of the scheme functions and have come across the ly:output-formats and ly:parser-output-name as welll as (ly:get-option 'backend). However, I have a few questions: ly:output-formats is a list whose contents are determined by the `--format` flags. However, when eps format is requested, ps, not eps is what’s added to the list. To determine that the output is eps I then also need to look at (ly:get-option 'backend), which will be eps or ps (or svg or scm, but they only produce a single file format, regardless of --format flags). I’ve also noticed that if both ps and eps files are requested with flags, then apparently only the eps file is produced, though ly:output-formats will have two ps entries. So, my question is can lilypond ever produce both ps and eps file from a single run, or does the use of the eps backend preclude the production of ps files? ly:parser-output-name stores the base name of the output file, but doesn’t contain directory information about where the output file is supposed to go (unlike the list of files in ly:source-files, which do contain the directory information about the location of the source files). This make sense because the output defaults to the current working directory when lilypond is called. However, if I use the --output option, I can force LilyPond to switch working directories before processing the file (and thus change the destination of the output). However, I cannot find where that directory information is stored. Is it stored somewhere (if so, where)? Use of the -dbackend=eps (or setting the backend to eps in the file) also causes the production of several other files (*-systems.tex, *-systems.texi, *-systems.count, and the eps and pdf files for each system) while -E (or --eps) does not. So far, however, I haven’t been to determine the difference between these two situations. Is there some variable (or scheme function) that can be used to figure out if these files are being produced (and how many systems there are)? Finally, what about midi? I have yet to find a scheme function that will tell me if the file being parsed will produce a midi file when typeset. Is there anything that would do that? ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
> On 18 May, 2020, at 11:30 AM, David Wright wrote: > > If you were compiling a C program foo.c into an executable, what you > would be trying to avoid is recompiling fnbar.c into fnbar.o over > and over again (and all of its similar companions). > > Can you explain which of your files are the equivalents of fnbar.o. > (In python, for another example, they'd be your *.pyc files, and > python looks after all this housekeeping itself.) As I see it, the filetype equivalencies roughly map as this: .ily -> .h .ly -> .c .pdf -> .o To this I would also add one more file type for storing dependency information .dly -> .d > On 18 May, 2020, at 11:35 AM, David Wright wrote: > > If you follow some simple rules in your source layout, constructing > such a list might be most straightforward to do in the shell, using > grep. For example, > > $ grep -e '^[[:space:]]*\\include ' foo-top-level.ly > > will find all the includes in the source, restricting it to the start > of lines, so that you can avoid false hits from, say, internal > documentation or test includes. > > You would insert the resulting filenames into two lists, files visited > and all files. Iterate on the files list, skipping those visited, > until the files to visit reaches zero (lists are of equal length). > > One complication is applying the search of libraries in the same > manner as LP, particularly if you rely on the order of searching. > Another is if you're using external libraries where you have no > control over their include format. > > If you're not comfortable with shell programming, obviously it would > be preferable to use a language like Python or Perl for coding. > > The resulting list could be used for, say, making a tarball of source > files for distribution, or for driving make to produce PDFs that are > assembled by, say, TeX programs into final documents. My original thoughts were to write something in Python or bash and it probably would have looked something like what you propose. Being a firm believer in not reinventing the wheel whenever possible, I decided to ask the list to see if this had been done already first. > > On 18 May, 2020, at 12:22 PM, antlists wrote: > > Okay, does that mean you want a list of all the lilypond include files, or > just your own? > > If you're digging into the internals of lilypond, then it'll be a big job, > and makes it dangerous to upgrade lilypond. Because I assume that means > you're actually modifying lilypond's internal structure. What I do, anything > of lilypond's that I modify, I split it out into my directory structure, and > then over-ride lilypond's version from within my source. That way, what > happens to lilypond during an upgrade is no concern of mine (other than > changes to syntax which mess up my source :-) > > If it's just your own files you're concerned about, then grep will probably > do the trick. I don't know how to recurse directories, but making it search > all the files in a directory for "include", and tell you which file it found > that line in, is pretty basic. > > You can then read up on make for how to create those virtual objects, and use > an editor to put them in your makefile. Not totally automated, I admit, but > fairly simple grunt-work. The sort of thing I could have written a BASIC > program to do in 10 minutes, except I don't have access to a BASIC I > understand how to use any more - ironic - as computers have got easier to > use, so the programming languages have got harder... > I’m not playing with the lilypond internals (and don’t need them in my list of prerequisites), but I do occasionally have files which make use of oll packages (I’ve been playing with the Edition Engraver recently). Those packages have their own hierarchy outside my project hierarchy. Further, the location of their hierarchy may be different on different machines (I always try to set things up with collaboration in mind, even when I’m not currently collaborating with anyone). As a result, scripts which don’t understand how LilyPond finds files and simply look for “\include” statements are likely to come up short and not find all prerequisites. > On 18 May, 2020, at 11:47 AM, Urs Liska wrote: > > I'm pretty sure that the only two ways to reasonably go forward is to > either invoke LilyPond to produce this list or to use a library that > already knows how LilyPond works. As I mentioned somewhere at the top > of this thread, Frescobaldi knows pretty well how to recurse into the > include files. > > I would write a tool in Python that calls python-ly (well, probably > quickly, it's designated successor ( > https://github.com/frescobaldi/quickly)) to produce the list of > dependencies and feed that into Make. I’ve reached a similar conclusion. Right now I’m going forward with the lilypond route simply because David K.’s parse-only.ly means I’m closer to that solution than I am with python-ly or quickly (as I’ve never
Re: Identify included files
On 18/05/2020 15:29, Fr. Samuel Springuel wrote: On 18 May, 2020, at 9:37 AM, antlists wrote: define trombone-notes.ly as a target, define it as changed if its dependencies change, and say "it doesn't exist as a file that can be created with a command". Right, that’s the step I’m trying to automate. Make itself cannot determine the list of prerequisites. You either need to do that manually (a real pain) or provide a tool that can examine a file, determine what its prerequisites are and then write them out in a way that make understands. From the manual for GNU Make: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites The example there uses the -M flag for a C compiler. I’m looking to come up with an equivalent for LilyPond. Okay, does that mean you want a list of all the lilypond include files, or just your own? If you're digging into the internals of lilypond, then it'll be a big job, and makes it dangerous to upgrade lilypond. Because I assume that means you're actually modifying lilypond's internal structure. What I do, anything of lilypond's that I modify, I split it out into my directory structure, and then over-ride lilypond's version from within my source. That way, what happens to lilypond during an upgrade is no concern of mine (other than changes to syntax which mess up my source :-) If it's just your own files you're concerned about, then grep will probably do the trick. I don't know how to recurse directories, but making it search all the files in a directory for "include", and tell you which file it found that line in, is pretty basic. You can then read up on make for how to create those virtual objects, and use an editor to put them in your makefile. Not totally automated, I admit, but fairly simple grunt-work. The sort of thing I could have written a BASIC program to do in 10 minutes, except I don't have access to a BASIC I understand how to use any more - ironic - as computers have got easier to use, so the programming languages have got harder... Cheers, Wol
Re: Identify included files
Am Montag, den 18.05.2020, 10:35 -0500 schrieb David Wright: > On Fri 15 May 2020 at 12:03:33 (-0400), Fr. Samuel Springuel wrote: > > > On 5/15/20, Fr. Samuel Springuel wrote: > > > > Before I start writing a script to do this, is there an > > > > existing tool which > > > > will identify all the `\include` files that a LilyPond file > > > > depends on? > > > > Even better, one that will work in a recursive fashion? > > > > I’m hoping for something that doesn’t require actually typesetting > > the document. My end goal is a script which will somewhat > > intelligently determine which files in a project have changed and > > re-typeset them as needed. Having to typeset the document in order > > to determine which files it depends on means I’ve already done the > > typesetting. Is there a way to pass that and \set > > Score.skipTypesetting = ##t at the command line? > > If you follow some simple rules in your source layout, constructing > such a list might be most straightforward to do in the shell, using > grep. For example, > > $ grep -e '^[[:space:]]*\\include ' foo-top-level.ly > > will find all the includes in the source, restricting it to the start > of lines, so that you can avoid false hits from, say, internal > documentation or test includes. > The include files may live in totally different directories, which are essentially knows to LilyPond only. I'm pretty sure that the only two ways to reasonably go forward is to either invoke LilyPond to produce this list or to use a library that already knows how LilyPond works. As I mentioned somewhere at the top of this thread, Frescobaldi knows pretty well how to recurse into the include files. I would write a tool in Python that calls python-ly (well, probably quickly, it's designated successor ( https://github.com/frescobaldi/quickly)) to produce the list of dependencies and feed that into Make. Urs > You would insert the resulting filenames into two lists, files > visited > and all files. Iterate on the files list, skipping those visited, > until the files to visit reaches zero (lists are of equal length). > > One complication is applying the search of libraries in the same > manner as LP, particularly if you rely on the order of searching. > Another is if you're using external libraries where you have no > control over their include format. > > If you're not comfortable with shell programming, obviously it would > be preferable to use a language like Python or Perl for coding. > > The resulting list could be used for, say, making a tarball of source > files for distribution, or for driving make to produce PDFs that are > assembled by, say, TeX programs into final documents. > > Cheers, > David. >
Re: Identify included files
On Fri 15 May 2020 at 12:03:33 (-0400), Fr. Samuel Springuel wrote: > > On 5/15/20, Fr. Samuel Springuel wrote: > >> Before I start writing a script to do this, is there an existing tool which > >> will identify all the `\include` files that a LilyPond file depends on? > >> Even better, one that will work in a recursive fashion? > > I’m hoping for something that doesn’t require actually typesetting the > document. My end goal is a script which will somewhat intelligently > determine which files in a project have changed and re-typeset them as > needed. Having to typeset the document in order to determine which files it > depends on means I’ve already done the typesetting. Is there a way to pass > that and \set Score.skipTypesetting = ##t at the command line? If you follow some simple rules in your source layout, constructing such a list might be most straightforward to do in the shell, using grep. For example, $ grep -e '^[[:space:]]*\\include ' foo-top-level.ly will find all the includes in the source, restricting it to the start of lines, so that you can avoid false hits from, say, internal documentation or test includes. You would insert the resulting filenames into two lists, files visited and all files. Iterate on the files list, skipping those visited, until the files to visit reaches zero (lists are of equal length). One complication is applying the search of libraries in the same manner as LP, particularly if you rely on the order of searching. Another is if you're using external libraries where you have no control over their include format. If you're not comfortable with shell programming, obviously it would be preferable to use a language like Python or Perl for coding. The resulting list could be used for, say, making a tarball of source files for distribution, or for driving make to produce PDFs that are assembled by, say, TeX programs into final documents. Cheers, David.
Re: Identify included files
On Mon 18 May 2020 at 10:29:22 (-0400), Fr. Samuel Springuel wrote: > > On 18 May, 2020, at 9:37 AM, antlists wrote: > > > > define trombone-notes.ly as a target, define it as changed if its > > dependencies change, and say "it doesn't exist as a file that can be > > created with a command". > > Right, that’s the step I’m trying to automate. Make itself cannot determine > the list of prerequisites. You either need to do that manually (a real pain) > or provide a tool that can examine a file, determine what its prerequisites > are and then write them out in a way that make understands. > > From the manual for GNU Make: > https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites > > The example there uses the -M flag for a C compiler. I’m looking to come up > with an equivalent for LilyPond. If you were compiling a C program foo.c into an executable, what you would be trying to avoid is recompiling fnbar.c into fnbar.o over and over again (and all of its similar companions). Can you explain which of your files are the equivalents of fnbar.o. (In python, for another example, they'd be your *.pyc files, and python looks after all this housekeeping itself.) Cheers, David.
Re: Identify included files
> On 18 May, 2020, at 9:37 AM, antlists wrote: > > define trombone-notes.ly as a target, define it as changed if its > dependencies change, and say "it doesn't exist as a file that can be created > with a command". Right, that’s the step I’m trying to automate. Make itself cannot determine the list of prerequisites. You either need to do that manually (a real pain) or provide a tool that can examine a file, determine what its prerequisites are and then write them out in a way that make understands. From the manual for GNU Make: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites The example there uses the -M flag for a C compiler. I’m looking to come up with an equivalent for LilyPond. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
Am Montag, den 18.05.2020, 14:37 +0100 schrieb antlists: > On 18/05/2020 13:44, David Kastrup wrote: > > antlists writes: > > > > > On 15/05/2020 21:17, Fr. Samuel Springuel wrote: > > > > Now I just need to turn this list into something that can be > > > > used to > > > > figure out if the target needs to be recompiled. > > > > > > As Jacques said, "make". > > > > > > At the top of your directory structure you can have a makefile, > > > and it > > > just contains a list of all your targets, and the files they > > > depend > > > on. Okay, every time you add a new include, you need to update > > > it, > > > but... > > > > > > Then when you change something, you just go to your top > > > directory, > > > type "make", and watch everything affected by your recent changes > > > recompile. > > > > > > The really nice thing about it, is it will handle recursive > > > includes > > > by itself. Can't remember the syntax, but if an include file > > > pulls in > > > other includes, you can define that include file as a target, > > > which > > > then flags any other that targets that use it. So each target in > > > your > > > makefile only needs to include the includes that it depends > > > *directly* > > > upon. > > > > That's not how Makefile dependencies work. Dependencies track the > > relation of _output_ files to their _input_. They do not track the > > hierarchy of different input files that only refer to each other by > > name: for the purpose of Make, those are independent and > > equivalent. > > But the _output_ file(s) generated from them are dependent on all > > of the > > respective input files in use, and tracking those and generating > > the > > dependencies was what Fr. Samuel was asking about in the first > > place. > > > Yup. But he wanted to know "which files do I need to recompile". > Which > is exactly what makefiles do. > > so if trombone.pdf is compiled from trombone.ly, which includes > trombone-notes.ly, which includes dynamics.ly, then I know there is > some > sort of syntax which will: > > define trombone-notes.ly as a target, define it as changed if its > dependencies change, and say "it doesn't exist as a file that can be > created with a command". > > So if dynamics.ly changes, it cascades up and causes trombone.pdf to > be > re-compiled, but this is the important bit - you don't need to > *ex*plicitly define trombone.pdf as relying on dynamics.ly > > > Just had a slight rethink - which affects things - namely what > exactly > is Fr. Samuel trying to achieve. Does he want a list of dependencies > as > a thing in its own right, or does he want to know which targets need > to > be recompiled as a result of changing a file. Because "make" is all > he > needs if the latter is what he's aiming for. If he really wants the > former, then yes he'll need all thse lily functions etc that people > have > pointed him to. Sounds nice, but how can you tell Make what include files a given .ly file depends on? Without inside knowledge into the LilyPond way of recursing into the input files? Urs > > > Cheers, > Wol >
Re: Identify included files
On 18/05/2020 13:44, David Kastrup wrote: antlists writes: On 15/05/2020 21:17, Fr. Samuel Springuel wrote: Now I just need to turn this list into something that can be used to figure out if the target needs to be recompiled. As Jacques said, "make". At the top of your directory structure you can have a makefile, and it just contains a list of all your targets, and the files they depend on. Okay, every time you add a new include, you need to update it, but... Then when you change something, you just go to your top directory, type "make", and watch everything affected by your recent changes recompile. The really nice thing about it, is it will handle recursive includes by itself. Can't remember the syntax, but if an include file pulls in other includes, you can define that include file as a target, which then flags any other that targets that use it. So each target in your makefile only needs to include the includes that it depends *directly* upon. That's not how Makefile dependencies work. Dependencies track the relation of _output_ files to their _input_. They do not track the hierarchy of different input files that only refer to each other by name: for the purpose of Make, those are independent and equivalent. But the _output_ file(s) generated from them are dependent on all of the respective input files in use, and tracking those and generating the dependencies was what Fr. Samuel was asking about in the first place. Yup. But he wanted to know "which files do I need to recompile". Which is exactly what makefiles do. so if trombone.pdf is compiled from trombone.ly, which includes trombone-notes.ly, which includes dynamics.ly, then I know there is some sort of syntax which will: define trombone-notes.ly as a target, define it as changed if its dependencies change, and say "it doesn't exist as a file that can be created with a command". So if dynamics.ly changes, it cascades up and causes trombone.pdf to be re-compiled, but this is the important bit - you don't need to *ex*plicitly define trombone.pdf as relying on dynamics.ly Just had a slight rethink - which affects things - namely what exactly is Fr. Samuel trying to achieve. Does he want a list of dependencies as a thing in its own right, or does he want to know which targets need to be recompiled as a result of changing a file. Because "make" is all he needs if the latter is what he's aiming for. If he really wants the former, then yes he'll need all thse lily functions etc that people have pointed him to. Cheers, Wol
Re: Identify included files
antlists writes: > On 15/05/2020 21:17, Fr. Samuel Springuel wrote: >> Now I just need to turn this list into something that can be used to >> figure out if the target needs to be recompiled. > > As Jacques said, "make". > > At the top of your directory structure you can have a makefile, and it > just contains a list of all your targets, and the files they depend > on. Okay, every time you add a new include, you need to update it, > but... > > Then when you change something, you just go to your top directory, > type "make", and watch everything affected by your recent changes > recompile. > > The really nice thing about it, is it will handle recursive includes > by itself. Can't remember the syntax, but if an include file pulls in > other includes, you can define that include file as a target, which > then flags any other that targets that use it. So each target in your > makefile only needs to include the includes that it depends *directly* > upon. That's not how Makefile dependencies work. Dependencies track the relation of _output_ files to their _input_. They do not track the hierarchy of different input files that only refer to each other by name: for the purpose of Make, those are independent and equivalent. But the _output_ file(s) generated from them are dependent on all of the respective input files in use, and tracking those and generating the dependencies was what Fr. Samuel was asking about in the first place. -- David Kastrup
Re: Identify included files
On 15/05/2020 21:17, Fr. Samuel Springuel wrote: Now I just need to turn this list into something that can be used to figure out if the target needs to be recompiled. As Jacques said, "make". At the top of your directory structure you can have a makefile, and it just contains a list of all your targets, and the files they depend on. Okay, every time you add a new include, you need to update it, but... Then when you change something, you just go to your top directory, type "make", and watch everything affected by your recent changes recompile. The really nice thing about it, is it will handle recursive includes by itself. Can't remember the syntax, but if an include file pulls in other includes, you can define that include file as a target, which then flags any other that targets that use it. So each target in your makefile only needs to include the includes that it depends *directly* upon. Cheers, Wol
Re: Identify included files
"Fr. Samuel Springuel" writes: >> On 16 May, 2020, at 5:31 PM, David Kastrup wrote: >> >> The problem is that there are quite a few things in there that make no >> overwhelming sense for the task you want to solve. In order to allow >> for "snappy" init files doing specific tasks like this version of >> parse-only.ly does, one should likely move some of its content to >> declarations-init.ly or elsewhere. At the current point of time, the >> ability to set up different init files is not really something one can >> cleanly put to good use. >> >> So generally I'd be wary expecting this to continue working forever, but >> hopefully if it stops working, the necessary changes should make for a >> cleaner solution then. >> >> -- >> David Kastrup > > That’s really too bad as this is something that seems like it would > really come in handy. Certainly, as I’m learning make having > something which is equivalent to the -M flag for a C compiler would be > very handy for generating dependencies. > > Though, I did find one problem thus far: \omit seems to create > problems when placed as a context mod. In the attached file I’ve got > the two methods for getting rid of bar numbers (from the manuals). If > I use the \omit version, then processing with parse-only.ly generates > "error: not a context mod”. If I use the \remove version, then > everything is fine. Uh. I might be clearing out too many hooks here. The ones for creating output mods and context mods would likely be fine. -- David Kastrup
Re: Identify included files
> On 16 May, 2020, at 5:31 PM, David Kastrup wrote: > > The problem is that there are quite a few things in there that make no > overwhelming sense for the task you want to solve. In order to allow > for "snappy" init files doing specific tasks like this version of > parse-only.ly does, one should likely move some of its content to > declarations-init.ly or elsewhere. At the current point of time, the > ability to set up different init files is not really something one can > cleanly put to good use. > > So generally I'd be wary expecting this to continue working forever, but > hopefully if it stops working, the necessary changes should make for a > cleaner solution then. > > -- > David Kastrup That’s really too bad as this is something that seems like it would really come in handy. Certainly, as I’m learning make having something which is equivalent to the -M flag for a C compiler would be very handy for generating dependencies. Though, I did find one problem thus far: \omit seems to create problems when placed as a context mod. In the attached file I’ve got the two methods for getting rid of bar numbers (from the manuals). If I use the \omit version, then processing with parse-only.ly generates "error: not a context mod”. If I use the \remove version, then everything is fine. Of course, I still get the list of files I want on the stdout, so I can totally live with this. The only difficulty is that when this occurs lilypond exits with a non-zero exit code, so any scripts I write based on this can’t use the error code to determine if the command completed successfully. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ test.ly Description: Binary data
Re: Identify included files
"Fr. Samuel Springuel" writes: >> On 15 May, 2020, at 5:04 PM, David Kastrup wrote: >> >> "Fr. Samuel Springuel" writes: >> >>> Before I start writing a script to do this, is there an existing tool >>> which will identify all the `\include` files that a LilyPond file >>> depends on? Even better, one that will work in a recursive fashion? >> >> You can use a file like >> >> ... >> and call it with >> >> lilypond --init parse-only.ly actual-file-name.ly 2> /dev/null >> >> and it should be pretty fast. Of course the file list includes >> parse-only.ly... >> >> >> -- >> David Kastrup > > Very nice. I’ve tested the various options and this seems to be the > best option. While I haven’t tested with a really big file, this > option appeared to be independent of file size while the option I came > up with isn’t. > > Is there any chance that something like this could be introduced into > LilyPond core? The problem is that there are quite a few things in there that make no overwhelming sense for the task you want to solve. In order to allow for "snappy" init files doing specific tasks like this version of parse-only.ly does, one should likely move some of its content to declarations-init.ly or elsewhere. At the current point of time, the ability to set up different init files is not really something one can cleanly put to good use. So generally I'd be wary expecting this to continue working forever, but hopefully if it stops working, the necessary changes should make for a cleaner solution then. -- David Kastrup
Re: Identify included files
> On 15 May, 2020, at 5:04 PM, David Kastrup wrote: > > "Fr. Samuel Springuel" writes: > >> Before I start writing a script to do this, is there an existing tool >> which will identify all the `\include` files that a LilyPond file >> depends on? Even better, one that will work in a recursive fashion? > > You can use a file like > > ... > and call it with > > lilypond --init parse-only.ly actual-file-name.ly 2> /dev/null > > and it should be pretty fast. Of course the file list includes > parse-only.ly... > > > -- > David Kastrup Very nice. I’ve tested the various options and this seems to be the best option. While I haven’t tested with a really big file, this option appeared to be independent of file size while the option I came up with isn’t. Is there any chance that something like this could be introduced into LilyPond core? ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
"Fr. Samuel Springuel" writes: > Before I start writing a script to do this, is there an existing tool > which will identify all the `\include` files that a LilyPond file > depends on? Even better, one that will work in a recursive fashion? You can use a file like %% Toplevel initialisation file. \version "2.19.22" #(if (guile-v2) (begin (use-modules (ice-9 curried-definitions)) (setlocale LC_ALL "") (setlocale LC_NUMERIC "C"))) #(session-initialize (lambda () ;; we can't use ly:parser-include-string here since that does not ;; actually do any parsing but merely switches inputs, so the ;; session saved by the session initializer after calling this ;; function has not actually started. A parser clone, in contrast, ;; can run and complete synchronously and shares the module with ;; the current parser. (ly:parser-parse-string (ly:parser-clone) "\\include \"declarations-init.ly\""))) #(define (do-nothing . x) #f) #(define toplevel-book-handler do-nothing) #(define toplevel-bookpart-handler do-nothing) #(define toplevel-music-handler do-nothing) #(define toplevel-score-handler do-nothing) #(define toplevel-text-handler do-nothing) #(define book-bookpart-handler do-nothing) #(define book-music-handler do-nothing) #(define book-score-handler do-nothing) #(define book-text-handler do-nothing) #(define bookpart-score-handler do-nothing) #(define bookpart-text-handler do-nothing) #(define bookpart-music-handler do-nothing) #(define output-def-music-handler do-nothing) #(define context-mod-music-handler do-nothing) #(note-names-language default-language) #(define toplevel-scores (list)) #(define toplevel-bookparts (list)) #(define $defaultheader #f) #(define $current-book #f) #(define $current-bookpart #f) #(define version-seen #f) #(define expect-error #f) #(define output-empty-score-list #f) #(define output-suffix #f) #(use-modules (scm clip-region)) #(use-modules (srfi srfi-1)) #(use-modules (ice-9 pretty-print)) \maininput #(format #t "~{~a\n~^~}" (ly:source-files)) and call it with lilypond --init parse-only.ly actual-file-name.ly 2> /dev/null and it should be pretty fast. Of course the file list includes parse-only.ly... -- David Kastrup
Re: Identify included files
> On 15 May, 2020, at 12:03 PM, Fr. Samuel Springuel > wrote: > >> On 15 May, 2020, at 3:43 AM, Valentin Villenave >> wrote: >> >> On 5/15/20, Fr. Samuel Springuel wrote: >>> Before I start writing a script to do this, is there an existing tool which >>> will identify all the `\include` files that a LilyPond file depends on? >>> Even better, one that will work in a recursive fashion? >> >> Since 2.19.39, you can simply use this: >> >> #(display (ly:source-files)) >> > > I’m hoping for something that doesn’t require actually typesetting the > document. My end goal is a script which will somewhat intelligently > determine which files in a project have changed and re-typeset them as > needed. Having to typeset the document in order to determine which files it > depends on means I’ve already done the typesetting. Is there a way to pass > that and \set Score.skipTypesetting = ##t at the command line? > So, I’ve done some experimenting on my own and here’s what I’ve discovered: `-dno-print-pages` will prevent lilypond from producing typeset output. My preliminary testing seems to indicate that this is indeed faster than actually typesetting, but I haven’t rigorously tested this to determine what kind of speed up is produced. `#(display (ly:source-files))` must be after any `\include` statements in the LilyPond file in order for the list to be complete. As such, it is best positioned at the end of the file. `lilypond -` will read in from stdin, allowing piping input into the command and thus using pipes to modify a file “on-the-fly” without actually changing the file on the disk. Combining all this, I get the following: echo "#(display (time ly:source-files))" | cat - | lilypond -dno-print-pages - This will send a list of the included files to stdout (there’s also some stuff on stderr which you’ll see if testing on the console). The first two entries will be `init.ly` (with full path) and `-`, which can be thrown away, but the remaining entries are what I’m looking for (and it’s fully recursive). One difficulty: if reading input from stdin, `\include` statements which navigate through the directory tree may experience problems if there is a mismatch between the current working directory and the location of the file being pushed through the pipes to stdin. One way to get around this is to make use of the --include option to add in the directory of the file. One easy way to do this is to define a variable `filename` with the name of the file, then the full command is: echo "#(display (time ly:source-files))" | cat “$filename" - | lilypond --include="$(dirname $filename)" -dno-print-pages - Now I just need to turn this list into something that can be used to figure out if the target needs to be recompiled. ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
Hello Samuel, The tool you’re looking for to track changed files and re-handle them is ‘make’. JM > Le 15 mai 2020 à 18:03, Fr. Samuel Springuel a écrit : > >> On 15 May, 2020, at 3:43 AM, Valentin Villenave >> wrote: >> >> On 5/15/20, Fr. Samuel Springuel wrote: >>> Before I start writing a script to do this, is there an existing tool which >>> will identify all the `\include` files that a LilyPond file depends on? >>> Even better, one that will work in a recursive fashion? >> >> Since 2.19.39, you can simply use this: >> >> #(display (ly:source-files)) >> > > I’m hoping for something that doesn’t require actually typesetting the > document. My end goal is a script which will somewhat intelligently > determine which files in a project have changed and re-typeset them as > needed. Having to typeset the document in order to determine which files it > depends on means I’ve already done the typesetting. Is there a way to pass > that and \set Score.skipTypesetting = ##t at the command line? > > ✝✝ > Fr. Samuel, OSB > (R. Padraic Springuel) > St. Anselm’s Abbey > 4501 South Dakota Ave, NE > Washington, DC, 20017 > 202-269-2300 > (c) 202-853-7036 > > PAX ☧ ΧΡΙΣΤΟΣ > >
Re: Identify included files
> On 15 May, 2020, at 3:43 AM, Valentin Villenave > wrote: > > On 5/15/20, Fr. Samuel Springuel wrote: >> Before I start writing a script to do this, is there an existing tool which >> will identify all the `\include` files that a LilyPond file depends on? >> Even better, one that will work in a recursive fashion? > > Since 2.19.39, you can simply use this: > > #(display (ly:source-files)) > I’m hoping for something that doesn’t require actually typesetting the document. My end goal is a script which will somewhat intelligently determine which files in a project have changed and re-typeset them as needed. Having to typeset the document in order to determine which files it depends on means I’ve already done the typesetting. Is there a way to pass that and \set Score.skipTypesetting = ##t at the command line? ✝✝ Fr. Samuel, OSB (R. Padraic Springuel) St. Anselm’s Abbey 4501 South Dakota Ave, NE Washington, DC, 20017 202-269-2300 (c) 202-853-7036 PAX ☧ ΧΡΙΣΤΟΣ
Re: Identify included files
On 5/15/20, Fr. Samuel Springuel wrote: > Before I start writing a script to do this, is there an existing tool which > will identify all the `\include` files that a LilyPond file depends on? > Even better, one that will work in a recursive fashion? Since 2.19.39, you can simply use this: #(display (ly:source-files)) And you can even embed all the required source files into the PDF with: #(ly:set-option 'embed-source-code #t) Cheers, V.
Re: Identify included files
Am 15. Mai 2020 03:21:55 MESZ schrieb "Fr. Samuel Springuel" : >Before I start writing a script to do this, is there an existing tool >which will identify all the `\include` files that a LilyPond file >depends on? Even better, one that will work in a recursive fashion? I know of Frescobaldi and lyluatex that have implemented thus recursive search. Urs > >✝✝ >Fr. Samuel, OSB >(R. Padraic Springuel) >St. Anselm’s Abbey >4501 South Dakota Ave, NE >Washington, DC, 20017 >202-269-2300 >(c) 202-853-7036 > >PAX ☧ ΧΡΙΣΤΟΣ -- Diese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet.