eclipse / upm

UPM is a high level repository that provides software drivers for a wide variety of commonly used sensors and actuators. These software drivers interact with the underlying hardware platform through calls to MRAA APIs.
MIT License
663 stars 411 forks source link

How to properly install optional libraries for building additional UPM sensors #563

Closed dnoliver closed 7 years ago

dnoliver commented 7 years ago

Hello,

I was checking the documentation, and it say that some sensors required libbacnet, libmodbus and libopenzwave, and will not build if those libs are missing. I was searching about libbacnet, and I couldn't find some accurate description on how to install it.
Can you help me here (and provide some commands maybe) to properly install this libraries into an Ubuntu 16.04 machine? (or a Docker container with Ubuntu 16.04).

Below is the part of a CmakeList.txt file where library versions are specified

# Check for BACNET
pkg_check_modules (BACNET libbacnet)

# Check for MODBUS
pkg_check_modules (MODBUS libmodbus>=3.1.2)

# Check for OPENZWAVE
pkg_check_modules (OPENZWAVE libopenzwave)

# Find JPEG
find_package (JPEG)

UPDATE:

  1. I found libmodbus instructions here https://www.howtoinstall.co/en/ubuntu/xenial/libmodbus-dev, apparently is correct

  2. Openzwave is installed from source. In this Dockerfile there are some commands to do it https://github.com/OpenZWave/docker-openzwave/blob/master/Dockerfile#L158

  3. I tried installing libopenjpeg-dev, but Cmake still complain: Could NOT find JPEG (missing: JPEG_LIBRARY JPEG_INCLUDE_DIR)

  4. Using libjpeg-dev solve the issue (at least for CMake, will test compilation on Travis CI)

  5. Still not able to install libbacnet

dnoliver commented 7 years ago

@Propanu @arfoll @pylbert

Propanu commented 7 years ago

Hi @dnoliver, libmodbus >= 3.1.2 is required, xenial provides 3.0.6 which is old. Thus you'll want to grab the source and build it from here: http://libmodbus.org/download/.

For the vcap driver, you need libjpeg-turbo8-dev which is essentially the libjpeg-dev metapackage you mentioned.

BACnet has to be built from source too, it's on sourceforge: https://sourceforge.net/projects/bacnet/ We only really use the MSTP stack, which is enabled with BACDL_DEFINE=-DBACDL_MSTP=1 when you build it.

dnoliver commented 7 years ago

@Propanu I will use bacnet4linux (http://bacnet4linux.sourceforge.net/)

# Install libbacnet 0.3.12
RUN wget https://downloads.sourceforge.net/project/bacnet4linux/bacnet4linux/bacnet4linux-0.3.12/bacnet4linux-0.3.12.tgz && \
    tar -zxvf bacnet4linux-0.3.12.tgz && cd bacnet && \
    BACDL_DEFINE=-DBACDL_MSTP=1 make clean all

Is this correct?

Propanu commented 7 years ago

That's a different project and it's not maintained anymore. You need the actual sources, but those build a static library which doesn't help much in our case since cmake won't find it unless we change things a bit. @pylbert is looking into this. There's also this project here that's supposed to build a shared lib + pc file for it, but my understanding is that it doesn't work as is.

jontrulson commented 7 years ago

IIRC, I had to create my own .pc file for bacnet. There was also no 'install' target to make, so I had to manually copy the library over to /usr/lib, and the header files into /usr/include/bacnet/*

jontrulson commented 7 years ago

Here is the libbacnet.pc file I created prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: bacnet Description: BACnet library Version: 0.8.3 Libs: -L${libdir} -lbacnet Cflags: -I${includedir}/bacnet

dnoliver commented 7 years ago

@Propanu I also tried backnet-stack project like this:

# Install libbacnet 0.3.12
RUN wget https://downloads.sourceforge.net/project/bacnet/bacnet-stack/bacnet-stack-0.8.3/bacnet-stack-0.8.3.zip && \
    unzip bacnet-stack-0.8.3.zip && cd bacnet-stack-0.8.3 && \
    BACDL_DEFINE=-DBACDL_MSTP=1 make clean all

It generates a libbacnet.a file:

root@5e5b97aef3cc:/# ls bacnet-stack-0.8.3/lib
Makefile    bacnetdll.cbp  main.cpp  makefile.b32
bacnet.cbp  libbacnet.a    main.h

But Cmake cannot find it (as you said)

Maybe I can use what @jontrulson is describing as a temporary solution. Where should I create the .pc file?

jontrulson commented 7 years ago

On my systems, it's in: /usr/lib/pkgconfig/libbacnet.pc

dnoliver commented 7 years ago

@jontrulson I run into a problem, not really know which is the problem

So, installing bacnet like this:

# Install libbacnet 0.3.12
RUN wget https://downloads.sourceforge.net/project/bacnet/bacnet-stack/bacnet-stack-0.8.3/bacnet-stack-0.8.3.zip && \
    unzip bacnet-stack-0.8.3.zip && cd bacnet-stack-0.8.3 && \
    BACDL_DEFINE=-DBACDL_MSTP=1 make clean all

#### .pc file created with jontrulson comments
# Temp solution for libbacnet install
COPY bacnet/libbacnet.pc /usr/lib/pkgconfig/libbacnet.pc
RUN cp /bacnet-stack-0.8.3/lib/libbacnet.a /usr/lib/libbacnet.a
RUN mkdir /usr/include/bacnet && cp /bacnet-stack-0.8.3/include/* /usr/include/bacnet/

cmake detects bacnet:

-- Checking for module 'libbacnet'
--   Found libbacnet, version 0.8.3
-- Checking for module 'libmodbus>=3.1.2'
--   Found libmodbus, version 3.1.4
-- Checking for module 'libopenzwave'
--   Found libopenzwave, version 1.4

But fail to compile:

Scanning dependencies of target hx711
[  5%] Building CXX object src/hx711/CMakeFiles/hx711.dir/hx711.cxx.o
[  5%] Linking CXX shared library libupm-bacnetmstp.so
[  5%] Linking CXX shared library libupm-wt5001.so
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../libbacnet.a(apdu.o): relocation R_X86_64_32S against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../libbacnet.a: error adding symbols: Bad value
clang: error: linker command failed with exit code 1 (use -v to see invocation)
src/bacnetmstp/CMakeFiles/bacnetmstp.dir/build.make:146: recipe for target 'src/bacnetmstp/libupm-bacnetmstp.so.1.3.0' failed
make[2]: *** [src/bacnetmstp/libupm-bacnetmstp.so.1.3.0] Error 1
CMakeFiles/Makefile2:18745: recipe for target 'src/bacnetmstp/CMakeFiles/bacnetmstp.dir/all' failed
make[1]: *** [src/bacnetmstp/CMakeFiles/bacnetmstp.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
Propanu commented 7 years ago

Give this a try: BACDL_DEFINE=-DBACDL_MSTP=1 MAKE_DEFINE=-fPIC make clean all

dnoliver commented 7 years ago

@Propanu that made it work! Thanks!

dnoliver commented 7 years ago

@jontrulson @pylbert I am getting a failure in java build because of ozw (https://github.com/intel-iot-devkit/upm/pull/564#issuecomment-305318422) I am contacting you because are listed at the last committers of ozw.cxx. I think there is a problem with the ozwave version. Can you tell me the version that is supposed to work?

jontrulson commented 7 years ago

I doubt it's the ozw version - it seems more like a link failure, and this is a C++ example failure, not Java. I have tested both libopenzwave 1.3 and 1.4 without problems, and I can say for certain that the symbols listed do in fact exist in the library.

Rather, it seems like the link dependency of libopenzwave on libupm-ozw.so would be the problem - ie: it's missing, or the library (libopenzwave) cannot be opened or is not in your LD_LIBRARY_PATH. Can you do an 'ldd on /usr/lib/libupm-ozw.so' and see if it's referencing the libopenzwave library, and if it can find it? That might provide a clue.

dnoliver commented 7 years ago

@jontrulson, ldd /usr/local/lib/libupm-ozw.so

root@5645b9396e4f:/usr/src/app/build# ldd /usr/local/lib/libupm-ozw.so
        linux-vdso.so.1 =>  (0x00007ffc8ad03000)
        libopenzwave.so.1.4 => /usr/local/lib64/libopenzwave.so.1.4 (0x00007f6fa6b76000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6fa67f4000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6fa64ea000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6fa62d4000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6fa5f0b000)
        libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f6fa5eea000)
        /lib64/ld-linux-x86-64.so.2 (0x0000562024780000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f6fa5ce2000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f6fa5ac5000)

UPDATE: the output above is after running make && make install. But this is what happen when I do ldconfig after that:

root@5645b9396e4f:/usr/src/app/build# ldd /usr/local/lib/libupm-ozw.so
        linux-vdso.so.1 =>  (0x00007fff07142000)
        libopenzwave.so.1.4 => not found
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f01b6341000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f01b6037000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f01b5e21000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f01b5a58000)
        /lib64/ld-linux-x86-64.so.2 (0x0000558ef5169000)

after ldconfig, libopenzwave is not found, but if I do not do ldconfing, python example test fails. Any hints?

jontrulson commented 7 years ago

Well, that's annoying. So the lib is there, or at least ldd can find it. One thing that seems odd is the /usr/local/lib64/ prefix. Does the linker need to know where to find this library?

Ie: if you do a "hack" and simply symlink libopenzwave.so* into /usr/lib/ and try the make again, does that get you farther?

dnoliver commented 7 years ago

It didn't help :(. But I can confirm that the library is not installed properly. There is a MinOZW command installed globally by the lib, but it fails to run:

root@7b7fae4a5e82:/usr/src/app/build# MinOZW
MinOZW: error while loading shared libraries: libopenzwave.so.1.4: cannot open shared object file: No such file or directory

root@7b7fae4a5e82:/usr/src/app/build# ldd /usr/local/bin/MinOZW
        linux-vdso.so.1 =>  (0x00007ffc397e3000)
        libopenzwave.so.1.4 => not found
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f01ea5aa000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f01ea393000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f01ea176000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f01e9dad000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f01e9aa3000)
        /lib64/ld-linux-x86-64.so.2 (0x0000564513718000)

So I think I am not installing the library properly, or the lib install flow has a bug

jontrulson commented 7 years ago

And if you ran 'ldconfig /usr/local/lib64' before running the command, does that change anything?

Also, it seem really odd that symlinking the libs into /usr/lib/ didn't change anything either...

dnoliver commented 7 years ago

it came to my mind now that this is only failing in java (when you call cmake -DBUILDSWIGJAVA=ON ..), but it is working in python! I think the only thing that changes here is what CMake is generating. I will try to debug both image, but please let me know if you have any hints about what is python doing and java not

for python:

$ docker-compose build python
$ docker-compose run python bash
$ make ozw-aeotecdw2e-example-cxx

Scanning dependencies of target ozw
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozw.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/zwNode.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozwinterface.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozwdump.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecss6.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecsdg2.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecdw2e.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecdsb09104.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/tzemt400.cxx.o
Linking CXX shared library libupm-ozw.so
Built target ozw
Scanning dependencies of target ozw-aeotecdw2e-example-cxx
Building CXX object examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/ozw-aeotecdw2e.cxx.o
Linking CXX executable ozw-aeotecdw2e-example-cxx
Built target ozw-aeotecdw2e-example-cxx

for java:

$ docker-compose build java
$ docker-compose run java bash
$ make ozw-aeotecdw2e-example-cxx

Scanning dependencies of target ozw
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozw.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/zwNode.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozwinterface.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/ozwdump.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecss6.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecsdg2.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecdw2e.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/aeotecdsb09104.cxx.o
Building CXX object src/ozw/CMakeFiles/ozw.dir/tzemt400.cxx.o
Linking CXX shared library libupm-ozw.so
Built target ozw
Scanning dependencies of target ozw-aeotecdw2e-example-cxx
Building CXX object examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/ozw-aeotecdw2e.cxx.o
Linking CXX executable ozw-aeotecdw2e-example-cxx
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeProductId(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Options::AddOptionBool(std::string const&, bool)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Options::AddOptionString(std::string const&, std::string const&, bool)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetValueAsString(OpenZWave::ValueID const&, std::string*)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeManufacturerId(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::SetValueLabel(OpenZWave::ValueID const&, std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::AddDriver(std::string const&, OpenZWave::Driver::ControllerInterface const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::RemoveDriver(std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::SetValueHelp(OpenZWave::ValueID const&, std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeProductType(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeProductName(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Options::Create(std::string const&, std::string const&, std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeQueryStage(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetNodeType(unsigned int, unsigned char)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::SetValueUnits(OpenZWave::ValueID const&, std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetValueHelp(OpenZWave::ValueID const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::SetValue(OpenZWave::ValueID const&, std::string const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetValueUnits(OpenZWave::ValueID const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Manager::GetValueLabel(OpenZWave::ValueID const&)'
../../src/ozw/libupm-ozw.so.1.3.0: undefined reference to `OpenZWave::Options::AddOptionInt(std::string const&, int)'
collect2: error: ld returned 1 exit status
examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/build.make:95: recipe for target 'examples/c++/ozw-aeotecdw2e-example-cxx' failed
make[3]: *** [examples/c++/ozw-aeotecdw2e-example-cxx] Error 1
CMakeFiles/Makefile2:32742: recipe for target 'examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/all' failed
make[2]: *** [examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/all] Error 2
CMakeFiles/Makefile2:32754: recipe for target 'examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/rule' failed
make[1]: *** [examples/c++/CMakeFiles/ozw-aeotecdw2e-example-cxx.dir/rule] Error 2
Makefile:9338: recipe for target 'ozw-aeotecdw2e-example-cxx' failed
make: *** [ozw-aeotecdw2e-example-cxx] Error 2

UPDATE: I think I found the problem. Using Clang, it works properly, but using gcc, it fails. I will trigger a travis build to confirm this

dnoliver commented 7 years ago

Now it works with clang :), only gcc fails! this is a great advance for me considering that I didn't executed a compiler in maybe 4 years :D.

So now, any hints why gcc do not work?

dnoliver commented 7 years ago

Created issue #567 to track openzwave examples fail with gcc. Closing this. Thank you all!