set numbers of variables for recursive make using another makefile - makefile

I am new to makefile and I am recursively calling make to build my libraries. I need to setup "n" number of variables to build libraries. I tried adding in a file and include it in the makefile but it doesnot seems to be working.
where am I going wrong? what is the better approach to achieve this.
My main makefile :
include main_setup.mk
VER := $(shell getVersion)
main_setup:
//setupsteps
release:
$(MAKE) main_setup
$(MAKE) -j8 --output_sync=target build_main
build_main:import_a import_b import_c
import_a: build_a
//import_steps
import_b: build_b
//import_steps
import_c: build_c
//import_steps
build_a:
cd $aDir ; $(MAKE) -j4 build
import_a:
cd $bDir ; $(MAKE) -j4 build
import_a:
cd $cDir ; $(MAKE) -j4 build
my setup file: main_setup.mk
plat_prefix = /main
buildroot = $(plat_prefix)/submain/another
ifneq ('$(JAVA_PATH)','')
export PATH := $(JAVA_PATH):$(PATH)
endif
export BUILD_ROOT = $(buildroot)
ifneq ('$(LOCAL_BUILD_ROOT)','')
export BUILD_ROOT= $(LOCAL_BUILD_ROOT)
endif
export VAR1 = 1
export VAR2 = 2
export VAR3 = 3
export VAR4 = 4
export PATH := /var/main/bin:$(VAR1)/tools/bin:$(VAR2)/tools/bin:$(VAR3)/tools/bin:$(PATH)
Error :
/bin/bash: getVersion: command not found
which getVersion
/var/main/bin/getVersion
UPDATED THE QUESTION

Related

Iterating directories and conditions in makefiles

I have a repository structure where dependencies can either be svn:external'd either in this repository or in a super-repository which has svn:external'd this one. The externals are only one level deep and so if my repo is externalized by a super-repository, then I need to be able to detect where to find the dependency at a higher level, and copy over all relevant data. If the dependency is indeed found in my own repository, then I need to build it.
I am having problems creating my makefile recipe to do this. Here is what I have so far:
DEPENDENCIES = dep1 dep2
ROOTDIR = .
deps :
for dep in $(DEPENDENCIES); do \
if [ -e $(ROOTDIR)/ext/$$dep ]; then \
depdir = $(ROOTDIR)/ext/$$dep; \
$(MAKE) -C $depdir; \
elif [ -e $(ROOTDIR)/../$$dep ]; then \
depdir = $(ROOTDIR)/../$$dep; \
else \
$(error Could not find dependency: $$dep) \
fi \
cp $$depdir/bin/* $(ROOTDIR)/bin; \
cp $$depdir/lib/* $(ROOTDIR)/lib; \
cp $$depdir/inc/$$dep $(ROOTDIR)/inc/$$dep; \
done
First problem is the $(error ) line. I'd like to be able to throw an error, but this is clearly not subjected to the bash condition statements. This is the output:
$ make deps
makefile:108: *** Could not find dependency: $dep. Stop.
If I comment out that else statement, then I'm still having troubles
$ make deps
for dep in dep1 dep2; do \
if [ -e ./ext/$dep ]; then \
/bin/sh: -c: line 2: syntax error: unexpected end of file
make: *** [makefile:106: deps] Error 1
Could someone provide some hints regarding how to accomplish this? I'm running GNU make in both cygwin and linux environments.
Edit: I'd really prefer to keep this as close to make as possible (and as little shell stuff). I think I've gotten a little closer, but still need to repeat this for each item in $(DEPENDENCIES).
DEPENDENCIES = foo bar
ROOTDIR = .
EXTDIR = $(ROOTDIR)/ext
BINDIR = $(ROOTDIR)/bin
INCDIR = $(ROOTDIR)/inc
# Need a foreach DEP in $(DEPENDENCIES) here
ifneq("$(wildcard $(EXTDIR)/$(DEP))","")
DEPDIR = $(EXTDIR)/$(DEP)
BUILDDEP = $(MAKE) -C $(DEPDIR)/build
else ifneq("$(wildcard $(ROOTDIR)../$(dep))", "")
DEPDIR = $(ROOTDIR)/../$(dep)
else
$(error Could not find dependency: $(DEP))
endif
$(DEPDIR) :
$(BUILDDEP)
cp $(DEPDIR)/bin/* $(BINDIR)
cp $(DEPDIR)/inc/$(DEP)/* $(INCDIR)/$(DEP)
Edit2:
I think I'm getting closer. The following looks more like what I want, but it still have problems:
1) I don't know how to call each recipe
2) It doesn't give an error if it doesn't find all dependencies
3) It doesn't let me dictate the build order
4) It doesn't let me filter to use only folders listed in dependencies (it does all folders)
ifneq "$(wildcard $(EXTDIR)/%/build)" ""
$(EXTDIR)/%:
$(MAKE) -C $(EXTDIR)/%/build
cp $(EXTDIR)/%/bin/* $(BINDIR)
cp $(EXTDIR)/%/int/*.a $(INTDIR)
cp $(EXTDIR)/%/inc/%/* $(INCDIR)/%
endif
ifneq "$(wildcard $(ROOTDIR)/../%/build)" ""
DEPDIR = $(ROOTDIR)/..
$(DEPDIR)/%:
cp $(DEPDIR)/%/bin/* $(BINDIR)
cp $(DEPDIR)/%/int/*.a $(INTDIR)
cp $(DEPDIR)/%/inc/%/* $(INCDIR)/%
endif
Edit3
After being told I was trying to solve too many problems at once, I've reduced it to this:
DEPENDENCIES = dep1 dep2 dep3
for each DEP in $(DEPENDENCIES)
$(DEP) :
$(MAKE) -C ../ext/$(DEP)
How can I create a recipe ($(DEP) ) for each item in $(DEPENDENCIES)?
Solved. This solves the problem above:
DEPENDENCIES = dep1 dep2 dep3
$(DEPENDENCIES) :
$(MAKE) -C ../ext/$#
The answer is very simple. I wish I knew enough about this stuff to ask a more legible question.

Dynamically generating a list of targets

If a file exists, I want to add a target to build. If the file does not exist, I want the target to be skipped.
an example:
FILENAME = f
TARGETS := normal
ifneq($(shell stat test_$(FILENAME).c), "")
TARGETS += test
endif
all: $(TARGETS)
normal:
#echo normal
test:
#echo test
I'm not sure the $(shell stat ...) part even works, but the bigger problem is that make with any file test_f.c in the current folder gives:
Makefile:4: *** multiple target patterns. Stop.
Removing the ifneq ... endif block makes the target normal. How can I only run the target test if test_f.c exists?
What you can do is generate a string variable (let's call it OPTIONAL) such that when 'test_f.c' exists, OPTIONAL=test; otherwise, OPTIONAL=_nothing_. And then add OPTIONAL as a prerequisite of all. e.g.:
FILENAME = f
TARGETS = normal
OPTIONAL = $(if $(wildcard test_f.c), test, )
all: $(TARGETS) $(OPTIONAL)
normal:
#echo normal
test:
#echo test
You can also iterate over targets with for loop
.PHONY: all
RECIPES = one
all: RECIPES += $(if $(wildcard test_f.c), two, )
all:
for RECIPE in ${RECIPES} ; do \
$(MAKE) $${RECIPE} ; \
done
one:
$(warning "One")
two:
$(warning "Two")
> make
for RECIPE in one ; do \
/Applications/Xcode.app/Contents/Developer/usr/bin/make ${RECIPE} ; \
done
makefile:11: "One"
make[1]: `one' is up to date.
> touch test_f.c
> make
for RECIPE in one two ; do \
/Applications/Xcode.app/Contents/Developer/usr/bin/make ${RECIPE} ; \
done
makefile:11: "One"
make[1]: `one' is up to date.
makefile:14: "Two"
make[1]: `two' is up to date.

how to call a makefile target it it contain variable name?

If let's say target of makefile (i.e. $(SESSION)/compiled.csh) contains a variable name .. how can we call a makefile to run with that target ??
--------------calling makefile -------------------------
make \
-f makefile \
session_name=rtl_unit \
---------------- makefile content ----------------------
ifeq ($(MAKECMDGOALS), all)
DEFAULT_DEP := dep1 dep2
else
DEFAULT_DEP := dep1
endif*
export SESSION = $(TESTBENCH_PATH)/blocks/$(session_name)
$(SESSION)/compiled.csh : something
Just add another phony target and make it depend on your hard-to-spell target:
$(SESSION)/compiled.csh : something
compiled : $(SESSION)/compiled.csh
.PHONY: compiled
And then:
make compiled

Makefile set variable in target

I have a makefile where a variable $DEBUG decides whether to build for deployment or debugging. There is one main Makefile, and multiple platform-specific makefiles that get included. I want the variable $DEBUG to be set to 1 automatically when the target test is built.
The main makefile:
DEBUG := 0
test : override DEBUG := 1
DIST_DIR := dist/
ifeq ($(DEBUG), 1)
BUILD_DIR := build/debug
else
BUILD_DIR := build/deploy
endif
# detect operating system
ifeq ($(OS), Windows_NT)
UNAME := Windows
else
UNAME := $(shell uname -s)
endif
# include platform-specific Makefile
export
ifeq ($(UNAME), Darwin)
include Makefile.darwin
endif
ifeq ($(UNAME), Linux)
include Makefile.linux
endif
And the platform-specific Makefile.linux:
...
CXX := clang++-3.8
CXXFLAGS := -std=c++14 -fPIC -I./external/include -fcolor-diagnostics
LDFLAGS :=
LDLIBS := -lpthread -lm
ifeq ($(DEBUG), 1)
CXXFLAGS += -g
else
CXXFLAGS += -O3 -DNDEBUG
endif
...
all : $(TARGET)
test : $(TEST_TARGET)
$(TEST_TARGET)
So there are two rules for test: One in the main makefile sets the target-specific variable $DEBUG, and the one in Makefile.linux builds the test. The variables used for building ($CXXFLAGS, $BUILDDIR, and others) are set before the rules, and use conditionals.
Everything in the makefiles is working correctly, however calling make test does not alter the variable $DEBUG: both $CXXFLAGS and $BUILDDIR still get set to the values they would have for a deployment built.
Is there a way to first set $DEBUG := 1 in Makefile when the target is test, and then normally proceed?
Or is there a special variable that contains the target name, for example
ifeq ($(MAKEFILE_TARGET), test)
...
endif
test : override DEBUG := 1 doesn't work because it declares a target-specific variable that is only visible within that recipe.
There does exist a variable containing the target names that were specified at the command line: MAKECMDGOALS. Note that it doesn't include the default target if it wasn't explicitly specified at the command line.
Example makefile:
DEBUG := $(filter test,$(MAKECMDGOALS))
all:
#echo all : $(MAKECMDGOALS) : $(DEBUG) : $(if $(DEBUG),1,0)
test:
#echo test : $(MAKECMDGOALS) : $(DEBUG) : $(if $(DEBUG),1,0)
Usage:
$ make
all : : : 0
$ make all
all : all : : 0
$ make test
test : test : test : 1
$ make all test
all : all test : test : 1
test : all test : test : 1
One simple option is to have your test target recursively invoke make with DEBUG=1. That works with included makefiles as well. Example:
DEBUG := 0
test:
make DEBUG=1
DIST_DIR := dist/
...

Makefile - How to call other makefiles with dependencies

Hey, I have a simple "master" Makefile who simply calls other makefiles. I'm trying to do the following in order to build components in the right order:
LIB_A = folder_a
LIB_B = folder_b
LIB_C = folder_c
MY_TARGETS = $(LIB_A) $(LIB_B) $(LIB_C)
.PHONY: $(LIB_A)
$(LIB_A):
#$(MAKE) -C $#;
.PHONY: $(LIB_B)
$(LIB_B):
#$(MAKE) -C $#;
.PHONY: $(LIB_C)
$(LIB_C): $(LIB_A) $(LIB_B)
#$(MAKE) -C $#;
.PHONY: all
all: $(MY_TARGETS)
However, when I make, only LIB_A gets built.
(I don't even get a folder_b up-to-date message or whatever).
Any hint ?
You need to make all the default. You can do this in either of these ways:
move it to be the first target in the file
Add .DEFAULT_GOAL := all
Alternatively, you could run make all instead of just make.
Neil Butterworth solved the problem, but you can also make this makefile a little more concise:
LIB_A = folder_a
LIB_B = folder_b
LIB_C = folder_c
MY_TARGETS = $(LIB_A) $(LIB_B) $(LIB_C)
.PHONY: all $(MY_TARGETS)
all: $(MY_TARGETS)
$(MY_TARGETS):
#$(MAKE) -C $#;
$(LIB_C): $(LIB_A) $(LIB_B)

Resources