Hi Paul,

On 3/11/23 15:20, Paul Smith wrote:
> On Sat, 2023-03-11 at 01:54 +0100, Alejandro Colomar wrote:
>> Let's say I have a build tree that has directories which are created
>> during build.  The build system has some linters in a `lint` target,
>> which touches files when it succeeds.  When I want to lint only a
>> specific file, it's interesting to convince make(1) to touch all
>> files, and then touch the source file I want to lint; a subsequent
>> make(1) invocation will only lint the file I want.
> 
> To me that seems like not a good solution.  TBH I've never really
> understood the use-case for the -t flag.  But basically what you're
> saying here is that you're willing to rebuild your entire source tree
> from scratch (because you've touched all the sources) just to run lint
> on a specific file you want.  That doesn't seem like a good trade-off
> to me.

For my own stuff, I don't do that.  However, for contributors, it's
interesting.  Since the man-pages tree triggers a lot of warnings in
the recently-added linters, it would be very noisy for contributors to
run it on the entire tree.  However, I don't want to add new warnings,
so I want them to run the linters on the pages they touch.

For that, I have the following recommendation in the CONTRIBUTING file:

   Lint
       If you plan to patch a manual page, consider running the linters
       configured in the build system, to make sure your change doesn't add
       new warnings.  However, you might still get warnings that are not your
       fault.  To minimize that, do the following steps:

       (1)  First use make(1)'s -t option, so that make(1) knows that it only
            needs to lint again pages that you will touch.

                $ make -t lint

       (2)  Touch the page that you'll edit, and run make(1) again, to see
            which warnings you'll still see from that page that are not your
            fault.

                $ touch man2/membarrier.2  # replace by the page you'll modify
                $ make -k lint

       (3)  Apply your changes, and then run make(1) again.  You can ignore
            warnings that you saw in step (2), but if you see any new ones,
            please fix them if you know how, or at least note them in your
            patch email.

                $ vi man2/membarrier.2  # do your work
                $ make -k lint


Since contributors usually clone the repo freshly, or update it very
infrequently, they have the exact situation you mentioned.

> 
> Why don't you just add a special target for linting a specific file:
> 
>     lint-%:
>             <lint> $*
> 
> and now if you want to run lint on foo.c you'd say "make lint-foo.c"?

I considered doing it, but it would be a lot of extra work in the Makefile.
Since I found a workaround with make -ij, I thought I don't really need
to do that extra work.  Also, it would make it even slower (a simple
`make clean` already takes 1.5 seconds).

$ time make clean V=1
RM -rf  tmp
rm -rf tmp

real    0m1.517s
user    0m1.130s
sys     0m0.446s

> 
>> However, that only works if I've created all the directories, so I
>> need to run `make -ij lint && make -t lint`.
>>
>> How about using `mkdir -p` instead of touch(1) for nonexistent files?
>> The effect would be the same, but it would allow such structures to
>> work with this feature.  I don't foresee big issues with it (I don't
>> imagine that some systems will depend on make -t creating regular
>> empty files).
> 
> As Dmitry points out, that would be a disaster because lots of tools
> will overwrite existing files without any problem, but no tools will
> delete an existing directory.

Yep.

> 
> The right way to handle this is to prefix your lines that you want to
> be invoked even with -t, with a "+" operator.  That's one of the things
> it's for.

Didn't know about it :)

> 
> From the GNU Make manual:
> 
> https://www.gnu.org/software/make/manual/html_node/Instead-of-Execution.html
> 
>> The ‘-n’, ‘-t’, and ‘-q’ options do not affect recipe lines that
>> begin with ‘+’ characters or contain the strings ‘$(MAKE)’ or
>> ‘${MAKE}’. Note that only the line containing the ‘+’ character or
>> the strings ‘$(MAKE)’ or ‘${MAKE}’ is run regardless of these
>> options. Other lines in the same rule are not run unless they too
>> begin with ‘+’ or contain ‘$(MAKE)’ or ‘${MAKE}’ (See How the MAKE
>> Variable Works.)
> 
> Your example if you change your mkdir rule to:
> 
>   dir:
>       +mkdir $@
> 
> instead then you get:
> 
>   $ make -t
>   mkdir dir
>   touch dir/file
> 

Yup, it's exactly what I needed.

<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=b4c10c038e103c04b4ed1e7446fd2f161e75eaf5>
<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=702b8bf597504e3860740209cc98827ab6830764>

Thanks for your help!


Cheers,

Alex

-- 
<http://www.alejandro-colomar.es/>
GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to