Multiple definitions for MQTT library when flash for debug

I am having trouble finding a cause for a hard fault in a transmission using the MQTT-TLS library, so I am trying to flash the Argon for debug. When I do this I get many errors for multiple definitions of variables that are found in the MQTT library and some mbedtls folders in firmware 1.4.0.

Does anybody know how to navigate these errors easily to run in debug mode?

I’m having the same issue here, also using MQTT-TLS. I have not found a way around it unfortunately, and have not been able to debug adequately since adding that library. I’d also love to see some solution to the problem. All of the libraries I’ve found that don’t use mbedTLS have licensing models not compatible with mine (MIT).

What multiple definitions do you see?
The samples that come with the library build fine for me.

When importing MQTT-TLS library you mustnot import TlsTcpClient (or any other TLS/SSL library) also. MQTT-TLS brings its own mbedtls copy.

How are you building?
What sources?
How does your project structure look?

I build debug builds from Workbench inside VS Code. MQTT-TLS was installed via Workbench from the Particle library. Standard project structure with src and lib directories, building from cpp (no .ino file to preprocess).

You can reproduce the problem by creating a test project, installing the MQTT-TLS library and attempting to compile for Debug.

Sample of compiler output (truncated due to many errors):

../build/target/hal/platform-13//libhal.a(aes_alt.o): In function `mbedtls_aes_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/aes_alt.c:60: multiple definition of `mbedtls_aes_init'
../build/target/user/platform-13/tls//libuser.a(aes.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/aes.cpp:522: first defined here
../build/target/hal/platform-13//libhal.a(aes_alt.o): In function `mbedtls_aes_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/aes_alt.c:60: multiple definition of `mbedtls_aes_free'
../build/target/user/platform-13/tls//libuser.a(aes.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/aes.cpp:405: first defined here
../build/target/hal/platform-13//libhal.a(aes_alt.o): In function `mbedtls_aes_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/aes_alt.c:60: multiple definition of `mbedtls_aes_setkey_enc'
../build/target/user/platform-13/tls//libuser.a(aes.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/aes.cpp:405: first defined here
../build/target/hal/platform-13//libhal.a(aes_alt.o): In function `mbedtls_aes_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/aes_alt.c:60: multiple definition of `mbedtls_aes_setkey_dec'
../build/target/user/platform-13/tls//libuser.a(aes.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/aes.cpp:405: first defined here
../build/target/hal/platform-13//libhal.a(aes_alt.o): In function `mbedtls_aes_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/aes_alt.c:60: multiple definition of `mbedtls_aes_crypt_ecb'
../build/target/user/platform-13/tls//libuser.a(aes.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/aes.cpp:405: first defined here
../build/target/hal/platform-13//libhal.a(sha1_alt_cc310.o): In function `mbedtls_sha1_init':
/Users/reidforrest/.particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/hal/src/nRF52840/mbedtls/sha1_alt_cc310.c:29: multiple definition of `mbedtls_sha1_init'
../build/target/user/platform-13/tls//libuser.a(sha1.o):/Users/reidforrest/software/picsilcloud/picsilsense/test/tls/lib/MQTT-TLS/src/mbedtls/sha1.cpp:83: first defined here
../build/target/hal/platform-13//libhal.a(sha1_alt_cc310.o): In function `cc310_enable':

Complete source for the project (after installing MQTT-TLS lib in Workbench):

/*
 * Project tls
 * Description:
 * Author:
 * Date:
 */
#include "MQTT-TLS.h"

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.
  pinMode(D7, OUTPUT);
  digitalWrite(D7, HIGH);
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.

}

This code compiles fine normally, but will throw errors about redefinition of all parts of mbedtls if compiled for debugging due to the library also being used by DeviceOS.

Nope, builds for me just the same (local and cloud compile): Example a1-example.ino with Workbench targeting Argon 1.4.0

C:/Users/xxx/.particle/toolchains/gcc-arm/5.3.1/bin/arm-none-eabi-size --format=berkeley c:/Particle/Test/VSCTest/generalDummy/target/generalDummy.elf
   text    data     bss     dec     hex filename
  77408     156   11540   89104   15c10 c:/Particle/Test/VSCTest/generalDummy/target/generalDummy.elf
rm -f c:/Particle/Test/VSCTest/generalDummy/target/platform_user_ram.ld
make[2]: Leaving directory '/cygdrive/c/Users/xxx/.particle/toolchains/deviceOS/1.4.0/firmware-1.4.0/modules/argon/user-part'
make[1]: Leaving directory '/cygdrive/c/Users/xxx/.particle/toolchains/deviceOS/1.4.0/firmware-1.4.0/main'

*** COMPILED SUCCESSFULLY ***

And this is my project structure

C:\PARTICLE\TEST\VSCTEST\GENERALDUMMY
β”‚   argon_firmware_1569585043632.bin
β”‚   project.properties
β”‚   README.md
β”‚
β”œβ”€β”€β”€.vscode
β”‚       launch.json
β”‚       settings.json
β”‚
β”œβ”€β”€β”€lib
β”‚   └───MQTT-TLS
β”‚       β”‚   library.properties
β”‚       β”‚   license.txt
β”‚       β”‚   README.md
β”‚       β”‚
β”‚       β”œβ”€β”€β”€examples
β”‚       β”‚   β”œβ”€β”€β”€a1-example
β”‚       β”‚   β”‚       a1-example.ino
β”‚       β”‚   β”‚
β”‚       β”‚   └───a2-example
β”‚       β”‚           a2-example.ino
β”‚       β”‚
β”‚       └───src
β”‚           β”‚   MQTT-TLS.cpp
β”‚           β”‚   MQTT-TLS.h
β”‚           β”‚
β”‚           β”œβ”€β”€β”€mbedtls
β”‚           β”‚       aes.cpp
β”‚           β”‚       aes.h
β”‚           β”‚       aesni.cpp
β”‚           β”‚       aesni.h
β”‚           β”‚       apache-2.0.txt
β”‚           β”‚       arc4.cpp
β”‚           β”‚       arc4.h
β”‚           β”‚       aria.cpp
β”‚           β”‚       aria.h
β”‚           β”‚       asn1.h
β”‚           β”‚       asn1parse.cpp
β”‚           β”‚       asn1write.cpp
β”‚           β”‚       asn1write.h
β”‚           β”‚       base64.cpp
β”‚           β”‚       base64.h
β”‚           β”‚       bignum.cpp
β”‚           β”‚       bignum.h
β”‚           β”‚       blowfish.cpp
β”‚           β”‚       blowfish.h
β”‚           β”‚       bn_mul.h
β”‚           β”‚       camellia.cpp
β”‚           β”‚       camellia.h
β”‚           β”‚       ccm.cpp
β”‚           β”‚       ccm.h
β”‚           β”‚       certs.cpp
β”‚           β”‚       certs.h
β”‚           β”‚       chacha20.cpp
β”‚           β”‚       chacha20.h
β”‚           β”‚       chachapoly.cpp
β”‚           β”‚       chachapoly.h
β”‚           β”‚       ChangeLog
β”‚           β”‚       check_config.h
β”‚           β”‚       cipher.cpp
β”‚           β”‚       cipher.h
β”‚           β”‚       cipher_internal.h
β”‚           β”‚       cipher_wrap.cpp
β”‚           β”‚       cmac.cpp
β”‚           β”‚       cmac.h
β”‚           β”‚       compat-1.3.h
β”‚           β”‚       config.h
β”‚           β”‚       ctr_drbg.cpp
β”‚           β”‚       ctr_drbg.h
β”‚           β”‚       debug.cpp
β”‚           β”‚       debug.h
β”‚           β”‚       des.cpp
β”‚           β”‚       des.h
β”‚           β”‚       dhm.cpp
β”‚           β”‚       dhm.h
β”‚           β”‚       ecdh.cpp
β”‚           β”‚       ecdh.h
β”‚           β”‚       ecdsa.cpp
β”‚           β”‚       ecdsa.h
β”‚           β”‚       ecjpake.cpp
β”‚           β”‚       ecjpake.h
β”‚           β”‚       ecp.cpp
β”‚           β”‚       ecp.h
β”‚           β”‚       ecp_curves.cpp
β”‚           β”‚       ecp_internal.h
β”‚           β”‚       entropy.cpp
β”‚           β”‚       entropy.h
β”‚           β”‚       entropy_poll.cpp
β”‚           β”‚       entropy_poll.h
β”‚           β”‚       error.cpp
β”‚           β”‚       error.h
β”‚           β”‚       gcm.cpp
β”‚           β”‚       gcm.h
β”‚           β”‚       havege.cpp
β”‚           β”‚       havege.h
β”‚           β”‚       hkdf.cpp
β”‚           β”‚       hkdf.h
β”‚           β”‚       hmac_drbg.cpp
β”‚           β”‚       hmac_drbg.h
β”‚           β”‚       LICENSE
β”‚           β”‚       md.cpp
β”‚           β”‚       md.h
β”‚           β”‚       md2.cpp
β”‚           β”‚       md2.h
β”‚           β”‚       md4.cpp
β”‚           β”‚       md4.h
β”‚           β”‚       md5.cpp
β”‚           β”‚       md5.h
β”‚           β”‚       md_internal.h
β”‚           β”‚       md_wrap.cpp
β”‚           β”‚       memory_buffer_alloc.cpp
β”‚           β”‚       memory_buffer_alloc.h
β”‚           β”‚       net.h
β”‚           β”‚       net_sockets.cpp
β”‚           β”‚       net_sockets.h
β”‚           β”‚       nist_kw.cpp
β”‚           β”‚       nist_kw.h
β”‚           β”‚       oid.cpp
β”‚           β”‚       oid.h
β”‚           β”‚       padlock.cpp
β”‚           β”‚       padlock.h
β”‚           β”‚       pem.cpp
β”‚           β”‚       pem.h
β”‚           β”‚       pk.cpp
β”‚           β”‚       pk.h
β”‚           β”‚       pkcs11.cpp
β”‚           β”‚       pkcs11.h
β”‚           β”‚       pkcs12.cpp
β”‚           β”‚       pkcs12.h
β”‚           β”‚       pkcs5.cpp
β”‚           β”‚       pkcs5.h
β”‚           β”‚       pkparse.cpp
β”‚           β”‚       pkwrite.cpp
β”‚           β”‚       pk_internal.h
β”‚           β”‚       pk_wrap.cpp
β”‚           β”‚       platform.cpp
β”‚           β”‚       platform.h
β”‚           β”‚       platform_time.h
β”‚           β”‚       platform_util.cpp
β”‚           β”‚       platform_util.h
β”‚           β”‚       poly1305.cpp
β”‚           β”‚       poly1305.h
β”‚           β”‚       ripemd160.cpp
β”‚           β”‚       ripemd160.h
β”‚           β”‚       rsa.cpp
β”‚           β”‚       rsa.h
β”‚           β”‚       rsa_internal.cpp
β”‚           β”‚       rsa_internal.h
β”‚           β”‚       sha1.cpp
β”‚           β”‚       sha1.h
β”‚           β”‚       sha256.cpp
β”‚           β”‚       sha256.h
β”‚           β”‚       sha512.cpp
β”‚           β”‚       sha512.h
β”‚           β”‚       ssl.h
β”‚           β”‚       ssl_cache.cpp
β”‚           β”‚       ssl_cache.h
β”‚           β”‚       ssl_ciphersuites.cpp
β”‚           β”‚       ssl_ciphersuites.h
β”‚           β”‚       ssl_cli.cpp
β”‚           β”‚       ssl_cookie.cpp
β”‚           β”‚       ssl_cookie.h
β”‚           β”‚       ssl_internal.h
β”‚           β”‚       ssl_srv.cpp
β”‚           β”‚       ssl_ticket.cpp
β”‚           β”‚       ssl_ticket.h
β”‚           β”‚       ssl_tls.cpp
β”‚           β”‚       threading.cpp
β”‚           β”‚       threading.h
β”‚           β”‚       timing.cpp
β”‚           β”‚       timing.h
β”‚           β”‚       version.cpp
β”‚           β”‚       version.h
β”‚           β”‚       version_features.cpp
β”‚           β”‚       x509.cpp
β”‚           β”‚       x509.h
β”‚           β”‚       x509write_crt.cpp
β”‚           β”‚       x509write_csr.cpp
β”‚           β”‚       x509_create.cpp
β”‚           β”‚       x509_crl.cpp
β”‚           β”‚       x509_crl.h
β”‚           β”‚       x509_crt.cpp
β”‚           β”‚       x509_crt.h
β”‚           β”‚       x509_csr.cpp
β”‚           β”‚       x509_csr.h
β”‚           β”‚       xtea.cpp
β”‚           β”‚       xtea.h
β”‚           β”‚
β”‚           └───MQTT-TLS
β”‚                   MQTT-TLS.h
β”‚
β”œβ”€β”€β”€src
β”‚       generalDummy.cpp
β”‚       generalDummy.ino
β”‚
└───target
    β”‚   generalDummy.bin
    β”‚   generalDummy.bin.crc_block
    β”‚   generalDummy.bin.no_crc
    β”‚   generalDummy.elf
    β”‚   generalDummy.hex
    β”‚   generalDummy.lst
    β”‚   generalDummy.map
    β”‚
    └───obj
        └───src
                module_info.o
                module_info.o.d
                newlib_stubs.o
                newlib_stubs.o.d
                user_export.o
                user_export.o.d
                user_module.o
                user_module.o.d

Are you compiling for debug (monolithic)? This compiles fine for a normal build, just not as monolithic.

I see - monolithic is the key word I obviously did miss :blush:

Since the device OS internal encryption features its own version this can’t be working - sorry for that oversight :pensive:

Is this something that can be adapted to a future OS release?

The only work around as I see it would be to rename all variables in the MQTT-TLS library. I’m not sure that is worth the time.

Hi @picsil and @varnerb - I’ll inquire internally with respect to future potential adaptation so as to permit this library in monolithic builds. I’ve received your support ticket and will convey any response I receive both there and here.

1 Like

Thank you

From the source:

The best, and easiest, workaround here would be to switch the protocol from UDP to TCP for your cloud connection while debugging so that DeviceOS won’t use mbedtls.

However, depending on the degree that the above is crucial to your debug process, you could mark the functions in DeviceOS that are duplicated by MQTT-TLS as weak (therefore replaceable). However, our team maintains that there is no guarantee that this will function - its possible that the mbedtls configuration at stake is different from the one we use in DeviceOS, and therefore the functions won’t necessarily have the same behaviors.

How would I switch the protocol from UDP to TCP? I can give that a try and see what shows up.