duncs has asked for the wisdom of the Perl Monks concerning the following question:

No, this isnt another CPAN question...

I help to maintain a perl app that depends on a number of perl modules. Instead of customers installing their own set of modules directly from CPAN we distribute a known set of working modules and install them into a known location (within the app's own directory rather than the perl system directories).

We currently have this working by maintaining our own (versioned) public CPAN repo that we point customer installs at (for use by 'CPAN'), but it is getting unwiedly in size (every new version of the software has to have its own CPAN repo with known working modules) and harder to maintain all the time (we create and update a new cpan repo with all the latest 'real' CPAN modules for every major release of the software).

Better would be to only supply those modules we actually need (in .tar.gz format) via a single large tarball and install them directly via a perl script (using an appropriate module as necessary, also within that tarball). Other people must be doing this already, but we havnt found the best (or even a working) way to do this.

Any suggestions?

Thanks

  • Comment on Installing a group of .tar.gz format perl modules

Replies are listed 'Best First'.
Re: Installing a group of .tar.gz format perl modules
by marto (Cardinal) on Jun 14, 2007 at 09:52 UTC
    Hi duncs,

    Have you looked at PAR (or pp)?

    Hope this helps

    Martin
      I didn't even know about PAR before...

      However, after skimming the docs, it looks like I need to have PAR installed on the target machine first, but I'll try it out to see if I can get it doing what I need.

      Thanks

Re: Installing a group of .tar.gz format perl modules
by perrin (Chancellor) on Jun 14, 2007 at 12:25 UTC
    Krang contains code to do this. It builds all of the bundled CPAN modules and installs them in a local directory.
Re: Installing a group of .tar.gz format perl modules
by rminner (Chaplain) on Jun 14, 2007 at 13:43 UTC
    Hi duncs,

    Unfortunately i won't be answering your question, but i think it might interest you nevertheless:
    At our company we use perlapp of Activestates Perl Dev Kit(included in the deployment tools). It creates a single executable out of your script and the modules the script uses. Till now we could compile all scripts. It also doesn't have a problem compiling graphical applications using Tk. The only thing you have to be aware of, that Modules which use source filters will stop working when compiled. In other words: you won't be able to use modules like Switch.pm and Pod::Usage.
    My impression was that most Modules don't use source filters, so i don't mind that limitation to much.
    Distributing our skripts in a compiled form completely removed the problem of having to worry about installed modules. Just copy the executatble and it works.
    The license also includes versions of perlapp for HPUX, Solaris and Linux.


    pp which marto mentioned seems to be doing the same, but i can't comment on it as i never used it.

    Disclaimer: I am not affiliated with activestate, i just like their product.
Re: Installing a group of .tar.gz format perl modules
by thinc (Novice) on Jun 14, 2007 at 22:45 UTC
    This works for me in a linux/bsd environment:
    I have a vendor directory which holds all the tar.gz's from cpan, and a makefile
    Makefile:
    PWD = $(shell pwd) CACHE_DIR ?= cache PERL = $(shell which perl) BUILD_INCS = -I $(PWD)/$(CACHE_DIR)/lib/perl5 INSTALL_TARGET ?= $(PWD)/$(CACHE_DIR) MAKEFILE_PL_ARGS = INSTALL_BASE=$(INSTALL_TARGET) PERL="$(PERL) $(BUIL +D_INCS)" TGZFILES = $(wildcard *.tar.gz) DEPENDS_ORDER2 = $(shell cat install_order) $(TGZFILES) # remove duplicates DEPENDS_ORDER = $(shell perl -e '@b=grep{!$$s{$$_}++} @ARGV;print "@b" +' $(DEPENDS_ORDER2)) # this gets a list of all the directories that the .tar.gz files unpac +k into UNPACK_DIRS = $(shell for t in $(DEPENDS_ORDER);do for f in `tar tzf $ +$t`;do R="$$R $$f/";break;done;done;echo $$R) BLIBS = $(patsubst %/,%/blib,$(UNPACK_DIRS)) # we want to link to gmake here, unless it is not available GMAKE = $(firstword $(shell which gmake) $(shell which $(MAKE)) ) PATH = $(PWD)/bin:$(shell echo $$PATH) .PHONY: all clean install $(TGZFILES) all: @ echo ------------------------------------------- @ echo "TGZFILES: $(TGZFILES)" @ echo ------------------------------------------- @ echo "DEPENDS_ORDER: $(DEPENDS_ORDER)" @ echo ------------------------------------------- @ echo "UNPACK_DIRS: $(UNPACK_DIRS)" @ echo ------------------------------------------- @ echo "BLIBS: $(BLIBS)" @ echo ------------------------------------------- @ echo "BUILD_INCS: $(BUILD_INCS)" @ echo ------------------------------------------- $(UNPACK_DIRS): @ echo unpacking $@ @ echo -n " " tar xfz $(@).tar.gz @ for patch_file in patches/*.$(@).tar.gz.*.patch; do \ if [ ! -e $$patch_file ]; then \ echo " No patches found for $(@).tar.gz"; \ continue; \ fi; \ echo " Running patch $$patch_file: "; \ patch -p1 < $$patch_file; \ done; @ echo " Making makefile $@ in $@"; @ cd $@ && TipTop=1 PERL_MM_USE_DEFAULT=1 perl $(BUILD_INCS) Makef +ile.PL $(MAKEFILE_PL_ARGS) >> build.log; @ echo " Making blib $@ in $@"; @ $(MAKE) -C $@ all >>build.log # ARCH=1 is to override BSDPAN (hateful software) @ echo " Installing $(@) into $(INSTALL_TARGET)" @ $(MAKE) -C $@ pure_install ARCH=1 >> build.log # force the use of gmake by putting it first in the path ENV: rm -rf bin/make ln -sf $(GMAKE) bin/make $(CACHE_DIR): ENV $(UNPACK_DIRS) install: $(CACHE_DIR) @ echo "Copying $(CACHE_DIR) to $(TARGET)"; mkdir -p $(TARGET)/ cp -Rf $(CACHE_DIR)/lib/perl5/* $(TARGET)/ @ touch $(CACHE_DIR) clean: rm -rf $(UNPACK_DIRS) rm -rf $(CACHE_DIR) rm -f ./build.log
    I can pretty much just add modules to the vendor directory and it picks it up.

    Some modules depend on others so there is an 'install_order' file that lists the order those modules should be installed.

    I also have a patches directory in case I need to patch the cpan modules before they get built.

    I call this from my main makefile like this:
    $(MAKE) -C $(VENDOR_DIR) install TARGET=$(LOCAL_BUILD_TARGET)/lib/
      Thanks very much - this looks fantastic. I'll try it out and let you know how I get on.