Export preprocessor macro in makefile - gcc

I want to export preprocessor macro to an internal makefile from the main makefile in a particular target.
example:
Main_Makefile
target1 :
CXXFLAGS+=-DNewFlag=NewFlag
cd some_directory; make
Here I want to use value of CXXFLAGS which is -DNewFlag=NewFlag and is only defined under target1 in some_directory/make
Please let me know how can I achieve this.

There is no way to append to a variable from the command line, unless you've made arrangements for it in the makefile of the subdirectory.
The simplest thing to do is use a different variable, like this:
target1:
cd some_directory && $(MAKE) EXTRA_CXXFLAGS=-DNewFlag=NewFlag
(note you should always use $(MAKE) or ${MAKE} when invoking a sub-make, never make directly.)
Then in the subdirectory makefile you do something like this:
CXXFLAGS += $(EXTRA_CXXFLAGS)

Related

How can I add a directory to the search path of GNU Make?

I have a makefile that looks something like this:
include anotherFile.mk
all:
someStuff
The file anotherFile.mk is like this:
include yetAnotherFile.mk
export SOME_VAR = 93
The problem is that anotherFile.mk and yetAnotherFile.mk are in a different directory from my Makefile. So my makefile can't just be changed to this:
include $(OTHER_PROJECT_PATH)/anotherFile.mk
all:
someStuff
The problem with this approach is that the include statement in anotherFile.mk will fail because it will be searching in the current directory.
A partial solution that I found is to pass the --include-dir=$OTHER_PROJECT_PATH flag to the invocation of make, but that's a bit user-unfriendly.
So my question is: Is there something I can put inside my makefile that will add to the directories that make searches for when executing an include? Something like MAKE_INCLUDE_DIRS += $(OTHER_PROJECT_PATH)
Surprisingly there doesn't seem to be a good answer to that question. Forcing .INCLUDE_DIR doesn't help and there doesn't seem to be any way around invoking make with --include-dir=$OTHER_PROJECT_PATH.
It is however possible to put the appropriate recursive make invocation inside the makefile but, in order to get it to work for all reasonable cases it quickly becomes too complicated to be worth it. In summary it requires:
a top level condition to check if the OTHER_PROJECT_PATH is in .INCLUDE_DIR
the appropriate target with the recipe invoking make recursively
possibly additional targets if there are multiple command goals
the real make file enclosed in the else part of the conditional
You Makefile would look like this:
OTHER_PROJECT_PATH := other
ifeq (,$(filter $(OTHER_PROJECT_PATH), $(.INCLUDE_DIRS)))
# this is the mechanism to add the include dir in a recursive make
$(or $(firstword $(MAKECMDGOALS)),all):
$(MAKE) -I$(OTHER_PROJECT_PATH) $(MAKECMDGOALS)
# add empty targets for additional goals if needed
ifneq (,$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)))
$(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)):
endif
else
# this is where the real makefile starts
all more:
echo $#: $< $^
include a.mak
endif
It still does not seem possible from a makefile, but if you have a script that sets up environment variables, you can use MAKEFLAGS (e.g. export MAKEFLAGS=I/your/path ordentlich on Linux, or SET on Windows)

calling sub makefiles in an easy way fails

I`m using a makefile and call some makefiles in subdirectories.
Can anyony explain me, why this works
$(MAKE) -C stub
$(MAKE) -C source
but this not
SUBDIRS = stub source
$(SUBDIRS):
$(MAKE) -C $#
First time I`m working with makefiles.
When you do not explicitly specify the target(s) to make, it will use the first target whose name doesn't start with a dot. Here, that target is stub.
Apparently, you expect all of the targets of the first rule to be used, but there can only be one default target.
The documentation isn't 100% clear on this.
You will get the desired behavior by prepending the rule:
all: $(SUBDIRS)

using the same make file in a separate directory

I have a makefile in directory foo and would like to use the same makefile in a subdirectory bar. I have been doing the following:
all:
<do work in foo>
cd bar;
make -f ../Makefile <target to make in bar>
This gets very messy when I try to do target specific variable values as I need to pass them on the command line when calling make in bar. Is there a cleaner way to do this?
I cannot tell from the question whether the following solution suites your needs, it might - or might not - work for you.
If your situation is that you simply want the same Makefile features available, include could be a solution. You can create a Makefile in directory bar in which you do everything you need specific to bar, and besides that, you do:
include ../foo/Makefile
Caveat! This doesn't work straight-forward. There cannot be two recipes with the same name. For example, if you want foo/Makefile to do recipeBar for all, and you want foo/Makefile to do recipeFoo and recipeBar for all, the following does not work:
foo/Makefile:
.PHONY: all
all:
recipeFoo
bar/Makefile:
.PHONY: all
all:
reciveBar
include foo/Makefile
Instead, the recipes have to be separated into unique names. However, dependency rules can be there multiple times, so it's not really a challenge to workaround this caveat. So, the following would work:
foo/Makefile:
.PHONY: all
all: allFoo
.PHONY: allFoo
allFoo:
recipeFoo
bar/Makefile:
.PHONY: all
all: allBar
.PHONY: allBar
allBar:
recipeBar
include foo/Makefile
Now, if you run make in bar, it would run recipeFoo and recipeBar.
If the sequence matters to you and recipeFoo must run before recipeBar, make allBar dependent on allFoo, like this:
bar/Makefile:
.PHONY: all
all: allBar
.PHONY: allBar
allBar: allFoo
recipeBar
include foo/Makefile
If you want your target-specific variables available when you call another make (for which I recommend to use $(MAKE) not make), you can export your variables - with the corresponding consequences (environment space overflow risk on some Windows versions, .
For example, if you have a target-specific variable FOO for target all in Makefile, and you want that when calling Submake.mak that variable is known, it works like this:
Makefile:
all: export FOO:=bar
.PHONY: all
all:
$(MAKE) -f Submake.mak
Submake.mak:
.PHONY: all
all:
echo $(FOO)
Create a link (hard or symbolic, your choice) in bar to ../Makefile. Then, as Carl points out in his comment, you can make -C bar and everything should work. (As of gmake 3.81, at least, make switches to the new directory first, then does its thing. I cannot speak for gmake 4.0.)

How to handle different targets for same directories in parallel making

The question is about parallel making w/ GNU makefile.
Given a folder structure as below, the goal is to deliver a makefile that it supports make release/debug/clean in parallel.
project folder structure:
foo
+-foo1
+-foo2
+-foo3
The makefile may be sth like:
SUBDIR = foo1 foo2 foo3
.PHONY $(SUBDIR) release debug clean
release: $(SUBDIR)
$(SUBDIR):
$(MAKE) -C $# release
debug: $(SUBDIR)
#below is incorrect. $(SUBDIR) is overriden.
$(SUBDIR):
$(MAKE) -C $# debug
..
Sub directory list are set as phony targets for parallel making. but it lost the information of original target (release, debug, clean etc).
One method is to suffix the names for the directories and recover it in commands, but it is weird. another method might be to use variables, but not sure how to work it out.
The questions is:
How to write the rules for directories, that supports parallel making w/ different targets (release/debug/clean)?
Any hints are greatly appreciated.
Setting variables on the command line certainly works. You can also use MAKECMDGOALS (see the GNU make manual):
$(SUBDIR):
$(MAKE) -C $# $(MAKECMDGOALS)

Compiling with different flags in Makefile?

I have a single program used to interact with a joystick. It uses conditional compilation to specify a specific joystick. We do this right now by just hard coding the correct flag into the Makefile.
I'd like to make it so it uses a different flag based on the command given to the Makefile. So for example, I currently have this:
.PHONY: saitek
saitek: $(SOURCES)
$(COMPILE) -DSAITEK
.PHONY: logitech
logitech: $(SOURCES)
$(COMPILE) -DLOGITECH
I want only one of these commands to ever be run, and I want them all to make the same executable. But if I rerun 'make' it will compile the program again. I'd like it to recognize that it's already built the program.
Is there anyway to do this with a Makefile?
If you're using GNUMake, this will do what you're asking. It uses a different flag based on the command given to Make, and it doesn't rebuild the program unnecessarily.
.PHONY: saitek logitech
saitek: JOYSTICK=SAITEK
logitech: JOYSTICK=LOGITECH
# Suppose the actual name of your executable is "program"
saitek logitech: program
program: $(SOURCES)
$(COMPILE) -D$(JOYSTICK)
GNU make inherits variables from its environment, so if you specify
$ JOYSICK=LOGITECH
in your shell, and use
CFLAGS+=-D$(JOYSTICK)
in your makefile.
I question the necessity of this. You could just call make as something like make CFLAGS=-DSAITEK or use autoconf and substitute in the correct defines.
That said, how about something like this:
saitek logitech: program
.PHONY: saitek logitech
ifeq ($(MAKECMDGOALS),saitek)
CFLAGS += -DSAITEK
endif
ifeq ($(MAKECMDGOALS),logitech)
CFLAGS += -DLOGITECH
endif
program: $(OBJS)
# Whatever

Resources