Passing Makefile variable to docker-compose is resulting in a "unknown shorthand flag" error - bash

I have a Makefile which I use to help our programmers get easily setup. At present I am writing one to pass an IMAGE tag to the docker-compose command, but I keep getting a unknown shorthand flag and I cant figure out why.
My Makefile is as follows;
.PHONY: all
ARCH = $(shell uname -m)
start:
if [ "$(ARCH)" = "x86_64" ]; then \
IMAGE_ARCH="amd64"; \
elif [ "$(ARCH)" = "aarch64" ]; then \
IMAGE_ARCH="arm64"; \
else \
echo "Unknown architecture: $(ARCH)"; \
fi
docker-compose up -d -e IMAGE=$IMAGE_ARCH
The error is;
unknown shorthand flag: 'e' in -e

docker-compose has no -e option.
You can run this way :
.PHONY: all
ARCH := $(shell uname -m)
start:
if [ "$(ARCH)" = "x86_64" ]; then \
IMAGE_ARCH="amd64"; \
elif [ "$(ARCH)" = "aarch64" ]; then \
IMAGE_ARCH="arm64"; \
else \
echo "Unknown architecture: $(ARCH)"; \
fi; \
IMAGE=$$IMAGE_ARCH docker-compose up -d
docker-compose command needs to be put in the same block as [if] in order to use $IMAGE_ARCH.

Related

Scripting using Zenity GUI

I try to make a script bash app with the help of Zenity.
https://help.gnome.org/users/zenity/stable/index.html.en
It works properly, however I encounter a problem ...
Here is my code:
#!/bin/bash
APP_NAME="bealeCrypter"
function select_letter () {
letter=("FALSE" "1" "Treasury location" "none"
"FALSE" "2" "Treasury contents" "yes"
"FALSE" "3" "Treasury beneficiaries" "none")
LETTER_FILES=$(zenity --list \
--width=430 \
--height=235 \
--title="$APP_NAME" \
--text="What letter do you want to $1 ?" \
--checklist \
--multiple \
--column=Selection \
--column=Letter \
--column=Description \
--column=Decrypted \
"${letter[#]}")
if [ $? -eq 0 ]; then
if [ -z "$LETTER_FILES" ]; then
select_letter "$1"
fi
else
app_main
fi
}
function select_letter_options () {
letter_options=("TRUE" "1" "Get the number of characters"
"TRUE" "2" "Get the smallest number"
"TRUE" "3" "Get the biggest number")
LETTER_OPTIONS=$(zenity --list \
--width=350 \
--height=210 \
--hide-header \
--title="$APP_NAME" \
--text="Choose the analyze letter options :" \
--checklist \
--multiple \
--column=Selection \
--column=Id \
--column=Description \
--hide-column=2 \
"${letter_options[#]}")
if [ $? -eq 0 ]; then
if [ -z "$LETTER_OPTIONS" ]; then
select_letter_options
fi
else
app_main
fi
}
function app_main () {
menu=("1" "Analyze a Letter")
SELECTION=$(zenity --list \
--width=350 \
--height=210 \
--hide-header \
--title="$APP_NAME" \
--text="What to do ?" \
--column=Id \
--column=Selection \
--hide-column=1 \
--cancel-label=Quit \
"${menu[#]}")
if [ $? -eq 0 ]; then
case "$SELECTION" in
1) select_letter "analyze"
select_letter_options
;;
*) app_main
esac
echo -e "LETTER: $LETTER_FILES\nKEY: $KEY_FILES\nLETTER_OPTIONS: $LETTER_OPTIONS\nKEY_OPTIONS: $KEY_OPTIONS"
else
exit 0
fi
}
app_main
Here is my problem, When I select the following menus/button (in this specific order):
Analyze a Letter
Cancel
Analyze a Letter
Select checkbox 1, 2 or 3 and OK
Select options and OK
the option window opens twice after the validation OK, I don't understand why?
Here is a video demo:
https://streamable.com/np7wzl
I specify that if I do not make a Cancel (point #2) it works correctly.
How is it possible?
I tried to empty the variables before recalling the function but the result and always identical, I do not understand?
Does anyone have an explanation for this?

Manage exit code in Makefile define

I am creating a target that can be used as a hook to add some extra procedure when is needed.
This is the code in the main Makefile
export MSG:="Linux hook"
linux-build:
# echo "Dependency target"
linux-build-post: linux-build
# make -s -f linux.hook -q linux_build_post 2> /dev/null ; \
if [ $$? -le 1 ] ; then \
echo "Target exist" ; \
make -s -f linux.hook linux_build_post ; \
else \
echo "Target doesn't exist" ; \
fi
# touch $#
This is the code in the file linux.hook
linux_build_post:
# echo ${MSG}
This code works correctly, but now I am trying to create a template in the main Makefile. For example:
export MSG:="Linux hook"
linux-build:
# echo "Dependency target"
# Common hook target
# Parameters:
# 1: Target name
# 2: Dependecies
# 3: Hook name
define COMMON_HOOK_TARGET
$(1): $(2)
make -s -f $(3).hook -q $(1) 2> /dev/null ; \
if [ $$? -le 1 ] ; then \
echo "Target exist" ; \
make -s -f $(3).hook $(1) ; \
else \
echo "Target doesn't exist" ; \
fi
touch $(1)
endef
$(eval $(call COMMON_HOOK_TARGET,linux-build-post,linux-build))
But in this case the make command fails because $$? is replaced with the dependency linux-build then the if condition is evaluated like this if [ linux-build -le 1 ].
Error reported:
/bin/sh: 1: [: Illegal number: linux-build
How I can change the code in order to use $$? as the exit code of the previous command make -s -f $(3).hook -q $(1) 2> /dev/null ?
I think the answer is actually this:
if [ $$$$? -le 1 ] ; ...
The call to call turns "$$$$" into "$$", then when Make executes the rule it converts "$$?" to "$?" and passes it to the shell.

Filter out directories using Makefile list

I'm trying to make this release rule for my makefile
It's job is to copy the directories in the folder, except for a few (like the destination etc)
I have looked at the makefile filter function but it seems like it's not working inside of the bash loop?
Is there an easy way to filter out the items in the list in bash?
SOURCE_DIR=builds/$(NAME)_$(VERSION)
#List of items to ignore
IGNORE=builds cfg compiled
release:
if [ -d "cfg" ]; then \
cp -r cfg $(SOURCE_DIR)/cfg; \
fi;
for folder in *; do \
if [ -d "$$folder" ]; then \
if [[ $(IGNORE) != $$folder ]]; then \
cp -r $$folder $(SOURCE_DIR)/addons/; \
fi; \
fi; \
done;
The filter-out function is a Make function, so if you want to use it, you must use it before you pass the command to the shell.
You can use it outside the rule:
THINGS := $(wildcard *)
IGNORE = builds cfg compiled
THINGS := $(filter-out $(IGNORE), $(THINGS))
release:
#for folder in $(THINGS); do \
if [ -d $$folder ]; then \
echo $$folder; \
fi; \
done
or inside the rule:
THINGS := $(wildcard *)
IGNORE = builds cfg compiled
release:
#for folder in $(filter-out $(IGNORE), $(THINGS)); do \
if [ -d $$folder ]; then \
echo $$folder; \
fi; \
done
Or you could stick with for folder in *... and filter the list in bash:
IGNORE = builds cfg compiled
release:
#for folder in *; do \
if [ -d $$folder ]; then \
[[ "$(IGNORE)" =~ $$folder ]] || echo $$folder; \
fi; \
done

Use the result of a shell command in a conditional in a makefile

I am trying to execute a command in a conditional in a makefile.
I got it working in a shell:
if [ -z "$(ls -A mydir)" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
but if I try it in a makefile, "$(ls -A mydir)" expands to nothing whatever if asdf is empty or not:
all:
if [ -z "$(ls -A mydir)" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
The ls command does not expand as I expect:
$ mkdir mydir
$ make
if [ -z "" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
empty dir
$ touch mydir/myfile
$ make
if [ -z "" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
empty dir
$ ls -A mydir
myfile
How do I make the command work inside the conditional?
I have little experience in writing makefiles. However I think you must use two dollar signs in your recipe:
all:
if [ -z "$$(ls -A mydir)" ]; then \
https://www.gnu.org/software/make/manual/make.html#Variables-in-Recipes:
if you want a dollar sign to appear in your recipe, you must double
it (‘$$’).
This is an example of output after I changed your makefile and added $$(ls -A mydir):
$ ls mydir/
1
$ make
if [ -z "$(ls -A mydir)" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
non-empty dir
$ rm mydir/1
$ make
if [ -z "$(ls -A mydir)" ]; then \
echo "empty dir"; \
else \
echo "non-empty dir"; \
fi
empty dir

Makefile Substituting for loop variables to functions

I'm not sure what the best way to do this, and some pointers in this regard would be helpful
Code:
#Else where in different file and included in this makefile i have
LIBRARY_LIST := CONFIG_MTS_PTHREADS
CONFIG_MTS_PTHREADS := y
collect-compilation:
if [ $(strip $(CONFIG_MTS_PTHREADS)) == y ]; then \
echo "ok"; \
fi;
for compile in $(LIBRARY_LIST) ; do \
if [ $(strip $$compile) == y ]; then \
echo "ok"; \
fi; \
done
So from the above code snippet., the top part the 'IF' loop works fine as expected and i see 'OK'.
displayed.
Now for the second for-loop, i have some problems substituting the $$compile to the 'IF'. Eventually i expect $$compile gets replaced by CONFIG_MTS_PTHREADS and the expression should evaluate to y == y and display 'OK' but for me.,
Output:
make -C ./Dev2.0.1/OSX
if [ y == y ]; then \
echo "ok"; \
fi;
ok <----- fine and expected
for compile in CONFIG_MTS_PTHREADS ; do \
if [ $compile == y ]; then \
echo "ok"; \
fi; \
done <------ Here it skips the then part and proceeds further, i expect 'OK' after this though.
The trouble is that you're mixing Make-expansion and shell-expansion.
We start with this command:
for compile in $(LIBRARY_LIST) ; do \
if [ $(strip $$compile) == y ]; then \
echo "ok"; \
fi; \
done
Make expands the variables:
for compile in CONFIG_MTS_PTHREADS ; do \
if [ $compile == y ]; then \
echo "ok"; \
fi; \
done
(note that compile has no value yet) and passes the command to the shell, which expands the variables, runs the for loop and winds up testing:
if [ CONFIG_MTS_PTHREADS == y ]; then
which clearly must fail. It is too late to expand CONFIG_MTS_PTHREADS; the shell doesn't know that it's a variable with a value. Make knew, but Make has already handed to command off to the shell.
One solution is to use the value function, so that Make will expand the variable before passing it to the shell:
for compile in $(value $(LIBRARY_LIST)) ; do \
if [ $(strip $$compile) == y ]; then \
echo "ok"; \
fi; \
done

Resources