Sat May 31 17:58:18 2014: Request 95809 was acted upon.
Transaction: Correspondence added by s...@parasite.cc
       Queue: Inline
     Subject: Re: [rt.cpan.org #95809] [PATCH] Using Inline in a distribution 
with multiple modules
   Broken in: (no value)
    Severity: (no value)
       Owner: Nobody
  Requestors: s...@parasite.cc
      Status: open
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=95809 >


On Wed, 28 May 2014 05:55:23 -0400
"sisyph...@optusnet.com.au via RT" <bug-inl...@rt.cpan.org> wrote:

> And I think it would be straightforward to get Inline::MakeMaker to do this.
> I::MM simply has to recurse through the ./lib folder and create the relevant 
> entry in the Makefile for every pm file it finds (irrespective of whether 
> that pm file actually uses Inline).
> 
> I think this corresponds to your "shotgun" approach.
> I don't think it's ugly. For sure it's an unnecessary step for the modules 
> that don't use Inline but (for those modules) it  does no harm other than to 
> consume a fraction of a second during the make stage.

Ok, so you talked me into the "shotgun" approach :)  After digging a
bit I found that ExtUtils::MakeMaker was already locating all modules
to be installed and placing that list in $mm->{PM} (where $mm is the
returned object from the call to ExtUtils::MakeMaker::WriteMakefile).

There is another attribute, $mm->{PMLIBDIRS} that contains a list of
directories those modules reside in.  I added some code to use those
two lists to generate the rules to add to the makefile without having
to scan for modules ourselves.

Let me know what you think.  It worked for my single-Makefile.PL
distribution and for your Foo-fixed distribution.

This method requires no additional config options nor documentation.

Thanks,
Jason

diff -r 8a9bc8d83cc9 -r 3474e7b1aab0 Inline.pm
--- a/Inline.pm	Thu May 15 07:03:36 2014 -0500
+++ b/Inline.pm	Sat May 31 16:52:08 2014 -0500
@@ -515,12 +515,12 @@ sub load {
     my $o = shift;
 
     if ($o->{CONFIG}{_INSTALL_}) {
-	my $inline = "$o->{API}{modfname}.inl";
+	my $inline = $o->{API}{modinlname};
 	open INLINE, "> $inline"
 	  or croak M24_open_for_output_failed($inline);
 	print INLINE "*** AUTOGENERATED by Inline.pm ***\n\n";
 	print INLINE "This file satisfies the make dependency for ";
-	print INLINE "$o->{API}{modfname}.pm\n";
+	print INLINE "$o->{API}{module}\n";
 	close INLINE;
 	return;
     }
@@ -983,6 +983,7 @@ sub install {
     my @modparts = split(/::/,$o->{API}{module});
     $o->{API}{modfname} = $modparts[-1];
     $o->{API}{modpname} = File::Spec->catdir(@modparts);
+    $o->{API}{modinlname} = join('-',@modparts).'.inl';
     $o->{API}{suffix} = $o->{INLINE}{ILSM_suffix};
     $o->{API}{build_dir} = File::Spec->catdir($o->{INLINE}{DIRECTORY},'build',
                                               $o->{API}{modpname});
diff -r 8a9bc8d83cc9 -r 3474e7b1aab0 lib/Inline/MakeMaker.pm
--- a/lib/Inline/MakeMaker.pm	Thu May 15 07:03:36 2014 -0500
+++ b/lib/Inline/MakeMaker.pm	Sat May 31 16:52:08 2014 -0500
@@ -23,7 +23,6 @@ sub WriteMakefile {
     my %args = @_;
     my $name = $args{NAME}
       or croak "Inline::MakeMaker::WriteMakefile requires the NAME parameter\n";
-    my $object = (split(/::/, $name))[-1];
     my $version = '';
 
     croak <<END unless (defined $args{VERSION} or defined $args{VERSION_FROM});
@@ -43,30 +42,68 @@ Must be of the form '#.##'. (For instanc
 END
 
     # Provide a convenience rule to clean up Inline's messes
-    $args{clean} = { FILES => "_Inline $object.inl" }
+    $args{clean} = { FILES => "_Inline *.inl " }
     unless defined $args{clean};
+
     # Add Inline to the dependencies
     $args{PREREQ_PM}{Inline} = '0.44' unless defined $args{PREREQ_PM}{Inline};
 
-    &ExtUtils::MakeMaker::WriteMakefile(%args);
+    my $mm = &ExtUtils::MakeMaker::WriteMakefile(%args);
 
-    open MAKEFILE, '>> Makefile'
-      or croak "Inline::MakeMaker::WriteMakefile can't append to Makefile:\n$!";
+    my (@objects, @obj_rules);
 
-    print MAKEFILE <<MAKEFILE;
+    if ($mm->{PMLIBDIRS} && $mm->{PM}) {
+        # Sort them longest first so we'll match subdirectories before their parents
+        my @libdirs = sort { length($b) <=> length($a) } @{$mm->{PMLIBDIRS}};
+
+        for my $path (keys %{$mm->{PM}}) {
+            for my $lib (@libdirs) {
+                if (index($path,$lib) == 0) {
+                    my ($vol, $dirs, $file) = File::Spec->splitpath(substr($path, length($lib)+1));
+                    my @dirs = File::Spec->splitdir($dirs);
+                    pop @dirs unless length($dirs[$#dirs]);
+                    $file =~ s/\.[^.]+$//;
+
+                    push @objects, join('::', @dirs, $file);
+                    push @obj_rules, join('-', @dirs, "$file.inl");
+                    last;
+                }
+
+                croak "Failed to find module path for '$path'";
+            }
+        }
+    } else {
+        # no modules found in PMLIBDIRS so assume we've just got $name to do
+        @objects = $name;
+        @obj_rules = (split(/::/, $name))[-1].'.inl';
+    }
+
+    if (@objects) {
+        open MAKEFILE, '>> Makefile'
+          or croak "Inline::MakeMaker::WriteMakefile can't append to Makefile:\n$!";
+
+        print MAKEFILE <<MAKEFILE;
 # Well, not quite. Inline::MakeMaker is adding this:
 
 # --- MakeMaker inline section:
 
-$object.inl : \$(TO_INST_PM)
-	\$(PERL) -Mblib -MInline=NOISY,_INSTALL_ -M$name -e1 $version \$(INST_ARCHLIB)
+MAKEFILE
+    for (0..$#objects) {
+        print MAKEFILE <<MAKEFILE;
+$obj_rules[$_]: \$(TO_INST_PM)
+	\$(PERL) -Mblib -MInline=NOISY,_INSTALL_ -M$objects[$_] -e1 $version \$(INST_ARCHLIB)
+MAKEFILE
+    }
 
-pure_all :: $object.inl
+print MAKEFILE "\npure_all :: ",join(' ',@obj_rules),"\n";
+
+print MAKEFILE <<MAKEFILE;
 
 # The End is here.
 MAKEFILE
 
-    close MAKEFILE;
+        close MAKEFILE;
+    }
 }
 
 1;

Reply via email to