Writing a makefile for an OS
Posted: Sun Jun 13, 2021 8:52 am
...
The Place to Start for Operating System Developers
http://f.osdev.org/
The same way.ngx wrote:actually I couldn't even understand how to write a makefile for any project that consists of more then one directory.
Code: Select all
(output): (input files)
(commands to be executed to create output from input files)
Code: Select all
dir/submodule.a:
make -C dir all
Code: Select all
bzip2/libbz2.a:
@make -C bzip2 libbz2.a
Code: Select all
CFLAGS = -g
Code: Select all
include Makefile.env
dir/out:
make -C dir all
Code: Select all
include ../Makefile.env
...whatever
What we do is use a system environment variable for this. E.g. from a component makefile:I also have thought of this, but if I will have deeper subdirectories then it will look like ../../../../… and if i change something it would not be obvious how many ../.. to remove
Code: Select all
TARGETNAME = nasm
TARGETTYPE = PROGRAM
TARGETPATH = $(SDK)/bin
INCLUDES = $(STDINC)
SOURCES = main.c\
table.c\
...
!INCLUDE $(NBE_ENVDIR)/makefile.def
Code: Select all
!if "$(TARGETTYPE)" == "LIBRARY"
$(TARGET) : $(OBJECTS)
$(LIB) $(LIBRARIAN_FLAGS) $(OBJECTS)
!else
$(TARGET) : $(OBJECTS) $(TARGETLIBS)
$(LINK) $(LINKER_FLAGS) $(OBJECTS) $(TARGETLIBS) -out:$(TARGET)
!endif
clean :
del "$(O:/=\)\*.obj"
del "$(TARGET:/=\)"
And what's the matter with that? You only have to write them once. Not using absolute paths has the great benefit that anybody can clone your repo anywhere on their disks and it will Just-Work (TM) without Anything-Crazy-Cmakeish-or-Sconsish-or-Automakeish-Ninjaish magic requiring many additional dependencies with incompatible versions in your toolchain. It just works as it should. Relative paths are good. Relative paths are useful.ngx wrote:I also have thought of this, but if I will have deeper subdirectories then it will look like ../../../../…
Yes, it is pretty obvious, you should be knowing your own directory structure, so should be no probs there. And how often do you reorganize your entire project structure? Chances are good that once you've settled with the structure you'll never ever change it again, max. you'll add some new directories later when you implement a new driver for example, in which case - I bet - you'll just copy an existing Makefile and update the target in it. No need to touch the paths and the include.ngx wrote:and if i change something it would not be obvious how many ../.. to remove
I wrestled with this for a while as well.ngx wrote:After struggling to easily modify my OS, I decided to rewrite all of the build system(makefiles). I read through a couple of makefile tutorials and I have no idea how to write a normal makefile for an OS(I use cmake for my other projects and also they are easier to build) or any other large project, actually I couldn't even understand how to write a makefile for any project that consists of more then one directory. What I came up with is very broken - either I have a root makefile which does "make -C dir" to start other makefiles, but in this case the variables from root makefile are not passed to other makefiles and I need to copy then over and over and over again even though they are 100% the same; the second thing I thought of is to include all of the make files from other directories, but then all of them would have project root as their working directory and so I would need to add /dir/dir before every file and every directory in every makefile. So how should I write makefiles for multi-directory projects? Any resources on how to use makefiles(except the offical doc which is 100% useless unless you need to find a specific feature or understand how some specific feature works) for larger projects? How do you do it in your OS?
Code: Select all
all::
TOP=$(CURDIR)
ARCH=i386
OBJS=$(SRCS_S:.S=.o) $(SRCS_C:.c=.o)
SRCS_C :=
SRCS_S :=
SYS_H := \
include/sys/times.h \
include/sys/stat.h \
include/sys/time.h \
include/sys/types.h \
include/sys/errno.h \
include/sys/unistd.h
subdir := build
include $(subdir)/subdir.mk
subdir := libk
include $(subdir)/subdir.mk
subdir := kernel
include $(subdir)/subdir.mk
subdir := posix
include $(subdir)/subdir.mk
subdir := fs
include $(subdir)/subdir.mk
subdir := drivers
include $(subdir)/subdir.mk
subdir := build
include $(subdir)/tools.mk
subdir := arch/$(ARCH)
include $(subdir)/subdir.mk
subdir := user
include $(subdir)/subdir.mk
subdir := initrd
include $(subdir)/subdir.mk
Code: Select all
SRCS_KERNEL_C := $(subdir)/main.c $(subdir)/core.c $(subdir)/pci.c $(subdir)/printk.c $(subdir)/panic.c $(subdir)/thread.c $(subdir)/sync.c $(subdir)/check.c $(subdir)/vm.c $(subdir)/vfs.c $(subdir)/dev.c $(subdir)/timer.c $(subdir)/input.c $(subdir)/intr.c $(subdir)/device.c
SRCS_C += $(SRCS_KERNEL_C)
Code: Select all
fsdir:=$(subdir)
subdir:=$(fsdir)/tarfs
include $(subdir)/subdir.mk
subdir:=$(fsdir)/devfs
include $(subdir)/subdir.mk
subdir:=$(fsdir)/fatfs
include $(subdir)/subdir.mk
subdir:=$(fsdir)/procfs
include $(subdir)/subdir.mk