Syllable
Developing for Syllable
Essential tools

There are some essential tools that any developer will require. These include a compiler, a linker and an editor. All of these tools together are known as the toolchain.

Syllable uses a combination of the familiar GNU toolchain along with its own powerful and easy to use editors and applications. The GNU toolchain includes GCC, BinUtils, GDB, GNU Make and the GNU AutoTools (AutoMake and AutoConf).

On Syllable these tools are combined to create several packs. The Developer's Delight pack contains the essential GNU tools, as well as tools such as the Concurrent Versioning System (CVS), DoxyGen, SPLint and CScope. The Developer's Delight pack also contains Builder, a Syllable application that can build and pack software.

Depending on your goals, you may also need to install the other packs. The Perl Pit pack contains the Perl scripting language and the GNU AutoTools that are necessary for reconfiguring ported software.

Installing these packs is simple. First, you must log in as the root user. Then unzip the pack and run the install.sh script which will install the individual packages for you:


[root@machine:~]unzip DevelopersDelight-7.i586.zip
Archive: DevelopersDelight-7.i586.zip
creating: DevelopersDelight/
extracting: DevelopersDelight/Builder-0.6.100.bin.1.zip
inflating: DevelopersDelight/README
extracting: DevelopersDelight/arch-1.3.5.bin.1.zip
extracting: DevelopersDelight/binutils-2.17.bin.2.zip
extracting: DevelopersDelight/bison-2.3.bin.2.zip
extracting: DevelopersDelight/cscope-15.5.bin.2.zip
extracting: DevelopersDelight/cvs-1.12.11.bin.2.zip
extracting: DevelopersDelight/doxygen-1.5.1.bin.1.zip
extracting: DevelopersDelight/flex-2.5.33.bin.2.zip
extracting: DevelopersDelight/gcc-4.1.1.bin.2.zip
extracting: DevelopersDelight/gdb-6.4.bin.2.zip
extracting: DevelopersDelight/indent-2.2.9.bin.3.zip
inflating: DevelopersDelight/install.sh
extracting: DevelopersDelight/m4-1.4.7.bin.1.zip
extracting: DevelopersDelight/make-3.80.bin.2.zip
extracting: DevelopersDelight/nasm-0.98.39.bin.2.zip
extracting: DevelopersDelight/patch-2.5.4.bin.3.zip
extracting: DevelopersDelight/ruby-1.8.5.bin.1.zip
extracting: DevelopersDelight/sindent.bin.1.zip
extracting: DevelopersDelight/splint-3.1.1.bin.3.zip
[root@machine:~]cd DevelopersDelight
[root@machine:~/DevelopersDelight]./install.sh
This will install the packages contained in the developer pack. Previously
installed packages of the same name will be removed first. Do you want
to continue (y/N)?

The Perl Pit and other collection packs can be installed in the same way.

You can verify the installation if you wish:


[user@machine:~]gcc -v
Using built-in specs. Target: i586-pc-syllable
Configured with: /boot/atheos/home/kaj/build/gcc-4.1.1/./configure
--prefix=/resources/gcc
--enable-languages=c,c++ --with-arch=i586
--enable-sjlj-exceptions
--enable-shared --enable-threads
--with-system-zlib
--disable-libstdcxx-pch
Thread model: syllable
gcc version 4.1.1
[user@machine:~]
IDEs and Editors

Syllable has several different editors and an Integrated Development Environment (IDE) available.

sIDE

[sIDE, Sourcery and Layout Editor] Syllable has its own IDE called sIDE. sIDE includes a programmers editor (Sourcery) and a GUI editor (Layout Editor).

sIDE keeps your project files organised for you, and comes with various "templates" for different types of Syllable applications, including GUI and CLI based applications in C++ and C. sIDE can also create projects that use Layout Editor.

Sourcery has been designed for developers and its features include line numbering, syntax highlighting, code folding and automatic indenting. Sourcery is the default editor for use with sIDE, or you can use Sourcery without sIDE if you prefer.

Layout Editor makes it easy to design the GUI for your application. It has a preview window that shows you what your GUI looks like as you make changes within Layout Editor, from which it will automatically generate the C++ code that creates and displays the GUI at run time. Using Layout Editor saves you the hassle of having to manually layout the GUI and can significantly speed up development time. If you prefer you can create an sIDE project without using Layout Editor.

AEdit

AEdit is the default text editor that comes with Syllable. It is not a full-featured programmers editor. If you prefer a simpler editor than Sourcery, AEdit may suit you.

VIM

VIm is a venerable and powerful text editor that comes from Unix. If you already know VI you'll probably feel comfortable with it. If you're a VIm newbie, the VIm website contains more information.

Emacs

Although an old version of XEMacs (19.34) was once available for Syllable, it no longer runs on newer releases. There is no port of EMacs currently available for Syllable.

Other editors

If none of the above are what you are looking for in an editor, you may find something else in the Builder recipes.

Debugging tools

There are several tools and techniques you can use to debug your software.

GDB

The GNU debugger (GDB) is a well known debugger. If you have developed on other systems such as Linux or *BSD then you may have already used GDB, or a similiar Unix debugger.

GDB on Syllable currently only supports real-time debugging, as crashed applications do not generate a "core" file (crash dump). Real-time debugging using GDB on Syllable is fairly complete, although some support for multi-threaded applications has not yet been implemented.

GDB is a powerful dubugging tool, so unless you are already familiar with it you should read the GDB manual. GDB is included in the Developer's Delight pack.

Strace

STrace allows you to see what system calls your application is making, as it runs. This can be very useful for understanding what is happening "under the hood" of your application, and can also help with profiling. You can trace an application that is already running, or start an application under the control of STrace.

STrace is very simple to use. It's options are:

-oSwitch tracing "On"
-fSwitch tracing "Off"
-gSelect the syscall groups to include in the trace. The groups are:
mmAll system calls related to memory management e.g. sbrk().
procProcess related system calls e.g. fork().
deviceDevice related system calls.
netNetwork related system calls e.g. recvmsg().
signalProcess signal related system calls e.g. kill().
ipcInterprocess Communication (IPC) related calls, e.g. create_msg_port().
ioInput/Ouput related system calls e.g. read().
debugDebugging system calls e.g. ptrace().
miscSystem calls that do not fit in any of the above catagories.
allAll of the above system call groups.
More than one group can be passed by separating them with a comma e.g. -g net,io will select all system calls in the net and io syscall groups.
-eExclude a given syscall from tracing. The syscall can be given by name, e.g. -e lock_semaphore will exclude all calls to lock_semaphore() from the trace.
-iInclude the given syscall. The oposite of -e.
-tThe thread ID (TID) to trace. You can use this to begin tracing an application that is already running.
-rRun an application with the supplied tracing arguments. You must specify the full path to the application you wish to run.

As an example, let's say you wanted to trace thread #41 and see what I/O and process syscalls it was making:


[user@machine:~]strace -o -g io,proc -t 41
Tracing thread 41, group mask 0x0042
[user@machine:~]

As a real example, let's trace a simple "Hello World" application:


[user@machine:~]strace -o -g all -r ./hello
Hello world!
[user@machine:~]

This produces the following trace:


0:strace::strace : ---->> 945 = get_thread_id("")
0:strace::strace : ---->> 275 = get_process_id("")
0:strace::strace : ---->> 3 = open("./hello", 0x0, (? 0))
0:strace::strace : ---->> 256 = read(3, 0xffffb9a3, 256)
0:strace::strace : ---->> 0 = close(3)
0:hello::hello : ---->> 0 = execve("./hello", 0x88000028, 0xffffbc18)
0:hello::hello : ---->> 1 = create_semaphore("libc_lock", 1, 0x0)
0:hello::hello : ---->> EOK = raw_lock_semaphore_x(1, 1, 0x0, 4294949728)
0:hello::hello : ---->> EOK = unlock_semaphore_x(1, 1, 0xa00f9000)
0:hello::hello : ---->> 0 = get_image_info(0, -1, 0xffffba58)
0:hello::hello : ---->> 0 = get_image_info(0, 0, 0xffffba58)
0:hello::hello : ---->> 0 = get_image_info(1, 0, 0xffffba58)
0:hello::hello : ---->> 0 = get_image_info(0, 1, 0xffffba58)
0:hello::hello : ---->> EOK = raw_lock_semaphore_x(1, 1, 0x0, 4294949728)
0:hello::hello : ---->> EOK = unlock_semaphore_x(1, 1, 0xa00f9000)
0:hello::hello : ---->> 0 = fstat(1, 0xffffbaa0)
0:hello::hello : ---->> 0 = ioctl(1, 21509, 0xffffba6c)
0:hello::hello : ---->> 2 = create_semaphore("libc_lock", 1, 0x0)
0:hello::hello : ---->> EOK = raw_lock_semaphore_x(2, 1, 0x0, 4294949432)
0:hello::hello : ---->> ? = sbrk(143360)
0:hello::hello : ---->> ? = sbrk(0)
0:hello::hello : ---->> EOK = unlock_semaphore_x(2, 1, 0xa00f9000)
0:hello::hello : ---->> 13 = write(1, 0x88000008, 13)
0:hello::hello : ---->> 0 = get_image_info(0, -1, 0xffffba00)
0:hello::hello : ---->> 0 = get_image_info(0, 0, 0xffffba00)
0:hello::hello : ---->> 0 = get_image_info(1, 0, 0xffffba00)
0:hello::hello : ---->> 0 = get_image_info(0, 1, 0xffffba00)
0:hello::hello : ---->> 3 = create_semaphore("libc_lock", 1, 0x0)
0:hello::hello : ---->> EOK = raw_lock_semaphore_x(3, 1, 0x0, 4294949712)
0:hello::hello : ---->> EOK = unlock_semaphore_x(3, 1, 0xa00f9000)

As the application is traced the syscall information is printed by the kernel debugger. You can watch the trace happening by watching the kernel log.

The kernel log

The Syllable kernel includes a simple, but very useful, kernel debugger. While Syllable is running, the output from the kernel debugger is written to the "kernel log". The kernel log file is /var/log/kernel.

It is a simple matter of using the tail command to read the kernel log as it is being written by the kernel debugger:


[user@machine:~]tail -f /var/log/kernel

This will display the kernel log in the terminal. This can be used to watch the output produced as you use STrace, but the kernel can also provide useful debugging information of its own. If an application crashes the kernel will produce a "stack trace" that shows the processor registers, memory area information and a backtrace of the functions that were called upto the point of the crash.

The following example application will cause a segmentation fault:

void foo( void )
{
  int *a = (int*)0;
*a = 1;
}

int main( void )
{
foo();
return 0;
}

If we compile and run this application it will crash with a segmentation fault. The following output is produced in the kernel log:


0:crash::crash : Invalid pagefault at 00000000 (NOTP:WRITE:USER)
0:crash::crash : EAX = 00000000 : EBX = 800017c4 : ECX = ffffbba4 : EDX = a00fa038
0:crash::crash : ESI = 00000001 : EDI = ffffbc08 : EBP = ffffbb88
0:crash::crash : SS::ESP = 0023::ffffbb78
0:crash::crash : CS::EIP = 0013::800005f4
0:crash::crash : DS = 0023 : ES = 0023 : FS = 0023 : GS = 00c0
0:crash::crash : EFLAGS = 00213286 (PF SF IF RF ID )
0:crash::crash : CPU ID = 0 : kernel stack = 04983014
0:crash::crash : 0 -> 800005f4
0:crash::crash : crash + 000005f4 -> foo + 00000010
0:crash::crash : 1 -> 8000061c
0:crash::crash : crash + 0000061c -> main + 00000020
0:crash::crash : 2 -> a001c389
0:crash::crash : libc.so.2 + 00014389 -> __libc_start_main + 000000b9
0:crash::crash : 3 -> 80000515
0:crash::crash : crash + 00000515 -> _start + 00000025
0:crash::crash : verify_area() got kernel address 00000000
0:crash::crash : 0:crash::crash : Areas :
0:crash::crash : Area 0000 (19999) -> 0x80000000-0x80000fff 0x03e75558 01 ro_crash
0:crash::crash : Area 0001 (20000) -> 0x80001000-0x80001fff 0x03e75558 01 rw_crash
0:crash::crash : Area 0002 (20001) -> 0xa0000000-0xa0006fff 0x00d8cb18 01 ro_libgcc_s.so.3
0:crash::crash : Area 0003 (20002) -> 0xa0007000-0xa0007fff 0x00d8cb18 01 rw_libgcc_s.so.3
0:crash::crash : Area 0004 (20003) -> 0xa0008000-0xa00f5fff 0x00d8cb98 01 ro_libc.so.2
0:crash::crash : Area 0005 (20004) -> 0xa00f6000-0xa00fdfff 0x00d8cb98 01 rw_libc.so.2
0:crash::crash : Area 0006 (20005) -> 0xffc00000-0xffffffff 0x00000000 01 main_stack
0:crash::crash : 0 -> 800005f4
0:crash::crash : crash + 000005f4 -> foo + 00000010
0:crash::crash : 1 -> 8000061c
0:crash::crash : crash + 0000061c -> main + 00000020
0:crash::crash : 2 -> a001c389
0:crash::crash : libc.so.2 + 00014389 -> __libc_start_main + 000000b9
0:crash::crash : 3 -> 80000515
0:crash::crash : crash + 00000515 -> _start + 00000025
0:crash::crash : verify_area() got kernel address 00000000
0:crash::crash : Killed by signal 11

The kernel log can be a very powerful debugging tool once you are familiar with it.

Builder

Builder is a powerful application for Syllable developers that can be used to build both third-party applications and Syllable itself, from source code. To do this, Builder uses "recipes" which tell it what steps are required to download, unpack, patch, configure, build, test, install, register and package the software on Syllable.

Using Builder is incredibly easy. From a Terminal you simply run build <recipe>, and Builder will do the rest. You can then run build install <recipe> to install the new software. An example of building GNU Gettext is:


[user@machine:~/]build gettext-0.15
...
[user@machine:~/]su -l
...
[user@machine:~/]build install gettext-0.15
...

Builder is intended as a developer tool only and will not attempt to perform any dependendency management for you, so you should not use it to attempt to upgrade individual system components. You may also find that many of the packages or libraries you require are already available as binaries from the Syllable resource package downloads.

If you are porting software to Syllable, you are strongly encouraged to write a suitable Builder recipe for it. This makes it much easier to maintain and upgrade the software. There are a large number of existing recipes already available, and the skeleton recipe details every option currently available.