adding additional sources directory to c makefile - linux

sorry if this is noob question.
In my c function, I use a macro defined in btrfs_inode.h file.
When I include the file directly to path:
#include "/data/kernel/linux-4.1.21-x86_64/fs/btrfs/btrfs_inode.h"
the project compiles with no errors, I dont want to use that direct path, I download the package kernel-source that contains this header file.
The location of the header file after installing the package is at: /usr/src/linux/fs/btrfs/
So I change the #include to :
#include "btrfs_inode.h"
and i wish to add "/usr/src/linux/fs/btrfs/" as a location that it will search for "btrfs_inode.h" and get: "/usr/src/linux/fs/btrfs/btrfs_inode.h"
I get error:
/bin/sh: 1: /usr/src/linux/fs/btrfs/: Permission denied
I am running make as root.
Makefile:
all:: user
obj-m += my-driver.o
# Make arguments
PWD := $(shell pwd)
INCLUDE := -I/usr/include/asm/mach-default/
KDIR := /lib/modules/$(KERNEL_HEADERS)/build;/usr/src/linux/fs/btrfs/
# Add flags to auto build
EXTRA_CFLAGS +=-D__Linux -std=gnu99
# extra warning flags
ccflags-y := -Wall -Wextra #-pedantic
# disable some warning flags
ccflags-y += -Wno-unused-parameter
# make all warnings into errors
ccflags-y += -Werror
# increase verbosity
KBUILD_VERBOSE := 1
all::
$(MAKE) -C $(KDIR) $(INCLUDE) SUBDIRS=$(PWD) modules

So first off, avoid making as root when possible. Next, you added your directory to KDIR, not to INCLUDE (and then you pass KDIR to the -C argument of make, so you would have a line that looks like:
make -C /lib/modules/$(KERNEL_HEADERS)/build;/usr/src/linux/fs/btrfs/ ...
Notice the semicolon, which bash will interperet as the end of a command, and beginning of the next command. So it tries to run make, and then tries to run /usr/src/linux/fs/btrfs/, and gives you your warning. What you should have is something like:
# Make arguments
PWD := $(shell pwd)
INCLUDE := -I/usr/include/asm/mach-default/
INCLUDE += -I/usr/src/linux/fs/btrfs/
KDIR := /lib/modules/$(KERNEL_HEADERS)/build
(you want a -I in front of the path to tell make to search for include files in that directory).
EDIT
You are also not passing the -I to your $(CC) or $(CXX) commands. To do this, you have a couple of options, though I'll suggest the least error prone one: First of all, you have to pass the flags to the sub make. To do this, first add the line:
export INCLUDE
to your main makefile. Your submake now has access to the variable $(INCLUDE). From there, if you have an explicit rule to compile the CC files, you can add $(INCLUDE) to the compile command. Something like
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) -o $# $<
or, if you are using the built-in implicit rules, simply add $(INCLUDE) to CPP_FLAGS:
CPP_FLAGS += $(INCLUDE)
(note, CPP_FLAGS are used by default for both c and c++ compilation).
Finally, do not pass $(INCLUDE) to your make command. If you do, it tells make to look look for sub-makefiles in those directories (not gcc...).

From what I could understand via this question, you can add multiple -I flags to your Makefile.

Related

Prevent variable overwrite into submakefile

I have a makefile compiling a shared library which I call from another makefile.
When developping the library I used the variable TARGET to name the library binary.
BUILD_DIR?=$(abspath ./build)
SRC=src/file.c
INC=-I inc
CFLAGS+=-Wall -Werror
LDFLAGS+=-Wl,--no-undefined
TARGET=libname
ifndef ARCH
$(error Undefined ARCH (Library targetted architecture))
endif
default: all
all: ${BUILD_DIR}/${ARCH}/${TARGET}
${BUILD_DIR}/${ARCH}/${TARGET}: ${BUILD_DIR}/${ARCH}
${CC} ${CFLAGS} ${LDFLAGS} -fPIC -shared -o $#.so ${SRC} ${INC}
${BUILD_DIR}/${ARCH}:
#mkdir -p $#
clean:
#rm -rf ${BUILD_DIR}/${ARCH}/${TARGET}
.PHONY: all clean ${BUILD_DIR}/${ARCH}/${TARGET} ${BUILD_DIR}/${ARCH}
However, into the parent makefile, I use the variable TARGET to specify the board on which I'm deploying the app.
ifeq (${TARGET},target1)
# Target1 compiling
${LIB}:
scp $# ${TARGET_USR}#${TARGET_IP}:
${SSH_CMD} make -C $# ARCH=arm
[...]
endif
ifeq (${TARGET},target2)
# Target2 compiling
${LIB}:
make -C $# BUILD_DIR=${BUILD_DIR} CC=${CC} ARCH=${ARCH}
[...]
endif
I'm compiling as follow: make TARGET=target2 and I'm using GNU make
Compiling the library from the parent makefile succeed but the name of the library is target2.so instead of libname.so.
I thought variables were passed to submakefiles only if explicitly precised on the command call (as for BUILD_DIR, CC and ARCH) but it seems that TARGET is also passed to sub makefile.
I know that I could just do override TARGET=libname into the sub makefile.
But I would like to know if there is another solution.
By default, any command line variable arguments will override any local assignments in the makefiles. There is a way around this by using the override directive:
override TARGET := libname
This will set the variable in the child makefile, regardless of whether the value was specified on the command line.

Makefile: compiling several objects with single target

I have several c++ objects that I'd like to compile using a single target. If possible I'll make a variable in the makefile that list all the object files and then have a single target that compiles them all.
Following this question I have the following "Makefile" so far:
#### Directories and flags
ifndef $(DIR_MAIN)
DIR_MAIN=../..
endif
DIR_EXE=$(DIR_MAIN)
DIR_SRC=$(DIR_MAIN)/src/Analyse_MC
DIR_MISC_SRC=$(DIR_MAIN)/src/Misc
DIR_BLD=$(DIR_MAIN)/build/Analyse_MC
DIR_MISC_BLD=$(DIR_MAIN)/build/Misc
COMP=g++
COMPILE_FLAGS= -std=c++11 -O3 -lstdc++ `pkg-config --cflags eigen3` -msse2 -I${DIR_MISC_SRC}
LINK_FLAGS= -O3 -fopenmp -lgsl -lgslcblas -lm -lhdf5_cpp -lhdf5
OBSERVABLE_OBJECTS=g_decomp_IP_orthog_sphere.o g_decomp_LS_orthog_sphere.o g_decomp_IP_disk.o g_decomp_LS_disk.o find_rank.o eigenvectors.o GramSchmidt.o diagonal_Hamiltonian.o mean_log_WF.o energy.o JK_EP_overlap.o overlap.o geo_mean_eigstate_overlap.o eigstate_overlap.o pair_corr_bins.o
#### Compile all
all: setup observables $(DIR_EXE)/Analyse_MC
setup:
#mkdir -p $(DIR_BLD)
#### Compile observable objects
observables: $(addsuffix -stamp,$(OBSERVABLE_OBJECTS))
%.-stamp : %.o
${COMP} -c -o $# $<
However when running make I get the following:
make: *** No rule to make target `g_decomp_IP_orthog_sphere.o-stamp', needed by `observables'. Stop.
So I've misunderstood something.
If possible I'd also like each of the objects to be updated with changes in .h-files with the name of the object in addition to some common .h-files for all of the objects. Is this possible?
Or do I have to / is it recommended to write a separate target for each object?
EDIT:
Some info about the variables:
DIR_MAIN is defined the way it is because usually this makefile will be called from another makefile which defines DIR_MAIN from its directory using pwd; but ut can also be called on its own from its own directory.
DIR_MISC_SRC points to some header files necessary for the files in DIR_SRC.
DIR_BLD and DIR_MISC_BLD will contain the corresponding resulting object files.
The error message does show you what you've done wrong, but a bit obliquely:
make: *** No rule to make target g_decomp_IP_orthog_sphere.o-stamp, needed by observables. Stop.
Your rule to make stamp files is:
%.-stamp: %.o
You probably wanted that to be
%.o-stamp: %.o
Compiling %.o to %.o-stamp looks very strange to begin with - probably you just want
observables: $(OBSERVABLE_OBJECTS)
.PHONY: observables
Stamp files are sometimes useful for actions you want to perform once but have no output file. For compilation, the object file is the output file, and that's all that make requires.
If possible I'd also like each of the objects to be updated with changes in .h-files with the name of the object in addition to some common .h-files for all of the objects. Is this possible?
That's a whole nother question in itself - you want to search for "makefile auto-dependency generation" for starting points.

Linker cannot find library file with explicit path

In my makefile, I have specified a library dependency as follows:
LDFLAGS := -l/home/karnivaurus/OpenCV-3.0.0/build/lib/libopencv_core.so
all: $(DYNAMIC_NAME)
$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
# echo LD -o $#
$(Q)$(CXX) -shared -o $# $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_FLAGS)
Now, if I run make all, I get the following error:
/usr/bin/ld: cannot find -l/home/karnivaurus/Libraries/OpenCV-3.0.0-RC1/build/lib/libopencv_core.so
However, in the directory /home/karnivaurus/Libraries/OpenCV-3.0.0-RC1/build/lib, there is definitely a file called libopencv_core.so. I have checked the spelling many times!
Are there any reasons why the linker cannot find this file, even though I have explicitly specified its exact location and passed that to the linker?
Thanks!
Either use -L for the library path and -lopencv_core:
LDFLAGS := -L /home/karnivaurus/OpenCV-3.0.0/build/lib/ -lopencv_core
or just include the full path to the .so file without -l.
LDFLAGS := /home/karnivaurus/OpenCV-3.0.0/build/lib/libopencv_core.so

Cannot use wildcard in kernel module makefile

I am pretty familiar with Makefiles and kernel modules, but recently I got a problem in my Makefile that doesn't make any sense -- on using wildcards.
To demonstrate this, I am compiling a hello world kernel module from scratch.
The directory structure is like this:
hello_mod/
|
--- hello.c
|
--- Makefile
Here is the actual makefile :
CFILES := $(wildcard hello.c*)
#CFILES := hello.c
OBJS := $(CFILES:.c=.o)
KSRC := /lib/modules/$(shell uname -r)/build
obj-m += hello_world.o
hello_world-y := $(OBJS)
all:
#echo $(CFILES)
$(MAKE) -C $(KSRC) M=$$PWD modules
clean:
$(MAKE) -C $(KSRC) M=$$PWD clean
.PHONY: clean
The problem is that even though the commented $(CFILES) and the uncommented $(CFILES) are exactly the same, the build fails on using the first $(CFILES) with the following error:
*** No rule to make target `/home/test/hello_mod/hello_world.c', needed by
/home/test/hello_mod/hello_world.o'. Stop.
If the commented $(CFILES) is used, it works perfectly.
If someone wants to test this out, I'm including the source for the hello world source which is hello.c :
#include <linux/kernel.h>
#include <linux/module.h>
static int mod_init()
{
printk("Hello\n");
return 0;
}
static void mod_exit()
{
printk("Bye world\n");
}
module_init(mod_init);
module_exit(mod_exit);
Does anyone know why it is behaving as such? And I need to use wildcards in the makefile. Any help will be appreciated.
There are two makes happening here. The first really only relies on the KSRC variable and the recursive make call. The second make only needs the CFILES, OBJS, obj-m, and hello_world-y variables, and doesn't make use of the all: target. So your debug is showing that CFILES is set correctly for the first Make, where it's not being used, and is not showing it in the second make, where it is.
You're wildcard expanding from a different directory, and not picking up the right files. Try this for CFILES:
CFILES := $(notdir $(wildcard $M/hello.c*))
SRCDIRS := subdir1 subdir2
CFILES := $(strip $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)))
should probably be (see foreach example in documentation)
SRCDIRS := subdir1 subdir2
CFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c))
(no need to $(strip), .... or perhaps
CFILES := $(wildcard {subdir1,subdir2}/*.c)
Use remake, probably as remake -x, to debug such issues.

How to keep asm output from Linux kernel module build

I'm working on a Linux kernel module for a 2.6.x kernel and I need to view the assembly output, though it's currently being done as a temporary file an deleted afterwords. I'd like to have the assembly output mixed with my C source file so I can easily trace where my problem lies. This is for an ARMv6 core and apparently objdump doesn't support this architecture. I've included my makefile below.
ETREP=/xxSourceTreexx/
GNU_BIN=$(ETREP)/arm-none-linux-gnueabi/bin
CROSS_COMPILE := $(GNU_BIN)/arm-none-linux-gnueabi-
ARCH := arm
KDIR=$(ETREP)/linux-2.6.31/
MAKE= CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make
obj-m += xxfile1xx.o
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
Objdump does support that architecture. Your executable will be called arm-none-linux-gnueabi-objdump
Assuming gcc and the gnu assembler a more readable output than objdump can be had. Tell the assembler to retain its intermediate code using flags to gcc:
-Wa,-alh=basename.s
And to get basename to be the actual source filename you need to tell make:
-Wa,-alh=$<.s
which will leave piles of foo.c.s files laying around your source directory. The big problem here is that the way gcc works it uses temporary files between code generation and assembly. I can't find a way to make gcc save its intermediates but the assembler is happy to stash a listing for you.
Getting that argument into the Makefile CFLAGS is left as an exercise for the reader (because I kinda hate "make" and hate "gnu info" even more.
To get an assembly language listing of my Linux kernel modules, I added the assembler switches to the kernel scripts/Makefile.build.
#cmd_cc_o_c = $(CC) $(c_flags) -c -o $(#D)/.tmp_$(#F) $<
cmd_cc_o_c = $(CC) $(c_flags) -c -Wa,-alh=$<.lst -o $(#D)/.tmp_$(#F) $<
You could try the flag "-save-temps" to gcc.
It works for me in my embedded project, I haven't tried it on kernel builds.
The proper way is likely to add target dependencies in your module makefile / Kbuild file:
always-m += basename.s
(As kbuild has the proper targets to generate the .s files)
If you are lazy as I am, this could look like:
MOD_NAME := some_module_name
myunits := file1 file2 file3 ... and many more... without .c extension
obj-m := $(MOD_NAME).o
$(MOD_NAME)-y := $(addsuffix .o,$(myunits))
# Comment/uncomment to generate assembly / preprocessor output
always-m += $(addsuffix .s,$(myunits)) $(MOD_NAME).mod.s
always-m += $(addsuffix .i,$(myunits)) $(MOD_NAME).mod.i
(2 bonuses here: assembly for the generated module meta-registration file, and the preprocessor output)

Resources