Makefile get calling rule name - makefile

I am trying to create a makefile so when calling it the syntax will be make release or make debug.
In order to do so, I have composed the following makefile:
release debug: mode := $#
release debug: build
build:
*** actual build commands using $(mode) ***
But in the making process, when reaching the build rule, $(mode) seems to be empty.
Is there a better/proper build debug and release binaries?

The '$#' automatic variable is only available when building a target. It does not have a value when a rule is evaluated. As a result '$#' is not set during the execution of the line:
release debug: mode := $#
Consider setting up rules for 'build' and 'release'
release debug:
$(MAKE) build mode=$#
build:
Or the alternative (which I think is less intuitive, but more efficient):
release: mode=release
debug: mode=debug
build:
...

Related

Is there a way to get the info from which makefile target is being running

I have huge code base that includes huge number of makefiles. I am trying to understand the flow. For that i am running make command with debug flags (--debug=basic) to get the information like what is the order of targets being executed.
build command:- make --debug=basic release
Here is the debug info:-
File 'release' does not exist.
Must remake target 'release'.
File 'all' does not exist.
File 'copy_exports_files' does not exist.
File '/test/sw/modules/bin/ctk' does not exist.
Must remake target '/test/sw/modules/bin/ctk'
...
I can see flow of the targets being triggered. But I want to understand from which makefile the target is being triggered. Is there a way to log that info? Because its been hard to find where one makefile include other and soo on.
Thanks!
Try make --debug=verbose release

Non phony target behaves like a phony target

I am working on a boot project. In my boot root directory there is a makefile that contains among other things, the following code which confuse me:
.DEFAULT_GOAL = all
.PHONY: all
all: xboot
xboot: $(TOP_DIR)/boot
#echo "Building Boot" $(TOP_DIR)
$(MAKE) -C $(TOP_DIR)/boot/src
Now, the problem is, that any time when this makefile is executed by calling make, the xboot receipt is always running. It seems that this xboot target acts like a phony target. From GNU Documentation regarding phony targets:
Phoniness is not inherited: the prerequisites of a phony target are
not themselves phony, unless explicitly declared to be so.
Means that xboot target is not a phony one, but it's receipt is always running. I could not find anywhere an explanation for that.
Project facts-
directory $(TOP_DIR)/boot contains sources and headers under $(TOP_DIR)/boot/src and $(TOP_DIR)/boot/include, directory $(TOP_DIR)/boot does not get touched at the build (it is not get updated)
Trying to understand the behavior I played around-
I tried touching $(TOP_DIR)/boot, and/or tried touching and creating file xboot file anywhere in the project, but behavior remains the same.
GNU Make 4.1
Built for x86_64-pc-linux-gnu
make is not always handling folder dependencies the way you expect.
Should use a file dependency inside $(TOP_DIR)/boot like $(TOP_DIR)/boot/.exists or, even better, all your source files with a $(wildcard ...) function.
Like:
xcode: $(widcard $(TOP_DIR)/boot/src/*.c $(TOP_DIR)/boot/src/*.h)
This will cause a rebuild only on code change.

How to configure Makefile to support build for all/multiple artifact types

What is the general best practice for creating a Makefile to support building for a specific type of artifact as well as support for building all artifact types in one command.
For example, let's say there is a Makefile which supports building of a app on a specific OS:
make app OS="Windows"
make app OS="Linux"
make app OS="Mac"
Let us say that the Makefile looks something like:
my-other-dependency:
...
# Performs commands specific to $(OS)
my-dependency: my-other-dependency
...
# Performs commands specific to $(OS)
app: my-dependency
...
# Performs commands specific to $(OS)
To build all artifacts, one can invoke these 3 commands sequentially:
make app OS="Windows"
make app OS="Linux"
make app OS="Mac"
What is a recommended structure of the Makefile to support an all in one command such as:
make app # build all artifact types (Windows, Linux, Mac)
or
make app OS="all" # build all artifact types (Windows, Linux, Mac)
Or is there something wrong with the pattern above? I am open to any suggestions. Thank you!
I would use make recursion. Create a new target like all-os or something:
.PHONY: all-os
all-os:
$(MAKE) app OS=Windows
$(MAKE) app OS=Linux
$(MAKE) app OS=Mac
ETA This is another option, that uses a separate target named for each OS to allow parallel builds:
OSLIST := Windows Linux Mac
_ostargets := $(addprefix app-,$(OSLIST))
$(_ostargets): app-%:
$(MAKE) app OS=$*
app-all: $(_ostargets)
.PHONY: app-all $(_ostargets)
You can also now run make app-Windows instead of make app OS=Windows, if you prefer.

How to specify priority in makefile

I have a makefile and several targets there. I want to clean directory first, then build directories and then run compilation of tasks1..4. Sometimes building directories starts after compilation and this makes compilation impossible.
Makefile in general looks like:
release: clean
release: build
release: task1 task2
release: task3 task4
Clean and build must be finished before tasks1..4 start running. In other words how to specify priority in makefile tasks. Now seems all 4 lines from the makefile start altogether in one moment.
I'm assuming you're using -j; without parallel builds enabled make will never start any rules together: it always runs them one at a time in the order the prerequisites are listed.
The only way to specify order is via prerequisites. So, this would look like:
release: task1 task2 task3 task4
task1 task2 task3 task4: build
build: clean
However, this last step is a very bad idea: you don't want your build target to depend on clean in general, otherwise it will always be run. You can either ask people to run clean by hand, but probably the most common way to deal with release targets like this is with make recursion:
release:
$(MAKE) clean
$(MAKE) build
$(MAKE) task1 task2 task3 task4

Build are not tagged as unstable when unit test fails

I have added a new job in my hudson server which builds the project with a makefile.
Execute shell command:
#!/bin/bash
cd $JOB_NAME
make
My makefile looks like this
SDK_31 = iphonesimulator3.1
TARGET_DEV = myProject
TARGET_TEST = unitTest
all: debug
debug:
xcodebuild -sdk ${SDK_31} -target "${TARGET_DEV}" -configuration Debug
xcodebuild -sdk ${SDK_31} -target "${TARGET_TEST}" -configuration Debug
clean:
xcodebuild -alltargets clean
rm -rf build
But when hudson build the projects, some unit tests fail but the build is tagged as successful.
What should I have to do to have an "unstable project" ?
Best regards,
You should configure Hudson to record unit test results, by enabling the 'Publish Junit test result report' post-build action.
post-build actions http://img141.imageshack.us/img141/5136/hudsonjunit.png
Update: If you can't get JUnit XML output, you should be able to use the Text-finder plugin to change the build status:
This plugin lets you search keywords in the files you specified and use that to mark the build as success or a failure.
I found this handy ruby script by Christian Hedin that converts the output of OCUnit tests (the format used by Xcode) into JUnit xml files (the format used by Hudson).
You can grab the script on github:
http://github.com/ciryon/OCUnit2JUnit
and for an explanation of how to use it, here's his blog post about it:
http://blog.jayway.com/2010/01/31/continuos-integration-for-xcode-projects/
Basically, you pipe xcodebuild into ocunit2junit.rb with a command like this:
/usr/bin/xcodebuild -target UnitTests | /usr/local/bin/ocunit2junit.rb
and it places the xml files into a test-reports folder that it creates at the root of your project folder. Then tell Hudson to copy the test-reports/*.xml artifacts as the JUnit results and you're set.
This setup will allow Hudson to correctly identify if a unit test has passed or failed and correctly mark the stability of the build.
I've been using it for a month now and it works great. The setup was very simple.

Resources