| Author |
Message |
|
|
Posted: Oct 22, 2007 - 02:37 AM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
Hi,
We cannot find how to get the linker to ignore unused functions.
E.g., if we have two functions in a common library file foobar.c, foo() and bar(), and we only use foo(), bar() still seems to be linked when we look at the link map.
We've looked at 'man ld' but we can't see anything that looks likely.
How can we stop this, please...?
Would turning the common files into a 'library.a' file help? We want to avoid this because every project uses its own definitions, etc.
Alf |
|
|
| |
|
|
|
|
|
Posted: Oct 22, 2007 - 03:00 AM |
|


Joined: Jan 23, 2004
Posts: 7014
Location: Melbourne, Victoria, Australia
|
|
Try using -ffunction-sections, which should result in the unlinked functions being thrown away from the binary.
- Dean  |
_________________
|
| |
|
|
|
|
|
Posted: Oct 22, 2007 - 03:04 AM |
|

Joined: Aug 16, 2005
Posts: 301
|
|
you can use #defines to describe what your project needs, and then have #ifdef statements to pull out things from your "library" file.
that's what I use. (though more for code configuration in a single project than function removal from different projects.... in my case, I've written different handler functions for different modem/GPS/combinations, and don't want all of the code for all possible devices being compiled into my microcontroller - but it's the same basic idea for what you might want to do, I think)
ie
Code:
#define USE_FOO
#define USE_BAR
.
.
.
#ifdef USE_FOO
int foo();
#endif
#ifdef USE_BAR
int bar();
#endif
.
.
.
#ifdef USE_FOO
int foo()
{
}
#endif
#ifdef USE_BAR
int bar()
{
}
#endif
I have a header file called _setup.h that I put these defines in, and then refer to that in the relevant .h and .c files I want to control. |
|
|
| |
|
|
|
|
|
Posted: Oct 22, 2007 - 09:15 AM |
|


Joined: Dec 20, 2002
Posts: 6697
Location: Dresden, Germany
|
|
> E.g., if we have two functions in a common library file foobar.c
That's not how libraries usually work. The usual way of things is
to use a "one file, one function" approach (except for things that
inherently belong together). When using that approach, if you
afterwards create a library xxx.a (using avr-ar) out of the individual
.o files, the linker will only pick those modules that are really
needed.
Individual .o files given on the command-line will however always be
linked. |
_________________ Jörg Wunsch
Please don't send me PMs, use email instead.
Please read the `General information...' article before.
|
| |
|
|
|
|
|
Posted: Oct 22, 2007 - 11:36 AM |
|


Joined: Jul 18, 2005
Posts: 34381
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
|
|
|
|
Posted: Oct 22, 2007 - 04:40 PM |
|


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains
|
|
|
abcminiuser wrote:
Try using -ffunction-sections, which should result in the unlinked functions being thrown away from the binary.
- Dean
Dean, that's not complete.
One must use -ffunction-sections (compiler switch) AND -Wl,-gc-sections (linker switch) to have the linker "garbage collect" (or remove) unused sections. The -ffunction-sections switch places all functions within their own section. You must use both together to make this work. |
|
|
| |
|
|
|
|
|
Posted: Oct 22, 2007 - 04:41 PM |
|


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains
|
|
|
clawson wrote:
What a shame no one bothered to explain this in the user manual ...
... oh, wait a minute, they did:
http://www.nongnu.org/avr-libc/user-manual/library.html
Thanks! I wrote that because I got tired of repeating myself when answering the same questions over again. |
|
|
| |
|
|
|
|
|
Posted: Oct 29, 2007 - 03:48 AM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
JulianHigginson:
The #ifdef FLAG (actually better to use #ifndef NOT_FLAG) only works for libraries which we have written: libraries from elsewhere in the company or the Net don't have this, and we don't want to start peppering that code with our own #ifndef's.
EW:
Thanks for the -ffunction-sections AND -Wl,-gc-sections: one project I just tried it on went from 15508 down to 14584 bytes: about 900 bytes of saving.
Definitely a 'keeper'.
Thanks muchly,
(at about 20m elevation)
Best regards,
Alf Lacis |
Last edited by lacis_alfredo on Nov 06, 2007 - 02:04 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Oct 29, 2007 - 04:31 AM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
clawson:
clawson wrote:
What a shame no one bothered to explain this in the user manual ...
... oh, wait a minute, they did:
http://www.nongnu.org/avr-libc/user-manual/library.html
Yes, I saw this page already before this post.... it did not provide the answer that EW gave of the compiler and linker options which I've added to the various makefiles:
Code:
CFLAGS += -ffunction-sections
LDFLAGS += -Wl,-gc-sections
However, thanks for your input.
Alf |
|
|
| |
|
|
|
|
|
Posted: Oct 29, 2007 - 10:47 AM |
|


Joined: Jul 18, 2005
Posts: 34381
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| Yeah but it's the best way to make a library (rather than later trying to remove the stuff that "accidentally" got included). Say, for example, that you later made the lib available to others, will they know (or remember) to use ffunction-section and gc-sections? If you make it a "normal" lib where each function is in a separate .o and is therefore only bound in if called then it works for everyone wiht no special stuff being required (just like libc in fact) |
_________________
|
| |
|
|
|
|
|
Posted: Oct 29, 2007 - 01:28 PM |
|

Joined: Feb 12, 2005
Posts: 7696
Location: Cratfield, England
|
|
dear Alf,
I echo Cliff.
Put all your library source in one directory tree.
Include every function object in your Makefile.
Compile every function as a separate file.
Create a single header file for the library function prototypes and any typedefs. Do not have any internal stuff in this header.
Make all the objects via Make.
Use avr-ar to build the libalfred.a via Make.
If you are posh you can generate the documentation too.
Then release <alfred.h> and libalfred.a with the source to the unsuspecting public.
The public says thankyou. The public needs no special compiler switches.
David. |
|
|
| |
|
|
|
|
|
Posted: Nov 06, 2007 - 02:09 AM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
Hi, david.prentice & clawson,
Yes, I hear you... and I've done this where it's practical and useful: at the pointy end of a new company's startup, or a new large standalone project.
The situation with the embedded targets with the company I joined 3 months ago, can be summed up with three ideas: history, money, and customer contentment.(1) The company has 12-year-long history of different embedded targets, with hundreds of thousands of devices shipped, across scores of product lines;
(2) the 'libraries' are really just places in the directory tree to hold collections of code source;
(3) the sources are full of #ifdef...#endif fences and other build switches that are different for practically every target, and therefore *must* be compiled for each target;
(4) the targets are different CPUs: i.e., Phillips, Renesas(Hitachi), and a few different ATmegas, and even the board layout may mean that the same external device is on another port or bit; and, you probably guessed, this is catered for by build switches, not configuration code;
(5) the compilers are varied, e.g., several versions of WIN-AVR-GCC (depending on the project!), Cygwin(for PC tools), Renesas/HEW (others?);
(6) because of 2 thru 5, and they way the company has grown, the code is highly coupled, and detangling it now would cause problems that we don't need to generate for our historical products; Considering all this: while I like libraries, I do not think that creating compiled libraries is the 'best' thing to do in this company. (And besides, it's not my call anyway.) Sometimes the 'best' thing to do (I know this may gall) is nothing. "If it ain't broke, don't fix it."
Best Regards, and I thank you for your inputs,
Alf Lacis |
|
|
| |
|
|
|
|
|
Posted: Nov 06, 2007 - 10:46 AM |
|

Joined: Feb 12, 2005
Posts: 7696
Location: Cratfield, England
|
|
dear Alf,
I take your point about conditional code. It is not worth the aggravation for complex code. I would leave as a source library that hangs off your project rather than a system library directory.
With simple 64 bit operations this will only be conditional on the AVR model.
So a compiled library IS possible. It just gets a separate incarnation in each "model" tree e.g. avr5 ...
As a source library, the library would be compiled in the project directory. Your project Makefile includes two new dependencies:
Code:
MY_LIB = alf
MY_LIBOBJS = lib_obj1.o lib_obj2.o ...
lib$(MY_LIB).a: $(MY_LIBS)
avr-ar rv $@ $?
# or let ar handle the update.
# avr-ar ruv $@ $(MY_LIBS)
project.elf: lib$(MY_LIB).a $(OBJS)
Just written this off the top of my head, rather than looking at one of my own project Makefiles.
David. |
|
|
| |
|
|
|
|
|
Posted: Nov 20, 2007 - 01:54 AM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
|
|
|
|
|
Posted: Nov 20, 2007 - 07:09 PM |
|

Joined: Sep 12, 2003
Posts: 529
Location: XX century
|
|
|
Quote:
/main.c:1: warning: -ffunction-sections may affect debugging on some targets
Quote:
avr-objcopy -O ihex -R .eeprom -j .text -j .data main.elf main.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex main.elf main.eep
avr-objdump -h -S main.elf > main.lss
avr-nm -n main.elf > main.sym
avr-objcopy --debugging --change-section-address .data-0x800000 --change-section-address .bss-0x800000 --change-section-address .noinit-0x800000 --change-section-address .eeprom-0x810000 -O coff-ext-avr main.elf ./main.cof
avr-objcopy: main.elf: no recognized debugging information
Size after:
AVR Memory Usage
----------------
Device: atmega128
Program: 0 bytes (0.0% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
Is this correct behavior? |
|
|
| |
|
|
|
|
|
Posted: Nov 20, 2007 - 10:44 PM |
|


Joined: Jan 23, 2004
Posts: 7014
Location: Melbourne, Victoria, Australia
|
|
I used to get that warning on an old version of AVR-GCC - it seems to be gone with the newer releases. IIRC, it was actually there in error, and was put in as a safety by the mainline GCC code for some targets, to remind the developers to test out the switch.
It all boiled down to the -ffunction-sections putting each function into its own section, which confused some debuggers (which expected all the data to be in the one section) I think.
- Dean  |
_________________
|
| |
|
|
|
|
|
Posted: Aug 10, 2008 - 01:58 PM |
|


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia
|
|
Not linking unused functions? Nine Months Later: GCC ARM Toolkit
(Yes, I know this is not strictly AVR, but we're all software engineers. This Forum will be crawled by Google, etc, so they will find the reference to the ARM processor, and may help some of us later: it's all karma, right?)
I'm now doing some code for an Atmel ARM AT91SAM7X256, using a GCC toolkit.
I'm pleased to say that the optimization works the same for the ARM as it did for the ATmega... lots of unused functions have been optimized out of the link map.
You may recall the Makefile flags were:
Code:
CFLAGS += -ffunction-sections
LDFLAGS += -Wl,-gc-sections
With the build tool I'm using, the -f option is passed to the compiler:
Code:
-ffunction-sections
For the linker, the option string is (you don't need the "-Wl," if passing straight to the linker):
Code:
-gc-sections
I hope this will have been useful,
Regards,
Alf Lacis
http://alfredo4570.customer.netspace.net.au |
|
|
| |
|
|
|
|
|
Posted: Aug 10, 2008 - 05:47 PM |
|


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains
|
|
Yes, since GCC is the same, whether for ARM or for AVR, those switches should work.
A small word of caution: It is up to the target back-end, whether or not garbage collection on unused sections is done. So it happens to work on ARM and AVR, but I cannot guarantee that it work on other GCC targets. However, it should work on targets that are well supported, I think. |
|
|
| |
|
|
|
|
|