OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 8:08 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Directory organization suggestions
PostPosted: Fri Mar 27, 2020 11:25 pm 
Offline
Member
Member

Joined: Sat Feb 08, 2020 11:11 am
Posts: 106
Hello! I have been writing a small operating system so far, from a bootloader to a basic kernel. Stuff like interrupt handling, keyboard drivers, etc. are already done. I want to organize my code a little better. Here's what I haven't done yet... No user mode, no libc, etc.

Here's a tree organization of my directory... (you can also find it on http://www.github.com/kssuraaj28)
Code:
├── boot
│   ├── stage1
│   │   ├── CHS.asm
│   │   ├── debug
│   │   ├── disk_read.asm
│   │   ├── print.asm
│   │   └── stage1.asm
│   └── stage2
│       ├── func16.asm
│       ├── func32.asm
│       ├── GDT.asm
│       ├── pagingsetup.asm
│       └── stage2.asm
├── disk.img
├── kernel
│   ├── asm
│   │   ├── cursor.asm
│   │   ├── cursor.o
│   │   ├── entry.asm
│   │   ├── entry.o
│   │   ├── hal.asm
│   │   ├── hal.o
│   │   ├── interruptstubs.asm
│   │   ├── interruptstubs.o
│   │   └── timer.o
│   ├── c
│   │   ├── io.c
│   │   ├── o.h
│   │   ├── io.o
│   │   ├── hal.c
│   │   ├── hal.h
│   │   ├── hal.o
│   │   ├── inthandling.c
│   │   ├── inthandling.h
│   │   ├── inthandling.o
│   │   ├── kernel.c
│   │   ├── kernel.o
│   │   ├── keyboard.c
│   │   ├── keyboard.h
│   │   ├── keyboard.o
│   │   ├── kshell.c
│   │   ├── kshell.o
│   │   ├── phymem.c
│   │   ├── phymem.h
│   │   ├── phymem.o
│   │   ├── timer.c
│   │   ├── timer.h
│   │   ├── timer.o
│   │   ├── virtmem.c
│   │   ├── virtmem.h
│   │   └── virtmem.o
│   ├── kernel.elf
│   └── linker.ld
├── kernel.bin
├── Makefile
├── readme.md
├── script.sh
├── stage1.bin
└── stage2.bin


Clearly the code organization of the kernel directory is very very poor. What's the tradtional way this is usually done?
Here's the makefile, which describes how I build the OS.
Code:
C_SOURCES = $(wildcard kernel/c/*.c)
ASM_SOURCES = $(wildcard kernel/asm/*.asm)
C_OBJECTS = ${C_SOURCES:.c=.o}
ASM_OBJECTS = ${ASM_SOURCES:.asm=.o}

.PHONY : all assemble run clean

all: assemble

run : assemble
   qemu-system-i386 -drive format=raw,file=disk.img  -monitor stdio

debug: assemble
   qemu-system-i386 -s -hda disk.img &
   gdb -ex "target remote localhost:1234" -ex "symbol-file kernel/kernel.elf" -ex "b kmain" -ex "continue"

assemble: disk.img kernel.bin stage1.bin stage2.bin
   dd if=stage1.bin of=disk.img bs=1 count=3 seek=0 skip=0 conv=notrunc
   dd if=stage1.bin of=disk.img bs=1 count=451 seek=62 skip=62 conv=notrunc
   mcopy -i disk.img stage2.bin kernel.bin ::  -D o


kernel.bin : kernel/kernel.elf 
   objcopy -O binary $^ $@
   chmod -x $@

#You can use the --print-map option to look at what the linker does
kernel/kernel.elf : $(C_OBJECTS) $(ASM_OBJECTS)
   i686-elf-ld  $^ -T kernel/linker.ld -e kmain -o $@
   chmod -x $@

%.o : %.c
   i686-elf-gcc -ffreestanding $< -c -o $@ -Wall -Werror -g
%.o : %.asm
   nasm $< -o $@ -f elf32

stage1.bin : boot/stage1/stage1.asm
   nasm $^ -f bin -o $@
stage2.bin: boot/stage2/stage2.asm
   nasm $^ -f bin -o $@
   
disk.img:
   truncate $@ -s 1M
   mkfs.vfat -F12 -S512 -s1 $@
   
clean :
   rm $(C_OBJECTS) $(ASM_OBJECTS) *.bin


This is really bad organization.... and I believe that it would cause scalability problems in the future.. Any suggestions/criticisms?


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 4:08 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,
sunnysideup wrote:
This is really bad organization.... and I believe that it would cause scalability problems in the future.. Any suggestions/criticisms?
I'm not sure what you mean by scalable source tree. But if you meant to be expendable or portable in the future, then I'd recommend organizing your code along those lines. For example, instead of "asm", use "x86" or something. Otherwise your structure is not bad, and if it's x86 only and monolithic, then it's perfectly fine. Maybe I'd create a separate "drivers" directory, but that's all.

No golden rule here, all OSes are different, so a different directory structure fits their need. I'd recommend to think about what parts you want to be extendable and separate those (boot, common executor, drivers etc.). If your OS is going to be multiplatform, then separate platform dependent code from common code too, otherwise don't care.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 4:15 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
There is no one-size-fits-all solution for this. If you want your OS to be portable, separate architecture specific code (assembly + C) from architecture-independent code (C files only). You might want to split your directories according to functionality (MM, tasking, etc.) instead of C/assembly.

A few other notes regarding your build system:
  • Storing object files and source files in the same directory is bad practice. It prevents you from using multiple build directories which in turn prevents other things like performing clean builds with clang-tidy, scan-build or other static analysis tools. With out-of-source trees, you just delete the build directory to "make clean". You can be 100% sure that a clean rebuild is reproducible, without any effort.
  • This might be controversial on this forum but plain makefiles are not an adequate solution in 2020. Use Meson, CMake or any other established build system (but not autotools, please!). Header dependency discovery in plain makefiles is a pain. configure scripts tend to be hand-rolled with plain make which is also a pain to deal with. Many custom makefiles neglect to support --prefix and/or DESTDIR. Many custom makefiles to not support out-of-source builds. Often, wildcards are used that prevent the makefiles from scaling to large directories. The list goes on...

If you don't have experience with build systems, I recommend Meson. It supports cross-compilation (also to bare metal ELF targets) out-of-the-box and does not need customization for non-mainstream OSes.

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Last edited by Korona on Sat Mar 28, 2020 4:23 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 4:20 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Korona wrote:
wildcards are used that prevent the makefiles from scaling to large directories.
What do you mean by that? Would you mind to elaborate? (I'm not saying you're not correct about this, I'm not sure what you mean).

Otherwise I completely agree with you on the other points. Unless you're an experienced programmer and you know exactly what you're doing, hand written configure and make only build is not suitable for you. That requires a lot of experience to do it right, beginners are better off with CMake or something similar.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 5:35 am 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 815
Location: Hyperspace
bzt wrote:
instead of "asm", use "x86" or something. Otherwise your structure is not bad, and if it's x86 only and monolithic, then it's perfectly fine.

This can work well, yes. Plan 9 gets a lot of mileage out of it. The kernel build files operate in arch-specific dirs, sometimes building source from `../port`.

Korona wrote:
  • Storing object files and source files in the same directory is bad practice. It prevents you from using multiple build directories which in turn prevents other things like performing clean builds with clang-tidy, scan-build or other static analysis tools. With out-of-source trees, you just delete the build directory to "make clean". You can be 100% sure that a clean rebuild is reproducible, without any effort.

Yeah. Plan 9 stores object files with source files, and developed bugs where `make clean` didn't clean properly. Also, it means Plan 9 has to use a different extension for each architecture, and uses that extension for a prefix for binaries before they're installed. This creates complexity for Plan 9 with its `mk` and unique compilers; it would be worse with mainstream compilers, make, or other build systems. Better to put object files in a separate directory. (The fact that the extension is different from $objtype also creates problems including complexifying scripts to premature obsolescence. They reassigned '7' from Alpha to Arm64 while my friend was still using Alpha machines. They could instead store object files and pre-install executables under, for example, /386/obj, where executables go in /386/bin and libraries in /386/lib.)

Other than that big caveat, Plan 9 has an interesting build system. Its `mk` is quite programmable. Defaults are provided by standard mkfiles included in most other mkfiles.

bzt wrote:
beginners are better off with CMake or something similar.

CMake itself seems to have developed a Red Hat style business model: Make all but beginner tasks difficult enough that people will pay for support contracts. It would probably be best to look into other build systems instead. I got burned badly when Red Hat adopted this business model just as I was getting into Linux.

_________________
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 9:36 am 
Offline
Member
Member

Joined: Sat Feb 08, 2020 11:11 am
Posts: 106
Alright, where would you suggest I put header files? The same directory as their corresponding .c files? This seems like a bad idea... Do I make a include directory? I feel this is more appropriate with a libc.. any suggestions?


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 10:38 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
I dont use header files, all is on start of c file.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Mar 28, 2020 12:50 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
sunnysideup wrote:
Alright, where would you suggest I put header files? The same directory as their corresponding .c files? This seems like a bad idea... Do I make a include directory? I feel this is more appropriate with a libc.. any suggestions?
Depends on taste, really. Include directories seem to be the standard way, though they can get quite complex (you didn't plan on dumping all header files into a single directory, did you?). Also note that there is no need to have one header for every C file, you can group headers together if you'd like. Also, you might need headers for your assembly files as well.

Klakap wrote:
I dont use header files, all is on start of c file.
That is an astonishingly bad idea. At work I have to deal with code created like this, and the fallout is horrible to this day. Because this way you end up repeating declarations all over the place, and if any declaration changes, but you overlook one declaration somewhere, the compiler will not notice, nor will the linker, and you end up calling functions with the wrong arguments. Just don't do this.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Mon Mar 30, 2020 4:16 am 
Offline
Member
Member

Joined: Sat Feb 08, 2020 11:11 am
Posts: 106
Alright, I've done a bit of remodelling, but my lack of experience seems very relevant :( :| :| .
Here's my new structure:
Code:
.
├── boot
│   ├── stage1
│   │   ├── CHS.asm
│   │   ├── debug
│   │   ├── disk_read.asm
│   │   ├── print.asm
│   │   └── stage1.asm
│   └── stage2
│       ├── func16.asm
│       ├── func32.asm
│       ├── GDT.asm
│       ├── pagingsetup.asm
│       └── stage2.asm
├── kernel
│   ├── driver
│   │   ├── ATA.c
│   │   ├── ATA.o
│   │   ├── cursor.asm
│   │   ├── cursor.o
│   │   ├── dadio.c
│   │   ├── dadio.o
│   │   ├── keyboard.c
│   │   ├── keyboard.o
│   │   ├── timer.c
│   │   └── timer.o
│   ├── hal
│   │   ├── hal.c
│   │   ├── hal.o
│   │   ├── interruptstubs.asm
│   │   ├── interruptstubs.o
│   │   ├── inthandling.c
│   │   ├── inthandling.o
│   │   ├── x86.asm
│   │   └── x86.o
│   ├── include
│   │   ├── ATA.h
│   │   ├── dadio.h
│   │   ├── FAT12.h
│   │   ├── hal.h
│   │   ├── inthandling.h
│   │   ├── keyboard.h
│   │   ├── phymem.h
│   │   ├── timer.h
│   │   └── virtmem.h
│   ├── kernel
│   │   ├── entry.asm
│   │   ├── entry.o
│   │   ├── kernel.c
│   │   ├── kernel.o
│   │   ├── kshell.c
│   │   └── kshell.o
│   ├── kernel.elf
│   ├── linker.ld
│   └── mem
│       ├── phymem.c
│       ├── phymem.o
│       ├── virtmem.c
│       └── virtmem.o
├── Makefile
├── readme.md
├── script.sh



Code:
C_SOURCES = $(wildcard kernel/*/*.c)
ASM_SOURCES = $(wildcard kernel/*/*.asm)
C_OBJECTS = ${C_SOURCES:.c=.o}
ASM_OBJECTS = ${ASM_SOURCES:.asm=.o}

.PHONY : all assemble run clean

all: run

run : assemble
   qemu-system-i386 -drive format=raw,file=disk.img  -monitor stdio

debug: assemble
   qemu-system-i386 -s -hda disk.img &
   gdb -ex "target remote localhost:1234" -ex "symbol-file kernel/kernel.elf" -ex "b kmain" -ex "continue"

assemble: disk.img kernel.bin stage1.bin stage2.bin
   dd if=stage1.bin of=disk.img bs=1 count=3 seek=0 skip=0 conv=notrunc
   dd if=stage1.bin of=disk.img bs=1 count=451 seek=62 skip=62 conv=notrunc
   mcopy -i disk.img stage2.bin kernel.bin ::  -D o


kernel.bin : kernel/kernel.elf 
   objcopy -O binary $^ $@
   chmod -x $@

#You can use the --print-map option to look at what the linker does
kernel/kernel.elf : $(C_OBJECTS) $(ASM_OBJECTS)
   i686-elf-ld  $^ -T kernel/linker.ld -e kmain -o $@
   chmod -x $@

%.o : %.c
   i686-elf-gcc  -ffreestanding $< -c -o $@ -Wall -Werror -g  -Ikernel/include  ## Using -I seems like a bad idea??
%.o : %.asm
   nasm $< -o $@ -f elf32

stage1.bin : boot/stage1/stage1.asm
   nasm $^ -f bin -o $@
stage2.bin: boot/stage2/stage2.asm
   nasm $^ -f bin -o $@
   
disk.img:
   truncate $@ -s 1M
   mkfs.vfat -F12 -S512 -s1 $@
   
clean :
   rm $(C_OBJECTS) $(ASM_OBJECTS) *.bin


The organisation looks better IMHO.. But I'm worried about two things right now:
1. How I deal with header files. This is really worrying me. As you can see, I use -I when I compile, and it seems really really 'patchy'
2. I still want to know how I can efficiently make all my object files get produced a separate directory. What changes can I make in the Makefile to make this happen? (I'm guessing I use some sort of pattern substitution?)
3."C_SOURCES = $(wildcard kernel/*/*.c)" - Really bad idea?


Top
 Profile  
 
 Post subject: Re: Directory organization suggestions
PostPosted: Sat Apr 04, 2020 7:03 am 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1071
In my operating system, all includes are in a directory called include in the root of my source tree. I specify this directory with the -I option in the gcc command line

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 115 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group