Getting a C++ compiler for Ndless
The more I work on nspire-gamekit, the more I think a object orientated programming language would be more suitable for the task. I’m currently playing around with C++ and getting it to work with the ndless SDK (which doesn’t natively support C++).
It is very likely I will consider making the whole project object orientated since it models the problem of game development much better. Overall it can produce cleaner looking code (the current example game has loads of static variables it’s not even funny).
So, if there are people who want to use C++ on ndless code, here is how you can get g++ working alongside the ndless SDK.
First, (if you haven’t already), install newlib for the arm architecture. Download it or check it out from CVS, cd into the directory and configure it with ./configure --target=arm-none-eabi
then the usual make
and make install
.
Next, we’ll need to compile g++ and have it work with ndless.
I configured my GCC installation with ../gcc-4.6.1/configure --target=arm-none-eabi --disable-libssp --disable-multilib --disable-nls --disable-threads --disable-shared --enable-languages=c,c++ --with-newlib --disable-newlib-supplied-syscalls
. Again, make
and make install
.
If you have trouble with redefinitions of “signal.h” like I did, simply delete the signal.h file in /usr/local/arm-none-eabi/include and replace it with an empty file.
Now, you need to go into your ndless/bin folder and copy nspire-gcc
to nspire-g++
. In the new file, change the last few lines so they look like this:
GCC=(which arm-elf-g++ arm-none-eabi-g++ arm-linux-gnueabi-g++ | head -1) 2>/dev/null
# -fno-builtin: We prefer to use syscalls. And GCC's builtins expansion (http://www.ciselant.de/projects/gcc_printf/gcc_printf.html)
# is incompatible with the inline definition of most syscalls.
"$GCC" -mcpu=arm926ej-s -I "$DIRNAME/../include" -fno-exceptions -nostdlib -fpic -fno-builtin "$@"
Pay special attention to adding -fno-exceptions -nostdlib
to the list of flags. We will be disabling built in functions and sacrificing being able to use exceptions since the ndless SDK doesn’t implement the required functions.
We also need to change the linker from GCC to G++ so the linker is capable of linking both C++ and C files. It also needs to insert some initialization logic for C++ into the final binary before main() is called.
Change your nspire-ld file so the last few lines look like this:
# some newlib symbols are not found if ld is used...
GCC=`(which arm-elf-g++ arm-none-eabi-g++ arm-linux-gnueabi-g++ | head -1) 2>/dev/null`
# lazy system build: must be built with the same toolchain
(cd "$DIRNAME/../system" && make -s all)
ret=$?
if [ $ret -ne 0 ]; then
exit $ret
fi
if [ $nostartup = false ]; then
[ $lightstartup = true ] && startupobj=crt0light.o || startupobj=crt0.o
args=("$DIRNAME/../system/$startupobj" "${args[@]}")
fi
# -nostartfiles: avoids newlib startup which would be added before ours
"$GCC" -nostartfiles -T "$DIRNAME/../system/ldscript" -e _nspire_start -L "$DIRNAME/../lib" -static "$DIRNAME/../system/crt0sym.o" "${args[@]}" -lndls -mcpu=arm9`
Lastly, in your code, you have to implement the new
and delete
operators using the ndless malloc()
and free()
. The built in functions uses the stubs in newlib I think so we can’t use that.
Somewhere in your code, implement this code:
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *p)
{
free(p);
}
void operator delete[](void *p)
{
free(p);
}
After all of the above modifications, your SDK should still work perfectly as before. You also now have a working C++ compiler!
Remember, you cannot use exceptions with this SDK since they require the use of unimplemented functions.