1

I'm using a makefile to deploy static content to an s3 bucket using Amazon's CLI. I want to throw in a variable to choose the target destination so I don't need to repeat the same script in different make verbs.

I seem to have got it to work but I want to make the argument case-insensitive from the terminal when it's executed. Here's what I have:

S3_NAME_DEV = com-mydomain-application-dev
S3_NAME_LIVE = com-mydomain-application
deploy:
    # e.g. make deploy t=LIVE
    aws s3 sync dist/ s3://$(S3_NAME_${t})

I tried adding the two carets (which is supported in bash 4 and I'm using) $(S3_NAME_${t^^}) but doesn't work :/. Here's the output when I do $ make deploy t=live (variable just disappears).

$ make deploy t=live
# e.g. make deploy t=LIVE
aws s3 sync dist/ s3://

I thought it might be useful to include what the aws command might look like (so that not knowing the AWS CLI doesn't throw you off).

aws s3 sync dist/ s3://com-mydomain-application

In the shell I call the make from I can do this successfully:

$ t=live
$ echo ${t^^}
LIVE

Any help would be greatly appreciated.

Bonus points: setting default value

UPDATE:

So make doesn't inherit the bash which executes it like I assumed. If I @echo "my version is: $$BASH_VERSION" in the make file I get version 3.2 (OS X default). Pretty good chance fixing this will solve the issue.

freebie
  • 2,161
  • 2
  • 19
  • 36
  • @Sundeep Sorry I didn't include that; I've edited the post. – freebie Oct 03 '16 at 12:26
  • no probs, does it work if you give all caps? – Sundeep Oct 03 '16 at 12:27
  • @Sundeep once I include the `^^` is will give the empty value with either `t=live` or `t=LIVE`. If I remove `^^` `$ make deploy t=LIVE` will work again. – freebie Oct 03 '16 at 12:30
  • okay, can you try `$(S3_NAME_"${t^^}")` ? – Sundeep Oct 03 '16 at 12:31
  • @Sundeep gave it a shot. Same output unfortunately. – freebie Oct 03 '16 at 12:32
  • apparently, you might need to [double the $ for variable](http://stackoverflow.com/questions/38769390/dollars-in-makefile-environment-variables).. so try `$(S3_NAME_"$${t^^}")` – Sundeep Oct 03 '16 at 12:37
  • That didn't work either :/ though I think you're on the right tracks – freebie Oct 03 '16 at 12:42
  • hmm, no more ideas.. hope someone else will help you :) – Sundeep Oct 03 '16 at 12:43
  • @Sundeep thanks anyway :) – freebie Oct 03 '16 at 12:48
  • Makefile uses `/bin/sh` by default. That just happens to be `/bin/bash` version 3.2 on your machine. Honestly, you are going to put far more work into trying to make your script "user-friendly" than anyone will ever spend just typing `LIVE`/`DEV` instead of `live`/`dev`. – chepner Oct 03 '16 at 15:07
  • Or rather, no one is likely to *want* to type `LIVE` instead of `live` from the command line, so just use the lowercase string in your Makefile variable (`S3_NAME_dev` and `S3_NAME_live`). – chepner Oct 03 '16 at 15:10
  • @chepner A fair point but I do want to do more complex things with these makefiles so this is only going to help me understand what's going on. Even though this particular use case is not very compelling. – freebie Oct 03 '16 at 15:13

1 Answers1

0

I tried adding the two carets (which is supported in bash 4 and I'm using) $(S3_NAME_${t^^}) but doesn't work.

This is because $(S3_NAME_...) part is being expanded by make, whereas you expect the ${t^^} part to be expanded by bash, but bash is not involved when make expands variables.

Convert t to uppercase early in your makefile:

override t := $(shell X="${t}"; echo $${X^^})

Without override it will need a new variable name:

u := $(shell X="${t}"; echo $${X^^})
# use ${u} instead of ${t}
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • This works, though the make script doesn't appear to have context of it's previously executed lines so I have to do it all inline i.e. `aws s3 sync dist/ s3://S3_NAME_$(shell X="${t}"; echo $${X^^})`. Am I right that that's the case – freebie Oct 03 '16 at 15:10
  • @freebie _the make script doesn't appear to have context of it's previously executed lines_ - that should not be the case. If you invoke other makefiles make sure you `export` the variable, e.g. `export u := ...` and use `${u}` instead of `${t}`. – Maxim Egorushkin Oct 03 '16 at 15:35
  • I did try putting export in front of the variable assignment but it didn't seem to work. Sorry on my phone so I dont have the error at hand. This answer is correct though and has solved my problem. I guess the scoping of the make variables is a different issue. Thanks – freebie Oct 04 '16 at 08:25