Using Makefiles In Nested Directories - makefile

A project that I am working on deals with multiple architectures. The code is divided into architecture specific and general modules (which can be shared between the architectures).
I am planning to organize the code as below
TOP
|
|---- Makefile
|
|---- src (arch independent)
|---- inc (arch independent)
|
|----arch1 (arch specific)
|---- src
|---- inc
|---- Makefile
|----arch2 (arch specific)
|---- src
|---- src
|---- Makefile
The arch specific project would be compiled by the Makefile within the arch directory. This makefile includes the Makefile at the TOP level.
The idea was that in the arch specific makefile will have all the src code from within the arch directory and the top level Makefile defines a variable which is simply the path of the TOP level directory, so that the arch specific Makefile can include code from the src folder in the top level.
However, when including the top level Makefile, the defined path variable (through shell pwd command) is evaluuated at the arch specific directory level.
How can I solve this? Is their a better way of doing this?
Right now it's a 2 level structure. But in future I plan top make it multi level with innermost level being arch specific and the layers become more and more general as one moves out to the top level.

What is your top-level makefile doing? - I mean, can you run make on it standalone? If not then all you really appear to gain from it is the list of source files and header locations - it would be easier to just specify those in a common_make.mk or somthing which only contains:
SOURCES += ../src/test1.c
SOURCES += ../src/test2.c
SOURCES += ../src/test3.c
INC += ../inc
then both of your lower level file include this very basic makefile "snippet" and you don't have to worry about the paths.
Usually I am putting common elements into separate config controlled repos and I have my projects the other way around:
arch1/
|--src
|--inc
|--common (repo)
|--inc
|--src
arch2/
|--src
|--inc
|--common (repo)
|--inc
|--src
So here I have two separate repo's with a shared sub-repo. If you wanted to tie the two archx projects together you can add those to into a super-repo with it's own makefile that just does:
make -C arch1
make -C arch2

I see two options for you
Common makefile template for archX/ directories
# ./Makefile.template
ARCH_DIR := $(PWD)
TOP_DIR := $(ARCH_DIR)/..
BUILD_DIR := $(TOP_DIR)/build
# non-architecture specific source code
NOARCH_SRC_DIR := $(TOP_DIR)/src
NOARCH_INC_DIR := $(TOP_DIR)/inc
# non-architecture specific source code
ARCH_SRC_DIR := $(ARCH_DIR)/src
ARCH_INC_DIR := $(ARCH_DIR)/inc
# other stuff...
CFLAGS := -I$(ARCH_INC_DIR) -I$(NOARCH_INC_DIR)
# directory specific variables, e.g. XXX_SRCS
include $(NOARCH_SRC_DIR)/Makefile.include
include $(ARCH_SRC_DIR)/Makefile.include
# generate object file lists
NOARCH_OBJS := $(NOARCH_SRCS:%.c=$(BUILD_DIR)/%.o)
ARCH_OBJS := $(ARCH_SRCS:%.c=$(BUILD_DIR)/%.o)
# add paths to source files
NOARCH_SRCS := $(addprefix $(NOARCH_SRC_DIR)/, $(NOARCH_SRC_DIR))
ARCH_SRCS := $(addprefix $(ARCH_SRC_DIR)/, $(ARCH_SRC_DIR))
# target-specific pattern rules for C files
$(NOARCH_OBJS): %.o: $(NOARCH_SRC_DIR)/%.c | $(BUILD_DIR)
$(CC) $(CFLAGS) -o $# -c $<
$(ARCH_OBJS): %.o: $(ARCH_SRC_DIR)/%.c | $(BUILD_DIR)
$(CC) $(CFLAGS) -o $# -c $<
... and so ...
ArchX/ directory makefile
# archX/Makefile
# common stuff
include $(PWD)/../Makefile.template
# arch specific targets follow here...
Now you can already run the build using
$ make -C arch1
Top-level directory Makefile
# ./Makefile
ifndef ARCH
$(error you must specifiy ARCH=)
endif
# forward all targets to arch directory
%:
$(MAKE) -C $(ARCH) $(MAKECMDGOAL)
Now you can run the build using
$ make ARCH=arch1
Personally I would not write the top-level makefile at all and use only the former approach.
IMHO you should avoid things like $(shell). But maybe that is just my personal view, take it with a grain of salt...

Related

multiple Makefile for a single project

I am trying build a project with several modules included. the file tree looks like this:
the individual Makefiles for lib_one, lib_two and Main.cpp works fine, generating the 2 DLL and the EXE for the project, but requires enter at each directory and execute the command 'make' for each module.
I want now a Makefile in the top level directory ('/project') which triggers the building for all the other modules (DLLs and EXE) once. Based on some search results I got something like that:
lib_one := ./src/lib_one
lib_two := ./src/lib_two
libraries := $(lib_one) $(lib_two)
player := ./src
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries):
$(MAKE) --directory=$#
$(player): $(libraries)
when I execute the command 'make' I got this error:
Makefile:10: ***. Stop.
(the line 10 is this one: $(MAKE) --directory=$#). Besides a way to fix this error, I am looking to a way to accomplish this 3 things:
1)
the object files (*.o) from all the modules (DLLs and EXE) should be stores on a directory build in the same place from the directory src.
2)
the final files (*.dll and *.exe) should be placed in a directory reelease alongside the directories src and build.
3) if item 2 was possible, would be nice if each type of file being placed in a specific directory inside release (bin for *.exe, lib for *.dll and shared for other types). also, even with the exe and dlls in different directories, would be possible run the executable from this directory (making it search for the necessary libraries in ../lib alongside the other usual places?).
#Maxim is likely right for the cause of the error -- spaces vs tabs. As far as a your other questions go, without using non-recursive make, you could do something like:
Makefile:
export base_dir := ${CURDIR}
export obj_dir := ${base_dir}/build
export release_dir := ${base_dir}/release
lib_one := ${base_dir}/src/lib_one
lib_two := ${base_dir}/src/lib_two
libraries := $(lib_one) $(lib_two)
player := ${base_dir}/src
.PHONY: all $(player) $(libraries)
all: $(player)
$(player) $(libraries): | ${obj_dir} ${release_dir}
$(MAKE) --directory=$#
$(player): $(libraries)
${obj_dir} ${release_dir} :
#mkdir -f $#
The sub-makefiles would have access to any exported variable from the parent (see here), so in these you could do stuff like:
${obj_dir}/%.o : %.c
#echo compiling "$^ ==> $#"
$(CC) -c -o $# $^ $(CFLAGS)
which would compile the objects to the right directory.
Beware though -- if you have two components that produce an object file with the same name, because they're being produced in the same directory, you will end up with a potentially hard to debug race condition. Typically each component produces object files in its own unique directory to avoid this very thing.

Makefile from top library

I'm trying to build my project from the top directory which have the subdirectories
root
Makefile
| common/
| lib/
| app1/
| app2/
| app3/
Assumption 1: I'm at the root directory
Assumption 2: Each subdirectory has its own Makefile
Assumption 3: root's Makefile doesn't actually give any output, it only wants to execute Makefiles in the subdirectories
Assumption 4: common/ and lib/ will contain library files lib1.a and lib2.a
Now, by running make at the root, I want to first build the two libraries lib1.a and lib2.a. And then I want to build the respective apps in app1/, app2/, and app3/. The 3 apps should be linked to lib1.a and lib2.a.
I'm at the stage where I want to first build the two libraries by calling their Makefiles respectively. Here's what I have so far.
CFLAGS = -Wall -pedantic -std=c11 -ggdb
CC = gcc
MAKE = make
LIBPATH = lib/
COMMONPATH = common/
$(LIBPATH)lib1.a : $(LIBPATH)lib1.a # i know this isn't appropriate but it executes make
$(MAKE) -C $(LIBPATH)
$(COMMONPATH)lib2.a : $(COMMONPATH)lib2.a
$(MAKE) -C $(COMMONPATH)
I know there are probably better ways to write this, but the main problem for me is that this makefile only executes whatever is first. Now it will recursveily run the lib1.a's makefile but not for lib2.a. As I want to write similar lines for app1 app2 and app3 I want to resolve this.
Thanks in advance!
You need to declare the dependencies of your applications in your targets.
If app1, app2 and app3 are depends on lib1.a and lib2.a you need to write these dependencies in your target as well . The same for your libraries ( just in case that there are any dependencies existing between both libs as well ).
For instance:
LIBS = lib1.a lib2.a
SRC = app1.cc
app1: $(SRC) $(LIBS) # you will say app1 depends on its source and the libs
# compile your app

Building an out-of-tree linux kernel module with separate output directory

I want to build an out of tree kernel module with the output directory being separate from my source directory? How would I do this? I'm willing to go any route. I'm okay with minimal changes to the kernel build system, I'm okay with copying source files (however I do not want to rebuild if I haven't made any changes to the source files and this doesn't work if I copy source files normally), and I'm okay with setting a parameter or something.
many many people face this problem, including me.
To support build external module at separate output directory.
I modify the kbuild:
firstly, modify src variable at scripts/Makefile.build and scripts/Makefile.clean
-src := $(obj)
+src := $(if $(KBUILD_EXTMOD_SRC),$(KBUILD_EXTMOD_SRC)$(patsubst $(KBUILD_EXTMOD)%,%,$(obj)),$(obj))
secondly, modify scripts/Makefile.modpost
-src := $(obj)
+src := $(if $(KBUILD_EXTMOD_SRC),$(KBUILD_EXTMOD_SRC),$(obj))
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
-include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
- $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
+include $(if $(wildcard $(src)/Kbuild), \
+ $(src)/Kbuild, $(src)/Makefile)
then build external module like this:
make -c $(kernel_src) M=$(extmod_outpu_dir) KBUILD_EXTMOD_SRC=$(extmod_src_dir) modules

GNU make: build all sources in a different directory

Given:
programs := apps/prog1 apps/prog2 # the actual list is quite long
sources := src/prog1.cpp src/prog2.cpp # showing only 2 files
Make file has 2 targets release and debug. Each target should build every program in bin/ directory and appends target name to the file name.
For example, building release should create bin/prog1_release and bin/prog2_release.
How to write static pattern rule to do it?
Thanks.
This will do it (in GNUMake 3.81):
BINS := $(patsubst apps/%,bin/%,$(programs)) # bin/prog1 bin/prog2 ...
release_bins := $(addsuffix _release,$(BINS)) # bin/prog1_release ...
debug_bins := $(addsuffix _debug,$(BINS)) # bin/prog1_debug ...
$(release_bins): bin/%_release: src/%.cpp
#build the binaries according to the release rule
$(debug_bins): bin/%_debug: src/%.cpp
#build the binaries according to the debug rule
release: $(release_bins)
debug: $(debug_bins)
.PHONY: release debug
# If it turns out that one of the progs needs something else too:
bin/prog20_debug: somethingElse.cpp
(There are ways to make this slightly more concise, but at the cost of clarity.)

Building an out-of-tree Linux kernel module in a separate object directory

I'm confronting the Linux kernel build system (Kbuild, kernel ≥2.6.28) with the directory structure and build system for a larger project. Our project contains an out-of-tree Linux kernel module, and our directory structure looks like this (simplified, obviously):
checkout/src/common/*.c source files (common to Linux and other platforms)
checkout/src/linux-driver/*.c source files (for the Linux kernel driver)
checkout/build/linux/Kbuild Kbuild
tmp/linux-2.6.xx/ where the Linux kernel is unpacked and configured
output/linux-arm-debug/ where object files must end up
The build process must not modify anything under checkout, and building the module must not modify anything under tmp/linux-2.6.xx. All output files must end up under output/linux-arm-debug (or whatever architecture and debug variant was selected at build time).
I've read kbuild/modules.txt, and started to write my Kbuild file:
MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
obj-m += $(MOD_OUTPUT_DIR)/foo_mod.o
$(MOD_OUTPUT_DIR)/our_module-objs := $(MOD_OUTPUT_DIR)/foo_common.o $(MOD_OUTPUT_DIR)/foo_linux.o
This handles storing the object files in a different directory from where Kbuild lives. Now how can I specify that foo_common.o needs to be compiled from …/checkout/src/common/foo_common.c and foo_linux.o from …/checkout/src/linux-driver/foo_linux.c?
Here is a Makefile which does out of source-tree builds for out of kernel-tree modules (adapted from #Mark's comment)...
KDIR ?= /lib/modules/$(shell uname -r)/build
BUILD_DIR ?= $(PWD)/build
BUILD_DIR_MAKEFILE ?= $(PWD)/build/Makefile
default: $(BUILD_DIR_MAKEFILE)
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules
$(BUILD_DIR):
mkdir -p "$#"
$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
touch "$#"
clean:
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean
Note: You still need a Kbuild file...
obj-m += my_driver.o
I had a similar problem. I modified linux_2_6_34/scripts/Makefile.build as follows.
ifdef SRCDIR
src := $(SRCDIR)
else
src := $(obj)
endif
SRCDIR is the directory source.
To compile the module, run
make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)`
My inelegant but effective solution is to copy the source files into the output tree.
FOO_SOURCES_DIR = $(src)/../../../checkout/src
FOO_MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
# Specify the object files
obj-m += $(FOO_MOD_OUTPUT_DIR)/foo_mod.o
FOO_MODULE_OBJS := $(FOO_MOD_OUTPUT_DIR)/foo_common.o $(FOO_MOD_OUTPUT_DIR)/foo_linux.o
$(FOO_MOD_OUTPUT_DIR)/foo_mod-objs := $(FOO_MODULE_OBJS)
# Where to find the sources
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_common.c: $(FOO_SOURCES_DIR)/common/foo_common.c
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_linux.c: $(FOO_SOURCES_DIR)/linux-driver/foo_linux.c
# Rules to copy the sources
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS))
$(FOO_COPIED_SOURCES):
$(Q)mkdir -p $(#D)
cp -f $< $#
clean-files += $(FOO_COPIED_SOURCES)
clean-dirs += $(FOO_MOD_OUTPUT_DIR)
While you haven't mentioned what you've tried so far (or whether you found a solution already), it looks like you just need to continue further down the modules.txt file a bit -- to Section 4.3:
--- 4.3 Several Subdirectories
kbuild can handle files that are spread over several directories.
Consider the following example:
.
|__ src
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
|__ include
|__ complex.h
To build the module complex.ko, we then need the following
kbuild file:
--> filename: Kbuild
obj-m := complex.o
complex-y := src/complex_main.o
complex-y += src/hal/hardwareif.o
ccflags-y := -I$(src)/include
ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located
in other directories. The trick is to specify the directory
relative to the kbuild file's location. That being said, this
is NOT recommended practice.
For the header files, kbuild must be explicitly told where to
look. When kbuild executes, the current directory is always the
root of the kernel tree (the argument to "-C") and therefore an
absolute path is needed. $(src) provides the absolute path by
pointing to the directory where the currently executing kbuild
file is located.
A bit late, but it looks like O= flag is what you need.
You can set the environment variable KBUILD_OUTPUT. This functions similar to the O= option; however, since it's an environment variable, it can span multiple makefiles where O= can't be passed or an out-of-directory module needs to be built. I was having this same issue with trying to build a set of compat-wireless modules and I needed to use O= for the actual kernel image build.

Resources