queezythegreat / arduino-cmake

Arduino CMake Build system
648 stars 216 forks source link

undefined reference to 'loop' #11

Closed treaves closed 12 years ago

treaves commented 12 years ago

I have a very simple project located https://code.launchpad.net/~treaves/+junk/blinkqp . The compile fails with the message in the title. This project is just a junk project to figure out how to get the qp library linked in to a project.

The loop function is defined: http://bazaar.launchpad.net/~treaves/+junk/blinkqp/view/head:/libraries/qp/qp_port.cpp#L33 . I can see from the verbose make output that the correct library seems to be in the linker command.

cd /home/treaves/Development/qp/blinkqp/builds/unix/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/blink.dir/link.txt --verbose=1
/usr/bin/avr-g++   -g -Os       -ffunction-sections -fdata-sections -fno-exceptions  -Wl,--gc-sections    -mmcu=atmega1284p CMakeFiles/blink.dir/project.cpp.obj CMakeFiles/blink.dir/blink.cpp.obj CMakeFiles/blink.dir/bsp.cpp.obj  -o blink.elf  libatmega1284_Wire.a ../libraries/libqp.a ../libraries/libatmega1284_CORE.a 
../libraries/libatmega1284_CORE.a(main.cpp.obj): In function `main':
/usr/local/arduino/hardware/arduino/cores/sanguino/main.cpp:10: undefined reference to `loop'

I see ../libraries/libqp.a there, so I'm not sure why the error. Any ideas?

treaves commented 12 years ago

When I copy the loop function from the above mentioned file into a source file (project source as opposed to library source), the compile finishes fine.

When I make VERBOSE=1 qp, I can see that the cpp file is being compiled into the .a.

So it has something to do with the command being generated to do the linking that is preventing it from being found when it's in the library.

queezythegreat commented 12 years ago

I think the problem might be in the linking order of the libraries. But thats just a huntch...

I haven't actually built your project (missing the patches for arduino), so I may be wrong on this one. By the way support for Arduino 1.0 has been finally added.

treaves commented 12 years ago

You need nothing additional to build this project. I tried to create one as simple as possible.

This would also be a good project to use for the defect where in-project libraries are not being found; the one I reported previously where I have to create cmake entries for the library folder.

treaves commented 12 years ago

I updated the arduino-cmake code, and changed the board to an uno, so, you should have no trouble try now.

treaves commented 12 years ago

O.K., so I've figured out what the problem is, just not how to solve it. The command that gets executed (the link step that fails) is:

/usr/bin/avr-g++   -g -Os       -ffunction-sections -fdata-sections -fno-exceptions  -Wl,--gc-sections    -mmcu=atmega328p CMakeFiles/blink.dir/project.cpp.obj CMakeFiles/blink.dir/blink.cpp.obj CMakeFiles/blink.dir/bsp.cpp.obj  -o blink.elf  libuno_Wire.a ../libraries/libqp.a ../libraries/libuno_CORE.a

The last two libraries need to be inverted, like so:

/usr/bin/avr-g++   -g -Os       -ffunction-sections -fdata-sections -fno-exceptions  -Wl,--gc-sections    -mmcu=atmega328p CMakeFiles/blink.dir/project.cpp.obj CMakeFiles/blink.dir/blink.cpp.obj CMakeFiles/blink.dir/bsp.cpp.obj  -o blink.elf  libuno_Wire.a ../libraries/libuno_CORE.a ../libraries/libqp.a

I think the issue here is that arduino-cmake expects to find all of the required symbols in the firmware, not in the library. But with this library, it takes over the loop function, hence it's location in the library.

So now I understand the problem, and I feel more comfortable with the work-around, but, is there a way to actually resolve this?

queezythegreat commented 12 years ago

That's exactly what I though (relating to the linking error)! It may be possible to use the add_dependencies command to make the core arduino library be dependent upon your library, making a cyclic linking dependency (cmake should be able to resolve this cycle by linking your library twice).

The board id did cause me problems, I thought your example was board specific, that's why I didn't think of changing the board id.

treaves commented 12 years ago

Any idea where this change should be made? If you can just paste the code, I can try it out. Thanks.

treaves commented 12 years ago

Actually, now that I understand what's going on here, I think it's working as-is. It's a bit odd for a library to define the loop method, and it works in he Arduino IDE because they really do not compile libraries as libraries.

queezythegreat commented 12 years ago

Yes, I would suggest referencing the library loop function from the firmware. Something like:

void loop() {
   library_loop();
}

That will give you what you want and eliminate the linking problem.