pod & git

Framework制作 Cocoapods私有库

2021-10-09  本文已影响0人  贤宇
Framework制作教程
  1. 详细步骤图
  2. 创建源码项目
  3. 创建对外发布的Framework项目
一、详细步骤图
FM制作流程.png
二、创建源码项目

以MAWebKit为例, 源码项目统一都是放到GitLab源码Group下。

1. 创建Framework项目

Xcode -> File -> New -> Project 选择Cocoa Touch Framework模板,新建项目MAWebKit,勾选Include Unit Tests 为写单元测试和Sonar扫描做准备。
点击下一步选择合适的目录保存。


image.png
2. 新生成的项目结构如图
image.png
3. 多个组件配置

如果一个组件库包含多个组件,类似Cocoapods的subspec。那需要新建其他组件的Framework。 例如:MAWebKitCore、MAWebKitNFC、MAWebKitGPS、MAWebKitFace

4. 配置项目

按照目前这种结构产生的文件目录,在项目目录下比较乱,可以把所有info.plist文件所在文件夹整 理到同一个文件夹Supports下,步骤如下:

5. 配置Framework之间的依赖关系

Framework之间的依赖关系分为两种:
项目内的Framework依赖 和 跨项目的Framework依赖 。

(1) 项目内的Framework依赖: 直接配置
例如:MAWebKitNFC依赖于MAWebKitCore、 MAWebKitGPS依赖于MAWebKitCore

image.png

(2) 跨项目的Framework依赖:cocoapods管理
例如:MAWebKitGPS依赖⻨芽的 MAGPSKit ,MAWebKitPhoto依赖第三方
库 TZImagePickerController ,这样我们就通过cocoapods来进行管理

image.png
6. 源码目录结构规划

为了方便统一管理主framework和各个subspec的framework源码,将所有源码按照以下步骤,进行集中 管理。

7. 编写Framework源码

选中Public或者Private目录,右键,新建类文件,例如UIView+MAPrivate.h、 UIView+MAPrivate.m。选择对应的Framework(MAWebKitCore)的target。

image.png
#import <MAWebKitCore/MAWebViewController.h>
// ... ...
8. 打包Framework操作

编写打包Framework脚本(最后有参考),命名为make-framework(可以其他名称),可以直接将 make-framework下载下来打包使用。

# 批量打包脚本示例 
maia-framework -w MAWebKit -s MAWebKit -p 
maia-framework -w MAWebKit -s MAWebKitCore -p 
maia-framework -w MAWebKit -s MAWebKitPhoto -p 
maia-framework -w MAWebKit -s MAWebKitAudio -p 
maia-framework -w MAWebKit -s MAWebKitNFC -p 
maia-framework -w MAWebKit -s MAWebKitCodeScan -p 
maia-framework -w MAWebKit -s MAWebKitGPS -p 
maia-framework -w MAWebKit -s MAWebKitFace -o
9. 创建podspec文件

有时候为了方便定位问题,需要通过源码的方式进行调试,这就需要创建源码podspec。 我们可以通过命令行来创建cocoapods的配置podspec文件。

三、创建对外发布的Framework项目
  1. 创建脚本maia-project(最后有参考),只要运行命令,按 照步骤一步一步的操作下去,会自动创建Assets、Frameworks、库名.podspec文件,同时会进行git的 关联操作。
脚本参考

mark-framework

#!/bin/sh

function usage() {
  echo "************************************************"
    echo "-s scheme的名称,必填"
  echo "-w workspace名称,可选项,默认从项目中检测xcworkspace文件"
    echo "-f 打包最终生成的framework的名字,可选参数,如果没有默认使用scheme的内容"
  echo "-o 打包成功后是否自动打开framework所在的文件夹,默认不打开"
  echo "-p 是否需要运行pod install,默认否"
  echo "-d 是否以Debug的配置进行打包,默认使用Release"
    echo "例: maia-framework -w MAWebKit -s MAWebKit -f MAWebKit -o -p -d"
    echo "************************************************"
  exit 1;
}

######################
# Options
######################

CONFIGURATION=Release
WORKSPACE_NAME=
SCHEME_NAME=
FRAMEWORK_NAME=
REVEAL_ARCHIVE_IN_FINDER=false
POD_INSTALL=false

######################
# Read Params
######################
while getopts "w:s:f:opd" arg
do
  case $arg in
    w )
      WORKSPACE_NAME=$OPTARG
      ;;
    s )
      SCHEME_NAME=$OPTARG
      ;;
    f )
      FRAMEWORK_NAME=$OPTARG
      ;;
    o )
      REVEAL_ARCHIVE_IN_FINDER=true
      ;;
    p )
      POD_INSTALL=true
      ;;
    d )
      CONFIGURATION=Debug
      ;;
    ? )
      usage
      ;;
  esac
done

if [[ ${SCHEME_NAME} == "" ]]; then
  echo "scheme必填, 使用-s来指定scheme。"
  usage
fi

if [[ ${FRAMEWORK_NAME} == "" ]]; then
  FRAMEWORK_NAME=${SCHEME_NAME}
fi

function printParams() {
  echo "****************************"
  echo "workspace: ${WORKSPACE_NAME}"
  echo "scheme: ${SCHEME_NAME}"
  echo "FRAMEWORK: ${FRAMEWORK_NAME}"
  echo "Pod install: ${POD_INSTALL}"
  echo "Reveal In Finder: ${REVEAL_ARCHIVE_IN_FINDER}"
  echo "****************************"
}
printParams

ma_default_workspace=""
function check_default_workspace() {
  echo "\n------ xcode workspace checking ..."
  workspace_files=$(ls | grep .xcworkspace$ | wc -l)

  if [ ${workspace_files} == 1 ] ; then

    ma_default_workspace="`ls | grep .xcworkspace$ | sed -e 's/.xcworkspace//g'`"
    echo "检测到workspace【 ${ma_default_workspace} 】"
  else
    echo "没有找到xcode的workspace或者项目下有多个workspace文件,请自行检查。"
    exit 1
  fi
}

check_default_workspace
if [[ ${WORKSPACE_NAME} == "" ]]; then
  WORKSPACE_NAME="${ma_default_workspace}"
fi

if [[ ${POD_INSTALL} = true ]]; then
  if [[ -f "Podfile" ]]; then
    echo "--- Removing Pods cache"
    rm -rf Podfile.lock
    rm -rf Pods

    pod install
  else
    echo "没有找到Podfile文件"
    exit 1
  fi
fi

######################
# Directories
######################
FRAMEWORK_TARGET_PATH="${HOME}/Documents/MaiaFrameworks/${FRAMEWORK_NAME}"
SIMULATOR_BUILD_DIR="${FRAMEWORK_TARGET_PATH}/${CONFIGURATION}-iphonesimulator"
DEVICE_BUILD_DIR="${FRAMEWORK_TARGET_PATH}/${CONFIGURATION}-iphoneos"
SIMULATOR_LIBRARY_PATH="${SIMULATOR_BUILD_DIR}/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${DEVICE_BUILD_DIR}/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${FRAMEWORK_TARGET_PATH}/${CONFIGURATION}-iphoneuniversal"
UNIVERSAL_LIBRARY_PATH="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"

function printDirs() {
  echo "----------------------------"
  echo "BUILD_DIR : ${FRAMEWORK_TARGET_PATH}"
  echo "SIMULATOR_LIBRARY_PATH : ${SIMULATOR_LIBRARY_PATH}"
  echo "DEVICE_LIBRARY_PATH : ${DEVICE_LIBRARY_PATH}"
  echo "UNIVERSAL_LIBRARY_DIR : ${UNIVERSAL_LIBRARY_DIR}"
  echo "FRAMEWORK : ${UNIVERSAL_LIBRARY_PATH}"
  echo "----------------------------"
}
printDirs

######################
# Create directory for universal
######################
rm -rf "${FRAMEWORK_TARGET_PATH}"

mkdir -p "${SIMULATOR_BUILD_DIR}"
mkdir -p "${DEVICE_BUILD_DIR}"
mkdir -p "${UNIVERSAL_LIBRARY_DIR}"

mkdir "${UNIVERSAL_LIBRARY_PATH}"

######################
# Build Frameworks
######################
BUILD_SETTINGS="ONLY_ACTIVE_ARCH=NO CLANG_ENABLE_CODE_COVERAGE=NO MACH_O_TYPE=staticlib DEFINES_MODULE=NO"


######################
# Build Simulator Frameworks
######################

SIM_BUILD_SHELL_PREFIX="xcodebuild -workspace ${WORKSPACE_NAME}.xcworkspace -scheme ${SCHEME_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION}"
SIM_BUILD_SHELL="${SIM_BUILD_SHELL_PREFIX} ${BUILD_SETTINGS} EXCLUDED_ARCHS=arm64 clean build"

echo "------ Build Simulator Framework ------"
echo "${SIM_BUILD_SHELL}"
${SIM_BUILD_SHELL} 2>&1

SIM_FRAMEWORK_TARGET_DIR=`${SIM_BUILD_SHELL_PREFIX} -showBuildSettings | grep "\<BUILT_PRODUCTS_DIR" | sed -e 's/BUILT_PRODUCTS_DIR = //g'`
echo "****** Simulator framework path:  ${SIM_FRAMEWORK_TARGET_DIR}"

SIM_COPY_SHELL="cp -r ${SIM_FRAMEWORK_TARGET_DIR}/${FRAMEWORK_NAME}.framework ${SIMULATOR_BUILD_DIR}"
echo "====== SIM COPY SHELL: ${SIM_COPY_SHELL}"
${SIM_COPY_SHELL}

######################
# Build Device Frameworks
######################
DEVICE_BUILD_SHELL_PREFIX="xcodebuild -workspace ${WORKSPACE_NAME}.xcworkspace -scheme ${SCHEME_NAME} -sdk iphoneos -configuration ${CONFIGURATION}"
DEVICE_BUILD_SHELL="${DEVICE_BUILD_SHELL_PREFIX} ${BUILD_SETTINGS} clean build"

echo "------ Build Device Framework ------"
echo "${DEVICE_BUILD_SHELL}"
${DEVICE_BUILD_SHELL} 2>&1

DEVICE_FRAMEWORK_TARGET_DIR=`${DEVICE_BUILD_SHELL_PREFIX} -showBuildSettings | grep "\<BUILT_PRODUCTS_DIR" | sed -e 's/BUILT_PRODUCTS_DIR = //g'`
echo "****** Device framework path:  ${DEVICE_FRAMEWORK_TARGET_DIR}"
DEVICE_COPY_SHELL="cp -r ${DEVICE_FRAMEWORK_TARGET_DIR}/${FRAMEWORK_NAME}.framework ${DEVICE_BUILD_DIR}"

echo "====== DEVICE COPY SHELL: ${DEVICE_COPY_SHELL}"
${DEVICE_COPY_SHELL}

######################
# Copy files Framework
######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${UNIVERSAL_LIBRARY_PATH}"


######################
# Make an universal binary
######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${UNIVERSAL_LIBRARY_PATH}/${FRAMEWORK_NAME}" | echo

# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${UNIVERSAL_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi

if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${UNIVERSAL_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi

cp -r "${UNIVERSAL_LIBRARY_PATH}" "${FRAMEWORK_TARGET_PATH}"

######################
# Move Final Bundles
######################
FRAMEWORK_FINAL_PATH="${FRAMEWORK_TARGET_PATH}/${FRAMEWORK_NAME}.framework"
FRAMEWORK_BUNDLES="${FRAMEWORK_FINAL_PATH}/*.bundle"

mv ${FRAMEWORK_BUNDLES} "${FRAMEWORK_TARGET_PATH}"

######################
# Remove Bundles
######################
SIMULATOR_LIBRARY_BUNDLES="${SIMULATOR_LIBRARY_PATH}/*.bundle"
DEVICE_LIBRARY_BUNDLES="${DEVICE_LIBRARY_PATH}/*.bundle"
UNIVERSAL_LIBRARY_BUNDLES="${UNIVERSAL_LIBRARY_PATH}/*.bundle"

echo "---------- **** Remove Bundles **** ----------"
echo "Simulator Bundles: ${SIMULATOR_LIBRARY_BUNDLES}"
echo "Device Bundles: ${DEVICE_LIBRARY_BUNDLES}"
echo "Universal Bundles: ${UNIVERSAL_LIBRARY_BUNDLES}"

rm -rf ${SIMULATOR_LIBRARY_BUNDLES}
rm -rf ${DEVICE_LIBRARY_BUNDLES}
rm -rf ${UNIVERSAL_LIBRARY_BUNDLES}

FWK_PRIVATE_HEADERS_PATH="${FRAMEWORK_FINAL_PATH}/PrivateHeaders"
rm -rf ${FWK_PRIVATE_HEADERS_PATH}

echo -e "Framework is in \033[31m ${FRAMEWORK_TARGET_PATH} \033[0m"

if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${FRAMEWORK_TARGET_PATH}/"
fi

make-project

#!/bin/bash

function usage() {
    echo
    echo "Usage:"
    echo
    echo -e "     \033[31m $ maia-project PROJECT-NAME \033[0m"
    echo
    echo "      maia-project, 输出标准的Maia-iOS私有库项目工程,PROJECT-NAME为必须参数"
    echo
}

if [[ $# -gt 0 ]]; then
    projectName="$1"
    if [[ -d $projectName ]]; then
        echo -e "项目 [ \033[31m ${projectName} \033[0m ] 已存在。"
    else
        echo -e "待创建的项目为:\033[31m ${projectName} \033[0m"
        echo "创建项目 ${projectName} ..."
        mkdir $projectName

        cd $projectName

        echo "创建Frameworks文件夹 ..."
        mkdir Frameworks

        echo "创建Assets文件夹 ..."
        mkdir Assets
        touch Assets/.gitkeep

        read -p "请输入组件库的版本号,直接回车默认为1.0.0 : " app_version
        if [[ $app_version == "" ]]; then
            app_version="1.0.0"
        fi

        read -p "请输入项目简介,直接回车默认为项目简介 : " project_info
        if [[ $project_info == "" ]]; then
            project_info="项目简介"
        fi

        read -p "请输入项目描述,直接回车默认为项目描述 : " project_desc
        if [[ $project_desc == "" ]]; then
            project_desc="项目描述"
        fi

        read -p "请输入最低支持的iOS系统版本,直接回车默认为8.0 : " miniVersion
        if [[ $miniVersion == "" ]]; then
            miniVersion="8.0"
        fi

        read -p "请输入作者姓名,直接回车默认为黄于 : " author
        if [[ $author == "" ]]; then
            author="黄于"
        fi

        read -p "请输入作者邮箱,直接回车默认为huangyu20@longfor.com : " author_email
        if [[ $author_email == "" ]]; then
            author_email="huangyi20@longfor.com"
        fi

        echo ""
        echo "============================================================"
        echo ""
        echo "版本号 : ${app_version}"
        echo "应用描述 : ${project_info}"
        echo "应用简介 : ${project_desc}"
        echo "最低支持的iOS系统版本 : ${miniVersion}"
        echo "作者 : ${author}"
        echo "作者邮箱 : ${author_email}"
        echo ""
        echo "============================================================"
        echo ""

        echo "生成Podspec文件 ..."
        podFile=$projectName.podspec

        echo "#" > $podFile
        echo "# Be sure to run \`pod lib lint ${podFile}\` to ensure this is a" >> $podFile
        echo "# valid spec before submitting." >> $podFile
        echo "#" >> $podFile
        echo "# Any lines starting with a # are optional, but their use is encouraged" >> $podFile
        echo "# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html" >> $podFile
        echo "#" >> $podFile
        echo "" >> $podFile
        echo "Pod::Spec.new do |s|" >> $podFile
        echo "" >> $podFile
        echo "  s.name         = '${projectName}'" >> $podFile
        echo "  s.version      = '${app_version}'" >> $podFile
        echo "  s.summary      = '${project_info}'" >> $podFile
        echo "  s.description  = <<-DESC" >> $podFile
        echo "                   ${project_desc}" >> $podFile
        echo "                   DESC" >> $podFile
        echo "" >> $podFile
        echo "  s.homepage = 'http://git.xxxxx.net/ios/${projectName}'" >> $podFile
        echo "  s.license  = { :type => 'Copyright', :text => 'Copyright 2018 - 2020 longfor.com. All rights reserved.\n' }" >> $podFile
        echo "  s.authors  = { '${author}' => '${author_email}' }" >> $podFile
        echo "" >> $podFile
        echo "  s.ios.deployment_target = '${miniVersion}'" >> $podFile
        echo ""  >> $podFile
        echo "  s.source = { :git => 'http://git.xxxxx.net/ios/${projectName}.git', :tag => s.version.to_s }" >> $podFile
        echo ""  >> $podFile
        echo "  # s.resource  = 'Assets/icon.png'" >> $podFile
        echo "  # s.resources = 'Assets/Resources/*.png'" >> $podFile
        echo "" >> $podFile
        echo "  s.vendored_frameworks = 'Frameworks/*.framework'" >> $podFile
        echo "  # s.frameworks = 'CoreLocation', 'Foundation', 'UIKit', 'SystemConfiguration', 'AdSupport', 'Security', 'CoreTelephony'" >> $podFile
        echo "" >> $podFile
        echo "  # s.library   = 'sqlite3.0'" >> $podFile
        echo "  # s.libraries = 'sqlite3.0','c++'" >> $podFile
        echo "" >> $podFile
        echo "  s.requires_arc = true" >> $podFile
        echo "" >> $podFile
        echo "  # s.xcconfig = { 'HEADER_SEARCH_PATHS' => '\$(SDKROOT)/usr/include/libxml2' }" >> $podFile
        echo "  # s.dependency 'JSONKit', '~> 1.4'" >> $podFile
        echo "" >> $podFile
        echo "end" >> $podFile

        echo "绑定Git ..."
        git init
        # 关联远程仓库
        git remote add origin http://git.xxxxx.net/ios/$projectName.git
    fi
else
    usage
fi
上一篇 下一篇

猜你喜欢

热点阅读