KISS

Keep It Simple Stupid

Workarounds for WeMo iOS SDK

| comments

I’ve been playing with the WeMo iOS SDK recently. The sample project works fine, however I stumbled upon a number of issues trying to add it into my own project. The SDK doesn’t seem to be supported anymore though: https://github.com/BelkinWemo/Wemo-Discovery-SDK/issues/7#issuecomment-69138162.

No 64-bit architectures support

The first set of errors:

1
2
3
4
5
6
7
8
9
ld: warning: ignoring file /Users/u/proj/wemotest/WeMoSDK/Cybergarage.a, missing required architecture x86_64 in file /Users/u/proj/wemotest/WeMoSDK/Cybergarage.a (3 slices)
ld: warning: ignoring file /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a, missing required architecture x86_64 in file /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a (3 slices)
ld: warning: ignoring file /Users/u/proj/wemotest/WeMoSDK/Reachability.a, missing required architecture x86_64 in file /Users/u/proj/wemotest/WeMoSDK/Reachability.a (3 slices)
ld: warning: ignoring file /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a, missing required architecture x86_64 in file /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a (3 slices)
Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_WeMoDiscoveryManager", referenced from:
      objc-class-ref in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Aha, the SDK libraries don’t contain 64-bit object files, will it ever? https://github.com/BelkinWemo/Wemo-Discovery-SDK/issues/4 — silence. You can’t build the project for the Simulator or a device in the default setup. OK, I’ll have to set the Architectures build setting for the target to $(ARCHS_STANDARD_32_BIT). (NB: You won’t be able to submit the app to the App Store though).

Undefined symbols for encryption

Now, the second issue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Undefined symbols for architecture i386:
  "_BIO_ctrl", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_f_base64", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_free_all", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_new", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_push", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_s_mem", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_BIO_write", referenced from:
      _baseEncode in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_EVP_BytesToKey", referenced from:
      _aes_init in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_EVP_CIPHER_CTX_cleanup", referenced from:
      _encryptPassword in BelkinSDKLibrary.a(OpenSSLEncryption.o)
      _encryptPasswordWithoutLength in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_EVP_CIPHER_CTX_init", referenced from:
      _aes_init in BelkinSDKLibrary.a(OpenSSLEncryption.o)
  "_EVP_DecryptFinal_ex", referenced from:
      _aes_decrypt in BelkinSDKLibrary.a(OpenSSLEncryption.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I’ve found a solution here: http://stackoverflow.com/questions/26061694/wemo-sdk-for-ios-architecture-issue/26370776#26370776, those missing symbols are from the OpenSSL library, which you’ll need to build. Do the following:

1
2
3
git clone https://github.com/x2on/OpenSSL-for-iPhone.git
cd OpenSSL-for-iPhone
./build-libssl.sh

, which in my case built the OpenSSL 1.0.2 for five architectures. Now copy the lib/libcrypto.a file into your project, and link with your target.

Duplicate symbols in the WeMo libraries

1
2
3
4
5
6
7
8
9
10
11
12
13
14
duplicate symbol _OBJC_IVAR_$_ConnectionCheck.wifiReach in:
    /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a(ConnectionCheck.o)
    /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a(ConnectionCheck.o)
duplicate symbol _OBJC_IVAR_$_ConnectionCheck.internetReach in:
    /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a(ConnectionCheck.o)
    /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a(ConnectionCheck.o)
duplicate symbol _OBJC_CLASS_$_ConnectionCheck in:
    /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a(ConnectionCheck.o)
    /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a(ConnectionCheck.o)
duplicate symbol _OBJC_METACLASS_$_ConnectionCheck in:
    /Users/u/proj/wemotest/WeMoSDK/WeMoLocalControl.a(ConnectionCheck.o)
    /Users/u/proj/wemotest/WeMoSDK/BelkinSDKLibrary.a(ConnectionCheck.o)
ld: 5 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Uh-oh. I’ll have to remove the duplicated object file from one of the libraries. The procedure is: split the fat library into individual libraries for each architecture, remove the ConnectionCheck.o object file from each, and create a new fat library. Here’s a little script I wrote to do this stuff:

(wemo_symbols_fix.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash

LIPO="xcrun lipo"
AR="xcrun ar"
RM="rm"

extract_architectures() {
    $LIPO -info "$1" | sed -nE '/in the fat file/ {s/^.*are: (.+)[[:space:]]+$/\1/; p;}' | tr ' ' '\n'
}

IN_FAT_LIBRARY="WeMoLocalControl.a"
IN_FAT_ARCHS=$( extract_architectures $IN_FAT_LIBRARY )
OBJECT_FILE="ConnectionCheck.o"

[[ -z "$IN_FAT_ARCHS" ]] && {
    echo "File $IN_FAT_LIBRARY is not a fat library";
    exit 1;
}
OUT_LIBRARIES=""
for arch in $IN_FAT_ARCHS; do
    # split the fat library into architectures
    OUT_LIBRARY=${IN_FAT_LIBRARY/.a/_${arch}.a}
    $LIPO $IN_FAT_LIBRARY -thin $arch -output $OUT_LIBRARY
    OUT_LIBRARIES="$OUT_LIBRARIES $OUT_LIBRARY"

    # remove the object file from the library
    $AR -d $OUT_LIBRARY $OBJECT_FILE
done

# reassemble the fat library
$LIPO $OUT_LIBRARIES -create -output $IN_FAT_LIBRARY

$RM $OUT_LIBRARIES

Finally, my app has compiled!

Comments