Closed feckert closed 3 years ago
Hi @feckert we have an option in CMake to build the shared libraries if you would like. Option is here: https://github.com/Azure/azure-iot-sdk-c/blob/593e81183e962c402790e76b41a63c776e78f420/CMakeLists.txt#L72
Please let us know if the experience is not as expected!
@danewalton Thank you for the quick feedback. It has worked and the so files for opwenwrt are created.
I am currently preparing your azure iot sdk for openwrt and integrating it into the upstream package feed for openwrt. From my point of view, the integration into the upstream project is better, than your suggestion to build it in the openwrt SDK! If we integrate it directly, more users will have the opportunity to use your sdk ;-) and thus you will reach more people.
I am not yet completely familiar with your azure iot sdk. So my question is: When packaging the sdk for openwrt is it better to use your suggested git submodules or package your dependency directly into openwrt. For this I have to integrate additional packets for openwrt. From my point of view, these would be uamqp, umqtt, parson, uhttp, umock-c and others that I have now overlooked.
I think that the problem with "packaging directly" might be that not being able to configure the SDK with different options would be a shortcoming. I haven't delved too far into openwrt so not an expert here. What kind of limitations from the user's perspective (of openwrt) are there packaging directly vs submodules?
Thanks for your comments. If I get some problem I will open a ticket ;-)
I have to say your sdk is quite complicated! The submodules in this sdk are still fine. But when the submodules in turn add additional submodules, it slowly becomes confusing to me.
From my point of view as a package maintainer for openwrt, I find it better if each component stands alone and can be packaged that way. That means concretely. The following components should be stored in separate git repositories.
There can then be a parent git repository. That then brings everything together.
It may be that I have not understood all this now and it may also be that I have to deal more closely with the SDK. After compiling the SDK, (which also works), I now have lots of header files and libraries. I now have to install them into the openwrt build system called STAGING_DIR so that I can write a program that uses the headers and libs. But that's too much for me now. I don't know what I need for an Azure IoT programme to get installed in the STAGING_DIR. This are all the libs and includes that the SDK wants to install into the openwrt STAGING_DIR install.txt. Of course I can install everything, but I think that will lead to problems at some point in the future. @danewalton Maybe you can give me some guidance on how others do it and what I realy need. I'm sure I'm not the first person to try to package the SDK for an opensource project.
We do have a port for VCPKG that you might be able to look at? https://github.com/microsoft/vcpkg/tree/master/ports/azure-iot-sdk-c https://github.com/microsoft/vcpkg/tree/master/ports/azure-c-shared-utility https://github.com/microsoft/vcpkg/tree/master/ports/azure-macro-utils-c https://github.com/microsoft/vcpkg/tree/master/ports/azure-umqtt-c
This essentially breaks each of the repos into a separate package.
We also have an embedded SDK here which you can have a look at. Its architecture is different and serves a slightly difference purpose but another option.
@danewalton Thanks for the links, but this is not an option, it does not fit into the buildsystem of OpenWrt. I have moved on. I have now packaged macro_utils_c and umock-c for openwrt. Unfortunately, I now get an error when building azure-c-shared-utility. This has a dependency to umock_c.
Make Error at /home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/cmake/umock_c/umock_cTargets.cmake:77 (message):
The imported target "umock_c" references the file
"/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/cmake/lib/libumock_c.a"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
"/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/cmake/umock_c/umock_cTargets.cmake"
but not all the files it references.
Call Stack (most recent call first):
/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/cmake/umock_c/umock_cConfig.cmake:40 (include)
dependencies.cmake:21 (find_package)
CMakeLists.txt:623 (include)
-- Configuring incomplete, errors occurred
The static lib umock-c is not found by azure-c-shared-utiltiy. /home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/target-mips_24kc_musl/usr/lib/cmake/lib/libumock_c.a" As I can see the search path is wrong. In the path ../usr/lib/cmake/lib/libumock_c.a there is slipped in a cmake too much.
As I see it, your install CMakeLists.txt for umock-c is not cross compile capable because the following lines are missing in the target of cmake (See. https://github.com/Kitware/CMake/blob/master/Source/cmExportInstallFileGenerator.cxx#L214) If I edit the umock Target cmake file by hand with the missing lines, then the static lib is found by azure-c-shared-utility. Unfortunately, I am not a cmake guru. But maybe you have a hint what I have to change in the CMakeLists.txt file of umock-c so that the correct install target is generated by cmake.
@danewalton I have done it now :tada:
It was because I put the generated cmake files under /usr/lib/cmake. This is the preferred directory of openwrt. However, the CmakeLists.txt from umock-c stores the files under /usr/cmake. That was all. If I now also apply the patch, it will compile.
Ayyy that's wonderful! That patch looks like it was merged to master with this PR here. So if you update your repo it should work just fine. Are you basing this off an LTS branch or master?
So now I have got further and have packaged all the azure-iot stuff for Openwrt. I have staged my changes for OpenWrt in my repository. https://github.com/TDT-AG/packages/commits/pr/20210209-azure-iot I really have to say that this git submodule handling is not realy exactly easy to understand! Why do you do that? Everything is built several times
I have now removed all git submodules build from your packages and build the dependency stack with openwrt dependency handling. All package use the versions from your latest LTS stable LTS_01_2021_Ref01
Everything compiles so far when I only use static libs.
But If I enable shared lib building with the option build_as_dynamic
and also set skip_samples
to NO
, then I get the following error for the iothub_client sample iothub_convenience_sample
make[5]: Entering directory '/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/build_dir/target-mips_24kc_musl/azure-iot-sdk-c-LTS_01_2021_Ref01/build_openwrt'
Scanning dependencies of target iothub_convenience_sample
make[5]: Leaving directory '/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/build_dir/target-mips_24kc_musl/azure-iot-sdk-c-LTS_01_2021_Ref01/build_openwrt'
make[5]: Entering directory '/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/build_dir/target-mips_24kc_musl/azure-iot-sdk-c-LTS_01_2021_Ref01/build_openwrt'
[ 64%] Building C object iothub_client/samples/iothub_convenience_sample/CMakeFiles/iothub_convenience_sample.dir/iothub_convenience_sample.c.o
[ 64%] Linking C executable iothub_convenience_sample
/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: ../../libiothub_client.so.1.6.0: undefined reference to `amqpvalue_get_symbol'
/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: ../../libiothub_client.so.1.6.0: undefined reference to `message_get_message_annotations'
/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: ../../libiothub_client.so.1.6.0: undefined reference to `cbs_open_async'
/home/feckert/workspace/openwrt/LDM-master-iot/build/openwrt/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: ../../libiothub_client.so.1.6.0: undefined reference to `properties_get_correlation_id
....
@danewalton I hope you can help me to understand why this happens? I think this is because the libuamqp.a is not linked with libiothub_client.so?
Interesting I tried to build with similar CMake options and it seemed to build for me. Can you give further details on how you are building/configuring your setup?
all these are defined in the AMQP submodule.
Are you targeting MQTT/AMQP/Both?
@ericwol-msft @danewalton I have everything turned on and if I compile everything together with the whole git submodules dependency tree it works.
But since I want to integrate the whole azure iot stuff into the OpenWrt upstream package feed, then I have to package all dependencies separately, for a proper and upstream acceptable integration in OpenWrt. I have pushed my work, so far into my repository. That's how I would imagine the whole thing works in OpenWrt if every dependency is in his own package.
When I compile the azure-iot-sdk-c (after all dependencies have been compiled and everything has been installed in the right places in the buildsystem) I still have to apply two patches otherwise it would not compile, even on static linking.
Patch: Since I no longer have parson as a git submodule I have to apply this patch, Otherwise the build will fails. I built parson as an openwrt packges, so it will be found by cmake
Patch: If I do not remove some lines in the CMakefile, I get the following error when compiling.
CMake Error at iothub_client/CMakeLists.txt:494 (install):
install TARGETS given target "uamqp" which does not exist
Unfortunately, I am still not very familiar with the sdk. I have however questions, which you can answer me surely.
Which libraries can now be built as shared object.
Are there efforts from your side to clean up the Cmake files. I find them confusing. If I look at the azure-sdk-iot-c as a whole project then it might work, but if I look at it as individual packages that can work separately then it might be tricky.
Like last time, I tried something shortly after I posted the previous comment. And surprise surprise, now the shared library compiles correctly and all symbols are found :tada:.
I still had to change the CMakeFile.txt with my patches to get the build working. Maybe one of you can take a look at why I have to patch your CMakeFile.txt like this. For me it works now. I have not tried other cmake setup's. That would be the next step, that we can turn on/off cmake configuration options via the OpenWrt buildsystem. As I said I think the CMakeFiles.txt needs some tidying up.
Alright so I'll get back to your other questions, but I can confirm that the combo of options cmake -Dbuild_as_dynamic=ON -Duse_installed_dependencies=ON ..
seems to be broken. I'll look to get that fixed which should unblock one of those problems.
Good to see the progress though! And thanks for bringing this to our attention.
I have now found time to work on the integration of azure-iot-sdk-c again. As I said, I have now divided the whole thing into the following packages in openwrt.
The whole thing also compiles somehow with the samples. But I'm not entirely happy about it. Especially as your cmake approach is not easy to look through.
Now I have moved a sample from iothub_client/samples/iothub_ll_telemetry_sample/iothub_ll_telemetry_sample.c
in a separate OpenWrt package so that it is not built in the azure-iot-sdk-c stack.
For this purpose I have written a separate CMakeLists.txt file (tazure means test-azure)
cmake_minimum_required(VERSION 2.6)
PROJECT(tazure C)
ADD_DEFINITIONS(-Os -Wall --std=gnu99 -Wmissing-declarations)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
FIND_LIBRARY(iothub_client NAMES iothub_client)
FIND_PATH(iothub_client_include_dir azureiot/iothub.h)
INCLUDE_DIRECTORIES(${iothub_client_include_dir})
FIND_LIBRARY(aziotsharedutil NAMES aziotsharedutil_dll)
FIND_PATH(aziotsharedutil_include_dir azureiot/azure_c_shared_utility/threadapi.h)
INCLUDE_DIRECTORIES(${aziotsharedutil_include_dir})
ADD_EXECUTABLE(tazure main.c)
TARGET_LINK_LIBRARIES(tazure ${iothub_client})
TARGET_LINK_LIBRARIES(tazure ${aziotsharedutil})
INSTALL(TARGETS tazure RUNTIME DESTINATION /usr/sbin)
Edit:
I have now solved the problem by extending the cmake include variables with azureiot
FIND_LIBRARY(iothub_client NAMES iothub_client)
FIND_PATH(iothub_client_include_dir azureiot/iothub.h)
INCLUDE_DIRECTORIES(${iothub_client_include_dir}/azureiot) <-----
FIND_LIBRARY(aziotsharedutil NAMES aziotsharedutil_dll)
FIND_PATH(aziotsharedutil_include_dir azureiot/azure_c_shared_utility/threadapi.h)
INCLUDE_DIRECTORIES(${aziotsharedutil_include_dir}/azureiot)<-----
But as expected, this does not work.
The includes are installed under /usr/include/azureiot/*
.
But in your headers you do not use the prefix azuriot
!
So i get the following build error
/home/feckert/workspace/openwrt/LDM-master-x86_64/build/openwrt/staging_dir/target-x86_64_musl/usr/include/azureiot/azure_c_shared_utility/map.h:19:10: fatal error: azure_c_shared_utility/strings.h: No such file or directory
#include "azure_c_shared_utility/strings.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@danewalton I hope you can help me further.
I just want to know if it is intended that the includes are found under /usr/include/azureiot
.
Additional not all libs are build as shared objects.
In openwrt there is a build target that shows which files are installed in the system during a build.
Here is the output for it. As you can see the includes are moved to /usr/include/azuriot/
and only the lib iothub_client.so
is build as shared object.
feckert@feckert: ~/workspace/openwrt/LDM-master-x86_64/build/openwrt/build_dir/target-x86_64_musl/azure-iot-sdk-c-LTS_01_2021_Ref01/
$ tree ipkg-install
ipkg-install
└── usr
├── cmake
│ ├── azure_iot_sdksConfig.cmake
│ ├── azure_iot_sdksConfigVersion.cmake
│ ├── azure_iot_sdksFunctions.cmake
│ ├── azure_iot_sdksTargets.cmake
│ └── azure_iot_sdksTargets-release.cmake
├── include
│ └── azureiot
│ ├── agenttypesystem.h
│ ├── blob.h
│ ├── codefirst.h
│ ├── commanddecoder.h
│ ├── datamarshaller.h
│ ├── datapublisher.h
│ ├── dataserializer.h
│ ├── iotdevice.h
│ ├── iothub_client_authorization.h
│ ├── iothub_client_core_common.h
│ ├── iothub_client_core.h
│ ├── iothub_client_core_ll.h
│ ├── iothub_client_diagnostic.h
│ ├── iothub_client.h
│ ├── iothub_client_ll.h
│ ├── iothub_client_ll_uploadtoblob.h
│ ├── iothub_client_options.h
│ ├── iothub_client_private.h
│ ├── iothub_client_retry_control.h
│ ├── iothub_client_version.h
│ ├── iothub_device_client.h
│ ├── iothub_device_client_ll.h
│ ├── iothub_deviceconfiguration.h
│ ├── iothub_devicemethod.h
│ ├── iothub_devicetwin.h
│ ├── iothub.h
│ ├── iothub_internal_consts.h
│ ├── iothub_message.h
│ ├── iothub_messaging.h
│ ├── iothub_messaging_ll.h
│ ├── iothub_module_client.h
│ ├── iothub_module_client_ll.h
│ ├── iothub_registrymanager.h
│ ├── iothub_sc_version.h
│ ├── iothub_service_client_auth.h
│ ├── iothubtransport_amqp_cbs_auth.h
│ ├── iothubtransport_amqp_common.h
│ ├── iothubtransport_amqp_connection.h
│ ├── iothubtransport_amqp_device.h
│ ├── iothubtransportamqp.h
│ ├── iothubtransport_amqp_messenger.h
│ ├── iothubtransportamqp_methods.h
│ ├── iothubtransport_amqp_telemetry_messenger.h
│ ├── iothubtransport_amqp_twin_messenger.h
│ ├── iothubtransportamqp_websockets.h
│ ├── iothubtransport.h
│ ├── iothubtransporthttp.h
│ ├── iothub_transport_ll.h
│ ├── iothub_transport_ll_private.h
│ ├── iothubtransport_mqtt_common.h
│ ├── iothubtransportmqtt.h
│ ├── iothubtransportmqtt_websockets.h
│ ├── jsondecoder.h
│ ├── jsonencoder.h
│ ├── message_queue.h
│ ├── methodreturn.h
│ ├── multitree.h
│ ├── schema.h
│ ├── schemalib.h
│ ├── schemaserializer.h
│ ├── serializer_devicetwin.h
│ ├── serializer.h
│ └── uamqp_messaging.h
└── lib
├── libiothub_client.a
├── libiothub_client_amqp_transport.a
├── libiothub_client_amqp_ws_transport.a
├── libiothub_client_http_transport.a
├── libiothub_client_mqtt_transport.a
├── libiothub_client_mqtt_ws_transport.a
├── libiothub_client.so -> libiothub_client.so.1
├── libiothub_client.so.1 -> libiothub_client.so.1.6.0
├── libiothub_client.so.1.6.0
├── libiothub_service_client.a
└── libserializer.a
Cmake has the nice feature that you can specify a build folder. When I look there, the other ones are also built as shared objects.
@feckert update on this item:
But in your headers you do not use the prefix azuriot! So i get the following build error
/home/feckert/workspace/openwrt/LDM-master-x86_64/build/openwrt/staging_dir/target-> x86_64_musl/usr/include/azureiot/azure_c_shared_utility/map.h:19:10: fatal error: azure_c_shared_utility/strings.h: No such file or directory #include "azure_c_shared_utility/strings.h" ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@danewalton I hope you can help me further. I just want to know if it is intended that the includes are found under /usr/include/azureiot.
We have a PR here which addresses that with a similar GH issue here
Also this PR to resolve the uamqp linking https://github.com/Azure/azure-iot-sdk-c/pull/1948
Are you able to state the remaining issues you are having @feckert? I know there were a few.
@danewalton thank you for taking care of this. I have now opened a pullrequest draft in the upstream repository of the openwrt package feed to integrate the azure-iot-sdk for c into openwrt buildsystem.
Sweet! So all the issues to get that working are taken care of from our (the SDK team) perspective?
Going to go ahead and close this for now but let us know if you still have issues and would like it reopened.
Thats fine with we, thanks for your @danewalton time, if I have problems then I'll get back to you :+1:
I have just started working on your SDK for azure iot project. I am in the process of integrating your SDK abstraction into the oprnwrt buildsystem. I have also managed to make the examples build and executable on a MIPS target and on the x86_64 target.
x86_64 target:
MIPS target:
All your sample programs are statically linked except the libraries you depend on. What about your abstraction layers.Are there no shared objects available? In a small system, that is a problem if I have several services running?