This tutorial shows you the basic usage of the GENDIST toolkit and explains the GENDIST concepts.
The tutorial shows you how to build a very simplistic Linux distribution, named ShellLinux. This distribution consists only of a kernel, a root-filesystem, a number of device nodes and a shell. If you have read the book "Just for Fun" from Linus Torvalds, you know that the first Linux-kernel was developed around the bash, since the bash uses most of the important system-calls.
The distribution is so simplistic, that you could also call it UselessLinux, but it should get you going with some more sensible stuff.
This tutorial assumes that you have installed GENDIST in /usr/local/gendist-version. You should read version as the current version number of GENDIST.
This is a step by step tutorial. The impatient users can install the example (including all files created within the tutorial) by switching to /usr/local/gendist-version/examples/ShellLinux and running 'make install PREFIX=/tmp' there.
Generating the basic build-system is straightforward:
# /usr/local/gendist-version/bin/gendist.sh -n ShellLinux -t all -p /tmp
The -n option gives the name of our distribution, with -t you can select the type of media and the -p option defines the prefix of the target directory. The target directory prefix/name is created automatically if it does not exist. If -p is ommitted, the current directory is used. Running gendist.sh with the switch -h will show all available options and types.
Since we want to experiment a bit with ShellLinux, we select all available types with -t all. The tradeoff is minimal: our build-system contains one additional makefile for every supported type.
The following screenshot shows the directories and files generated:
The toplevel directory contains some administrative files (e.g. README, NEWS, ChangeLog), the toplevel makefile and the file with the version information (version.inc).
The directories media and rules contain most of the logic of the build-system. Note that GENDIST is designed to be very flexible. One of the design-goals is that it is not necessary to change any of the generated makefiles, thus making it very easy to upgrade to a newer version of GENDIST.
The bin and doc-subdirectories are stubs for your own files. The src-directory contains the real-stuff.
The subdirectories of src contain the files which make up the distribution. All directories except the packages-directory contain some template files, the packages-directory itself is initially empty.
The build-system contains a number of help-targets. E.g.
# make help Toplevel makefile for ShellLinux Use 'make help-targets' for a list of targets 'make help-types' to show available types 'make help-params' to describe config-parameters 'make help-config' to show the current configuration 'make help-version' to show version information
The way the build-system works is controlled by a number of configuration variables. This is nothing special about GENDIST, it is a standard feature of make.
The current configuration is available with:
# make help-config Current configuration: TYPE: classic2 KERNEL: missing IMG_SIZE: 1440 RD_SIZE: 2600 RD_FS: minix RD_NODES: auto root-fs_PACKAGES: Type-specific configuration: no type specific configuration for type classic2
An explanation of these configuration variables is provided by 'make help-params' but they also should be self-explanatory (RD stands for ramdisk).
There are three possible ways to configure the build-system:
For our ShellLinux-project, we will use the latter two options. To begin, create a file config.inc with the following content:
# cat config.inc root-fs_PACKAGES := dirs dev shell libs RD_FS := ext2
With this file, and additional command-line parameters, 'make help-config' will now yield:
# make help-config TYPE=el-torito IMG_SIZE=2880 Current configuration: TYPE: el-torito KERNEL: missing IMG_SIZE: 2880 RD_SIZE: 2600 RD_FS: ext2 RD_NODES: auto root-fs_PACKAGES: dirs dev shell libs Type-specific configuration: IMG_TYPE: syslinux cd-fs_PACKAGES: MKISOFS_ARGS: -A "Bootable Linux CD created with ShellLinux 0.0.1" -V "ShellLinux 0.0.1" -p "Bablokb@canopus" -R
As you can see, the parameters in config.inc overwrite the defaults. The same is true for parameters passed on the command-line. The latter have the highest priority. So you can put your own default parameters in config.inc, and temporarily overwrite them from the command-line.
A note on the parameters in config.inc: most stock kernels don't have built-in support for minix (they support it using modules, but this is not enough for us). Therefore this example uses RD_FS=ext2. The default value (minix) will create smaller initial ramdisks, and if space is a problem, you should create a special-purpose kernel anyhow.
The second parameter, root-fs_PACKAGES lists all GENDIST-packages to go into the root-filesystem. The next section gives you details.
A GENDIST-package is not another package-format (there are enough of these around). Consider a GENDIST-package as a unit of work to do during the creation of the root-filesystem. The package can do anything, but it usually just copies or unpacks some files into the root-filesystem.
ShellLinux uses four packages:
Each package "lives" in it's own subdirectory underneath /tmp/ShellLinux/src/packages/root-fs. The dirs and dev packages are very simple: they only contain a makefile.
To create the packages, just create the directories and add the makefiles. The rules for creating package-level makefiles are simple:
You will find a template makefile in /tmp/ShellLinux/rules/Makefile.package. An example implementation for the dirs-package could look like this:
# cat /tmp/ShellLinux/src/packages/root-fs/dirs/Makefile DEP-PACKAGES := include $(DIST_ROOT)/rules/package.inc DIR_SET=bin boot cdrom dev etc floppy home lib mnt opt proc \ root sbin tmp usr var/log install: for d in $(DIR_SET); do \ mkdir -p $(TARGET_DIR)/$$d; \ done
The makefile for the dev-package is also simple:
# cat /tmp/ShellLinux/src/packages/root-fs/dev/Makefile DEP-PACKAGES := ../dirs include $(DIST_ROOT)/rules/package.inc DEV_SET := tty0 tty1 console ram ram0 ramdisk null install: tar -cpf - -C /dev $(DEV_SET) | tar -xpf - -C $(TARGET_DIR)/dev
As you can see, the dev-package depends on the dirs-package. The variable $(TARGET_DIR) always points to the directory, where the root-filesystem is built (the default value is /tmp/ShellLinux/build/root-fs).
Both makefiles show another useful technique. They define their own configuration variables. If for example you define "DEV_SET=." on the command-line, all devices in the current /dev-directory would be copied to the newly created root-fs.
The remaining two packages (shell and libs) are a bit more complicated. You can copy them from the /usr/local/gendist-version/examples/ShellLinux/files/src/packages/root-fs directory and have a look at them.
Now that you configured the build-system and added the packages, you can start creating disk-images of your target-media. At this point you also have to supply a kernel. Try the following:
# make KERNEL=path-to-your-kernel # ... (a lot of output) # ls -lAF build/media -rw-r--r-- 1 root root 1474560 Jan 20 17:55 ShellLinux-bootdsk.img -rw-r--r-- 1 root root 1474560 Jan 20 17:55 ShellLinux-rootdsk.img
You can copy these files to floppy-disks with:
# dd if=build/media/ShellLinux-bootdsk.img of=/dev/fd0 # dd if=build/media/ShellLinux-rootdsk.img of=/dev/fd0
If you have a CD-writer (and have installed the mkisofs-utility), you could also create an ISO9660-image with the command:
# make clean # make KERNEL=path-to-your-kernel TYPE=el-torito IMG_SIZE=2880 IMG_TYPE=syslinux # ... (a lot of output) # ls -lAF build/media -rw-r--r-- 1 root root 3006464 Jan 20 18:00 ShellLinux.iso
An El-Torito CD emulates a boot-disk. Since bash together with all it's dynamic libraries is so large that it does not fit together with a kernel on a single disk, we have increased the image size to 2.88MB.
Useful during development is an emulator, e.g. VmWare or Bochs (the latter is LGPLed but very, very slow). They work directly of the disk-images, so the turnaround time is much faster.
Now that everything is working, we want to change the version number of our distribution. Just calling 'make inc-dist-major' does the job (and sets the version to 1.0.0). Alternatives are 'make inc-dist-minor' to increase the minor version number or 'make inc-dist-pl' to increase the patch-level.
The last step is to create the distribution archives. At this point, you should also edit the administrative files in the toplevel directory (README, ChangeLog and NEWS). You should also add a LICENSE file, (the -g-option of gendist.sh adds the GPL as the license-file).
Creating distribution archives is simple. You have the choice between 'make src-dist', which creates a source-distribution including the build-system and all other files not removed by 'make distclean'. The alternative is 'make bin-dist', which only packages the administrative files and the generated disk-images (since 'make bin-dist' recreates the disk-images, you should pass all necessary parameters on the command-line).
# make bin-dist KERNEL=... # make src-dist # ls -lAF ShellLinux* -rw-r--r-- 1 root root 1372542 Jan 20 18:12 ShellLinux-1.0.0-bin.tar.bz2 -rw-r--r-- 1 root root 7158 Jan 20 18:12 ShellLinux-1.0.0-src.tar.bz2
Now that you know how to use the build-system, you should start with your own distribution. The main work will be to create appropriate packages. You can find additional examples in the various subdirectories of /usr/local/gendist-version/examples.
Reading documentation is not really fun (compared with programming), but if you are interessted in details (and want to use advanced features of GENDIST), you should take the time to read all sections of the documentation.