4
\$\begingroup\$

I recently started following the James M Kernel Dev tutorials and was able to create an operating system in C++.

Here is the source on GitHub.

I have a couple of questions:

  1. Is my coding style ok?
  2. Is it wrong to write bash scripts for building the project?

JOSMake.sh

#
# Build File for JOS
#
# To Build
#    bash build.sh
# To Run
#   bash run.sh

# ----------------------------------------------------------------------------------------------
# JOS uses assembly to build the bootsector
# Compile the boot Sectors in boot
echo "==============================================="
echo "-------- Building Boot Sectors ----------------"
cd boot
# Run the Make Script inside the boot directory
bash buildboot.sh
cd ..
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
# Compile the C++ Sources into Respective Objects
# Compile main.cc
echo "==============================================="
echo "--------- Compiling C++ Sources --------------"
g++ -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -o main.o main.cc
mv main.o build
# Run scons to build the Entire Lbrary of C++ Files
cd include
rm *.o
scons
# Move all Object Files into Build Directory
cp *.o ../build
cd ..
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
## When Everything is Finished Link together the Objects into a Kernel File
echo "==============================================="
echo "--------- Linking ----------------"
cd build
# require ld , link.ld
ld  -T '../link.ld' -m elf_i386 -o  kernel.jos *.o
# Clean Up After Build
#rm *.o
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
## When Everything is Finished Run the Kernel
qemu-system-i386 -kernel kernel.jos
# -----------------------------------------------------------------------------------------
\$\endgroup\$
0
3
\$\begingroup\$

Instead of repeated statements like this:

echo "==============================================="

I suggest adding a helper function, for example:

print_hr() {  # hr - as in horizontal rule
    echo "==============================================="
}

The advantage of this is if you later decide to change the length of the = in the line, you can change it in one place.


Instead of entering into sub-directories with cd dirname and later stepping back with cd .., I recommend to use sub-shell environments with (...). For example, instead of this:

cd include
rm *.o
scons
# Move all Object Files into Build Directory
cp *.o ../build
cd ..

Do like this:

(
    cd include
    rm *.o
    scons
    # Move all Object Files into Build Directory
    cp *.o ../build
)

Notice that there is no more cd ... Working directory changes in a (...) sub-shell environment are only in effect within.


This maybe a matter of taste, but I find that the many comment lines like this are just noise, and make the script hard to read, I suggest to remove them:

# ----------------------------------------------------------------------------------------------
\$\endgroup\$
3
\$\begingroup\$

It's not wrong to use a Bash script to build your project, but it is suboptimal and unconventional. Usually, a makefile is preferred, since Make can compare timestamps and rebuild just the objects that need to be rebuilt.

There are other advantages to makefiles as well. For example, a common convention would be to define variables like

CXX = g++
CXXFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 $(EXTRA_CXXFLAGS)

Then, you would have the flexibility to run make EXTRA_CXXFLAGS=-O2 to compile with -O2 without having to edit the script.


A lot of your script's sequences of operations seem complicated and error-prone. For example:

cd include
rm *.o
scons
# Move all Object Files into Build Directory
cp *.o ../build
cd ..

When your script changes directories, that's a bit of global state information that you need to keep track of. That makes the script "brittle" — deleting or rearranging a few lines of the script can have massive effects on all subsequent commands. If you need to change directories, use a subshell as @janos suggested. Better yet, avoid changing directories at all, if possible — and you should be able to build a simple project like this without jumping around.

Why are there .o files in the include directory? By convention, a directory named include would only contain .h header files that are included elsewhere, and don't need to be compiled (unless you are using precompiled headers — but that's not the case here).

Why copy the .o files into the ../build directory? Find some way to get the compiler to produce them in the right place the first time (using the -o option). Copying is inefficient, messes up timestamps, and leaves unnecessary junk.


Your script violates the Single Responsibility Principle:

## When Everything is Finished Run the Kernel
qemu-system-i386 -kernel kernel.jos

If you advertise your script as a build script, then it should be just that. Imagine you were packaging this software as a component in a Linux distribution. Having such a line in the build script would be a serious annoyance.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks ! I will dump the bash script and Rewrite it in make . \$\endgroup\$ Dec 3 '15 at 8:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.