How to call another task with argument in Makefile? - makefile

I want to call another task with argument like this:
FILES = `find . -type d -name '*_server' -maxdepth 1`
UNAME = $(shell uname)
build:
ifeq (${UNAME}, Darwin)
build: build-os os=darwin # I want to set os to darwin, then call build-os
else
build: build-os os=linux
endif
build-os:
gox -verbose \
-os="${os}" \
-arch="amd64" \
-output="${DIST}/{{.OS}}-{{.Arch}}/{{.Dir}}" ${FILES}
As you can see, task build I want to call build-os depends on shell uname

At first you set the OS and then you use it in the target :
FILES = `find . -type d -name '*_server' -maxdepth 1`
UNAME = $(shell uname)
ifeq ($(UNAME), Darwin)
os=darwin
else
os=linux
endif
build: build-os
build-os:
gox -verbose \
-os="${os}" \
-arch="amd64" \
-output="${DIST}/{{.OS}}-{{.Arch}}/{{.Dir}}" ${FILES}
Please be aware that it is recommended that your target name does match the real output of the build. If it's not the case, it's better to use .PHONY targets, like this :
.PHONY: build build-output

Related

makefile error: No rule to make target How to fix?

The error:
make: *** No rule to make target 'build-x86_64'. Stop.
My makefile:
x86_64_asm_source_files := $(shell find src/impl/x86_64 -name *.asm)
x86_64_asm_object_files := $(patsubst src/impl/x86_64/%.asm, build/x86_64/%.o, $(x86_64_asm_source_files))
$(x86_64_asm_object_files): build/x86_64/%.o : src/impl/x86_64/%.asm
mkdir -p $(dir $#) && \
nasm -f elf64 $(patsubst build/x86_64/%.o, src/impl/x86_64/%.asm, $#) -o $#
.PHONY: build-x86_64
build-x86_64: $(x86_64_asm_object_files)
mkdir -p dist/x86_64 && .
x86_64-elf-ld -n -o dist/x86_64/kernel.bin -T targets/x86_64/linker.ld $(x86_64_asm_object_files) && \
cp dist/x86_64/kernel.bin targets/x86_64/iso/boot/kernel.bin && \
grub-mkrescue /usr/lib/grub/i386-pc -o dist/x86_64/target.iso targets/x86_64/iso

Makefile not writing files to /usr/local/lib/ in cygwin

I ran a particular Makefile on my Lubuntu machine, and it created a couple directories of files in my /usr/local/lib directory.
Tonight I'm trying to create a similar setup in a cygwin window on my Windows 10 machine. Same Makefile, but the /usr/local/lib directory ends up empty. So when I run a different Makefile later on that wants to call these /usr/local/lib libraries, it fails.
What could I be doing wrong? Is there an environment variable that needs to be set such that the /usr/loal/lib directory can be written to during the make?
Thanks.
Update: I just figured out that I can install Ubuntu as an application in Windows https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/ , and my makefile install is working great now. No problems at all, so it appears to be a cygwin problem only. That being said, here is my make file:
#! /usr/bin/make -f
# -*- make -*-
#
# Main gcc Makefile.
# This makefile is maintained by Greg King <greg.king4#verizon.net>.
# Goals that are supported by the cc65 package
.PHONY: all bins libs docs samples tests clean zap
.PHONY: uninstall install install-bins install-libs install-docs install-samps
# If SYS is defined on this makefile's command-line, then we want it to go
# to "samples" and "tests", but not to the other rules. So, we disable a
# feature of GNU make that would have given ${SYS} to every sub-make.
#MAKEOVERRIDES=
# (That trick has been disabled.)
# To compile with custom make-options, set them here; for example:
#MAKEOPTS = -j 2 CFLAGS=-O4 CC=clang
MAKEOPTS =
# The install prefix and directories
prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
datadir = $(prefix)/share
docdir = $(datadir)/doc
libdir = $(exec_prefix)/lib
CC65_DOC = $(docdir)/cc65
CC65_HOME = $(libdir)/cc65
CA65_INC = $(CC65_HOME)/asminc
CC65_INC = $(CC65_HOME)/include
LD65_CFG = $(CC65_HOME)/cfg
LD65_LIB = $(CC65_HOME)/lib
LD65_OBJ = $(CC65_HOME)/obj
# Programs
MKDIR = mkdir -m 755
# BSD-like install-script/-program
INSTALL = make/install-sh
INSTALL_DATA = $(INSTALL) -c -m 644
INSTALL_PROG = $(INSTALL) -c -m 755
INSTALL_STRIP = $(INSTALL_PROG) -s
# This file-name extension is needed on DOS/Windows systems.
ifdef COMSPEC
EXT = .exe
endif
# Rules
# The sample and library-test programs must be compiled for only one platform
# at a time. So, those rules are done automatically only when a user names
# a system on the command-line. (A user can do those rules with their
# defaults by putting "all samples tests" on the command-line.)
#
all: bins libs docs $(SYS:%=samples tests)
bins:
#$(MAKE) -C src -f make/gcc.mak $(MAKEOPTS) \
CA65_INC=\\\"${CA65_INC}/\\\" CC65_INC=\\\"${CC65_INC}/\\\" \
LD65_CFG=\\\"${LD65_CFG}/\\\" LD65_LIB=\\\"${LD65_LIB}/\\\" \
LD65_OBJ=\\\"${LD65_OBJ}/\\\"
libs:
#$(MAKE) -C libsrc
# This rule won't try to generate HTML files
# if a host system doesn't have LinuxDoc Tools.
docs:
#if linuxdoc -B check doc/index >/dev/null 2>&1; \
then $(MAKE) -C doc $(MAKEOPTS) html; \
else echo '"LinuxDoc Tools" is not installed; skipping HTML documentation.'; \
fi
# Some platforms cannot compile all of the sample and library-test programs.
# So, these rules ignore errors.
samples:
-#$(MAKE) -k -C samples prefix=$(prefix) $(SYS:%=SYS=%)
tests:
-#$(MAKE) -k -C testcode/lib prefix=$(prefix) $(SYS:%=SYS=%)
clean zap:
#$(MAKE) -C src -f make/gcc.mak $#
#$(MAKE) -C libsrc $#
#$(MAKE) -C doc $#
#$(MAKE) -C samples $#
# #$(MAKE) -C testcode/lib $# $(SYS:%=SYS=%)
uninstall: install-test
cd $(bindir) && $(RM) ar65${EXT} ca65${EXT} cc65${EXT} cl65${EXT} \
co65${EXT} da65${EXT} ld65${EXT} od65${EXT} grc65${EXT} ca65html
$(RM) -R $(CC65_HOME) $(CC65_DOC)
install: install-test install-dirs install-bins install-libs install-docs
#echo
#echo 'If you installed the files into non-default directories, then'
#echo 'you might need to export some shell environment variables:'
#echo
#echo 'CC65_HOME=$(CC65_HOME)'
#echo ' or'
#echo 'CA65_INC=$(CA65_INC)'
#echo 'CC65_INC=$(CC65_INC)'
#echo 'LD65_CFG=$(LD65_CFG)'
#echo 'LD65_LIB=$(LD65_LIB)'
#echo 'LD65_OBJ=$(LD65_OBJ)'
#echo
#if [ -x $(bindir)/grc${EXT} ]; then \
echo 'grc was renamed to grc65; but, a grc command is in your binaries directory.'; \
echo "If that command is an old copy of CC65's program,"; \
echo 'then you should use a "${MAKE} erase-grc" command to remove it.'; \
fi
.PHONY: install-test
install-test:
#if [ `id -u` != 0 ]; then \
echo; \
echo 'If you are denied permission to install or uninstall this package,'; \
echo 'then you will need to do "make/gcc.mak install" or "make/gcc.mak uninstall"'; \
echo 'as either the root user or an administrator.'; \
echo; \
fi 2>/dev/null
.PHONY: install-dirs
install-dirs: $(bindir) $(datadir) $(docdir) $(libdir) \
$(CC65_DOC) $(CC65_HOME) \
$(CA65_INC) $(CC65_INC) \
$(CC65_INC)/em $(CC65_INC)/geos $(CC65_INC)/joystick \
$(CC65_INC)/mouse $(CC65_INC)/sys $(CC65_INC)/tgi \
$(LD65_CFG) $(LD65_LIB) $(LD65_OBJ) \
$(CC65_HOME)/emd $(CC65_HOME)/joy $(CC65_HOME)/mou \
$(CC65_HOME)/ser $(CC65_HOME)/tgi
$(bindir) $(datadir) $(docdir) $(libdir) \
$(CC65_DOC) $(CC65_HOME) \
$(CA65_INC) $(CC65_INC) \
$(LD65_CFG) $(LD65_LIB) $(LD65_OBJ):
$(MKDIR) -p $# || $(MKDIR) $#
$(CC65_HOME)/% $(CC65_INC)/% $(CC65_DOC)/%:
$(MKDIR) $#
install-bins:
for f in ar65 ca65 cc65 cl65 co65 da65 ld65 od65 grc65 sp65; \
do $(INSTALL_STRIP) src/$$f/$$f${EXT} $(bindir) || exit $$?; \
done
$(INSTALL_PROG) src/ca65html/ca65html $(bindir)
install-libs:
for f in asminc/*.inc; \
do $(INSTALL_DATA) $$f $(CA65_INC) || exit $$?; \
done
for f in include/*.h; \
do $(INSTALL_DATA) $$f $(CC65_INC) || exit $$?; \
done
for d in em geos joystick mouse sys tgi; \
do for f in include/$$d/*.h; \
do $(INSTALL_DATA) $$f $(CC65_INC)/$$d || exit $$?; \
done || exit $$?; \
done
for f in libsrc/*.lib; \
do $(INSTALL_DATA) $$f $(LD65_LIB) || exit $$?; \
done
for f in libsrc/*-*.o; \
do $(INSTALL_DATA) $$f $(LD65_OBJ) || exit $$?; \
done
for f in src/ld65/cfg/[!g]*-*.cfg; \
do $(INSTALL_DATA) $$f $(LD65_CFG) || exit $$?; \
done
for d in emd joy mou ser tgi; \
do for f in libsrc/*.$$d; \
do $(INSTALL_DATA) $$f $(CC65_HOME)/$$d || exit $$?; \
done || exit $$?; \
done
install-docs:
for f in src/ca65/macpack/*.mac; \
do $(INSTALL_DATA) $$f $(CC65_DOC) || exit $$?; \
done
for f in readme.1st compile.txt CREDITS BUGS internal.txt newvers.txt; \
do $(INSTALL_DATA) doc/$$f $(CC65_DOC) || exit $$?; \
done
if [ -f doc/index.htm* ]; \
then for f in doc/*.htm*; \
do $(INSTALL_DATA) $$f $(CC65_DOC) || exit $$?; \
done; \
fi
install-samps: ${addprefix $(CC65_DOC)/, $(shell find samples -type d)}
#$(MAKE) -C samples zap
for d in `find samples -type d`; \
do for f in $$d/*; \
do if [ -f $$f ]; \
then $(INSTALL_DATA) $$f $(CC65_DOC)/$$d || exit $$?; \
fi; \
done || exit $$?; \
done
erase-grc:
$(RM) $(bindir)/grc${EXT}

Makefile with multiple values for a parameter

Currently, I am working on a makefile that takes a parameter "CLASS=xxx" and then compiles and does stuff with that value.
In the end, it runs an application ($APP) on a bunch of files.
I enter this command:
make default CLASS=Test_UART
and the makefile processes it thusly:
pc: $(APP)
make -C BUILDENV CLASS=$(CLASS) BUILD=just_filelist OUTPUT=filelist.txt SKIPSELF=yes
../classCvt/classCvt <./Applications/$(CLASS).class> ./Applications/$(CLASS).ujc
time -p ./$(APP) ./Applications/$(CLASS).ujc `cat filelist.txt`
Hence it calls a makefile in my BUILDENV folder which does the following:
#USAGE: make -C <PATH_TO_THIS_FILES_PARENT_DIR> CLASS=<MY_JAVA_FILE_NAME_WITHOUT_JAVA_EXTENSION> OUT=<OUTPUT_FILE_NAME>
SELF := $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
CLASS ?= PLEASE_SPECIFY_CLASS_PARAM
DIR := $(PWD)#print working directory
CCVT ?= $(SELF)/../../classCvt/classCvt
TOBIN ?= $(SELF)/../../classCvt/tobin
OUTPUT ?=
### Comment: Defining CMD.
ifeq ($(BUILD), just_filelist)
CMD = echo
else
ifeq ($(BUILD), PC)
CMD = echo
else
ifeq ($(BUILD), unopt)
CMD = $(TOBIN)
else
### Comment: Optimized CMD = tobin -c ccvt
CMD = $(TOBIN) -c $(CCVT)
endif
endif
endif
ifeq ($(OUTPUT), )
OUT = &1
else
OUT = $(DIR)/$(OUTPUT)
endif
ifeq ($(SKIPSELF), yes)
MYCLASS =
else
MYCLASS = $(DIR)/Applications/$(CLASS).class
endif
all:
CLASSPATH=$(SELF)/RT/real:$(SELF)/RT/fake:$(DIR) javac $(DIR)/Applications/$(CLASS).java
find $(SELF)/RT/real -iname "*.class" -type f > $(SELF)/files
ls $(DIR)/Applications/*.class | grep -v "$(CLASS)\.class" >> $(SELF)/files || true
cat $(SELF)/files | xargs $(CMD) $(MYCLASS) >$(OUT)
rm -f $(SELF)/files
What I would like to do is give a command like:
make default CLASS=Test1,Test2,Test3
and the makefile to process it for the 3 classes and put the given classes in a .txt and the default classes in a different .txt, something like this like this:
pc: $(APP)
make -C BUILDENV default_classes BUILD=list_default_classes OUTPUT=list_default_classes.txt
# make -C BUILDENV given_classes BUILD=list_given_classes OUTPUT=list_given_classes.txt CLASS=$(CLASS) SKIPSELF=yes
../classCvt/classCvt `cat list_given_classes.txt`./Applications/$(CLASS).ujc
#here the list_given_classes should now contain the .ujc files
time -p ./$(APP) `cat list_given_classes.txt` `cat list_default_classes.txt`
and for the makefile in the BUILDENV, I expect something like:
default_classes:
CLASSPATH=$(SELF)/RT/real:$(SELF)/RT/fake:$(DIR)
find $(SELF)/RT/real -iname "*.class" -type f > $(SELF)/files
ls $(DIR)/Applications/*.class | grep -v "$(CLASS1)\.class" "$(CLASS2)\.class">> $(SELF)/files || true
cat $(SELF)/files | xargs $(CMD) >$(OUT)
rm -f $(SELF)/files
given_classes:
javac $(DIR)/Applications/$(CLASS).java
find $(SELF)/RT/real -iname "*.class" -type f > $(SELF)/files
ls $(DIR)/Applications/*.class | grep -v "$(CLASS)\.class" >> $(SELF)/files || true
cat $(SELF)/files | xargs $(CMD) $(MYCLASS) >$(OUT)
rm -f $(SELF)/files
However, I'm not sure how to do this for a CLASS parameter containing multiple classes.
I'm thinking to try and parse the Test1,Test2,Test3 value into a list of 1,2,3 and then iterating over it. But no clue if this is a good way and even on how to do it.
What do you guys suggest?
Pretty way:
pc: $(APP)
define BUILD_CLASS
pc: pc-$(CLASS_SPLIT)
pc-$(CLASS_SPLIT):
make -C BUILDENV CLASS=$(CLASS_SPLIT) BUILD=just_filelist OUTPUT=filelist.txt SKIPSELF=yes
../classCvt/classCvt <./Applications/$(CLASS_SPLIT).class> ./Applications/$(CLASS_SPLIT).ujc
time -p ./$(APP) ./Applications/$(CLASS_SPLIT).ujc `cat filelist.txt`
endef
CLASSES := $(shell echo $(CLASS) | tr ',' ' ')
$(foreach CLASS_SPLIT, $(CLASSES), $(eval $(BUILD_CLASS)))
Simple way:
pc: $(APP)
$(foreach C, $(shell echo $(CLASS) | tr ',' ' '), \
make -C BUILDENV CLASS=$(C) BUILD=just_filelist OUTPUT=filelist.txt SKIPSELF=yes && \
../classCvt/classCvt <./Applications/$(C).class> ./Applications/$(C).ujc && \
time -p ./$(APP) ./Applications/$(C).ujc `cat filelist.txt` &&) true

Bash command in Makefile

I am trying to get the basename of filenames in Makefile; but it always fails: basename command does not work.
Here is my code:
list = a.xlib b.lib
all:
for each_lib in $(notdir $(list)); \
do \
if [[ $$each_lib == *.xlib ]]; then \
*** Here I need to get the basename of $$each_lib to some variable, say base_lib *** \
cp -p $$base_lib-un.xlib ../../dist/lib/$$each_lib \
else \
cp -p $$each_lib ../../dist/lib/$$each_lib \
fi; \
done;
If we can create a variable with the value of basename of each file in list, that would be perfect.
Thanks.
$(basename ...) is a make function. It cannot operate on shell variables, because they are expanded later than make commands. You can use the shells $(...) substitution, but you have to double the dollar sign, so makefile does not interpret it as a function.
See if one of the following options does what you want:
list = a.xlib b.lib
libs = $(filter-out %.xlib,$(list))
xlibs = $(filter %.xlib,$(list))
V ?= #
allsh:
$(V)for each_lib in $(notdir $(libs)); do \
echo cp -p $$each_lib ../../dist/lib/$$each_lib; \
done;
$(V)for each_lib in $(notdir $(xlibs)); do \
base_lib="$$(basename $$each_lib .xlib)"; \
echo cp -p $$base_lib-un.xlib ../../dist/lib/$$each_lib; \
done;
xlibsstripped = $(patsubst %.xlib,%,$(xlibs))
allmake:
$(V)for each_lib in $(notdir $(libs)); do \
echo cp -p $$each_lib ../../dist/lib/$$each_lib; \
done;
$(V)for each_lib in $(notdir $(xlibsstripped)); do \
echo cp -p $$each_lib-un.xlib ../../dist/lib/$$each_lib.xlib; \
done;
Run with make allsh/allmake V= to see the commands being run.
If what you want to do is get the basenames, I'm surprised that basename doesn't work. (What version of Make are you using?) Note that it is a Make function, so it goes outside the rules:
list = a.xlib b.lib
BASES = $(basename $(list))
You can do it with other Make functions (note the colons):
list := a.xlib b.lib
list := $(patsubst %.lib,%,$(list))
list := $(patsubst %.xlib,%,$(list))
If what you really want to do is move the files and modify the names of the xlib files (a-un.xlib => .../a.xlib), there's an easier way:
targets := $(addprefix ../../dist/lib/,$(list))
all: $(targets)
../../dist/lib/%.lib: %.lib
mv $< $#
../../dist/lib/%.xlib: %-un.xlib
mv $< $#

error during the compilation of a source code: No such file or directory

I am getting an error during compilation of a source code. I searched it but fail to find name of package which fix the problem.
Error
ls: cannot access /lib/modules/3.5.0-17-generic/source: No such file or directory
source code of make file
# Makefile for bcm_wimax module
# Customized for ZTE AX226
# Makefile recreated be Minhazul Haq Shawon
KERNEL_VER := $(shell uname -r)
KDIR := /lib/modules/$(KERNEL_VER)/build
KSRC := /lib/modules/$(KERNEL_VER)/source
INSTALL_DIR := /lib/modules/$(KERNEL_VER)/kernel/drivers/staging/bcm/
TARGET_DRV := bcm_wimax
EXTRAFLAGS := -Wall O=$(KDIR)
PWD:= $(shell pwd)
obj-m = $(TARGET_DRV).o
$(TARGET_DRV)-objs :=InterfaceDld.o InterfaceIdleMode.o InterfaceInit.o InterfaceRx.o \
InterfaceIsr.o InterfaceMisc.o InterfaceTx.o \
CmHost.o IPv6Protocol.o Qos.o Transmit.o\
Bcmnet.o DDRInit.o HandleControlPacket.o\
LeakyBucket.o Misc.o sort.o Bcmchar.o hostmibs.o PHSModule.o\
led_control.o nvm.o vendorspecificextn.o
default:
$(MAKE) $(EXTRAFLAGS) -C $(KSRC) SUBDIRS=$(PWD) modules
rm -f *.o *.mod.* .*.cmd
install:
cp $(TARGET_DRV).ko $(INSTALL_DIR)
clean:
find . -name \*.o -exec rm -rf '{}' ';'
find . -name .\*.o.cmd -exec rm -rf '{}' ';'
find . -name \*.*~ -exec rm -rf '{}' ';'
find . -name \*.*.bak -exec rm -rf '{}' ';'
rm -f *.ko *.o *.mod.* .*.cmd
rm -fr .tmp_versions
rm -rf Module.symvers
You have to compile kernel source first.

Resources