0

Make process on a C library causing the linking errors related to architecure.I am trying to build library for iOS but it has got dependancy on libxml2 which in this case I guess is Mac only library

lipo -info confirms the same

admin$lipo -info /usr/local/lib/libxml2.dylib Non-fat file: /usr/local/lib/libxml2.dylib is architecture: x86_64

ld: warning: ignoring file /usr/local/lib/libxml2.dylib, file was built for x86_64 which is not the architecture being linked (armv7): /usr/local/lib/libxml2.dylib Undefined symbols for architecture armv7: "_xmlAddChild", referenced from: _setIsoId in libspatialite.a(gg_xml.o) referenced from: _vxpath_eval_expr in libspatialite.a(libsplite_la-virtualxpath.o) ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[4]: * [demo1] Error 1 make[3]: [install-recursive] Error 1 make[2]: [install-strip] Error 2 make1: * [/Users/admin/Downloads/libspatialite-ios-master/build/armv7/lib/libspatialite.a] Error 2 make: *** [build_arches] Error 2

Edit#1

After commenting, the libspatailite configuration and make section in the make file, I noticed that rest of the dependencies like gets,proj,sqlite are getting generated for all platforms armv7,armv7s,arm64,i386,x86_64. Snapshot from finder

lipo -info on these libraries confirm the same.So the problem lies limited to building libspatialite.

Makefile ( To build only libspatialite.a)

XCODE_DEVELOPER = $(shell xcode-select --print-path)
IOS_PLATFORM ?= iPhoneOS

# Pick latest SDK in the directory
IOS_PLATFORM_DEVELOPER = ${XCODE_DEVELOPER}/Platforms/${IOS_PLATFORM}.platform/Developer
IOS_SDK = ${IOS_PLATFORM_DEVELOPER}/SDKs/$(shell ls ${IOS_PLATFORM_DEVELOPER}/SDKs | sort -r | head -n1)

all: lib/libspatialite.a
lib/libspatialite.a: build_arches
    mkdir -p lib
    mkdir -p include

    # Copy includes
    cp -R build/armv7/include/geos include
    cp -R build/armv7/include/spatialite include
    cp -R build/armv7/include/*.h include

    # Make fat libraries for all architectures
    for file in build/armv7/lib/*.a; \
        do name=`basename $$file .a`; \
        lipo -create \
            -arch armv7 build/armv7/lib/$$name.a \
            -arch armv7s build/armv7s/lib/$$name.a \
            -arch arm64 build/arm64/lib/$$name.a \
            -arch i386 build/i386/lib/$$name.a \
            -arch x86_64 build/x86_64/lib/$$name.a \
            -output lib/$$name.a \
        ; \
        done;

# Build separate architectures
build_arches:
    ${MAKE} arch ARCH=armv7 IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin
    ${MAKE} arch ARCH=armv7s IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin
    ${MAKE} arch ARCH=arm64 IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin
    ${MAKE} arch ARCH=i386 IOS_PLATFORM=iPhoneSimulator HOST=i386-apple-darwin
    ${MAKE} arch ARCH=x86_64 IOS_PLATFORM=iPhoneSimulator HOST=x86_64-apple-darwin

PREFIX = ${CURDIR}/build/${ARCH}
LIBDIR = ${PREFIX}/lib
BINDIR = ${PREFIX}/bin
INCLUDEDIR = ${PREFIX}/include

CXX = ${XCODE_DEVELOPER}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
CC = ${XCODE_DEVELOPER}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
CFLAGS = -isysroot ${IOS_SDK} -I${IOS_SDK}/usr/include -arch ${ARCH} -I${INCLUDEDIR} -miphoneos-version-min=7.0
CXXFLAGS = -stdlib=libc++ -std=c++11 -isysroot ${IOS_SDK} -I${IOS_SDK}/usr/include -arch ${ARCH} -I${INCLUDEDIR} -miphoneos-version-min=7.0
LDFLAGS = -stdlib=libc++ -isysroot ${IOS_SDK} -L${LIBDIR} -L${IOS_SDK}/usr/lib -arch ${ARCH} -miphoneos-version-min=7.0

arch: ${LIBDIR}/libspatialite.a

${LIBDIR}/libspatialite.a: ${LIBDIR}/libproj.a ${LIBDIR}/libgeos.a ${LIBDIR}/libsqlite3.a ${CURDIR}/spatialite
    cd spatialite && env \
    CXX=${CXX} \
    CC=${CC} \
    CFLAGS="${CFLAGS} -Wno-error=implicit-function-declaration" \
    CXXFLAGS="${CXXFLAGS} -Wno-error=implicit-function-declaration" \
    LDFLAGS="${LDFLAGS} -liconv -lgeos -lgeos_c -lc++" ./configure --host=${HOST} --disable-freexl --prefix=${PREFIX} --with-geosconfig=${BINDIR}/geos-config --disable-shared && make clean install-strip


clean:
    rm -rf build geos proj spatialite sqlite3 include lib

@gagan-ios , @kristina-brooks - It seems Makefile within spatialite directory is getting generated automatically from above Makefile.I am not sure how I can control the lib ,include path to libxml2 dynamically.

Edit2 One more level of investigation shows ,library getting generated for i386 and x86_64 and failing for armv7,armv7s and arm64

${MAKE} arch ARCH=armv7 IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin ${MAKE} arch ARCH=armv7s IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin ${MAKE} arch ARCH=arm64 IOS_PLATFORM=iPhoneOS HOST=arm-apple-darwin ${MAKE} arch ARCH=i386 IOS_PLATFORM=iPhoneSimulator HOST=i386-apple-darwin ${MAKE} arch ARCH=x86_64 IOS_PLATFORM=iPhoneSimulator HOST=x86_64-apple-darwin

addcolor
  • 455
  • 8
  • 23

2 Answers2

0

A suitable libxml2 stub should be present in the iPhoneOS SDK, just adding -lxml2 to linker flags should work. I'm guessing you've explicitly specified an absolute path to libxml2.dylib instead of letting the linker use the SDK relative path, so you're trying to link an ARM static library against an x86_64 version of libxml2 from your OS distribution.

Kristina
  • 15,859
  • 29
  • 111
  • 181
  • I am trying to build from here https://github.com/gstf/libspatialite-ios , With your suggestion, I noticed that Makefile contains below entry LIBXML2_LIBS = -L/usr/local/lib -lxml2.....perhaps I have to edit this to point another location.. – addcolor May 09 '17 at 05:15
  • No luck editing the Makefile resulting in same error – addcolor May 09 '17 at 05:44
0

Finally able to find a workaround with the help of Makefile at Compiling external C++ library for use with iOS project

The work around is an amalgamation of 2 different make files and involved below steps.

1.Use the Makefile partially to generate libraries for all platforms for dependencies (pros,geos,sqlite3) https://github.com/gstf/libspatialite-ios

2.Compiled libxml2 from source using the Makefile from Compiling external C++ library for use with iOS project

3.Makefile from Compiling external C++ library for use with iOS project is used to generate spatialite libraries for all platforms

4.Use lipo from Step#1 Makefile to generate fat library

#!/bin/bash

PLATFORMPATH="/Applications/Xcode.app/Contents/Developer/Platforms"
TOOLSPATH="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin"
export IPHONEOS_DEPLOYMENT_TARGET="8.0"
pwd=`pwd`

findLatestSDKVersion()
{
    sdks=`ls $PLATFORMPATH/$1.platform/Developer/SDKs`
    arr=()
    for sdk in $sdks
    do
       arr[${#arr[@]}]=$sdk
    done

    # Last item will be the current SDK, since it is alpha ordered
    count=${#arr[@]}
    if [ $count -gt 0 ]; then
       sdk=${arr[$count-1]:${#1}}
       num=`expr ${#sdk}-4`
       SDKVERSION=${sdk:0:$num}
    else
       SDKVERSION="8.0"
    fi
}

buildit()
{
    target=$1
    hosttarget=$1
    platform=$2

    if [[ $hosttarget == "x86_64" ]]; then
        hostarget="i386"
    elif [[ $hosttarget == "arm64" ]]; then
        hosttarget="arm"
    fi

    export CC="$(xcrun -sdk iphoneos -find clang)"
    export CPP="$CC -E"
    export CFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
    export AR=$(xcrun -sdk iphoneos -find ar)
    export RANLIB=$(xcrun -sdk iphoneos -find ranlib)
    export CPPFLAGS="-arch ${target}  -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
    export LDFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk"

    mkdir -p $pwd/output/$target

     ./configure --prefix="$pwd/output/$target" --disable-shared --disable-sqlite --host=$hosttarget-apple-darwin

    make clean
    make
    make install
}

findLatestSDKVersion iPhoneOS

buildit armv7 iPhoneOS
buildit armv7s iPhoneOS
buildit arm64 iPhoneOS
buildit i386 iPhoneSimulator
buildit x86_64 iPhoneSimulator

Add these libraries to a new Xcode project and start using it. Well here is my first success using this library

Include these libraries

#include <sqlite3.h>
#include <spatialite/gaiageo.h>
#include <spatialite.h>

Use the below APIs to get the Spatialite version

spatialite_init(0);
printf("Spatialite version: %s\n", spatialite_version());

Output

Spatialite version: 4.3.0
Community
  • 1
  • 1
addcolor
  • 455
  • 8
  • 23