Writing a generic makefile for C and ASSEMBLY files - c

I'm building a linux kernel module written in ASM and C.
individually, the code can compile, but I can't figure out how to compile it together (Both C and ASM files).
I have 2 c files (entry.c, cpu_checks.c), 1 header file (cpu_checks.h) and 1 assembly file (cpu.asm).
I'm trying to compile all to .o object files and then link them together. My problem is that for some resaon the makefile doesn't recognize the rule for building .asm files.
This is how my makefile looks as of now:
CONFIG_MODULE_SIG=n
KDIR ?= /lib/modules/`uname -r`/build
DRIVER_DIR=path/to/driver/dir
CC = gcc
CFLAGS += -g -DDEBUG
LD = ld
LDFLAGS = -melf_i386
NASM = nasm
NASMFLAGS = -f elf64 -F stabs
obj-m := hyper.o
hyper-objs := $(patsubst $(DRIVER_DIR)/%.asm, $(DRIVER_DIR)/%.o, $(wildcard $(DRIVER_DIR)/*.asm))
hyper-objs += $(patsubst $(DRIVER_DIR)/%.c, $(DRIVER_DIR)/%.o, $(wildcard $(DRIVER_DIR)/*.c))
default:
make -C $(KDIR) M=$(PWD) modules
$(LD) $(LDFLAGS) $(hyper-objs)
# Makefile recognizes this rule.
$(DRIVER_DIR)/%.o: $(DRIVER_DIR)/%.c
$(CC) $(CFLAGS) $# $<
# Makefile doesn't recognize this rule.
$(DRIVER_DIR)/%.o: $(DRIVER_DIR)/%.asm
$(NASM) $(NASMFLAGS) $#
clean:
rm -rf *.o *~
real_clean:
rm -f *.o *.ko *~
I'm not very good at writing makefiles, so I might (even probably) have written something wrong. If not, what can I do to et the makefile to recognize that rule?

The problem is that your default: rule doesn't have any dependencies to check. So it will just run the commands under it without building any of the .o files that you need. Adding $(hyper-objs) as a dependency will ensure all the .o files are built first
default: $(hyper-objs)

Related

How to execute a generic target in a C makefile?

I want to create a Makefile, which compiles each .c file in the the directory to a .o file with the same name.
But for some reason, it does not work. I am not sure if I "call" the generic target properly. Can you help me?
CC = clang
CFLAGS = -std=c11 -pedantic -Wall -Wextra
.PHONY: clean all
all: *.o
clean:
rm -f *.o
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
Greetings
As others commented, this line:
all: *.o
expands the right side just to the existing files.
You can use these functions to "collect" all C sources, and exchange the extension:
all: $(patsubst %.c, %.o, $(wildcard *.c))
However, not every make will support these functions.
(Note: Why can't you explicitly list the object files you want generated?)

Makefile Stops Building Files After First .o In Out-of-Source Build

I have a bit of a huge Makefile that basically works as I want it to.
Issue: The problem I'm having is that the makefile only checks if the first .o needs updating and not if any others do. I'm not sure what part of my makefile is in error.
Context: I have project structure like this:
quendor
src
main.c
options.c
quendor.h
Makefile
When my Makefile builds, it constructs a build directory and things look as follows:
quendor
build
src
main.d
main.o
options.d
options.o
src
main.c
options.c
quendor.h
Makefile
To See the Problem: Now let's say I don't change my main.c but I do change my options.c file. In that case, when I run make again I get this:
make: 'build/./src/main.o' is up to date.
I'm not sure if this is because it's building into a build/src directory rather than just build as I intended.
Here is the full Makefile and I'm including all of it just because I'm not sure what might be a problem and I don't want to make unwarranted assumptions.
.PHONY : all clean
NAME := quendor
PLATFORM := windows
CC := gcc
LINK := gcc
BUILD_DIR ?= ./build
SRC_DIR ?= ./src
ifeq ($(PLATFORM), windows)
TARGET ?= quendor.exe
else
TARGET ?= quendor
endif
ifeq ($(CC), gcc)
CFLAGS += -std=c11 -Wall -Wextra -Wpedantic -Wconversion -Wmissing-prototypes -Wshadow -MMD -MP
LDFLAGS +=
OPT +=
endif
SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:%.o=%.d)
MKDIR_P ?= #mkdir -p $(dir $#)
-include $(DEPS)
all : $(TARGET)
#echo "Building $(TARGET)"
$(TARGET) : $(OBJS)
$(LINK) $(OPT) -o $# $^ $(LDFLAGS)
$(BUILD_DIR)/%.o : %.c
$(MKDIR_P)
$(CC) $(CFLAGS) -c $< -o $#
clean:
$(RM) $(TARGET) -r $(BUILD_DIR)
This may be an artifact of how StackOverflow is parsing my Makfile but I do notice that it's showing different syntax highlighting after this line:
SRCS := $(wildcard $(SRC_DIR)/*.c)
The problem is that you are including the dependencies before you define the all rule:
-include $(DEPS)
all : $(TARGET)
If you don't specify a particular target to build on the command line (e.g., if you don't run make all) then make chooses the first explicit target in the makefile (and any included makefiles!!) as the target to build.
I assume that the dependency definitions in the $(DEPS) variable define main.o as a target and since that comes before all, it's the only thing that's run by default.
Move the -include statement later in the makefile (I typically put these all at the end of the makefile) and it will work.

Automatic rebuilding dependencies (makefiles)

I have a huge project which is compiled with GCC.
I know that usually preforming build should rebuilds all not up-to-date dependencies but some of the .h files that we change does not cause rebuilding of the files which uses them. There is a hierarchy of make files, the main make file include the needed make file according to the need.
is there a way to insure rebuilding of the files which "#include" recently modified .h files?
You have to make sure that your header-files are correctly listed in the prerequisites. For large projects, it's not feasible to do this by hand, but the combination of gcc (or clang) and GNU Make gives you a powerful way to automate it.
Assuming you have some pretty standard Makefile using pattern rules:
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -pedantic
OBJS := main.o module.o
all: program
program: $(OBJS)
$(CC) -o$# $^
%.o: %.c
$(CC) -c $(CFLAGS) -o$# $<
clean:
rm -f *.o
.PHONY: all clean
Then you can use the automatic remaking of Makefiles capability of GNU Make to include files adding additional prerequisites that are generated by gcc:
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -pedantic
OBJS := main.o module.o
all: program
program: $(OBJS)
$(CC) -o$# $^
# rule to create "dependency files", make the dependency file itself
# depend on the same prerequisites
%.d: %.c
$(CC) -MM -MT"$# $(#:.d=.o)" -MF$# $(CFLAGS) $<
# include dependency files except for targets not building anything
ifneq ($(filter-out clean,$(MAKECMDGOALS)),)
-include $(OBJS:.o=.d)
endif
# add Makefiles themselves to prerequisites here (with a changed Makefile,
# the only safe thing is to rebuild all):
%.o: %.c Makefile
$(CC) -c $(CFLAGS) -o$# $<
# remove dependency files on clean
clean:
rm -f *.o *.d
.PHONY: all clean
This is just an example, there are a lot of possibilities how you could use these features.

Improving Makefile so it only creates and cleans programs that have been changed/specifically requested

Based on this stackoverflow response, I've created a Makefile that compiles all .c files into separate executables. I've added a clean section that removes all programs. It now looks like:
CFLAGS=-Wall -g
SRCS = $(wildcard *.c)
PROGS = $(patsubst %.c,%,$(SRCS))
all: $(PROGS)
clean:
rm -f $(PROGS)
%: %.c
$(CC) $(CFLAGS) -o $# $<
My questions are:
How would you have Makefile read additional command line arguments so that it can clean just the programs specified?
You could add a clean-% target that only cleaned specific binaries or other such games but why? Your "clean" recipe is just rm so just run rm yourself.
As to building only specific binaries just run make $binary instead of make or make all.
All make/make all is doing is running the target for each listed binary by name.

How do I make a simple makefile for gcc on Linux?

I have three files: program.c, program.h and headers.h.
program.c includes program.h and headers.h.
I need to compile this on Linux using gcc compiler. I'm not sure how to do this. Netbeans created one for me, but it's empty.
Interesting, I didn't know make would default to using the C compiler given rules regarding source files.
Anyway, a simple solution that demonstrates simple Makefile concepts would be:
HEADERS = program.h headers.h
default: program
program.o: program.c $(HEADERS)
gcc -c program.c -o program.o
program: program.o
gcc program.o -o program
clean:
-rm -f program.o
-rm -f program
(bear in mind that make requires tab instead of space indentation, so be sure to fix that when copying)
However, to support more C files, you'd have to make new rules for each of them. Thus, to improve:
HEADERS = program.h headers.h
OBJECTS = program.o
default: program
%.o: %.c $(HEADERS)
gcc -c $< -o $#
program: $(OBJECTS)
gcc $(OBJECTS) -o $#
clean:
-rm -f $(OBJECTS)
-rm -f program
I tried to make this as simple as possible by omitting variables like $(CC) and $(CFLAGS) that are usually seen in makefiles. If you're interested in figuring that out, I hope I've given you a good start on that.
Here's the Makefile I like to use for C source. Feel free to use it:
TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
It uses the wildcard and patsubst features of the make utility to automatically include .c and .h files in the current directory, meaning when you add new code files to your directory, you won't have to update the Makefile. However, if you want to change the name of the generated executable, libraries, or compiler flags, you can just modify the variables.
In either case, don't use autoconf, please. I'm begging you! :)
For example this simple Makefile should be sufficient:
CC=gcc
CFLAGS=-Wall
all: program
program: program.o
program.o: program.c program.h headers.h
clean:
rm -f program program.o
run: program
./program
Note there must be <tab> on the next line after clean and run, not spaces.
UPDATE Comments below applied
all: program
program.o: program.h headers.h
is enough. the rest is implicit
The simplest make file can be
all : test
test : test.o
gcc -o test test.o
test.o : test.c
gcc -c test.c
clean :
rm test *.o
Depending on the number of headers and your development habits, you may want to investigate gccmakedep. This program examines your current directory and adds to the end of the makefile the header dependencies for each .c/cpp file. This is overkill when you have 2 headers and one program file. However, if you have 5+ little test programs and you are editing one of 10 headers, you can then trust make to rebuild exactly those programs which were changed by your modifications.

Resources