I'm having difficulties with a CMake project that builds an ELF executable with avr-gcc. My executable is supposed to run a custom bytecode file using a virtual machine my colleague and I have written, so I would expect it to be several kilobytes large. However, when I run my CMake script, I get a 321 byte ELF file, whereas from the terminal avr-gcc command I get a 20KB file.
I've done quite a bit of searching, and it seems CMake does separate compilation -- it builds the object files, and then links them. That seems to the the source of my problem.
But, of course, my actual code is a bit long. So here is a more minimal, complete and verifiable example :) .
Here is a file that I want to compile using avr-gcc.
// foo.c
#define sz 400
volatile unsigned int foo[sz] = { 0, 1, 2, 3, 4 };
int main() {
volatile unsigned int bar = 0;
for (volatile int i = 0; i < sz; ++i) {
bar += foo[i];
}
for (volatile int i = 0; i < sz; ++i) {
bar += foo[i];
}
for (volatile int i = 0; i < sz; ++i) {
bar += foo[i];
}
return bar;
}
Then run this bash script:
#!/bin/bash
rm -rf build
mkdir -p build
cd build
# Single command compilation
avr-gcc ../foo.c -o foo_all_in_one.elf -std=c99 -mmcu=atmega328p -Wall -Wl,-s -Wl,--gc-sections
# Separate compilation
avr-gcc ../foo.c -c -o foo_separate.c.obj -std=c99 -mmcu=atmega328p -Wall
avr-gcc foo_separate.c.obj -o foo_separate.elf -Wall -Wl,-s -Wl,--gc-sections
ls -lh
Output:
total 12K
-rwxrwxr-x 1 anthonyd973 anthonyd973 1.7K May 26 09:35 foo_all_in_one.elf
-rw-rw-r-- 1 anthonyd973 anthonyd973 2.0K May 26 09:35 foo_separate.c.obj
-rwxrwxr-x 1 anthonyd973 anthonyd973 296 May 26 09:35 foo_separate.elf
All-in-one compilation yields 1.7KB elf file, whil separate compilation yields a 296B file. Why the difference?
AVR's linker must know which microcontroller you are programming for. I don't have enough technical knowledge to explain why, but I guess it has to do with segment placements or something like that. If you have a better explanation, feel free to give another answer to this question and I'll accept it.
At any rate, if I add -mmcu=atmega328p
to the linking command, everything works fine.
#!/bin/bash
rm -rf build
mkdir -p build
cd build
# Single command compilation
avr-gcc ../foo.c -o foo_all_in_one.elf -std=c99 -mmcu=atmega328p -Wall -Wl,-s -Wl,--gc-sections
# Separate compilation
avr-gcc ../foo.c -c -o foo_separate.c.obj -std=c99 -mmcu=atmega328p -Wall
avr-gcc foo_separate.c.obj -o foo_separate.elf -mmcu=atmega328p -Wall -Wl,-s -Wl,--gc-sections
ls -lh
Output:
total 12K
-rwxrwxr-x 1 anthonyd973 anthonyd973 1.7K May 26 09:41 foo_all_in_one.elf
-rw-rw-r-- 1 anthonyd973 anthonyd973 2.0K May 26 09:41 foo_separate.c.obj
-rwxrwxr-x 1 anthonyd973 anthonyd973 1.7K May 26 09:41 foo_separate.elf