Building OSX App Bundle

后端 未结 7 531
[愿得一人]
[愿得一人] 2020-11-29 14:40

Suppose I have have made a an osX app without using Xcode. After compiling with GCC I get an executable which is linked to several other libraries. Some of those libraries m

7条回答
  •  南笙
    南笙 (楼主)
    2020-11-29 15:18

    I wish I've found this post earlier....

    Here's my sketchy way of solving this problem using a Run script phase which is invoked every time I build a Release version of my app:

    # this is an array of my dependencies' libraries paths 
    # which will be iterated in order to find those dependencies using otool -L
    libpaths=("$NDNRTC_LIB_PATH" "$BOOST_LIB_PATH" "$NDNCHAT_LIB_PATH" "$NDNCPP_LIB_PATH" "/opt/local/lib")
    frameworksDir=$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH
    executable=$BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH
    
    #echo "libpaths $libpaths"
    bRecursion=0
    lRecursion=0
    
    # this function iterates through libpaths array
    # and checks binary with "otool -L" command for containment
    # of dependency which has "libpath" path
    # if such dependency has been found, it will be copied to Frameworks 
    # folder and binary will be fixed with "install_name_tool -change" command
    # to point to Frameworks/ library
    # then, dependency is checked recursively with resolveDependencies function
    function resolveDependencies()
    {
        local binfile=$1
        local prefix=$2
        local binname=$(basename $binfile)
        local offset=$((lRecursion*20))
        printf "%s :\t%s\n" $prefix "resolving $binname..."
    
        for path in ${libpaths[@]}; do
            local temp=$path
            #echo "check lib path $path"
            local pattern="$path/([A-z0-9.-]+\.dylib)"
            while [[ "$(otool -L ${binfile})" =~ $pattern ]]; do
                local libname=${BASH_REMATCH[1]}
                otool -L ${binfile}
                #echo "found match $libname"
                printf "%s :\t%s\n" $prefix "fixing $libname..."
                local libpath="${path}/$libname"
                #echo "cp $libpath $frameworksDir"
                ${SRCROOT}/sudocp.sh $libpath $frameworksDir/$libname $(whoami)
                local installLibPath="@rpath/$libname"
                #echo "install_name_tool -change $libpath $installLibPath $binfile"
                if [ "$libname" == "$binname" ]; then
                    install_name_tool -id "@rpath/$libname" $binfile
                    printf "%s :\t%s\n" $prefix "fixed id for $libname."
                else
                    install_name_tool -change $libpath $installLibPath $binfile
                    printf "%s :\t%s\n" $prefix "$libname dependency resolved."
                    let lRecursion++
                    resolveDependencies "$frameworksDir/$libname" "$prefix>$libname"
                    resolveBoostDependencies "$frameworksDir/$libname" "$prefix>$libname"
                    let lRecursion--
                fi
                path=$temp
            done # while
        done # for
    
        printf "%s :\t%s\n" $prefix "$(basename $binfile) resolved."
    } # resolveDependencies
    
    # for some reason, unlike other dependencies which maintain full path
    # in "otool -L" output, boost libraries do not - they just appear 
    # as "libboost_xxxx.dylib" entries, without fully qualified path
    # thus, resolveDependencies can't be used and a designated function is needed
    # this function works pretty much in a similar way to resolveDependencies
    # but targets only dependencies starting with "libboost_", copies them
    # to the Frameworks folder and resolves them recursively
    function resolveBoostDependencies()
    {
        local binfile=$1
        local prefix=$2
        local binname=$(basename $binfile)
        local offset=$(((bRecursion+lRecursion)*20))
        printf "%s :\t%s\n" $prefix "resolving Boost for $(basename $binfile)..."
    
        local pattern="[[:space:]]libboost_([A-z0-9.-]+\.dylib)"
        while [[ "$(otool -L ${binfile})" =~ $pattern ]]; do
            local libname="libboost_${BASH_REMATCH[1]}"
            #echo "found match $libname"
            local libpath="${BOOST_LIB_PATH}/$libname"
            #echo "cp $libpath $frameworksDir"
            ${SRCROOT}/sudocp.sh $libpath $frameworksDir/$libname $(whoami)
            installLibPath="@rpath/$libname"
            #echo "install_name_tool -change $libname $installLibPath $binfile"
            if [ "$libname" == "$binname" ]; then
                install_name_tool -id "@rpath/$libname" $binfile
                printf "%s :\t%s\n" $prefix "fixed id for $libname."
            else
                install_name_tool -change $libname $installLibPath $binfile
                printf "%s :\t%s\n" $prefix "$libname Boost dependency resolved."
                let bRecursion++
                resolveBoostDependencies "$frameworksDir/$libname" "$prefix>$libname"
                let bRecursion--
            fi
        done # while
    
        printf "%s :\t%s\n" $prefix "$(basename $binfile) resolved."
    }
    
    resolveDependencies $executable $(basename $executable)
    resolveBoostDependencies $executable $(basename $executable)
    

    Hope this might be useful to someone.

提交回复
热议问题