Using the Cygwin/Bash on Ubuntu on Windows (UWin) Command Line to Cross-Compile PowerPC (ppc) Amiga OS4 Code via the Built-from-Source Cygwin-hosted or UWin-hosted adtools (cyg-adtools/uwin-adtools) Toolchain
[First Published 2017-10-21]
[Updated 2019-10-26 -- Note, there are 3 related posts here that cover cross-compiling for Amiga OS4 from Windows:
1) A post on how to build a Windows-hosted toolchain (
http://www.amigans.net/modules/xforum ... hp?topic_id=7623&forum=25)
2) The post you're reading now, on how to use the toolchain built by the first post, from a Windows / cygwin command line (
http://www.amigans.net/modules/xforum ... m=25&topic_id=7654&order=)
3) A post on how to use the toolchain built in the first post from inside Visual Studio for Windows (
http://www.amigans.net/modules/xforum ... 9&forum=25&post_id=108233) ]
Pre-Requisites:This guide is intended to pick up where my prior guide left off, wherein I showed how to use Cygwin64 as a host environment to build from source, and run, the latest Windows-based / Cygwin-based Amiga Developer Tools (cyg-adtools) toolchain capable of generating ppc AmigaOS/OS4 binaries from a Windows 10 developer workstation.
Although I've only tested these instructions on the Cygwin environment with my cyg-adtools toolchain, they _should_ work unaltered with the uwin-adtools toolchain (also from my prior guide) except where noted below.
These instructions should also work with Linux and Mac adtools toolchains, although my prior guide only alludes to, and doesn't fully describe, how to build the adtools cross-compiling toolchains from source.
If you do manage to get mac/lin-adtools built, the instructions in this guide should work with only trivial changes.
Likewise, given how close Cygwin/UWin are to Linux/Macports, my prior guide showing how to build a cyg-adtools and uwin-adtools toolchain from source should also be _very_ close to what's needed for Linux and Mac.
The prior guide (aka "original guide" or "originating guide") I keep alluding to throughout this guide is a prerequisite for this guide, and it can be found at:
http://www.amigans.net/modules/xforum ... hp?topic_id=7623&forum=25That is, this guide is intended to show how to actually _use_ the cyg-adtools/uwin-adtools toolchain with your own or some 3rd party's headers/libraries, because the example programs from my original guide ("Hello, World" and "easy") aren't all that useful in and of themselves. Those examples do prove, however, that everything works perfectly with the adtools setup, as described.
In essence, this guide intends to show how to include any OS4.x, arbitrary 3rd party, or your own, code with headers and libraries for use by your cyg/uwin-adtools toolchain. You'll need only your cyg/uwin-adtools toolchain, your Cygwin/UWin bash shell, plus your favourite Windows-based text/programmer's editor.
By way of context, this guide is really just a very specific/particular application of the general knowledge needed to get gcc/g++ working as you'd like. I am simply modifying the standard gcc/g++ instructions, and tweaking them to account for the AmigaOS cross-compiling adtools-specific configurations as baked-in by the built-from-source adtools chain (assuming you've followed my originating adtools post without modification).
Lastly, like all my guides, this is lengthy. Really lengthy. But only because I'm trying to impart knowledge that, once imparted, it takes mere seconds to use subsequently.
A little backgrounder:In my originating guide, aside from the fact that you're able to create an Amiga OS4 executable from within a truly up-to-date/modern gcc/g++ environment running on a Windows machine (which is awesome), the "Hello World" tests I show don't actually call any Amiga-specific functions or use any Amiga-specific libraries/headers like any real program/library needs to do.
That's what my "easy" test showed -- but, even though the "easy" build test _absolutely_ proves you're successfully cross-compiling/linking Amiga-specific headers/libs using your Windows Cygwin/Uwin development environment -- it's not necessarily obvious how all this is working or how you'd use all these adtools yourself for your own code, or 3rd party Amiga code.
As in, how do the cyg/uwin-adtools' ppc-amigaos-gcc/g++ commands, as seen in my original guide's "Hello, World" and "easy" examples, actually work?
Well, if you've followed all of my original guide's instructions, whether in Cygwin or Uwin, then all the cross-compiling/building tools are found in your Cygwin/Uwin's "/usr/local/amiga/adtools-<xyz_version>" directory and below; and if you've really followed my instructions, you have a symbolic link "/usr/local/amiga/adtools" that can point to whatever version of the adtools you've built from source.
With that in mind, let's dive in to things...
How-To:If you'd like a very slick IDE setup instead of using the command line, see my other guide on how to integrate your cyg/uwin-adtools toolchain with the Microsoft Visual Studio 2017 IDE:
http://www.amigans.net/modules/xforum ... 9&forum=25&post_id=108233By contrast, this guide is for all the command-line warriors out there, like me, who quite prefer life outside an IDE. For you, there are basically 2 ways to use your cyg/uwin-adtools toolchain.
You can either:
a) use command-line switches, where you
i) pass-in to ppc-amigaos-gcc/g++/ld, all the compiler parameters needed such as Include and Library search paths, or
ii) use environment variables to tell ppc-amigaos-gcc/g++/ld what Include and Library search paths to use, or
b) use "make" files to tell ppc-amigaos-gcc/g++/ld the Include and Library search paths that you'd like to use.
In this guide I'll show very basic examples of (a)(i), (a)(ii), and (b).
Also, note that although I've written this guide for the cyg-adtools toolchain only (because I personally only use Cygwin myself and not UWin), but for the uwin-adtools users, simply substitute "uwin64" whenever you see "cyg64".
Includes/Headers -- The gcc/g++ Include Search PathsTo identify the built-in Include search path used by your adtools, you can execute both of these commands (without the quotes):
"echo | ppc-amigaos-gcc -E -Wp,-v -"
This will show the default Include search path being used by the adtools' gcc command.
Similarly, execute:
"echo | ppc-amigaos-g++ -E -Wp,-v -"
Which will show the adtools' g++ default Include search path.
If you compare those 2 commands' output, you'll note that both ppc-amigaos-gcc and ppc-amigaos-g++ share the following search paths:
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/ppc-amigaos/SDK/newlib/include"
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/ppc-amigaos/SDK/include/include_h"
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/ppc-amigaos/SDK/include/netinclude"
Or, for your own convenience, if you've used the symlink I suggested in my original guide:
"/usr/local/amiga/adtools/ppc-amigaos/SDK/newlib/include""/usr/local/amiga/adtools/ppc-amigaos/SDK/include/include_h""/usr/local/amiga/adtools/ppc-amigaos/SDK/include/netinclude"These directories are about to become very important....
When you built your cyg/uwin-adtools toolchain from source, its very extensive build scripts baked-in a bunch of default search paths for Includes/header files; those baked-in paths include the ones I just listed above.
To understand how all the pieces fit, look again at the "easy.c" source file in my original guide, or indeed just look at any standard Amiga source file, and you'll see various Amiga-specific #include directives. For example, in "easy.c" you'll find:
#include <proto/exec.h>
#include <proto/intuition.h>
Now, in your Cygwin/Uwin bash shell, if you look in the
"/usr/local/amiga/adtools/ppc-amigaos/SDK/include/include_h" directory, you'll find a subdirectory called "proto" inside which you'll find the "exec.h" and "intuition.h" header files.
So, that's a really long way to say that inside the
"/usr/local/amiga/adtools-<xyz version>/ppc-amigaos/SDK/include/include_h" directory or, for convenience, if you've used the adtools symlink I recommended in my original guide, the
"/usr/local/amiga/adtools/ppc-amigaos/SDK/include/include_h" directory is where you find all the base OS4.x header files to do standard Amiga OS4 development.
Similarly, by default, if you followed my original post, you'll also find:
"/usr/local/amiga/adtools/ppc-amigaos/SDK/clib2/include" directory, and also the
"/usr/local/amiga/adtools/ppc-amigaos/SDK/newlib/include" directory which contain the header files for clib2 or newlib respectively.
And, lastly, if you've followed my original post for SDK updates, all these directories should stay intact and should continue to work, even after updating the Amiga OS4 SDK.
Libs: The gcc/g++/ld Library Search PathsSo, we've seen how your adtools gcc/g++'s default Include/header search paths work. What about Library files and the search paths used by the adtools' linker (named "ppc-amigaos-ld") for finding libs to link your code against?
Well, if you run the following command (without the quotes) from your bash shell:
"ppc-amigaos-gcc -print-search-dirs"You'll see something like:
...
libraries: =/usr/local/amiga/adtools-ppc-cyg64-20170623-404/lib/gcc/ppc-amigaos/5.4.0/:/usr/local/amiga/adtools-ppc-cyg64-20170623-404/lib/gcc/ppc-amigaos/5.4.0/../../../../ppc-amigaos/lib/ppc-amigaos/5.4.0/:/usr/local/amiga/adtools-ppc-cyg64-20170623-404/lib/gcc/ppc-amigaos/5.4.0/../../../../ppc-amigaos/lib/
If you parse-out that output, you'll see:
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/lib/gcc/ppc-amigaos/5.4.0/../../../../ppc-amigaos/lib/"Which translates to:
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/ppc-amigaos/lib"Or if you have your symlink working:
"/usr/local/amiga/adtools/ppc-amigaos/lib"Similarly, in that output you'll see:
"/usr/local/amiga/adtools-ppc-cyg64-20170623-404/lib/gcc/ppc-amigaos/5.4.0"Which, with a symlink, translates to:
"/usr/local/amiga/adtools/lib/gcc/ppc-amigaos/5.4.0"That is, the 2 major directories used as default lib search directories by the ppc-amigaos-ld linker are:
"/usr/local/amiga/adtools/ppc-amigaos/lib""/usr/local/amiga/adtools/lib/gcc/ppc-amigaos/5.4.0"And all their subdirectories.
What about the other 3rd party/other headers and library files that you'll need to use?So, we now know where, by default, your ppc-amigaos-gcc/g++ toolchain looks for its headers, which is inside the follow directories and their subdirectories:
"/usr/local/amiga/adtools/ppc-amigaos/SDK/newlib/include""/usr/local/amiga/adtools/ppc-amigaos/SDK/include/include_h""/usr/local/amiga/adtools/ppc-amigaos/SDK/include/netinclude"And where your ppc-amigaos-ld linker looks for its libs, which is the following directories and their subdirectories:
"/usr/local/amiga/adtools/ppc-amigaos/lib""/usr/local/amiga/adtools/lib/gcc/ppc-amigaos/5.4.0"That's good to know, and it's good to know that if you update your SDK or update your toolchain from source, all the above will change a little, but if you use/update the "adtools" symlink as instructed in my prior guide, this guide will still work.
What about 3rd party, or your own, headers/libs?
Well, the Amiga gcc/g++ cross toolchains don't actually care where your header/lib files are, so long as they can find, or be told where to find them.
So that means you can simply create subdirectories under the various directories I just listed above, and then copy your new/3rd party headers/libs to those respective subdirs, and call those headers in your #include directives. The ppc-amigaos-gcc/g++/ld commands should find your headers/libs and work -- but that's rather messy and non-standard, and will create more work for you every time you update your AmigaOS SDK.
Much cleaner, much more standard, and far less work after every SDK update is if you put your own/3rd party libraries/headers in some separate directory apart from the standard SDK directory, and then tell the Amiga gcc/g++ toochains where to look for your libs/headers using Cygwin/UWin command-line switches, environment variables, or makefiles.
For the following instructions, let's assume that you've put all your own headers/libs and some 3rd party headers/libs in the following directories:
"/usr/local/amiga/myproj/include""/usr/local/amiga/myproj/lib""/usr/local/amiga/3rdparty/include""/usr/local/amiga/3rdparty/lib"We'll also assume for the following instructions that your source files "myproj.c" and "myproj.cpp" are in the
/usr/local/amiga/myproj/src/ directory. And that each of these source files has all the proper #include directives in them.
Adtools Includes and Libs via Command-Line SwitchesIn many ways, using command-line switches is the easiest way to accomplish what you're looking to do ... just know that it can create really long commands.
[As a little tip, I like to keep a text editor with the multi-line command typed in -- that's what the backslash is at each line, a bash multi-line command delimiter -- like you see below, so I can simply copy/paste the long command into the bash command line every time I need it. I don't usually create shell scripts for this. If I want something like a shell script, I use the proper tool -- a makefile, as described below.]
For example, to compile your "myproj.c" file with Amiga-friendly debugging symbols inserted, assuming your code, your 3rd party headers and libs, and your own headers and libs are placed as noted above, then you would use the following command (without the quotes):
"ppc-amigaos-gcc -Wall -ggdb -gstabs \
-I /usr/local/amiga/myproj/include \
-I /usr/local/amiga/3rdparty/include \
-L /usr/local/amiga/myproj/lib \
-L /usr/local/amiga/3rdparty/lib \
-o /usr/local/amiga/myproj/myproj /usr/local/amiga/myproj/src/myproj.c"Similarly, if you wanted to compile your "myproj.cpp" file with debug symbols inserted:
"ppc-amigaos-g++ -Wall -ggdb -gstabs \
-I /usr/local/amiga/myproj/include \
-I /usr/local/amiga/3rdparty/include \
-L /usr/local/amiga/myproj/lib \
-L /usr/local/amiga/3rdparty/lib \
-o /usr/local/amiga/myproj/myproj /usr/local/amiga/myproj/src/myproj.cpp"Note that both the -I and -L switches simply add to the default/baked-in header/lib directories that we identified previously, meaning you don't have to also set-out where all the standard Amiga SDK libs/headers are.
Lastly, if you want to compile your code _without_ the debug symbols, then just delete the "-ggdb" and "-gstabs" command-line switches.
For more information, see the main authority on the matter, the GCC official documentation, specifically:
https://gcc.gnu.org/onlinedocs/gcc/Dir ... ns.html#Directory-Optionsand
https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-OptionsAdtools Includes and Libs via Environment VariablesYou can also use bash environment variables to accomplish what you seek.
For example:
LIBRARY_PATH specifies a list of directories to search for libs, as if specified with -L
CPATH specifies a list of directories to be searched as if specified with -I
C_INCLUDE_PATH and CPLUS_INCLUDE_PATH are like CPATH, but for C/C++ specifically, if there's some difference in your headers.
So, mirroring the command-line-switch example above, from your bash shell you'd execute the following commands (without the quotes), and only once per logged in bash session:
"export LIBRARY_PATH=/usr/local/amiga/myproj/lib:/usr/local/amiga/3rdparty/lib""export CPATH=/usr/local/amiga/myproj/include:/usr/local/amiga/3rdparty/include"And, then, every time you want to compile your code (without the quotes):
"ppc-amigaos-gcc -Wall -ggdb -gstabs \
-o /usr/local/amiga/myproj/myproj /usr/local/amiga/myproj/src/myproj.c"or
"ppc-amigaos-g++ -Wall -ggdb -gstabs \
-o /usr/local/amiga/myproj/myproj /usr/local/amiga/myproj/src/myproj.cpp"If you want to remove the debug symbols, just omit the "-ggdb" and "-gstabs" command-line switches.
Again, for more information, see the main source for this guide, the GCC official documentation, specifically:
https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.htmlAdtools Includes and Libs via makefilesBy far, makefiles are the most powerful/flexible/clean way to accomplish your build. But, they're also a bit more work, and the following are only the most stupid/simple examples of a makefile, and also the simplest subsequent use of a makefile, that I could imagine.
There are countless publicly-available resources about GNU makefiles. Use them to your heart's content; just keep these examples in-mind when you do so, really just the "-gdb", "-gstabs" and your own/3rd party header and library search paths.
Step 1: Assuming we're using all the same directories as above, create a makefile, named "makefile" using your favourite editor or just "nano". Save that makefile as "/usr/local/amiga/myproj/src/makefile"
Copy the following contents into the "makefile" file, copying everything between but excluding the quotes. After you do a copy/paste, make sure you actually insert a Tab where I note <put a tab here> and delete the words "<put a tab here>":
"all:
<put a tab here> /usr/local/amiga/adtools/bin/ppc-amigaos-gcc -o /usr/local/amiga/myproj/myproj /usr/local/amiga/myproj/src/myproj.c -Wall -ggdb -gstabs -I/usr/local/amiga/myproj/include -I/usr/local/amiga/3rdparty/include -L/usr/local/amiga/myproj/lib -L/usr/local/amiga/3rdparty/lib
clean:
<put a tab here> rm /usr/local/amiga/myproj/myproj"Step 2: To build your code, in your bash shell, execute (without the quotes)
"cd /usr/local/amiga/myproj/src""make"That should build your executable, "myproj" and put it in your /usr/local/amiga/myproj directory.
Note that both the -I and -L switches simply add to the default/baked-in header/lib directories that we identified previously, meaning you don't have to also set-out where all the standard Amiga SDK libs/headers are.
Lastly, if you want to compile your code _without_ the debug symbols, then just delete the "-ggdb" and "-gstabs" command-line switches.
Step 3: To re-build your code, you probably want to delete the prior-compiled executable and then compile again.
Execute (without the quotes):
"cd /usr/local/amiga/myproj/src""make clean""make"Search keywords:
Cross
Cross-compile
Cross-compiler
Cross-compiling
compile
compiler
compiling
adtools
Win
Windows
Bash
Ubuntu
Cygwin
Amiga Development Tools
Developer
Intel
x86
x64
PPC
PowerPC
Power PC
OS4
Ami
AmigaOS