GP2X Non Static Linking


colba

Still Fresh
Joined
Dec 9, 2005
Messages
14
I've searched the board and I can't find an answer to this.

I want to compile and link without the -static option inorder to create smaller gpe and gpu files. I noticed that sterm is only 24K precompiled but I can only compile the source successfully with the -static option and end up with a 800k gpu.

Has anyone successfully linked without -static ?

I'm using devkitgp2x with the SDL libraries and minsys under Windows XP. (standard windows tool chain).

Any help would be greatly appreciated. Thanks.
 
To dynamically link you have to use gcc 2.95 supplied by GPH (I think it's on gp32spain's ftp), and not devkitgp2x or any of the other gcc 4 toolchains that are around.
 
If you don't want to use static linking then you will need to use a MUCH older version of GCC and the gLibC setup. The GPH provided one is based on GCC 2.95 and the version of gLibC used on the GP2X is really old and will not cleanly build with GCC 3.4> so you are stuck with hacking gLibC or using a really old GCC (without any of the nice ARM optimisation that is present in the later 3.4> versions).

The GPH tool-chain is only available for Linux and ‘most’ of the more recent tool-chains (Open2x, DevKitGP2X etc.) opted for static linking to support the simplest deployment and to prevent some of the issues associated with library versions, unsupported API’s and all that jazz (things that I feel you really don’t need to be messing with on a little embedded system like the GP2X).

Have you tried Rlyeh’s port of UCLX for the GP2X, that should shrink down your resulting executable nicely ;) (works a lot like B2FXEC on the GP2X)
 
You can still link dynamically if you also supply the libraries you're linking against, and set the LD_LIBRARY_PATH appropriately before running your app, e.g. export LD_LIBRARY_PATH=`pwd` if they're in the current directory. Note that shared libraries are massive though - much bigger than your little static binary, which only includes the bits it actually uses. You might need to unset LD_LIBRARY_PATH before chaining to gp2xmenu. It may be better to just set it for the actual command which runs your program, i.e. prefix that command with LD_LIBRARY_PATH=...

If you are going to install the shared libraries to a fixed location, you can instead specify the runtime search path when linking the executable. IMHO this is what makes most sense for dynamic linking on the GP2X - it means you only need to install one copy of libc for all programs that use it, because it's going into a fixed path common to all programs, and the toolchains could specify the runtime search path automatically.

It's still pretty messy though, and size is not a very good reason to do this. One better reason is adherence to the terms of the LGPL, if you don't want to give away your source code. Not meaning to start yet another GPL argument, but I'm pretty sure all staticly linked binaries need to be supplied with full source or object code! Dynamically linked binaries don't have this requirement.
 
gfoot,

You make some very valid points, I had been thinking about doing just what you write and talking to the other people who build tool-chain scripts to standardise on a lib folder (say /mnt/sd/libs or say libs-gp2x for uniqueness) and adding that path in at tool-chain build time. That way if people wanted to dynamically link there apps using a newer tool-chain they could if the correct lib set was on the SD.

My main reservations with this (and why I tend to make the blanket statement of “link statically”) is that it can get really, really messy.

There are valid reasons for it however but considering you would be mad to store the libs on the NAND there is a lot of “give with one hand and take away with the other” going on when you do this (much bigger libs for dynamic linking (with everything in them) then the subset you may compile into a few small apps).

With stripping of the resulting binaries and executable compression you can get files that are acceptably small (SD’s are not that expensive) and I see the lack of dependencies a bonus, esp. in the early stages of the life cycle we are in currently, libraries, esp. things like SDL are going to mature and change and 100% API compatibility may not guaranteed between community and GPH versions of the libs. If you static link your app works, end of story ;).

Not really given too much credence to the licensing issues but I think you make a good point that it may be wise to put some clear statements in with the tool-chains to prevent any misunderstanding on what is doable without a source release (I’ll look into getting my head around the legal aspects of this).
 
OK,

Thanks for the help guys.

I want to use the best optimisation so it looks like I'll be doing static links for now.

When you static link and use strip does that remove all unused libraries?

It's just that I'm a bit supprised at how big static linked exes are. The main libraries I'm using are SDL, stdlib, stdio.
 
Static linking and then striping will remove unused symbols. You will have the parts of the libs you use still statically linked in (and there dependencies).

What is the result like if you compress the stripped executable?

I find the pain of static linking gets more dramatic with smaller apps (i.e. ScummVM is not that bloated in real terms when statically linked, hello world is ;)) as a lot of the core stuff from LibC and friends gets linked in once to provide the most basic functions whatever you code.
 
I haven't tried compressing the executable yet. I'll have a go at it later and see what I get.

Sure enough the apps I'm playing with at the moment are tiny as I familiarise myself with the GP2X, SDL etc.

BTW. This making the exe smaller started because I had modified sterm to improve the joypad handling (taking account of diagonals) when selecting characters and I was trying to get my version's gpu down to the size of the original.
 
stripping and compressing the gpe works well, heres my sdltest program before and after:

before stripping = 2,594 KB
after stripping = 2,327 KB
after compressing = 925 KB

still not as small as what it would be if it was not static linked, but it is in my opinion neater and less trouble for the users to run straight away without having to install libs to the gp2x.
 
One way to find out what's in your binary is using nm (probably arm-linux-nm on devkitGP2X). It will tell you every symbol defined in your program, what address it is at, and how big it is (if you give the -S option). Symbols tend to be present in the binary in the order the libraries were linked, so specify -n to sort by address and you can easily see how much space is taken up by each library you linked.

nm won't work on stripped binaries, as they have no symbol data, but that doesn't really matter, you can still see how much code you're getting from each library by running on a non-stripped executable.

Object files (embedded in libraries) are either in or out of the link - it can't pull in a couple of symbols and leave out the rest of the file. That works well for libc style libraries - they put small groups of related functions in each file, so you only end up linking what you need. It works less well for hardware abstraction libraries like Allegro and presumably SDL, because they still reference all the code for drivers you're not using - it doesn't know you won't need them until runtime. For Allegro I disabled most of the stuff that's not relevant, so it's leaner than the PC equivalent. In Allegro you can also disable support for different color depths, if you really want to limit your options at runtime!

Note that selective linking only happens to libraries linked with the -l option. If you link the library directly (e.g. putting liballeg.a on the command line) it will link the whole thing.
 
Back
Top