$VER: SPOT'S PORTING FOR DUMMIES 1.7.8 ====================================== INDEX ===== 00) Quick Reference 01) Why should I read this? I can't code! 02) History 03) What to port 04) Getting the SDK up to date -Essentials -Languages -Misc -Misc Linklibs 05) The basics 06) How to configure -Newlib or Clib2? -For newlib -For clib -For cygnix -Configuring a link library -Tricky configures -A small hint -Explanation of some GCC flags 07) Common errors that occur when configuring 08) Converting unix path's to Amiga path's 09) Defines 10) Understanding error messages 11) Errors and how to fix them -Common errors -Not so commong errors 12) Tips and tricks 13) Creating a Makefile by hand 14) Converting a Windows makefile into an AmigaOS makefile -Fixing the sources 15) Creating a GUI using Emperor (Alpha!) 16) Compiling SDL/GL apps 17) Adding support for AmiUpdate 18) Help me! 19) Contact me 20) Thanks 00) QUICK REFERENCE =================== For lazy geezers like me, I use these lines a lot and I don't want to wade through the guide to find them all the time, if you are new to this guide, just skip this chapter for now. NEWLIB CONFIGURE QUICK REFERENCE Finetuned for SDL projects. sh ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix" LDFLAGS=-mcrt=newlib Finetuned for SDL projects with old configure scripts, see COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING. CC=gcc CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix" LDFLAGS=-mcrt=newlib ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib For generic non-SDL projects. sh ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lauto -lunix" LDFLAGS=-mcrt=newlib For generic non-SDL projects with old configure scripts, see COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING. CC=gcc CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lauto -lunix" LDFLAGS=-mcrt=newlib ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib For link libraries with headers in SDK:Local/common/include/ sh ./configure --disable-shared --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib --includedir=/SDK/Local/common/include CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS=-lauto LDFLAGS=-mcrt=newlib For link libraries with headers in SDK:Local/newlib/include/ sh ./configure --disable-shared --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib --includedir=/SDK/Local/newlib/include CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS=-lauto LDFLAGS=-mcrt=newlib For old link libraries with headers in SDK:Local/newlib/include/ (see COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING) CC=gcc CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lauto -lunix" LDFLAGS=-mcrt=newlib ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib --includedir=/SDK/Local/newlib/include CLIB2 CONFIGURE QUICK REFERENCE Finetuned for SDL projects. (Type 'SH PATH=/SDK/Local/clib2/bin:$PATH' first!) sh ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix" LDFLAGS=-mcrt=clib2 Finetuned for SDL projects with old configure scripts. See COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING. (type PATH=/SDK/Local/clib2/bin:$PATH from ABC-Shell first!) CC=gcc CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix" LDFLAGS=-mcrt=clib2 ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib For generic non-SDL projects. (Type 'sh PATH=/SDK/Local/clib2/bin:$PATH' first!) sh ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 For generic non-SDL projects with old configure scripts. See COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING. (type sh PATH=/SDK/Local/clib2/bin:$PATH from ABC-Shell first!) CC=gcc CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib For link libraries with headers in SDK:Local/common/include/ (Type 'sh PATH=/SDK/Local/clib2/bin:$PATH' first!) sh ./configure --disable-shared --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib --includedir=/SDK/Local/common/include CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS=-lauto LDFLAGS=-mcrt=clib2 For link libraries with headers in SDK:Local/clib2/include/ (use this one if you want to make a clib2 only version) (Type 'sh PATH=/SDK/Local/clib2/bin:$PATH' first!) sh ./configure --disable-shared --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib --includedir=/SDK/Local/clib2/include CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS=-lauto LDFLAGS=-mcrt=clib2 For old link libraries with headers in SDK:Local/common/include/ (See COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING) (Type 'sh PATH=/SDK/Local/clib2/bin:$PATH' first!) CC=gcc CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib --includedir=/SDK/Local/common/include COMPILING SDL PROJECTS THE HARDCORE WAY WITHOUT MAKEFILES (Use ABC-Shell) g++ -mcrt=newlib -Wall -O2 -I/sdk/local/newlib/include/SDL -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -c *.cpp g++ -mcrt=newlib -Wall -O2 *.o -mcrt=newlib -lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix -o test gcc -mcrt=newlib -Wall -O2 -I/sdk/local/newlib/include/SDL -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -c *.c gcc -mcrt=newlib -Wall -O2 *.o -mcrt=newlib -lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix -o test COMPILING ALLEGRO PROJECTS THE HARDCORE WAY WITHOUT MAKEFILES (Use ABC-Shell) g++ -mcrt=newlib -Wall -O2 -Wno-deprecated-declarations -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -c *.cpp g++ -mcrt=newlib -Wall -O2 *.o -lal2xsai -lalmp3 -lalogg -laldumb -lalfont -lldpng -lpng -lz -laljpgalleg -lalfblend -lalagup -lallegro -lpthread -lstdc++ -lauto -lunix -o test gcc -mcrt=newlib -Wall -O2 -Wno-deprecated-declarations -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -c *.c gcc -mcrt=newlib -Wall -O2 *.o -lal2xsai -lalmp3 -lalogg -laldumb -lalfont -lldpng -lpng -lz -laljpgalleg -lalfblend -lalagup -lallegro -lpthread -lstdc++ -lauto -lunix -o test 01) WHY SHOULD I READ THIS? I CAN'T CODE! ========================================= Well, the sad fact is that, neither can I! :) I am just a stubborn geezer! And look at me now... 300+ uploads to http://os4depot.net compiling multiplatform stuff for AmigaOS 4.0 isn't THAT hard, c'mon! If I can do it, you can do it too! You'll jump up and down screaming when you manage to compile your first SDL app, I did! To my defence I have to say that I had to figure out a lot of the process the hard way! :P /Spot 02) HISTORY =========== Version 1.7.8 Added a new common error. Version 1.7.7 Added a new common error. Version 1.7.6 Added a new not so common error, thanx to Zerohero for the help with the solution! Version 1.7.5 Added a new (advanced) chapter written by Rigo, on how to deal with AmiUpdate. Thanx for letting me use it Rigo! Version 1.7.4 Minor tweaks to the configure lines. Version 1.7.3 Added a new error and a solution submitted by Blacky_Stardust. Thanx a lot man! Version 1.7.2 Added a tip on how to add AmigaOS version strings to your exes to the tips and tricks chapter. Version 1.7.1 Added configure lines finetuned for SDL projects to the quick reference section. Thid should help newbies get rid of linking errors and save me from wasting time on makefile editing. Dunno why I didn't do this before. Cleaned up the Quick Reference guide, I hope it is much clearer now. Version 1.7.0 Added -ltiff to the CFLAGS, as my latest compile of SDL_Image needs and supports it. Version 1.6.9 Added a new common error to chapter 07. Version 1.6.8 Added some URL's to the 'What to Port' chapter. Version 1.6.7 Added a really weird 'not so common error' that costed me some hair! Grrr! Version 1.6.6 Added a new subchapter 'Newlib or Clib2?' Added some clarifications to the quick references. Thanx to Lio for the feedback! Added some new stuff to 'Tips and Tricks' Added a 'not so common error' Version 1.6.5 Added a new 'not so common error' Version 1.6.4 Added a new chapter 'Compiling SDL/GL apps' Added a new tip to the 'Common errors that can occur when configuring' chapter. Version 1.6.3 Added a new chapter: 'Converting a Windows makefile into an AmigaOS makefile' Version 1.6.2 Extended the common error section with a small guide on how to find out what header is missing. Version 1.6.1 Misc small changes and additional info 'backported' from the AROS 'port' of this guide. Version 1.6.0 Added a guide on how to make GUI's using Emperor. Added lots of small things that I can't remember. Version 1.5.3 Added a tip on Fullscreen modes in SDL apps/games. Thanks Lio. Added some quick references related to Allegro compiling. Woooot? Already? ;) Version 1.5.2 Corrected some small things related to SDL_Mixer Version 1.5.1 Added SVN to tips and tricks Version 1.5 Fixed a typo. I had writen -lpng -lpng, when it should be -lpng -ljpeg. Thanx to Raziel for the report. Added a new chapter: History Added a new chapter: Getting your SDK up to date Added a new chapter: The basics Added a new chapter: Configuring linklibs Added a new chapter: Quick Reference Added more common errors Defines section updated Common errors section updated Corrections to the configure lines. Thanx HNL! Corrections to the example makefile. Thanx Booger! A lot of small changes that I can't remember. Corrected the cygnix config line. 03) What to port? ================= Look what additional packages are required for the software you want to port. You cannot simply port when GUI toolkits like GTK or QT are needed. Only software which runs under a console can be ported directly. When you want to port games, look if they use libSDL. Avoid software which requires OpenGL. Here's some good sources for open source games and apps using SDL or Allegro; http://www.happypenguin.org http://www.allegro.cc http://www.libsdl.org 04) GETTING THE SDK UP TO DATE ============================== Lots of parts of the SDK have been updated since the last official release, so install the following libs to get an up to date SDK. This is especially important for the SDL libs, as the ones included in the SDK are buggy. ESSENTIALS ABC-Shell - Amiga Bourne Compatible Shell http://www.os4depot.net/share/development/utility/abc-shell.lha GNU make including parallel compile http://www.os4depot.net/share/development/utility/make-bin.lha Diffutils - file comparison tools http://www.os4depot.net/share/development/utility/diffutils-hnl.lha m4 - Unix macro processor http://www.os4depot.net/share/development/misc/m4.lha GNU core utilities http://www.os4depot.net/share/development/utility/coreutils-bin.lha Texinfo - GNU documentation system http://www.os4depot.net/share/development/misc/texinfo-bin.lha clib2 http://sourceforge.net/project/showfiles.php?group_id=115224 LANGUAGES Free Pascal Compiler http://os4depot.net/share/development/language/fpc.lha Perl 5.8.5 http://www.os4depot.net/share/development/language/perl.tar.bz2 Lua - powerful embeddable programming language http://os4depot.net/share/development/language/lua.lha MISC Boost C++ libraries http://os4depot.net/share/development/library/boost.lha Expat C library for parsing XML http://os4depot.net/share/development/library/expat-ppc.lha GNU termcap library http://os4depot.net/share/development/library/termcap.lha MISC LINKLIBS LibCurl - the multiprotocol file transfer library http://os4depot.net/share/development/library/libcurl.lha libFreetype2 http://www.os4depot.net/share/library/misc/freetype2.lha libJPEG http://www.rcdrummond.net/amiga/libjpeg-6b.lha libODE - ODE and Opcode http://os4depot.net/share/development/library/ode.tgz libOGG http://www.rcdrummond.net/amiga/libogg-1.1.lha libOpenSSL - OpenSSL: The Open Source toolkit for SSL/TLS http://os4depot.net/share/development/library/libopenssl.lha libPNG http://www.rcdrummond.net/amiga/libpng-1.2.6.lha libSDL_gfx http://os4depot.net/share/development/library/sdl_gfx.lha libSDL_perl http://os4depot.net/share/development/library/sdl_perl.tar.bz2 libSDL_ttf and libSDL_net http://os4depot.net/share/development/library/sdl_ttf_net.lha libVorbis http://www.rcdrummond.net/amiga/libvorbis-1.0.1.lha libXML2 - The XML C parser and toolkit of Gnome http://os4depot.net/share/development/library/libxml2.lha zlib http://www.rcdrummond.net/amiga/zlib-1.2.1.lha 05) THE BASICS ============== The first thing you do is to check how to build your project. If there is a file called configure in the root directory of the archive, it means you'll have to configure it for your platform. Start ABC-Shell by typing 'sh' in your shell, and configure it. See the next chapter for a description on how to do that. After the project is properly configured it's time to roll out the compiler. Start building your project by typing 'GMAKE'. However, if there was no file called Configure, look for a file called Makefile. Edit it to suit AmigaOS 4.0 and build the project with 'GMAKE'. If everything compiled and linked you are ready to test your port. A very common problem is that it won't find it's datafiles, and crash. Fix the path's as described in the path-fixing chapter, and try to run it again. If you've compiled a link library a 'GMAKE INSTALL' is recommended, as it will copy all neeeded files to the right places. OK, you're done now, upload it to os4depot and aminet! 06) HOW TO CONFIGURE ==================== NEWLIB OR CLIB2? A Clib is a library with standard functions used by all apps written in C. Newlib is the official C library for OS4, so always try to configure for newlib first. It is also a shared library, which CLib2 isn't, so your binaries will be smaller. If you get errors when compiling, you could try using CLib2 as it has some unix functions that are missing in Newlib. FOR NEWLIB ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lauto -lunix" LDFLAGS=-mcrt=newlib Use the same line if you are going to compile a linklibrary, but if you want to compile exclusively for newlib or clib2 change /common/ to clib2 or newlib. FOR CLIB2 If you want to configure for CLIB2, first fix the PATH, start ABC-Shell by typing 'sh' in Amiga-Shell and then type; PATH=/SDK/Local/clib2/bin:$PATH ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 Use the same line if you are going to compile a linklibrary, but if you want to compile exclusively for newlib or clib2 change /common/ to clib2 or newlib. FOR CYGNIX CFLAGS="-O2 -mcrt=clib2 -I/usr/X11R6.3/include/ -I/usr/include" LDFLAGS="-L/usr/X11R6.3/lib -laos4util -L/usr/lib -lunix -lnet -lamiga -lm -lauto" CPPFLAGS="-O2 -I/usr/X11R6.3/include -I/usr/local/include -I/usr/include" LIBS="-L/usr/X11R6.3/lib -laos4util -L/usr/local/lib -L/usr/lib -lunix -lnet -lm -lamiga -lauto" ./configure CONFIGURING A LINK LIBRARY When configuring a linklib we need an extra option, --includedir= this is to specify where to install the header files. Use /common/ if you are going to compile the linklib for both clib2 and newlib. Change it to /newlib/ or /clib2/ if you are going to compile for just one of them. It's recommended to make versions for both when possible. Here's the example configure lines; NEWLIB with headers in .../common/include/ (Use this if you intend to compile for both newlib and clib2.) ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib --includedir=/SDK/Local/common/include CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL" CXXFLAGS=-mcrt=newlib LIBS=-lauto LDFLAGS=-mcrt=newlib NEWLIB with headers in .../newlib/include/ (Use this if you intend to compile for newlib only.) ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib --includedir=/SDK/Local/newlib/include CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL" CXXFLAGS=-mcrt=newlib LIBS=-lauto LDFLAGS=-mcrt=newlib CLIB2 with headers in .../common/include/ (Use this if you intend to compile for both clib2 and newlib.) ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib --includedir=/SDK/Local/common/include CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL" CXXFLAGS=-mcrt=clib2 LIBS=-lauto LDFLAGS=-mcrt=clib2 CLIB2 with headers in .../clib2/include/ (Use this if you intend to compile for clib2 only.) ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib --includedir=/SDK/Local/clib2/include CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL" CXXFLAGS=-mcrt=clib2 LIBS=-lauto LDFLAGS=-mcrt=clib2 TRICKY CONFIGURES Some configure scripts just don't want to do what you want them to, here's some real world examples, from when I have had to tweak a configure script by issuing some flags; Xmoto configured without Automake (notice the amigaos path fix: --srcdir=/Scene/Coding/xmoto-0.2.4); ./configure --disable-dependency-tracking --srcdir=/Scene/Coding/xmoto-0.2.4 --datadir=/PROGDIR/ --bindir=/SDK/Local/C --prefix=/PROGDIR/ CFLAGS=-mcrt=clib2 CXXFLAGS="-mcrt=clib2 -DMINIGL" LIBS="-mcrt=clib2 -lGL -lGLU -llua -lode -lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix" --with-sdl-prefix=/sdk/local/clib2 And some manual changes to the Xmoto Makefile; remove: $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) ... from LINK remove: $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) ... from CXXLINK libXML: ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -DLIBXML_DOTTED_VERSION=2.6.26 -DLIBXML_TEST_VERSION=20626 -DLIBXML_VERSION=20626 -DLIBXML_VERSION_STRING=20626" CXXFLAGS=-mcrt=clib2 LIBS=-lunix LDFLAGS=-mcrt=clib2 GNGEO: Notice the UNIX path fix at the end (pkgdatadir=/PROGDIR/data) ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 pkgdatadir=/PROGDIR/data A SMALL HINT It makes sense to write the configure statement to a text file. This way we can easily re-run it like this 'sh mybuildscript.sh' But before we re-run the script we have to do 'gmake distclean' or 'rm -f config.cache' (the unix way) or simply 'delete config.cache' (the Amiga way) in order to reset the configuration process. EXPLANATION OF SOME GCC FLAGS LDLAGS="-lunix" This enables Linux semantics for paths. Linux applications often use absolute paths to their data files. But an absolute Linux path like /usr/local/app means for AmigaOS to go one level up, then go into the usr directory. --prefix=/PROGDIR Prefixes all paths with /PROGDIR. Together with the -lunix option this allows to use Linux paths during compiling and AmigaOS paths when running the exe. 07) COMMON ERRORS THAT CAN OCCUR WHEN CONFIGURING ================================================= It's a VERY good idea to ALWAYS add this argument to your configure line; --srcdir=/DH1/Path/To/MyProject/ It cures a LOT of configure related problems. I get errors like this; configure: warning: CFLAGS=-mcrt=newlib: invalid host type Solution; The configure script is probably old, don't worry, we can still use it, but we have to issue the commands a little bit differently. Here's how; FOR NEWLIB (Old Configure script) CC=gcc CFLAGS=-mcrt=newlib CPPFLAGS="-mcrt=newlib -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=newlib LIBS="-lauto -lunix" LDFLAGS=-mcrt=newlib ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/newlib/lib FOR CLIB2 (Old Configure script) CC=gcc CFLAGS=-mcrt=clib2 CPPFLAGS="-mcrt=clib2 -DMINIGL -D__USE_INLINE__" CXXFLAGS=-mcrt=clib2 LIBS="-lauto -lunix" LDFLAGS=-mcrt=clib2 ./configure --disable-dependency-tracking --bindir=/SDK/Local/C --prefix=/SDK/Local --libdir=/SDK/Local/clib2/lib I get errors like this; configure: error: C compiler cannot create executables Solution; AmigaOS doesn't support the -pipe and -s flags. Remove the -pipe and -s flags from the configure script. (The file called 'Configure'). I get errors with libpng and libtiff; checking for png_create_read_struct in -lpng... no checking for TIFFClientOpen in -ltiff... no Solution; Edit the configure script, add -lz after -lpng and -ltiff. I get errors like this; checking for IMG_Load in -lSDL_image... no Solution; We are linking with static libraries, and we need to be tell exactly what to link in. Locate this line in the configure script; LIBS="-lSDL_image $LIBS" SDL_image depends on some more libraries to function correctly, add them like this; LIBS="-lSDL_image -ltiff -lpng -ljpeg -lz $LIBS" I get errors like this; checking for Mix_OpenAudio in -lSDL_mixer... no Solution; We are linking with static libraries, and we need to tell exactly what to link in. Locate this line in the configure script; LIBS="-lSDL_mixer $LIBS" SDL_mixer depends on some more libraries to function correctly, add them like this; LIBS="-lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ $LIBS" The same thing also often happens when configure is searching for SDL_ttf, and you know why by now. We need to specify some more libs that SDL_ttf depends on. It needs -lfreetype and -lz. I will leave the rest to you as an excersize. If you have added the needed dependencies to the configure script, and it still doesn't work it can be due missing files in the SDK. freetype-config and smpeg-config are missing in the archives available on http://www.os4depot.net. I compiled my libs by myself to get the missing files, but hopefully the authors of the AmigaOS 4.0 versions will notice and fix these issues. Another common problem are wrong paths in the .la files found in SDK:Local/newlib/lib or SDK:Local/clib2/lib. Check your .la files to see if they are configured correctly, locate the following lines; # Directory that this library needs to be installed in: libdir='/SDK/Local/newlib/lib' This one is set up correctly, notice libdir='/SDK/Local...' if it's set to '/USR/Local...' it's wrong. If it still doesn't work, and you are sure that you have the library installed, try to remove the whole section where it checks for the failing library in the configure file. This is not recommended, but if there is no other way... Now you should be ready to build your project. When porting unix apps always type GMAKE. MAKE is for Amiga projects only. 08) CONVERTING UNIX PATH'S TO AMIGA PATHS ========================================= How do I convert UNIX paths into AmigaDOS paths? Exchange getenv("HOME"); to "/PROGDIR/" Examples; org: strcpy(path, getenv("HOME")); new: strcpy(path, "/PROGDIR/"); org: strcpy(home,getenv("HOME")); new: strcpy(home,"/PROGDIR/"); old: sprintf(rc_dir, "%s/.gngeo/romrc.d", getenv("HOME")); new: sprintf(rc_dir, "%sgngeo/romrc.d", "/PROGDIR/"); Notice that I removed "/." in the last example. Paths to datadirs are often set during the configure process by issuing -DDATADIR= if this is the case set it to -DDATADIR=/PROGDIR/ It's also common that the datadir are set in the makefiles locate DATADIR= and change it to DATADIR=/PROGDIR/ 08) DEFINES =========== Defines are often set in config.h, if something is configured wrongly, you can often change it here by using #DEFINE and #UNDEF. A define example that considers all AmigaOS flavours; #ifdef __AMIGA__ blah blah blah #else blah blah blah #endif A define example that only considers AmigaOS 4.0; #ifdef __amigaos4__ blah blah blah #else blah blah blah #endif A define example, that considers BeOS and AmigaOS 4.0; #if !defined(__BEOS__) && !defined(__amigaos4__) An example of a more complex #ifdef #ifdef GP2X char *gngeo_dir="save/"; #elif defined __amiga__ char *gngeo_dir="/PROGDIR/save/"; #else char *gngeo_dir=get_gngeo_dir(); #endif 10) UNDERSTANDING ERROR MESSAGES ================================ Error: No return statement in function returning non-void What does it really mean? There is no return in a function that needs a return. Error: Control reaches end of non-void function What does it really mean? it is reaching the end of a function that needs a return, but there is no return. Error: May be used uninitialized in this function What does it really mean? The variable is not initialized. Error: Warning: implicit declaration of function 'blah blah' What does it really mean? You need to include a header. 11) ERRORS AND HOW TO FIX THEM ============================== COMMON ERRORS If you can't find the answer here, it's usually a good idea to google the error message, for example, enter warning: implicit declaration of function 'strlen' and in many cases the sollution will be there for you. In general, when you get an error of this type; warning: implicit declaration of function 'strlen' warning: incompatible implicit declaration of built-in function 'strlen' It means that the sources are missing an include. To find out which include it wants, open a shell and CD to SDK: then do; "grep -R strlen *" in this case you will get a LOT of output, so having KingCon installed is a good idea. 99% of the info printed is irrelevant, what you are looking for is a header that includes the function the source wants. Includes are stored in SDK:Local/Newlib/Include, SDK:Local/Common/Include, SDK:Local/Clib2/Include, SDK:newlib/Include/ and SDK:Clib2/Include. So only check the hits found in those directories. For the lazy bunch, i've included the most common ones here; warning: incompatible implicit declaration of built-in function 'exit' warning: incompatible implicit declaration of built-in function 'abort' solution: #include warning: implicit declaration of function 'strlen' warning: incompatible implicit declaration of built-in function 'strlen' solution: #include warning: implicit declaration of function 'memcpy' warning: incompatible implicit declaration of built-in function 'memcpy' solution: #include error: memory.h: No such file or directory solution: #include error: malloc.h: No such file or directory solution: #include warning: incompatible implicit declaration of built-in function 'printf' solution: #include error: 'int64_t' undeclared (first use in this function) solution: #include warning: implicit declaration of function 'srandom' warning: implicit declaration of function 'random' solution: We don't have random() and srandom() in neither clib2 or newlib. You "could" use rand() and srand() instead they are not totally compatible, but it should work. One way to do it is to manually edit the sources and replac srandom and random with srand and rand. Another way to do it is to; #define srandom srand in the source. warning: implicit declaration of function 'MyRemove' solution: #define MyRemove Remove error: 'sqrtl' was not declared in this scope solution: #define sqrtl sqrt Fullscreen modes doesn't work in your newly ported SDL game? solution: try replacing SDL_HWSURFACE with SDL_SWSURFACE. error: conversion from 'float' to non-scalar type 'fix' requested solution: #include error: In file included from SDK:newlib/include/pthread.h:2, from tools.h:52, from bonus.c:30: SDK:local/common/include/pthread.h:39: error: redefinition of 'struct timespec' In file included from bonus.c:42: options_panel.h:64: error: redefinition of 'struct option' If a struct is defined in a source code that already exists in your dev headers but it is defined completely different, rename the struct in the source code to something else and change all references to it in the source code. Example: Defined in SDK sys/time.h: struct timeval { unsigned long tv_secs; unsigned long tv_micro; }; Defined in source code WRONG.H: struct timeval { unsigned char something; signed short something_else; }; In source code CLEAR.C: timeval hereitis; This would give a struct redefinition error. Solution: Rename the struct in wrong.h to some other name, timeval2 for example. and change the reference in clear.c to match the rename ( change to timeval2 hereitis; ) The working example would look like this; WRONG.H; struct timeval2 { unsigned char something; signed short something_else; }; CLEAR.C; timeval2 hereitis; NOT SO COMMON ERRORS I will put sollutions to not so common errors here, that I've managed to solve. Partly as a reminder to myself, but also as it might be handy for you. Here we go! If you get an error similiar to this one; ../include/xmpi.h:55: error: conflicting types for 'uint32' SDK:include/include_h/exec/types.h:94: error: previous declaration of 'uint32' was here check the mentioned line in xmpi.h it looks like this; typedef unsigned int uint32; It's clashing with a typedef in the SDK. To solve this, let's have a look at the other lines close to that one in xmpi.h; typedef signed char int8; typedef signed short int int16; typedef signed int int32; typedef unsigned char uint8; typedef unsigned short int uint16; typedef unsigned int uint32; We don't want to typedef these, as they are already present in our SDK in exec/types.h, so what we do is to make AOS4 ignore these lines and include like this; #ifdef __amigaos4__ #include #include #else typedef signed char int8; typedef signed short int int16; typedef signed int int32; typedef unsigned char uint8; typedef unsigned short int uint16; typedef unsigned int uint32; #endif If you get a requester stating; 'Unknown/unsupported Reloc' when you start your newly linked exe, and a message in shell stating something like this; 'syntax error: `((' unexpected' then check the makefiles for '-fPIC' and remove it. error: array bound forbidden after parenthesized type-id solution: The guilty line looks something like this; frames = new(BITMAP*)[number_of_frames]; remove the paranteses, so that it looks something like this; frames = new BITMAP*[number_of_frames]; error: stray '\26' in program solution: There's an single space on the last line, remove it. error: expected primary-expression before '=' token solution: in this case, a space needed to be removed. original line: if ( i > = 320 ) changed line: if ( i >= 320 ) 12) TIPS AND TRICKS =================== Add this line to your S:shell-startup to get easier access to this guide; Alias dummy multiview DH1:path/to/SpotsPortingForDummies.txt If you want to do the same for ABC-Shell, add this line to SDK:Data/abc-shell/variables; alias dummy="multiview DH1:path/to/SpotsPortingForDummies.txt" Now, whenever you are in AmigaShell or ABC-Shell just type dummy and hit enter, and you have the guide in your face, cut and paste away! How do I search for text strings using GREP? From ABC-Shell type; grep -R "I am looking for this" * How do I make a DIFF file with my changes? From ABC-Shell type; diff originalfile.cpp mychangedfile.cpp >./originalfile.patch My executeable is crashing, how do I debug it? You can use Snoopy to find out what your application tries to do. It's VERY common that the app doesn't find a file that it needs. Check the section about fixing UNIX path's to fix it. In the Grim Reaper, click generate stack trace under the Stack Trace tab. Now you'll see a lot of numbers and things. Now use addr2line to find out where in the source the crash occured. Here's an example; addr2line -e xmoto.exe 0x39c48 How do I use Python? Assign python: to your python dir, and then add it to your path from abc-shell: PATH=$PATH:/python How do I redirect GCC warnings and errors to a text file? gmake 2>/ram/warnings.txt How do I make a tar.gz archive out of my source dir? tar czvf myarchive.tar.gz mysources/ How do I fetch a source when all I have is an URL like this one? svn://svn.72dpiarmy.com/smw install Subversion aka SVN and type this in shell; svn checkout svn://svn.72dpiarmy.com/smw How do I redirect GCC warnings and errors to a text file? gmake 2>warnings.txt How do I add AmigaOS version strings to my binaries? Add this code to main.cpp #ifdef __amigaos4__ const char *version_tag = "$VER: xxxxxx 1.0 (01.01.2007)"; #endif 13) CREATING A MAKEFILE BY HAND =============================== AN EXAMPLE MAKEFILE this makefile could be used if the build system is a mess and you want to simplify it a bit, alter it to fit your needs. Usually you only need to modify an existing makefile, and add -mcrt=newlib or -mcrt=clib2, add these include paths; -I/sdk/local/newlib/include/SDL -I/sdk/local/common/include/SDL and add some linklibraries. Here's an explanation of what the flags does. CC - the name of the C compiler executeable CXX - the name of the C++ compiler executeable RM - the name of the delete command STRIP - the name of the strip command (used to remove debug data from exe files) CFLAGS - tells the compiler where to find the includes and what clib to use etc. specify -mcrt=newlib or -mcrt=clib2 here. LDFLAGS - tells the compiler what link libraries to include etc. specify -mcrt=newlib or -mcrt=clib2 here too, aswell as the other needed linklibs depending on what you are compiling. OBJS - The compiler (GCC/G++) compiles object files (#?.o) from your .C or .CPP files that are later linked together to become an exe file. Specify the object file names here. OUTPUT - The name of the final exe file. ---cut-here-------------------------------------------------------------------- CC = gcc -mcrt=newlib CXX = g++ -mcrt=newlib RM = rm STRIP = strip CFLAGS = -mcrt=newlib -Wall -O2 -I/sdk/local/newlib/include/SDL -I/sdk/local/common/include/SDL LDFLAGS = -mcrt=newlib -lSDL_gfx -lSDL_net -lSDL_image -ltiff -lpng -ljpeg -lz -lSDL_mixer -lsmpeg -lm -lvorbisfile -lvorbis -logg -lstdc++ -lSDL_ttf -lfreetype -lz -lsdlmain -lsdl -lauto -lpthread -lm -lunix OBJS = a.o b.o c.o OUTPUT = test.exe all: $(OBJS) $(CXX) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(OUTPUT) main.o: main.cpp main.h $(CXX) $(CFLAGS) -c main.cpp ---cut-here-------------------------------------------------------------------- 14) CONVERTING A WINDOWS MAKEFILE INTO AN AMIGA MAKEFILE ======================================================== When compiling an Allegro game for example, it often comes with a makefile for Windows, and obviously no makefile for AmigaOS. That's where you come in. I'll guide you through it step by step. The game used in the example is called Pikzels. Download it here, if you like; http://www.allegro.cc/files/depot/505/PikselzFinal.zip, extract it and load pikselzfinal/source/makefile.win into your favourite editor. You'll notice that it uses Windows line breaks, every other line is blank, which makes it harder to overview. If you are using CED you can fix that by marking everything and selecting 'Strip CR marked' in the Cut/Paste menu. No you should have a nicer layout to work with. The first thing we notice are these two lines; CPP = g++.exe CC = gcc.exe We have to get rid of the Windows extensions and tell GCC to use Newlib, like this; CPP = g++ -mcrt=newlib CC = gcc -mcrt=newlib Good, now GCC will be found. On to the next two lines; WINDRES = windres.exe RES = ../Obj/ErkleLnD_private.res I am not sure what windres does, I guess it's related to the windows build environment. We don't need it anyway. Remove those lines completely. On to the next line; OBJ = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o $(RES) Notice the $(RES) thingie at the end? It tries to fetch the parameters from the "RES = ../Obj/ErkleLnD_private.res" line that we removed. Not good. Remove $(RES) from that line, and also from the other lines where it occurs, in this case, it only occurs on Line 6 and 7. Those two lines shall look like this now; OBJ = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o LINKOBJ = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o On to the next line; LIBS = -L"lib" -lalleg -mwindows -lalleg This is where the libs to be used are specified. We don't need some of it. -mwindows has to go. -L"lib" too. I am a bit lazy, so I usually copy/paste my line from this guide, that has all allegro libs in it. The ones that aren't needed won't get used anyway. So make it look like this; LIBS = -mcrt=newlib -lalmp3 -laldumb -lalfont -lalfblend -lalagup -lallegro -lpthread -lstdc++ -lauto -lunix As I said, most of these aren't used by this game, but it doesn't matter. As GCC will just ignore them. Notice the -mcrt=newlib part, don't forget it, as it tells GCC to use Newlib when linking. On to the next two lines; INCS = -I"include" -I"../include" CXXINCS = -I"lib/gcc-lib/mingw32/3.3.1/include" -I"include/c++/3.3.1/backward" -I"include/c++/3.3.1/mingw32" -I"include/c++/3.3.1" -I"include" -I"H:/Common/Include" -I"H:/Libs/Lua/include" -I"../include" These lines tell GCC where to look for the needed includes that we specified on the LIBS line. The includes on the INCS = line are project specific, these are the includes for the game. We need those. The ones on the next line are windows specific. We don't need those. This is an allegro project, so we type the paths to our allegro includes, and add the game specific includes at the end; INCS = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include" -I"../include" CXXINCS = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include" -I"../include" I usually put the inclued path's on both those lines, just to make sure they get used. On to the next line; BIN = ../ErkleLnD.exe Change the windows path to an AmigaOS path like this; BIN = ErkleLnD.exe Do the same for these lines; all: all-before ../ErkleLnD.exe all-after $(CPP) $(LINKOBJ) -o "ErkleLnD.exe" $(LIBS) make them look like this; (Line 16) all: all-before ErkleLnD.exe all-after (Line 23) $(CPP) $(LINKOBJ) -o ErkleLnD.exe $(LIBS) OK, the flags seems to look fine now. At this stage i usually search the makefile for RES to make sure I haven't missed any occurances of it. Do that now. At the end of the makefile you'll find two lines that looks like this; ../Obj/ErkleLnD_private.res: ErkleLnD_private.rc $(WINDRES) -i ErkleLnD_private.rc --input-format=rc -o ../Obj/ErkleLnD_private.res -O coff They only deal with that WINDRES thing, remove them completely. Now save it as 'makefile.aos4'. I tidied up the makefile a bit (I lined up the = chars, to make it more readable) but you should now have a makefile that looks something like this; # Project: ErkleLnD # Makefile created by Dev-C++ 4.9.9.2 CPP = g++ -mcrt=newlib CC = gcc -mcrt=newlib OBJ = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o LINKOBJ = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o LIBS = -mcrt=newlib -lalmp3 -laldumb -lalfont -lalfblend -lalagup -lallegro -lpthread -lstdc++ -lauto -lunix INCS = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include" -I"../include" CXXINCS = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include" -I"../include" BIN = /ErkleLnD.exe CXXFLAGS = $(CXXINCS) -DALLEGRO_GUESS_INTTYPES_OK -fexpensive-optimizations -O3 CFLAGS = $(INCS) -DALLEGRO_GUESS_INTTYPES_OK -fexpensive-optimizations -O3 RM = rm -f .PHONY: all all-before all-after clean clean-custom all: all-before ErkleLnD.exe all-after clean: clean-custom ${RM} $(OBJ) $(BIN) $(BIN): $(OBJ) $(CPP) $(LINKOBJ) -o ErkleLnD.exe $(LIBS) ../Obj/Main.o: Main.cpp ../include/erkTypes.h ../include/erkMap.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h ../include/erkBmpGen.h $(CPP) -c Main.cpp -o ../Obj/Main.o $(CXXFLAGS) ../Obj/erkMap.o: erkMap.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkMap.cpp -o ../Obj/erkMap.o $(CXXFLAGS) ../Obj/erkTile.o: erkTile.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkTile.cpp -o ../Obj/erkTile.o $(CXXFLAGS) ../Obj/erkTileType.o: erkTileType.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h ../include/erkBmpGen.h $(CPP) -c erkTileType.cpp -o ../Obj/erkTileType.o $(CXXFLAGS) ../Obj/erkBmpGen.o: erkBmpGen.cpp ../include/erkBmpGen.h ../include/erkTypes.h $(CPP) -c erkBmpGen.cpp -o ../Obj/erkBmpGen.o $(CXXFLAGS) ../Obj/erkUnit.o: erkUnit.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkUnit.cpp -o ../Obj/erkUnit.o $(CXXFLAGS) ../Obj/erkTTHive.o: erkTTHive.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkTTHive.cpp -o ../Obj/erkTTHive.o $(CXXFLAGS) ../Obj/erkTTTrainer.o: erkTTTrainer.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkTTTrainer.cpp -o ../Obj/erkTTTrainer.o $(CXXFLAGS) ../Obj/erkCommand.o: erkCommand.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCommand.cpp -o ../Obj/erkCommand.o $(CXXFLAGS) ../Obj/erkCmdGo.o: erkCmdGo.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCmdGo.cpp -o ../Obj/erkCmdGo.o $(CXXFLAGS) ../Obj/erkCmdClear.o: erkCmdClear.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCmdClear.cpp -o ../Obj/erkCmdClear.o $(CXXFLAGS) ../Obj/erkCmdTrainer.o: erkCmdTrainer.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCmdTrainer.cpp -o ../Obj/erkCmdTrainer.o $(CXXFLAGS) ../Obj/erkCmdHive.o: erkCmdHive.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCmdHive.cpp -o ../Obj/erkCmdHive.o $(CXXFLAGS) ../Obj/erkTTThorns.o: erkTTThorns.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkTTThorns.cpp -o ../Obj/erkTTThorns.o $(CXXFLAGS) ../Obj/erkCmdThorns.o: erkCmdThorns.cpp ../include/erkMap.h ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h $(CPP) -c erkCmdThorns.cpp -o ../Obj/erkCmdThorns.o $(CXXFLAGS) ../Obj/erkAI.o: erkAI.cpp ../include/erkTypes.h ../include/erkMap.h ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h ../include/erkTTThorns.h ../include/erkBmpGen.h $(CPP) -c erkAI.cpp -o ../Obj/erkAI.o $(CXXFLAGS) FIXING THE SOURCES It's now time to try to build the game. Unfortunately this game needed some work on the actual sources, so it didn't compile and link, bummer! :) But now you know how to convert a windows makefile into an Amiga makefile. Try it on some other Allegro/SDL game/tool. When you know what you are doing, this whole process of converting the makefile will only take a minute or so. It's not as timeconsuming as it looks like in this tutorial. If you still want to build the game, this is how i solved it. I googled for the error that I got. (error: '::main' must return 'int') and I found this page; http://www.linuxforums.org/forum/linux-programming-scripting/33421-main-must-return-int.html One of the replies suggests this; Don't write 'void main' write 'int main'. Great! I edited line 29 in main.cpp, and changed void main() to int main() this helped, and now I only had a simple error left, error: winalleg.h: No such file or directory This game is obviously written with Windows in mind, and it tries to include the windows specific Allegro header winalleg.h, remove this from all the .cpp files where you find it. They already include allegro.h, so you don' need to add that. Once this is done, the game will compile and link! Yeah! Copy the exe ErkleLnD.exe into the pikselzfinal/ dir and try it. Bummer. It crashed when launched. It also killed my mouse. And Snoopy didn't give me any useful info, and as it killed my mouse I can't get any stacktrace to use with addr2line, sorry, my knowledge ends here. I am off to compile another one, you? ;) 15) CREATING A GUI USING EMPEROR (ALPHA!) ========================================= This section of the guide is to be considered alpha, it's untested, and the guide was given to me in a hurry in #amigadev by Ami603. Open your project and go to the Variables page. Open the edit window by clicking the 'edit' button. Add a stringpointer called commandfile. do not add any values to it. Step by Step: Go to the request page Step by step; page variable, click on edit, select stringpointer, name commandfile, click add. Return back to the reaction page. Go to the requester page. Open the edit window again if it's not opened. Select errorrequest. Type "your emulator executable doesn't exists" or something similar as BodyText, and add it. Select errorrequest again. Type "The file you selected does not exist" as BodyText, and add it. Go to the reaction page. Click twice on your added getfile gadget (on the left). A text editor will be opened with a function called GetFileX_GadgetUP_evt. Enter this code between the brackets; IIntuition->IDoMethod((Object *)gad[GID_Getfile1],GFILE_REQUEST,NULL,win[WID_Window1],NULL,TAG_DONE); IIntuition->GetAttrs(gad[GID_Getfile1],GETFILE_FullFile,&commandfile,TAG_DONE); IIntuition->RefreshGadgets(gad[GID_Getfile1],win[WID_Window1],NULL); (Assuming your gadget is called GetFile1 and you didn't edit the gadget name). Close the editor, click twice on the launch button. Another function will be displayed in the text editor, 'Button1_GadgetUP_Evt' Enter this code between the brackets; BPTR executable,file; STRPTR commandbuffer; if (!(executable = IDOS->Lock("here_goes_The_emulator_cli_executable_name",ACCESS_READ))) { // First requester below here } if (!(file = IDOS->Lock(commandfile,ACCESS_READ))) { // Second requester below here } else if ((executable)&&(file)) { commandbuffer = IUtility->ASPrintf("here_goes_the_emulator_cli_executable_name \"%s\"",commandfile); if (IDOS->SystemTags(commandbuffer, SYS_Input, NULL, SYS_Output, NULL, SYS_Asynch, TRUE, TAG_END)==-1) { IDOS->Printf("Commandline: %s failed\n",commandbuffer); } IExec->FreeVec(commandbuffer); } IDOS->UnLock(executable); IDOS->UnLock(file); Now without closing the texteditor go to the requester page again and put your editor cursor below the "//first requester below here", click twice on the ErrorRequester1 same for "//Second requester below here", click twice on ErrorRequester2, close the editor, save all, shell ->make Try to edit the your_command_cli_executable with the name of your exe in both places in this function. You can add a third requester, with your about info inside, add another button and do the same as before click button twice, select function, go to requesters page and click twice on it. 16) COMPILING SDL/GL APPS ========================= First of all, if you are brave enough to try this, and finds an SDL/GL project that don't throw hundreds of errors at you, this might help you. Add -DMINIGL to your CFLAGS. Add -lGL -lGLU to your LDFLAGS. It's important to add them first, before any other link libs. Then, there's a bug in the AmigaOS 4.0 version of SDL. It ALWAYS opens a fullscreen mode, and many apps wants to open a window mode. This is a very common reason as to why GL apps crashes when compiled for OS4. So, some changes needs to be done to the code. Look for SDL_SetVideoMode in the sources, and change it to use fullscreen instead. Here's an example; Original: screen = SDL_SetVideoMode( 800, 600,24, SDL_OPENGL | SDL_HWSURFACE ); Changed: screen = SDL_SetVideoMode( 800, 600,24, SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN ); I have reported this bug to Evil Rich, but he haven't answered the mail, so if you read this Evil oner, consider it a bug report. ;) I just got a new, yet unreleased game called Bomber Bastards compiled using this method, keep your eyes focused on amigaweb.net as it will be released on that site exclusively. 17) ADDING SUPPORT FOR AMIUPDATE ================================ This chapter is a bit more advanced than the rest. But it's useful info, so I wanted to include it here anyway. You have been warned. ;) Thanx to Rigo for letting me include it, it's taken from his site (www.amiupdate.net), and it is written by him. On other systems, there is a central repository system that each and every application and component registers itself with, and this makes it easy to find out what has been installed on the host system. Unfortunately, AmigaOS doesn't have this facility (and lets be honest, would we really want to be tied down with such a mechanism?), so AmiUpdate needed a way of detecting what applications and components had been installed and where. Without this, there would be no way to be able to inform the user that an update is available. The solution is two-fold, and it involves the application writing a environment variable upon startup. This variable can then be checked, and the installation location obtained. From there on, the system checks that location just like any other fixed location (as in the OS components and libraries etc). In the case of system components or third party additions that are always installed to a fixed location, you can disregard the following instruction. Files that are always in the same place (libs: devs: Utilities etc) do not need to do any special setup before being run, as AmiUpdate can use a fixed location to search for it. This applies to any system extention installed in the Sys: disk, but if satellite programs (applications that use the library, for example) are to be installed anywhere the user chooses, then that application must comply with the following pre-start setup. So, from a developers point of view, what is needed to be "AmiUpdate compatible"? Well, as was mentioned earlier, the application or component needs to write an environment variable every time it starts up. One of the nice things with AmigaOS is the ability to be able to move things at will on disk without worrying about the installation being corrupted. By writing the variable each time the application is run, the contents of the variable is always correct, and thus the application may always be found, even when moved. So, let's look at the steps needed for this: Here is a function written in ANSI C which will write the variable for you. Thanks go to Colin Wenzel for this function (with slight alterations by Rigo - ed!) /********************************************************** ** ** The following function saves the variable name passed in ** 'varname' to the ENV(ARC) system so that the application ** can become AmiUpdate aware. ** **********************************************************/ void SetAmiUpdateENVVariable( char *varname ) { /* AmiUpdate support code */ BPTR lock; APTR oldwin; /* obtain the lock to the home directory */ if(( lock = IDOS->GetProgramDir() )) { TEXT progpath[2048]; TEXT varpath[1024] = "AppPaths"; /* get a unique name for the lock, this call uses device names, as there can be multiple volumes with the same name on the system */ if( IDOS->DevNameFromLock( lock, progpath, sizeof(progpath), DN_FULLPATH )) { /* stop any "Insert volume..." type requesters oldwin = IDOS->SetProcWindow((APTR)-1); /* finally set the variable to the path the executable was run from don't forget to supply the variable name to suit your application */ IDOS->AddPart( varpath, varname, 1024); IDOS->SetVar( varpath, progpath, -1, GVF_GLOBAL_ONLY|GVF_SAVE_VAR ); /* turn requesters back on */ IDOS->SetProcWindow( oldwin ); } } } The function is well commented, so it should be fairly obvious what is happening. The function also stops DOS requesters during the write to allow for users that lock the system drive. Don't edit the function code, else there may be problems. To use the function from your own code, simply call it with the name of your application. As these variables are stored in one central directory, it is of paramount importance that each variable has a unique name. The easiest way to acheive this is to name it the same as your application. If you steal someone elses location variable, it could have serious consequences on the system during update time. char *appname = "myapp"; SetAmiUpdateENVVariable( appname ); Is all that is needed each time the application starts, so it needs to be in the main() function, preferably after all the library checks etc are done and the application is ready to start. Then what, how does it update? The next step is then to notify the AmiUpdate system that your application is compatible, and this is done with the notification form located here This will then allow your application to be entered into the online database of updates, and once a new version is available, all users will be able to take advantage of being able to download it. Please Note: The update to your application will not trigger until the second release with the compatibility code. The first release installs the setup required, but there is nothing to update yet, until the second release. Automatic installation, how? Some of the supported applications in the Contents section are able to automatically install themselves, and this acheived by using a special script located in the root of the update archive. Let's use the CopyStore archive as an example. A listing of the archive is as follows: AutoInstall 256 12-Feb-2007 CopyStore 24013 05-Aug-2007 CopyStore.doc 3255 05-Aug-2007 CopyStore_relnotes 2575 05-Aug-2007 This is the root of the archive once unpacked. The script we are interested in is called AutoInstall. This script is a standard DOS script which is executed once the archive has been downloaded and unpacked. Being a standard DOS script means that the developer can choose to take any number of actions in the script that they so choose. You may elect to do some simple copying, or even start an Installer script, but the real power comes from using the CopyStore command. CopyStore gives you the facility to install your application as you would normally, but also allows a backup to be made that can be accessed by the RollBack system. This is where the real power of the AmiUpdate suite comes into play, as in the event of an update which has caused problems, the RollBack tool can be used to "Undo" the installation. Tell me more about CopyStore Firstly, lets take a look at the AutoInstall script for CopyStore, this will hopefully help to explain the situation better: ; get the path to copy to GetEnv AUPath >NIL: ; copy CopyStore and create a RollBack opportunity CopyStore CopyStore $AUPath ; copy the doc Copy CopyStore.doc "$AUPath" CLONE QUIET ; copy the relnotes Copy CopyStore_relnotes "$AUPath" CLONE QUIET The first task is to get the path to install the update to, and this is done by GetEnv. The AUPath variable is located in ENV(ARC): and is written by AmiUpdate itself, so it always points to the location on disk where it is installed. This variable is also used to update not only CopyStore, but also AmiUpdate and the RollBack tool. Once we have the path, the CopyStore command is used to copy the executable to the location received from the variable. While this copies the new version to it's destination, it also saves the old copy into the Rollback system so that we may be able to restore the old version if needed. The rest of the script uses the standard AmigaDOS Copy command to install the document and release notes, which obviously are not saved into the Rollback system. Let us consider another example, this time from the Tunenet archive. This shows us a small difference in discovering the path that the application must be installed to. ; autoinstall for TuneNet ; %VER: TunetNet AutoInstall 1.2 (7.1.2007) ; get the path to the executable from the ENV variable Set TuneNet `GetEnv AppPaths/TuneNet` ; now copy everything in the archive (apart from the executable) Copy tunenet/~(Tunenet) "$TuneNet" ALL CLONE QUIET ; copy and store a backup of the executable for Rollback CopyStore tunenet/tunenet "$TuneNet" ; finally, free the variable UnSet TuneNet This time we are setting a local variable (called TuneNet) to the contents of the AppPaths/TineNet variable, which is written by TuneNet itself each time it runs. Now we have the location of TuneNets installation, we simply copy everything apart from the executable to the directory. The executable is copied via CopyStore, and this again allows the RollBack system to access the old version which is being updated. You may have noticed that the variable name has been quote-enclosed in the two example scripts listed above, and this is to protect against possible spaces in the location received from the environment variable. It is quite legal to have spaces in any part of the path that is stored in the variable, but once the script has expanded the variable contents, the spaces will produce unexpected results, and quotes around the variable name will allow us to use spaces without problems. That is all you need to do in order to get your application or component not only AmiUpdate compatible, but also to get it to automatically install itself too. Just a quick word on the usage of CopyStore. As it creates a backup of the old version for possible later restoration, it is wise to consider disk space when choosing what to backup and what not to. As a general rule, only use CopyStore to install vital parts of the installation. Non critical parts (documentation etc) can be simply copied which will not take up space in the Rollback system. 18) HELP ME! ============ I created this document mainly to aid myself from the beginning, but it turned out to be quite useful in the end, so I decided to clean it up and release it. I'd love to get help extending this document, if you've spotted an error, want to clarify a section or add a new section, please join me in my mission! I am sure it will be appreciated by many! --- And hey! What could happen? os4depot could be flooded by new files? That wouldn't be so bad would it? 19) CONTACT ME ============== Send a mail to: spot AT triad DOT se You can also find me and a bunch of other helpful developers in #amigadev on irc.amigaworld.net 20) THANKS ========== This wouldn't be possible without: HNL_DK, NICOMEN, ITIX, ZEROHERO, VARTHALL, BLACKY_STARDUST, AMI603, RAZIEL, LIO AMIGAGUY, SSOLIE, RIGO and the rest in #amigadev! THANX A LOT GUYS! .___________________________________________________________. | | | G U I D E W R I T TE N B Y | ._______ .______. | | ____/________________________________________| |__ . ._|____._ | ._ | ._ | _/______. | |/ | |/ | |/ | |/ | | | _________| | | |_________________|______|spt/up |_______________|_______________| . . | | | I am in a shitty economical situation, so if you feel | | that what I do is worth anything, use paypal to donate | | to my email addy, spotATtriadDOTse, thanx! | | | | Spot / Up Rough 2007 | |___________________________________________________________|