When linking C programs there are (in general) only a couple of errors you’re likely to see. If, for example, you have two functions in different files, both with external linkage, then the files will compile okay, but when you link you’ll likely see an error along these lines:

linking…

weak_linkage.axf: Error: L6200E: Symbol foo multiply defined (by foo.o and foo2.o).

Target not created

Most of the time this makes sense and is as expected; however there is a particular instance where it gets in the way.

If we need to supply a code framework where we need placeholders (stubs) for someone else to fill in at a later date, it can sometimes mean developing complex makefiles and/or conditional compilation to allow new code to be introduced as seamlessly as possible.

However, there is a hidden gem supported by most linkers called “weak linkage”. The principle of weak linkage is that you can define a function and tag it as (surprisingly) weak, e.g.

// foo_weak.c

__weak int foo(void)

{

// ...

return 1;

}

This then can be called from the main application:

// main.c

int foo(void);

int main(void)

{

foo();

while(1);

}

This project can build built as normal:

compiling main.c…

compiling foo_weak.c…

linking…

Program Size: Code=372 RO-data=224 RW-data=4 ZI-data=4196

“weak_linkage.axf” – 0 Error(s), 0 Warning(s).

At some time later we can add another file with the same function signature to the project

// foo.c

int foo(void)

{

// override weak function

return 2;

}

If we rebuild, normally we would get the “multiply defined” symbols error, however with weak linkage the linker will now bind the new “strong” function to the call in main.

compiling main.c…

compiling foo_weak.c…

compiling foo.c…

linking…

Program Size: Code=372 RO-data=224 RW-data=4 ZI-data=4196

“weak_linkage.axf” – 0 Error(s), 0 Warning(s).

As you can also see, the weak function is optimized away.

A good example of the use of weak linkage is the definition of the default interrupt handlers in CMSIS.

This example code is based on Keil’s uVision v4.60 compiler/linker, however both GCC and IAR also support weak linkage.