编译外部C++库以用于iOS项目

HHH*_*HHH 17 c++ xcode objective-c objective-c++ ios

我对使用C++库完全不熟悉,所以请理解这可能对我的情况有点具体(让我知道,我可以提供更多细节).

我有一个外部C++库,我正在尝试使用iOS项目.该库遵循configure,make,make构建模式以输出.a库文件.当我尝试将此库文件添加到Xcode时,我收到以下错误:

忽略文件/Users/Developer/iOS/TestProj/libpresage.a,文件是为归档而构建的,而不是被链接的体系结构(i386):

/Users/Developer/iOS/TestProj/libpresage.a

基于这个问题,我尝试将Build Active Architecture Only转为NO,我得到了同样的错误.这让我怀疑我为不正确的架构编译了库.

在.a文件上运行lipo -info给出:

输入文件libpresage.a不是胖文件非胖文件:libpresage.a

是架构:x86_64

鉴于这不是armv7s,armv7或arm64,我尝试使用以下参数再次编译C++库:

1)试试

./configure CC="gcc -arch armv7s" \
                 CXX="g++ -arch armv7s" \
                 CPP="gcc -E" CXXCPP="g++ -E"
Run Code Online (Sandbox Code Playgroud)

编译时出错,我得到:

ld: library not found for -lcrt1.3.1.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

2)试试

./configure CC="gcc -arch arm64" \
                 CXX="g++ -arch arm64" \
                 CPP="gcc -E" CXXCPP="g++ -E"
Run Code Online (Sandbox Code Playgroud)

编译时出错,我得到:

ld:警告:ld:警告:忽略文件/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libSystem.dylib,缺少所需的架构arm64 in文件/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libSystem.dylib(2个切片)忽略文件/Applications/Xcode.app/Contents/开发人员/平台/ MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libstdc ++.dylib,在文件/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer中缺少所需的架构arm64 /SDKs/MacOSX10.10.sdk/usr/lib/libstdc++.dylib(2片)

ld:动态主可执行文件必须与libSystem.dylib链接,用于体系结构arm64 clang:错误:链接器命令失败,退出代码为1(使用-v查看调用)

有什么明显的东西让我失踪吗?

编辑:

感谢您的回复,所以我设法将库作为自定义构建目标放入Xcode,将'make'命令指向库MakeFile.这个构建很好.

我从这里开始:

  • 从Objective C iOS应用程序目标添加依赖项到自定义构建目标.
  • 引用库并制作Objective C++包装器.
  • 这看起来很好,直到我需要调用外部C++库,然后我在编译时得到错误:

架构armv7的未定义符号:"Presage :: Presage(PresageCallback*)",引自: - PresageBridge.o中的[PresageBridge init]"Presage ::〜Presage()",引用自: - PresageBridge中的[PresageBridge init]. o ld:找不到架构armv7 clang的符号:错误:链接器命令失败,退出代码为1(使用-v查看调用)

  • 我的目标C++包装器(链接外部C++库头文件presage.h):

    #import "PresageBridge.h"
    #include "presage.h"
    
    @implementation PresageBridge
    
    - (instancetype)init
    {
        if(self = [super init])
        {
    
           Presage hello(&callback);
        }
    
        return self;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 根据上面的代码,它似乎不像我错过了标题,有趣的是我还尝试在外部库中创建其他类的实例,它们似乎正在工作,这表明Xcode可以由于某种原因,正确链接presage.h.

Mob*_*Ben 34

所以我在iOS项目中使用了很多第三方C++库.人们使用不同的策略.正如一些人已经提到的,您可以直接在项目中包含代码,使用Xcode构建静态库,或者构建命令行.对于使用GNU配置和构建系统的跨平台C++库,我更喜欢命令行.您只需要构建一次,如果需要更新版本或添加新的体系结构切片,则只需重新访问它.

您想要的通用方法是:

  • 找出用于构建每个切片的正确配置参数.通常情况下,您只需要专注于让其中一个手臂以及i386正常工作.其余的很容易就可以完成.在某些情况下,您实际上需要修改配置文件以添加主机或进行一些其他调整.

  • 一旦你可以构建所有切片,你想运行lipo来构建一个胖二进制文件.

处理此问题的最佳方法是创建一个构建脚本,它将为您完成所有工作.这样,重做更容易.更重要的是,您可以重用脚本或对其进行置换以构建其他外部库.

您可以通过多种方式构建脚本.这是一个.我碰巧有这种类型的脚本的几种变体.该脚本用于构建cURL.它或多或少地用于预设,具有非常少的mod(即改变卷曲到预期).注意我没有在Xcode中测试它(即链接它并运行它).我确实发现我必须禁用sqlite,否则它会构建不正确构建的工具项.如果你需要它,你可以找出那个部分.

有很多方法可以使它更光滑.例如,使用数组来存储所有体系结构.这只是蛮力.

该脚本的关键点是:

  1. 获取最新的SDK
  2. 构建每个切片
  3. 然后运行脂肪

请注意,它应该开箱即用,但YMMV.如有必要,请准备好进行调试.例如,我还没有确认主机类型,但通常这是我一直使用的.你想把它放在预告的目录(配置相同的目录).完成后,所有体系结构都在输出目录中.通用lib位于presage目录中.

还要记住,您有责任正确链接通用库,并正确定义头文件搜索路径.

#!/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

LIPO=$(xcrun -sdk iphoneos -find lipo)
$LIPO -create $pwd/output/armv7/lib/libpresage.a  $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a
Run Code Online (Sandbox Code Playgroud)

  • 小提示:似乎`hostarget="i386"` 缺少一个`t` (2认同)

Mic*_*CMS 6

考虑到你是C++库的新手,我想你需要做更多的研究.

但是,我将尝试概述您需要考虑的一些步骤:

  • 您需要确保为静态库(.a)和项目编译相同的体系结构
  • 从您的错误中,您需要为i386编译静态库或将项目更改为x86_64(这些体系结构之间的差异有点复杂,但现在让我们说i386意味着桌面32位而x86_64意味着桌面64位)
  • arm架构适用于iPhone,而不适用于MacOS(这就是为什么它无法在MacOSX文件夹中找到带有arm架构的库)!

有多种方法可以解决这些问题.

对于第一个,我建议在您的工作区中包含静态库,并将其作为依赖项添加到构建目标.为此,您需要了解XCode构建.

我猜你实际上是在尝试制作一个手机应用程序,所以对于第三个选项,你需要配置你的g ++构建,以便在链接arm目标(看看iPhoneOS.platform)时从XCode查看iPhoneSDK.

制作手臂版只适用于iPhone.如果您希望它在模拟器上运行,您需要将静态库链接到iPhoneSimulator.platform中的库.

如果你想让你的静态库适用于iPhone和iPhone模拟器,你需要制作一个胖lib(基本上是一个包含两个平台符号的库)

如果您缺少这些平台,可以从XCode下载它们(但我相信它们在那里)

正如您所看到的,在此过程中事情将变得越来越复杂,因此我强烈建议使用XCode来编译静态库(它仍然可以使用g ++).

我相信您将有用于研究的以下概念:

  • arm,x86,x86_64
  • 静态库
  • 静态联动
  • 胖lib(通用库)
  • 具有多个项目的XCode工作区

希望这可以帮助 :).