package My::Module; use Exporter 'import'; use My::Module::Another; our @EXPORT = ( qw/asub1 asub2 asub3/, @My::Module::Another::EXPORT ); #### package My::Module::Another; use base 'Exporter'; our @EXPORT = qw/bsub1 bsub2 bsub3/; #### package My::Module; use base 'Exporter'; our @EXPORT = qw/asub1 asub2 asub3/; use My::Module::Another; sub import { warn "WARNING: Ignoring export list!" if @_>1; __PACKAGE__->export_to_level(1, $_[0]); My::Module::Another->export_to_level(1, $_[0]); } #### package My::Module; # no "use Exporter" or "use base 'Exporter'", we're on our own! # ... use Carp; our @EXPORT_FROM_PACKS = qw/ My::Module My::Module::Another /; sub import { my ($class, @export) = @_; my ($callerpack) = caller; my %export = map {$_=>1} @export; for my $frompack (@EXPORT_FROM_PACKS) { # loop over packages # attempt to load that module eval "require $frompack; 1" or croak "failed to load $frompack: $@"; # get their @EXPORT variable my @exps = do { no strict 'refs'; @{"${frompack}::EXPORT"} }; for my $ex (@exps) { # loop over their exports next if @export && !$export{$ex}; no strict 'refs'; # limit scope of "no strict" # target function <-- source function *{"${callerpack}::$ex"} = \&{"${frompack}::$ex"}; } } }