Difference between preprocessor macros D__KERNEL__ and __KERNEL__ - linux-kernel

I am an absolute beginner in programming in linux kernel programming, so sorry if the question is to elementary.
Here https://www.oreilly.com/library/view/linux-device-drivers/0596000081/ch02s02.html I found following example:
# Change it here or specify it on the "make" command line
KERNELDIR = /usr/src/linux
include $(KERNELDIR)/.config
CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include \ -O -Wall
ifdef CONFIG_SMP
CFLAGS += -D__SMP__ -DSMP
endif
all: skull.o
skull.o: skull_init.o skull_clean.o
$(LD) -r $^ -o $#
clean:
rm -f *.o *~ core
And my question is simply what is the difference between preprocessor macro __KERNEL__ and the used -D__KERNEL__? Especially what is the meaning of "-D" here? (by the way the same story with MODULE and -DMODULE).

-D is an option to the compiler (or preprocessor), telling it to define a macro. So putting -D__KERNEL__ on the compiler command line is exactly the same as putting #define __KERNEL__ at the top of the file. Likewise, -DFOO would define a macro named FOO.
No macro named D__KERNEL__ is being defined anywhere here.

Related

Test the support of a linker flag

I need to test the support of a specific linker flag (--no-undefined) before eventually making it part of a Makefile recipe.
This linker flag is not guaranteed to be supported on all platforms (as a matter of fact, it breaks macosx link stage), so it's important to only enable it when it's actually supported.
I lean towards a runtime test, which seems preferable to a static list of compilers / systems which would be more difficult to maintain.
Preferably, the test would be run from the Makefile, which would then conditionally set the flag.
The most reliable test would be a linking test, i.e. try to actually link something. This kind of test would depend on whether you are linking through the compiler or directly with the linker. My approach would be to create a generic template for testing arbitrary flag so it could be reused for different flags in different places, e.g.:
$ cat Makefile
CHECK_CC_FLAGS := -Wl,--no-undefined -Wl,--whatever
CHECK_LD_FLAGS := --no-undefined --whatever
define check_cc_flag
$(shell echo 'int main() { return 0; }' | $(CC) $(1) -xc - 2>/dev/null && echo $(1))
endef
define check_ld_flag
$(shell $(LD) $(1) -e 0 /dev/null 2>/dev/null && echo $(1))
endef
# If linking with $(CC)
test: LDFLAGS += $(foreach flag,$(CHECK_CC_FLAGS),$(call check_cc_flag,$(flag)))
# If linking with $(LD)
test_ld: LDFLAGS += $(foreach flag,$(CHECK_LD_FLAGS),$(call check_ld_flag,$(flag)))
test_ld: test.o
$(LD) $(LDFLAGS) -o $# $<
The template tries to run the compiler or linker and if it succeeds (i.e. exits with 0) it will print out the flag, otherwise the output will be empty. May be more cumbersome if the compiler and/or linker do not behave good (return 0 on failed attempts).
Actual output on Ubuntu 20.04 LTS:
$ make test
cc -c -o test.o test.c
cc -Wl,--no-undefined test.o -o test
$ make test_ld
ld --no-undefined -o test_ld test.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000

Why aren't my variables expanding in my makefile?

I'm using mingw32-make to run my makefile. The contents of the Makefile are the following:
#OBJS specifies which files to compile as part of the project
OBJS = SDLpp.o SDLpp_exception.o SDLpp_window.o
#CC specifies which compiler we're using
CC = g++
#INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS = -IC:\mingw_dev_lib\include\SDL2 \
-IC:\mingw_dev_lib\include\SDL_image \
-IC:\mingw_dev_lib\include\SDLpp
#LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS = -LC:\mingw_dev_lib\lib
#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
# -Wall includes all warnings
# -Wl,-subsystem,windows gets rid of the console window
COMPILER_FLAGS = -Wall
#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
#LIB_NAME specifies the name of our library
LIB_NAME = libSDLcpp.a
#This is the target that compiles our executable
all : $(OBJS)
ar rvs $(LIB_NAME) $(OBJS)
%.o : %.c
$(CC) $< $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) -c $(LINKER_FLAGS) -o $#
^(the white-space before the commands are tabs)^
When run, the shell outputs
g++ -c -o SDLpp.o SDLpp.cpp
which indicates that the other variables are not being expanding in the first pattern rule. Oddly, only CC is expanding into g++. Why is this happening?
The issue is not one of non-expanding variables. Rather, the makefile is using the default rule instead of the one you provided.
The reason may be that your rule uses *.c, while you likely have *.cpp files, IIRC.

Import variables from C preprocessor into Makefile

I want to create one Makefile for Windows and Linux builds. The problem is I have to link with different dynamic libraries for each platform. The C preprocessor may have few nice variables, for example _WIN32. How to extract this information?
The solution have to work with a cross compiler. I cannot create and then run a small program. I have only one, different variable, the CC, the environment may be the same.
The other way around is easy, the -D switch.
Similar but different questions:
Makefile that distincts between Windows and Unix-like systems
I use the same make program. Only the CC variable is different.
I don't know if you can get directly those variables but you can try this solution:
CPP=i686-w64-mingw32-cpp
CPPFLAGS= -P
WIN32=$(shell echo _WIN32 | $(CPP) $(CPPFLAGS))
iswin32:
#echo $(WIN32)
This example will output 1:
$ make iswin32
1
If you are dealing with multiple declarations consider also creating a file with all the declarations, preprocess it and include it in a makefile.
$ cat declaration
WIN32 = _WIN32
Based on answer from TTK
Create file with variables, something like this:
#ifdef _WIN32
-lgdi32 -lopengl32
#else
-lpthread -lX11 -lXxf86vm -lXcursor -lXrandr -lXinerama -lXi -lGL
#endif
And something like this to the Makefile:
A_FLAGS = $(strip $(shell $(CPP) -P $(CPPFLAGS) ./a_flags.cpp))
# or
A_FLAGS = $(strip $(shell $(CPP) -P -xc $(CPPFLAGS) ./a_flags))
$(CPP) – the C preprocessor executable, should be defined by the Make program
-P – the flag to inhibit generation of linemarkers
-xc – the flag to force preprocessor to treat file as C source
$(CPPFLAGS) – optional flags for the preprocessor defined by programmer

Compiling and linking fortran code with MakeFile using Intel compiler

I have a code that is about 8,000 lines and is contained in the same one big bigcode.f90 file. It compiles without problems from the command line with intel compiler with the options:
mpif90 bigcode.f90 -r8 -O2 -xHost -override-limits -o output.out
I want to split this large file into modules and link them using makefile. Below I am listing the makefile. (So here I have main.f90, and also 8 modules linked to it, such as modparams.o and other 7). So I just broke the bigcode.f90 into 9 files. The problem is that when I compile with the makefile, it complains about things like
subroutine ended with "end" statement instead of "end subroutine"
integer passed to reals
some name conflicts between variable names and subroutine names.
All these may well be bad style. However the original bigcode.f90 had all of these, and it did not prevent it from compiling at all. I want to first replicate the results between the bigcode.f90 and the split version - and then I will make other changes.
I also made a copy of this makefile without any OBJECTS to link (just the single bigcode.f90), and that also compiled without any complains. Could somebody help me understand why is there inconsistency about what the compiler complains when there is one file versus when there are several linked files?
# DEFAULT FLAGS
CFLAGS := -I$(CPATH) -I$(F90_MODULES_PATH)
F90 := mpif90
# ADD ALL LIBRARIES HERE (with -l$LIBRARY_NAME)
LDFLAGS := -llapack -v
# ADD ALL SOURCE FILES HERE (with .o extension)
OBJECTS := modparams.o
OBJECTS += modleeplex.o
OBJECTS += modutilsmain.o
OBJECTS += modecon.o
OBJECTS += modindirect.o
OBJECTS += modijutils.o
OBJECTS += modselectstata.o
OBJECTS += modfcn.o
# ADD ADDITIONAL COMPILER FLAGS HERE
CFLAGS += -fbounds-check
CFLAGS += -ffree-line-length-350
CFLAGS += -r8
CFLAGS += -O2
CFLAGS += -xHost
CFLAGS += -override-limits
# ADD ADDITIONAL MODULE FOLDERS HERE (with -I$PATH_TO_FOLDER)
F90_MODULES += -I.
all: main
main: main.f90 $(OBJECTS)
$(F90) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $< -o $#
%.o : %.f90
$(F90) -c $< $(CFLAGS) $(F90_MODULES) $(LDFLAGS) -o $#
clean:
rm -rf $(OBJECTS) *.mod
When I compile, I get the following, and then a long list of errors.
mpif90 -c modfcn.f90 -I/opt/intel/composer_xe_2013.5.192/mkl/include:/opt/intel/composer_xe_2013.5.192/tbb/include:/opt/intel/composer_xe_20 13.5.192/mkl/include:/opt/intel/composer_xe_2013.5.192/tbb/include -I -fbounds-check -ffree-line-length-350 -r8 -O2 -xHost -override-lim its -I. -llapack -v -o modfcn.o
ifort: command line warning #10006: ignoring unknown option '-ffree-line-length-350'
ifort: command line remark #10010: option '-pthread' is deprecated and will be removed in a future release. See '-help deprecated'
ifort version 13.1.3

makefiles CFLAGS

In the process of learning TinyOS I have discovered that I am totally clueless about makefiles.
There are many optional compile time features that can be used by way of declaring preprocessor variables.
To use them you have to do things like:
CFLAGS="-DPACKET_LINK" this enables a certain feature.
and
CFLAGS="-DPACKET_LINK" "-DLOW_POWER" enables two features.
Can someone dissect these lines for me and tell me whats going on? Not in terms of TinyOS, but in terms of makefiles!
CFLAGS is a variable that is most commonly used to add arguments to the compiler. In this case, it define macros.
So the -DPACKET_LINK is the equivalent of putting #define PACKET_LINK 1 at the top of all .c and .h files in your project. Most likely, you have code inside your project that looks if these macros are defined and does something depending on that:
#ifdef PACKET_LINK
// This code will be ignored if PACKET_LINK is not defined
do_packet_link_stuff();
#endif
#ifdef LOW_POWER
// This code will be ignored if LOW_POWER is not defined
handle_powersaving_functions();
#endif
If you look further down in your makefile, you should see that $(CFLAGS) is probably used like:
$(CC) $(CFLAGS) ...some-more-arguments...
Somewhere in the makefile the CFLAG will be used in compilation line like this:
$(CC) $(CFLAGS) $(C_INCLUDES) $<
and eventually in the execution will be translated to :
gcc -DPACKET_LINK -DLOW_POWER -c filename.c -o filename.o
This define will be passed to the source code as it was define in the header file
The -D option set pre-processor variables, so in your case, all code that is in the specified "#ifdef / #endif" blocks will be compiled.
I.e.
#ifdef PACKET_LINK
/* whatever code here */
#endif
The CFLAGS is a variable used in the makefile which will be expanded to it's contents when the compiler is invoked.
E.g.
gcc $(CFLAGS) source.c
-D stands for define (in gcc) at least, which lets you #define on the command line instead of a file somewhere. A common thing to see would be -DDEBUG or -DNDEBUG which respectively activate or disable debugging code.
Just for completeness in this - if you're using Microsoft's nmake utility, you might not actually see the $(CFLAGS) macro used in the makefile because nmake has some defaults for things like compiling C/C++ files. Among others, the following are pre-defined in nmake (I'm not sure if GNU Make does anything like this), so you might not see it in a working makefile on Windows:
.c.exe:
commands: $(CC) $(CFLAGS) $<
.c.obj:
commands: $(CC) $(CFLAGS) /c $<
.cpp.exe:
commands: $(CXX) $(CXXFLAGS) $<
.cpp.obj:
commands: $(CXX) $(CXXFLAGS) /c $<

Resources