The real solution is to get the compiler and binutils (linker) to do this automatically.
I tend to agree, and in fact, avr-g++
incorporated a PROGMEM-specific fix regarding the -fmerge-constants compiler option
That seemed to be exactly what I wanted, so I tried that first (with GCC 4.7.0 and 4.8.0) -- and with the right combination of compiler switches (-fno-data-sections
, as somewhat obliquely implied by that bugzilla comment I linked to above, and of course -fmerge-constants
), I actually managed to get avr-g++
to merge strings defined through the regular PSTR()
macro -- but only
for global variables and static locals in non-member functions.
I absolutely couldn't
to merge strings in static locals defined in member
functions (even static member functions), which is unfortunate because that's precisely where I need them. And I think that's not a bug but rather an unfortunate consequence of a design choice and essential C++ semantics, so it's basically unfixable.
(I'm out of my depth where compiler and linker internals are concerned, so the following may be completely off the mark. It's just my attempt to make sense of the things I've observed.)
I think the basic underlying problem is the design choice that attribute((progmem))
needs to be attached to a variable
-- everything that follows is just an unavoidable chain of consequences:
- attribute((progmem)) must be attached to a variable, so PSTR() must use a (static local) variable;
- static local variables in class methods have non-trivial linking semantics across translation units (because the logically same static local might conceivably be defined in several translation units when methods are inlined), so the compiler must emit weak symbols for them;
- the linker won't merge strings referenced through weak symbols, presumably because it can never know if any weakly-referenced string will actually end up being used.
So I wouldn't even know what to suggest to the avr-g++
makers -- short of scrapping the entire attribute((progmem))
approach and adding some built-in way that comes close to my asm
-based workaround, which just puts the string literal directly in the right kind of section. :-/