From 66697360832da018ea0423dda32024a8819f294b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sun, 24 Jul 2022 21:11:09 +0200 Subject: Improve makedeps. This version correctly finds dependencies inside dependencies. One may wonder why I don't just use gcc -MM c/*.cpp, which produces basically the same result. The simple reason is that gcc does it very slowly. It would be unfeasible to run before every compilation. --- makedeps | 58 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/makedeps b/makedeps index 829d389..70589ca 100644 --- a/makedeps +++ b/makedeps @@ -1,24 +1,58 @@ #!/usr/bin/env perl -use strict; +use v5.12; use warnings; +use subs qw/for_includes/; open my $fh, ">", "deps.mk"; print $fh "# This file is generated by makedeps.\n"; + while (my $f = glob("c/*.cpp")) { - open my $gh, "<", $f; $f =~ s,^c/,,; $f =~ s/\.cpp$//; - if ($f eq "main") { - print $fh "b/\$(EXE):"; - } else { - print $fh "b/$f.obj:"; + + if ($f eq "main") { print $fh "b/\$(EXE):"; } + else { print $fh "b/$f.obj:"; } + + # Print dependencies in source file. + my @deps; + for_includes "c/$f.cpp", sub { + my $f = shift; + return if grep { $_ eq $f } @deps; + push @deps, $f; + print $fh " c/$f"; + + # Print dependencies in dependency. + for_includes "c/$f", sub { + my $f = shift; + return if grep { $_ eq $f } @deps; + push @deps, $f; + print $fh " c/$f"; + } + }; + + print $fh "\n"; +} + +sub for_includes ($&) { + my $f = shift; + my $c = shift; + state %cache; + + # Retrieve dependencies from cache. + if (exists $cache{$f}) { + $c->($_) for @{$cache{$f}}; } - while ($_ = <$gh>) { - next if /^$/; - goto n if not /#/; - print $fh " c/$1" if /^#include\s*"([^"]+)"/; + + # Find dependencies in file. + else { + open my $gh, "<", $f or die "($f) $!"; + while ($_ = <$gh>) { + next if /^$/; + last if not /#/; + next if not /^#include\s*"([^"]+)"/; + push @{$cache{$f}}, $1; + $c->($1); + } } - n: - print $fh "\n"; } -- cgit v1.2.3