Search code examples
shellmakefilevariable-expansion

Chopping suffixes in variable expansion within a Makefile


As the title states, I have a problem being able to remove suffix from a package name if I need to provide several suffixes (pattern-list)

Note: I have forced bash usage in the Makefile (SHELL=/bin/bash)

  • DEST_DIR: Makefile variable

  • PKG_LIST: Makefile variable, hold a list of folders names (e.g. "packageFsOPT1 packageAdc packageMemOPT2 ....."). Some of the names might have OPT1 suffix, some other don't.

  • tmp: folder that is existing and contains the folder packageFs, packageAdc, packageMem.....

Here the part of the Makefile that perform copy from tmp to dest along with the name chopping:

for pkg in $(PKG_LIST) ; do \
    cd tmp && tar xzf $$pkg-$(MAJOR).$(MINOR).$(TARGET).tar.gz tmp ; \
    cp -a tmp/$${pkg%OPT1} $(DEST_DIR) ; \
done

This is "working", meaning that OPT1 is indeed chopped from packageFsOPT1. But what I need is to be able to chop different suffixes. In this case OPT1 or OPT2

I tried this:

cp -a tmp/$${pkg%+(OPT1|OPT2)} $(DEST_DIR) ; \

Which is working if tested directly in console but not within the Makefile (not able to chop => OPT1 stays in the folder name, which doesn't exist => copy fail)

I some kind of stuff like this (but lead to pkg_stripped being empty):

pkg_stripped=$(shell echo ${pkg%+(OPT1|OPT2)}) ; \
cp -a tmp/$$pkg_stripped $(DEST_DIR) ; \

Does anyone have an idea?

Edit: Solutions

Either (using extended global)

for pkg in $(PKG_LIST) ; do \
    cd tmp && tar xzf $$pkg-$(MAJOR).$(MINOR).$(TARGET).tar.gz tmp ; \
    shopt -s extglob ; \
    cp -a tmp/$${pkg%+(OPT1|OPT2)} $(DEST_DIR) ; \
done

Or (using sed)

See MadScientist answer


Solution

  • Maybe it's simpler to use GNU make functions? Something like this:

    for pkg in $(patsubst %OPT1,%,$(patsubst %OPT2,%,$(PKG_LIST))) ; do \
        cp -a tmp/$${pkg} $(DEST_DIR) ; \
    done
    

    This will do the wrong thing (maybe?) if you have names like fooOPT1OPT2 (both will be stripped) but that can be solved as well.

    ETA

    If you need both you'll have to do it in the shell. You can't use $(shell ...) in a recipe: that's a make function so it's expanded by make before the shell is started: it can't operate on the value of any shell for loop variables of course.

    I would simply use sed for this:

    for pkg in $(PKG_LIST) ; do \
        prefix=$$(echo "$$pkg" | sed 's/OPT[12]$$//'); \
        cd tmp && tar xzf $$pkg-$(MAJOR).$(MINOR).$(TARGET).tar.gz tmp ; \
        cp -a tmp/$$prefix $(DEST_DIR) ; \
    done