queezythegreat/arduino-cmake

Build a project with a library that depends on another library

blemasle opened this issue · 12 comments

Hi,

New to Cmake here. I try to hack my CMakeLists.txt and follow tutorials but I can't build my project which include an arduino library that has a dependency on another arduino library :
| Project
| ---> EEPROMEx
| --------->EEPROM

Here is my CMakeLists.txt :

set(ARDUINO_DEFAULT_BOARD uno) #default board ID, when not specified
set(ARDUINO_DEFAULT_PORT /dev/ttyUSB0) #default port, when not specified

link_directories(${CMAKE_SOURCE_DIR}/libraries)
set(Wire_RECURSE True)

generate_arduino_firmware(mls400
        SKETCH ./
        HDRS SomeHeader.h
        SRCS SomeHeader.cpp)

I even try to

  • add EEPROM to the "LIBS" argument, no luck
  • add link_directories [...]/libraries to the root CMakeLists.txt, no luck
  • call generate_arduino_library before generate_arduino_firmware, no luck
  • move EEPROMEx library to the ARDUINO_SDK libraries folder, no luck

For reference, I do not see my the EEPROM directory being included when building (by looking at build.make) EEPROMEx whereas I see the Wire directoy :

-I"/opt/arduino-1.0.5/hardware/arduino/cores/arduino"
-I"/opt/arduino-1.0.5/libraries"
-I"/opt/arduino-1.0.5/hardware/arduino/variants/standard" 
-I"/home/blemasle/tmp/workdir/libraries/EEPROMEx"
-I"/home/blemasle/tmp/workdir/libraries/EEPROMEx/utility" 
-I"/home/blemasle/tmp/workdir/MLS400"
-I"/home/blemasle/tmp/workdir/libraries/EEPROMEx" 
-I"/opt/arduino-1.0.5/libraries/Wire" 
-o CMakeFiles/uno_EEPROMEx.dir/__/libraries/EEPROMEx/EEPROMEx.cpp.obj 
-c /home/blemasle/tmp/workdir/libraries/EEPROMEx/EEPROMEx.cpp

Here is the make output :

Linking CXX static library libuno_CORE.a
[ 68%] Built target uno_CORE
Scanning dependencies of target uno_Wire
[ 72%] Building CXX object MLS400/CMakeFiles/uno_Wire.dir/opt/arduino-1.0.5/libraries/Wire/Wire.cpp.obj
[ 75%] Building C object MLS400/CMakeFiles/uno_Wire.dir/opt/arduino-1.0.5/libraries/Wire/utility/twi.c.obj
Linking CXX static library libuno_Wire.a
[ 75%] Built target uno_Wire
Scanning dependencies of target uno_EEPROM
[ 82%] Building CXX object MLS400/CMakeFiles/uno_EEPROM.dir/opt/arduino-1.0.5/libraries/EEPROM/EEPROM.cpp.obj
Linking CXX static library libuno_EEPROM.a
[ 82%] Built target uno_EEPROM
Scanning dependencies of target uno_EEPROMEx
[ 86%] Building CXX object MLS400/CMakeFiles/uno_EEPROMEx.dir/__/libraries/EEPROMEx/EEPROMEx.cpp.obj
In file included from /home/blemasle/tmp/workdir/libraries/EEPROMEx/EEPROMEx.cpp:23:
/home/blemasle/tmp/workdir/libraries/EEPROMEx/EEPROMEx.h:23:20: error: EEPROM.h: File or directory not found
make[2]: *** [MLS400/CMakeFiles/uno_EEPROMEx.dir/__/libraries/EEPROMEx/EEPROMEx.cpp.obj] Error 1
make[1]: *** [MLS400/CMakeFiles/uno_EEPROMEx.dir/all] Error 2
make: *** [all] Error 2

Could someone enlight me on how I can achieve this ?
The EEPROMEx library can be found here : http://thijs.elenbaas.net/files/EEPROMEx.0.8.3.zip

Thanks,
blemasle

Hi, could you run make as follows:

VERBOSE=1 make

That should output the full compiler commands.

Here is the requested compiler output : http://pastebin.com/dN4ZDKdK
Notice this is not the "simplified" project I exposed earlier. This is the full project with more libraries.

Thanks for your help

That's a lot to read, but it seems I come accross two different bugs with arduino-cmake !

I tweaked the Arduino.cmake file a bit and managed to get all the needed files to be included. I'll submit it once all works properly (and cleaned up those modifications a bit).
Now I realise that on top on the first issue, it seems that the library itself won't compile. This is what I get when I try to separatly compile the EEPROMEx library : http://pastebin.com/KKYhbypE

The problem stands with the "extern" declaration at the end of both EEPROM.h and EEPROMEx.h being of different class. But the standard arduino compiler does not complains about this. How to solve that ?

Here is the CMakeLists.txt

set(ARDUINO_DEFAULT_BOARD uno) #default board ID, when not specified
set(ARDUINO_DEFAULT_PORT /dev/ttyUSB0) #default port, when not specified
set(VERBOSE 1)

generate_arduino_library(eepromex
        HDRS EEPROMEx.h
        SRCS EEPROMEx.cpp)

And the root CMakeLists.txt :

set(VERBOSE 1)
set(CMAKE_TOOLCHAIN_FILE cmake/ArduinoToolchain.cmake) # Arduino Toolchain
link_directories(${CMAKE_SOURCE_DIR}/libraries)

cmake_minimum_required(VERSION 2.8)
project(eepromex C CXX)

print_board_list()
print_programmer_list()

add_subdirectory(libraries/EEPROMEx)   #add the example directory into build

Thanks again for any help provided ! :)

OK, I finally get it all working ! And it seems that there is no bug, just an undocumented argument ! :)

For those who come across the same issues I did, here the solution :
EEPROMEx won't compile on newer avr-gcc (see thijse/Arduino-Libraries#3. The library is being rewritten, but in the meantime you have to edit the library and rename the EEPROMClassEx default instance from "EEPROM" to "EEPROMEx"
After that, you'll see that avr-gcc is missing an include of EEPROM.h. The solution is to use the "ARDLIBS" parameter when you call generate_arduino_firmware :

generate_arduino_firmware(myproject
    SKETCH ./
    HDRS header.h
    SRCS src.cpp
    ARDLIBS EEPROM)

The drawback of that is file inclusion is not automated, you need to specify which librairies headers need to be included by default in (sadly) every single file compiled !
A recursive dependency detection would be much better, and also more intuitive. Hope that @queezythegreat is listening to that suggestion :p

blemasle

Hi, I'm a little bit confused, Arduino type libraries have automatic library detection (which is recursive). With the example you provided in previous post, ie the one where you build EEPROMex via generate_arduinio_library auto-detection of libraries is disabled, that function is only intended to pure static libraries (as stated in the documentation).

The purpose of it is to be able to create static libraries which are compiled for a specific version of a Arduino board, that's it, no other automatic stuff happens in that function. That function is no intended for building Arduino type libraries (the name might be misleading, but was chosen because it shares a common prefix and that it's part of Arduino-CMake)!

The option ARDLIBS was added for a very specific reason, it's for libraries which are named differently (the directory name of the library does not match the header include), or when using is in conjunction with generate_avr_XXX functions (which also is undocumented right now).

I hope that clears up some confusion, and sorry for not responding earlier, I am very busy lately and haven't had time to tinker on Arduino-CMake.

Actually, I think I made a mistake on the generate_arduino_library, apparently I did include Arduino library detection.... I just looked at the code, it should have detected the EEPROM library.

Do you have your project accessible somewhere on the internet, so I can try to build it?

Hi,

Thanks for answering me, and don't worry for the delay ! That made me scratching my head and discovering how cmake works :)

I uploaded a simple project which does nothing but to demonstrate the error.
https://dl.dropboxusercontent.com/u/10744359/failed_project.zip
All you need to do is to dig into that build folder and input the traditionnal cmake .. then make.

In those files, I included two scenarios : N°1 is direct inclusion of the library, and N°2 is inclusion via another cpp file. The two scenarios will fail unless you uncomment the "ARDLIBS EEPROM" directive in the CMakeLists.txt (as you said, this is not the intended purpose but it does work !).

The recursive library detection seems to work according to the compiler output, but what is missing is the "-I /your/path/to/that/library" argument. That's why the ARLIBS solve my issue, because if I remember it correctly, it forces the inclusion path all along the way !

I somehow fixed the case 1 one scenario (my original case) by tweaking the inclusion path list argument inside setup_arduino_libraries function (a quick and ugly fix but that may gave you a hint). See this diff file : https://dl.dropboxusercontent.com/u/10744359/Arduino.cmake.diff

But that do not fix the case 2 scenario which requires some modifications under the main generate_arduino_firmware routine...

If I'm being unclear, please advise me so I can fill the blanks. I'll be more than happy to help !

Hi, thanks for giving me access to your project, I will have a look at that bug and try to fix it when I have some time. Hopefully I will be quicker in the response this time.

Be advise that it's not my project, it's just a extremely simple project that demonstrates the compilation issue. I just thought it would be much easier for you or anyone else to understand the problem without all my project sources.

Thanks !

Hi, I'll try to have a look at your example this weekend...

Hi, I just committed in a bug fix to your issue. The include paths where not being set everywhere. Please check out the develop branch and tell me if it fixes your problem.

Hi,

Sorry for the delay, I was on vacations :)
Just tested your fix, and it seems to be fixed ! Both in the test project I provided and the real one.

Thanks a lot !