Makefile tree for debug/test/release builds with multiple targets - makefile

Structure:
makefile
system/
-> makefile
-> kernel/
-> -> makefile
-> -> src/
-> FutureModules
-> -> makefile
-> -> src/
userland/
-> makefile
-> FutureModules
-> -> makefile
-> -> src/
Currently I'm building it with make system.
I'd like to split it up into Debug/Test/Release builds so that i can do something like make debug system or make -d system with multiple targets (e.g. make debug system userland or something like that).
I'd like to change the targets so i can directly build a target instead of building system and manually have to add the desired targets in system/makefile.
Now in order to achieve this:
Do constants get shared between makefiles? So when i do make system and i define CFLAGS += -g -Og in the root makefile, does the system/makefile get the constants from the root makefile?
Do constants stay the same in a make session? So when i do make debug system userland and have something like debug: CFLAGS += -g -Og, do system and userland get the -g -Og flags?
EDIT: I managed to achieve 2. by using $(shell find -maxdepth 1 -type d) and some other commands.

Solved it with:
#Build mode. m=d => Debug | m=t => Test | m=r => release | default => release
ifeq ($(m), d)
NASBUILD = $(NASDEBUG)
GASBUILD = $(GASDEBUG)
CPPBUILD = $(CPPDEBUG)
CBUILD = $(CDEBUG)
else ifeq ($(m), t)
NASBUILD = $(NASTEST)
GASBUILD = $(GASTEST)
CPPBUILD = $(CPPTEST)
CBUILD = $(CTEST)
else ifeq ($(m), r)
NASBUILD = $(NASRELEASE)
GASBUILD = $(GASRELEASE)
CPPBUILD = $(CPPRELEASE)
CBUILD = $(CRELEASE)
else
NASBUILD = $(NASRELEASE)
GASBUILD = $(GASRELEASE)
CPPBUILD = $(CPPRELEASE)
CBUILD = $(CRELEASE)
endif
export NASBUILD
export GASBUILD
export CPPBUILD
export CBUILD
Where xxxBUILD and so on gets added to the corresponding xxxFLAGS.

Related

Conditional variable assignement in makefile target

I'm trying to get conditional assignment in a makefile target, only if it was not set by the requiring target:
REPO_PROD = prod
REPO_DEV = dev
.PHONY: ko-build-container
ko-build-container: KO_DOCKER_REPO ?= $(REPO_PROD)
ko-build-container:
#echo $(KO_DOCKER_REPO)
.PHONY: ko-build-container-dev
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container
Unfortunately make ko-build-container-dev prints prod.
What am I missing here ?
Another alternative is to use a third target, like:
ko-build-container-base:
echo $(KO_DOCKER_REPO)
ko-build-container: KO_DOCKER_REPO = $(REPO_PROD)
ko-build-container: ko-build-container-base
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container-base
Apparently, with GNU make, the outcome of the conditional assignment (assign or not assign) is decided in a phase where only global variables are available, but the selection of the final value comes from a later phase where inherited target-specific variables are also available. So, even more bizarre than what you observed, after skipping a conditional assignment because a global variable was set, the final value is not necessarily that of the global variable, it can be inherited from a parent target! Demo:
$ cat Makefile
.PHONY: sub all
all: VAR = all
all: sub
# no global VAR set => assign instead of using inherited VAR = all
sub: VAR ?= sub
sub:
#echo $(VAR)
$ make
sub
$ cat Makefile
.PHONY: all
VAR = global
# global VAR set => do not assign, use global VAR = global
all: VAR ?= all
all:
#echo $(VAR)
$ make
global
$ cat Makefile
.PHONY: sub all
VAR = global
all: VAR = all
all: sub
# global VAR set => do not assign... but use inherited VAR = all
sub: VAR ?= sub
sub:
#echo $(VAR)
$ make
all
This strange behavior is reported here: https://savannah.gnu.org/bugs/?18305 and there is also a discussion about whether it should/could be fixed.
Separating the outcome from the selection of the value in conditional assignments is clearly a bug, I think. Nobody would imagine such a weird behavior. Anyway, instead of a target-specific conditional assignment you could use the workaround suggested in the discussion:
$ cat Makefile
REPO_PROD = prod
REPO_DEV = dev
.PHONY: ko-build-container
ko-build-container:
#echo $(or $(KO_DOCKER_REPO),$(REPO_PROD))
.PHONY: ko-build-container-dev
ko-build-container-dev: KO_DOCKER_REPO = $(REPO_DEV)
ko-build-container-dev: ko-build-container
$ make ko-build-container-dev
dev

tinydtls configuration in Contiki

I am currently trying to configure tinydtls as described in the README in order to later include it into an application, or at least, make the examples run.
The first steps, including the resulting warnings:
home/name/contiki/apps/tinydtls$ autoreconf
aclocal: warning: autoconf input should be named 'configure.ac', not 'configure.in'
home/name/contiki/apps/tinydtls$ ./configure --with-contiki
home/name/contiki/apps/tinydtls$ make
with both TARGET=native and TARGET=zoul
The compilation always ends with (many) undefined reference errors:
obj_zoul/dtls.o: In function dtls_add_ecdsa_signature_elem':
dtls.c:(.text.dtls_add_ecdsa_signature_elem+0x10): undefined reference to `dtls_ec_key_from_uint32_asn1'
dtls_ec_key_from_uint32_asn1 is located in contiki/apps/tinydtls/crypto.c.
Adding #include crypto.h in dtls.c doesn't fix the problem, but #include crypto.c does (fix this first error). Accordingly I assume the problem must have to do something with the linking.
How should the Makefile, of which I pasted a (hopefully significant) part under this question, be adjusted?
SHELL = /bin/sh
MKDIR = mkdir
ETAGS = /bin/false
prefix = /usr/local
exec_prefix = ${prefix}
abs_builddir = /home/name/contiki/apps/tinydtls
top_builddir = .
libdir = ${exec_prefix}/lib
includedir = ${prefix}/include/tinydtls
package = tinydtls-0.8.2
install := cp
# files and flags
SOURCES:= dtls.c crypto.c ccm.c hmac.c netq.c peer.c dtls_time.c session.c
ifneq ("", "1")
SOURCES += debug.c
endif
SUB_OBJECTS:=aes/rijndael.o ecc/ecc.o sha2/sha2.o
OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) $(SUB_OBJECTS)
HEADERS:=dtls.h hmac.h debug.h dtls_config.h uthash.h numeric.h crypto.h global.h ccm.h \
netq.h t_list.h alert.h utlist.h prng.h peer.h state.h dtls_time.h session.h \
tinydtls.h
CFLAGS:=-Wall -pedantic -std=c99
CPPFLAGS:= -DDTLSv12 -DWITH_SHA256 -DDTLS_CHECK_CONTENTTYPE
SUBDIRS:=tests doc platform-specific sha2 aes ecc
DISTSUBDIRS:=$(SUBDIRS) examples/contiki
DISTDIR=$(top_builddir)/$(package)
FILES:=Makefile.in configure configure.in dtls_config.h.in tinydtls.h.in \
Makefile.tinydtls $(SOURCES) $(HEADERS)
LIB:=libtinydtls.a
LDFLAGS:=
ARFLAGS:=cru
doc:=doc
Edit: Changed the directory for this post to /home/name/...
Edit2: Added warnings after 'autoreconf'.

run a target always along with default target

I have a default target "all" but I want to initialize a few variables ever time I run the makefile . whatever is the target for make flow.
cat Makefile
all: last_step
initialize:
ifeq (,$(filter $(ps),0 1))
#$(eval override ps=0)
endif
step1:
<>
step2: step1
<>
....
last_step: second_last_step
<>
I want to initialize the variable every time a make file is run .
initialize target should be run in both the following flow styles.
make .
make nth-step
Nothing easier:
ifeq (,$(filter $(ps),0 1))
override ps=0
endif
all: last_step
...
step1:
...
...

GNU Make: How to perform second expansion with suffix-changing substitution

What I'm going for (what's failing)
I have a list of dependencies for each file:
point_deps =
bounds_deps = point
triangle_deps = point bounds
Image_deps = types bounds triangle
main_deps = Image triangle bounds point types
I'd like to write a rule to include the relevant dependencies. Here's my best attempt:
out/%.o: src/%.cpp src/%.h $$($$*_deps:%=src/%.h)
g++ -o $# -c $<
I expect $* to evaluate to, for instance, "main". Then the suffix-changing substitution should change each entry in the dependency list to begin with "src/" and end with ".h".
When I try to run the code above, I get an error (on the out/%.o line):
makefile:26: *** multiple target patterns. Stop.
What's working (non-optimal)
For now I have to create a separate variable for each file's header dependencies:
point_deps_h = $(point_deps:%=src/%.h)
bounds_deps_h = $(bounds_deps:%=src/%.h)
triangle_deps_h = $(triangle_deps:%=src/%.h)
Image_deps_h = $(Image_deps:%=src/%.h)
main_deps_h = $(main_deps:%=src/%.h)
Then I can use secondary-expansion to include the correct header files:
out/%.o: src/%.cpp src/%.h $$($$*_deps_h)
g++ -o $# -c $<

Compiling C++ with textmate

I have problem with compiling cpp that include another cpp files
so I have Main.cpp Numbers.h and Numbers.cpp and it seems that TextMate only compile my Main.cpp and doesn't include the rest. I tried using xcode and it was working fine..
Here is the error from TextMate cmd+R:
Undefined symbols:
"Numbers::Numbers(int)", referenced from:
_main in ccMrD1Eq.o
"Numbers::print()", referenced from:
_main in ccMrD1Eq.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Any suggestion?
Btw, here is the invoked command:
#!/usr/bin/env ruby
require ENV["TM_SUPPORT_PATH"] + "/lib/tm/executor"
require ENV["TM_SUPPORT_PATH"] + "/lib/tm/save_current_document"
mode = ENV["TM_SCOPE"].slice(/.*?\bsource\.((?:obj)?c(\+\+)?)/, 1)
case mode
when "c"
g = "GCC"
env = "C"
ext = "c"
lang = "c"
when "c++"
g = "GXX"
env = "CXX"
ext = "cc"
lang = "c++"
when "objc"
g = "GCC"
env = "OBJC"
ext = "m"
lang = "objective-c"
when "objc++"
g = "GXX"
env = "OBJCXX"
ext = "mm"
lang = "objective-c++"
end
TextMate.save_current_document(ext)
TextMate::Executor.make_project_master_current_document
flags = ENV["TM_#{env}_FLAGS"] || "-Wall -include stdio.h #{"-include iostream" unless mode[/c\+\+$/].nil?} #{"-framework Cocoa" unless mode[/^obj/].nil?}"
args = [ENV["TM_#{g}"] || g.downcase.gsub("x", "+"), flags + " -x #{lang}", ENV["TM_FILEPATH"]]
TextMate::Executor.run(args, :version_args => ["--version"], :version_regex => /\A([^\n]*) \(GCC\).*/m)
TextMate only does a simple compile of the .cpp file you're currently editing. Unlike Xcode or other full development environments it won't compile other source files in the project or perform linking.
(In TextMate click Bundles > Bundle Editor > Show Bundle Editor, then choose Run in the C section and you'll see exactly what TextMate is doing when you "Run" a .cpp file.)
You probably need to add additional command line parameters...
You can add additional command line parameters to g++ by altering the variable TM_CXX_FLAGS.
The best way to do this is probably to add a per project variable:
http://manual.macromates.com/en/environment_variables#project_dependent_variables
If the change is meant to be global you can add it to TextMate's static vars section
http://manual.macromates.com/en/environment_variables#static_variables
i don't have enough info to be certain of the command you're invoking.
if it's Xcode.tmbundle Build and Run, then it's invoking xcodebuild -- you should be able to reproduce and fix the error in Xcode.

Resources