连接与Symbol

284 阅读5分钟

多环境配置

每个项目都存在:

  • Project:包含了项目所有的代码,资源文件,所有信息
  • Target:对指定代码和资源文件的具体构建方式
  • Scheme:对指定Target的环境配置

项目默认两个环境Debug和Release环境

#if DEBUG 
NSLog(@"DEBUG--测试环境"); 
#else 
NSLog(@"生产环境"); 
#endif

多环境配置

方式1配置多Targets

选中对应的TARGET, CMD+D直接拷贝一分。会有新的TARGET、 plist文件Scheme产生.最好修改下对应的名字与 BundleID。就是俩个APP。只不过执行的是同一份代码。这个时候 区分更多的环境 直接加洪

image.png

这样就多了一套环境配置,根据不同的场景进行相关的配置

#ifdef LoginApp
    NSLog(@"LoginApp");
#elif LoginAppDev
    NSLog(@"LoginApp-Dev");
#elif LoginApp2
    NSLog(@"LoginApp2");
#else
    NSLog(@"no");
#endif
 缺点:
 会存在多个info.plist文件,同时也要进行相关的路径配置
 环境多了,配置就会比较乱

方式2配置Configurations

Project工程配置 info配置项下面的Configurations image.png

配置Scheme

image.png

  • Scheme与Configurations的关系是一一对应的。添加不同的环境即可。 在项目Build Settings里新建User-Defined,起名就叫HOST_URL这是会有不同的环境,可以做不同的配置

image.png

  • 最后在Info.plist进行配置,暴露出来 验证:
 NSString *path = [NSBundle.mainBundle pathForResource:@"Info" ofType:@"plist"];
 NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:path];
 NSLog(@"%@",infoDic[@"HOST_URL"]);

方式3配置.xcconfig

  1. 我们应该都清楚cocoapods对第三方进行管理,其实就是通过.xcconfig文件进行管理的,创建好cocoapods会自动根据环境帮我们生成好.xcconfig文件 .xcconfig文件内容是已Key-Value形式存在,'='左侧是key值,右侧为value值
  2. 创建Config文件,在文件中创建.xcconfig文件

image.png 注意命名规则:.xcconfig文件所在的文件夹名称+项目名称+.环境名称

  1. xcconfig文件是可以配置Build Settings里面的内容,比如我们平时配置动态库,静态库时,要配置到Other Link Flags,通过.xcconfig我们可以直接配置。这个xcconfig以后会经常用,key值的写法比较独特。查找地址:Xcode Build Settings

然后再执行类似于 方式二 配置 HOST_URL的方式,配置于不同环境下的.xcconfig

  1. xcconfigcocoapods 会冲突 下面是解决 冲突的方式
//1. 其实就是 Pods-LoginApp.debug.xcconfig 所在的文件目录 

#include "Pods/Target Support Files/Pods-LoginApp/Pods-LoginApp.debug.xcconfig"

//2.OTHER_LDFLAGS 等相关选项可能 冲突或者 覆盖 $(inherited) 即可解决,例如下面

OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"
HEADER_SEARCH_PATHS = /use/info/inclue

5.xcconfig 语法

Mach-o与连接器

Mach-O定义

  • Mach-O(Mach Object)是macOS、iOS、iPadOS存储程序和库的文件格式。对应系统通过应用二进制接口(application binary interface,缩写为ABI)来运行该格式的文件。
  • Mach-O格式⽤来替代BSD系统的a.out格式。Mach-O⽂件格式保存了在编译过程和链接过程中产⽣的机器代码和数据,从⽽为静态链接和动态链接的代码提供了单一文件格式。
  • 项目运行会生成一个.app文件显示包内容即可看到 Mach-O⽂件
  • Mach-o = 配置文件 + 二进制代码 其实 这里 都是二进制代码 Mach-O

调用过程

1.调用fork函数,创建一个process
2.调用execve或其衍生函数,在该进程上加载,执行我们的Mach-O文件
当我们调用时execve(程序加载器),内核实际上在执行以下操作:
  1.将文件加载到内存
  2.开始分析Mach-O中的mach_header,以确认它是有效的Mach-O文件
  • Mach-O文件分析
    1.通过 MachOView,也就是我们所说的烂苹果
    2.通过命令:objdump --macho --private-headers
    其实macho = 文件配置 + 二进制代码 查看Mach-O文件既可以看到。这里就不展示了。
    3.Mach-O是一个可读写文件
    4.Mach-O这里只做简单的陈述,详细了解的话后面会慢慢详述。
1查看mach-header
objdump --macho -private-header ${MACH_PATH}
2查看导出符号
objdump --macho --exports-trie ${MACH_PATH}
3查看间接符号表
objdump --macho --indirect-symbols ${MACH_PATH}
4查看__TEXT
objdump --macho -d ${MACH_PATH}

Symbol

xcode_run_cmd.sh 执行脚本

#!/bin/sh
RunCommand() {

  #判断全局字符串VERBOSE_SCRIPT_LOGGING是否为空。-n string判断字符串是否非空
  #[[是 bash 程序语言的关键字。用于判断
  if [[ -n "$VERBOSE_SCRIPT_LOGGING" ]]; then

    #作为一个字符串输出所有参数。使用时加引号"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数
      if [[ -n "$TTY" ]]; the
          echo "♦ $@" 1>$TTY
      else
          echo "♦ $*"
      fi
      echo "------------------------------------------------------------------------------" 1>$TTY
  fi

  #与$*相同。但是使用时加引号,并在引号中返回每个参数。"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数
  if [[ -n "$TTY" ]]; then
      echo `$@ &>$TTY`
  else
      "$@"
  fi
  #显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
  return $?
}

EchoError() {
    #在shell脚本中,默认情况下,总是有三个文件处于打开状态,标准输入(键盘输入)、标准输出(输出到屏幕)、标准错误(也是输出到屏幕),它们分别对应的文件描述符是0,1,2
    # >  默认为标准输出重定向,与 1> 相同

    # 2>&1  意思是把 标准错误输出 重定向到 标准输出.

    # &>file  意思是把标准输出 和 标准错误输出 都重定向到文件file中

    # 1>&2 将标准输出重定向到标准错误输出。实际上就是打印所有参数已标准错误格式

    if [[ -n "$TTY" ]]; then

        echo "$@" 1>&2>$TTY
    else
        echo "$@" 1>&2
    fi
}

RunCMDToTTY() {

    if [[ ! -e "$TTY" ]]; then

        EchoError "=========================================="

        EchoError "ERROR: Not Config tty to output."

        exit -1

    fi

    if [[ -n "$CMD" ]]; then

        RunCommand "$CMD" ${CMD_FLAG}
    else

        EchoError "=========================================="

        EchoError "ERROR:Failed to run CMD. THE CMD must not null"
    fi
}

RunCMDToTTY

/bin/sh "$SRCROOT/xcode_run_cmd.sh"

sh.png


//#CMD = 运行到命令
//#CMD_FLAG = 运行到命令参数
//#TTY = 终端

// xcode 内置变量
MACHO_PATH=${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/*
TTY=/dev/ttys002
CMD = nm
CMD_FLAG = -pa ${MACHO_PATH}

在终端执行 man ld 查看连接器里面的内容

// O1 Oz 生成目标文件
//死代码的剥离  dead code strip 实际上也是剥离符号 链接的时候
//调试符号的剥离 strip    mach-o 修改的时候

// man nm 在终端查看一个命令

符号表

符号

持续更新