0. Introduction

XCode是macOS上开发app不可缺少的开发者工具,不管是开发macOS上的应用,还是iOS上的应用,都离不开XCode环境。尽管其易用性广受诟病,但由于苹果app开发的封闭性,众多开发者也不有苦不能言。近年来微软针对macOS平台发布了Visual Studio Code和Visual Studio for Mac这两款开发工具,但是其目的显然只是作为XCode的一种补充,要全盘替代XCode目前还不太现实。平时工作中由于负责开发维护Windows和Mac两个平台的应用,因此常常需要用到XCode。但由于macOS系统本来就比较逆反,用惯了Winodws陡然切换到macOS,根本无所适从。对于XCode的使用更是如此。在此记录下平时开发过程中经常用的操作,以免自己再次切换到macOS上时一脸懵逼。

1. Install name and Runpath

      install name是个什么玩意儿?简单的说,是便于加载器dyld找到程序链接的库文件。一般情况下dyld在加载程序的时候,会去一些固定的路径(如/usr/local/lib/usr/lib)下寻找需要的库文件。如果没有找到库文件,程序就会加载失败并报错。install name的出现就是为了解决这种问题,允许用户把库文件放到其他位置,通过install name告诉dylb到哪去寻找这个库文件。
      在XCode中用好install name需要设置两个地方:
(1)Build Settings->Linking,设置了Dynamic Library Install NameDynamic Library Install Name Base两项。这里用到了@rpath变量,其含义和用法在前面的博客中有细说过。@rpath其实是“runpath”的缩写,其值在第二步中设置。
 
     (2)Build Settings->Runpath Search Paths,设置了runpath的搜索路径。在这一项里面可以设置多个路径。这里设置的每个项都会替换@rpath,从而达到灵活设置多个位置的目的。可以在下图中看到,我们使用了@loader_path这个变量,其值实际上是可执行程序的所在位置。因此,假设可执行程序所在路径为:/Users/zhangzhongke/Library/bin/test,@loader_path/../Resources”把上面设置的@rpath替换了之后就变成了:/Users/zhangzhongke/Library/bin/test/../Resources,实际也就是:/Users/zhangzhongke/Library/Resources/。我们这里runpath只设置了一个值,实际上有需要可以设置多个值。
 
      通过命令otool -L可查看dylib文件的install name确实已经设置成了我们需要的值。其中:-L选项打印dylib所使用到的库,-D打印dylib文件的ID名。如果是修改其他动态库,则可使用install_name_tool命令来修改。

2. Header, Compiler and Build Locations

       Build Settings->Build Locations可以修改编译输出位置。
 
      Build Settings->Search Paths可设置编译时头文件和库文件的搜索路径。
 
      Build Settings->Apple LLVM8.0-Language C++设置C++运行时库。有的项目中需要在libstdc++和libc++之间切换,否则编译过程各种错误。
 

3. dSYM and App crashes

dSYM是Debug Symbols的缩写,也就是说dSYM里面存储的都是可执行程序的调试符号,对于Windows下Visual Studio生成的pdb文件。保存Release版的dSYM文件对于程序崩溃时的调试可以说极为重要。调试符号文件在调试中的作用其实非常简单,就是把那些16进制值转换为我们源代码中对应的符号变量。这样能够帮助开发者快速定位到程序崩溃的地方,极大的提高调试效率。

      那么怎么利用调试符号文件来调试程序崩溃呢?顺便记录下Windows的调试方法:
(1)Windows下利用pdb文件调试崩溃程序。首先要注意的是,要保存好Release版的pdb文件。最好发布程序时,把pdb文件也一起打包进去。
  • 调试时使用windbg,需要设置好调试符号文件和源代码文件(如果有)路径:
  • Attach to a Process适用于动态库等不能直接运行的程序,Open Executable则适用于exe可执行程序。程序起来后,直接输入g命令开始执行。在出现异常的地方运行命令:!analyze -v进行分析。windbg就能给出具体的崩溃的位置了。

(2)macOS下利用dSYM文件调试崩溃程序。首先解释下dSYM和DWARF的关系:

  • DWARF是一种被众多编译器和调试器使用的用于支持源代码级别调试的调试文件格式。它满足了许多程序语言的需求,比如C,C++和Fortran,而且被设计成可拓展到其它语言。DWARF是平台独立的且适用于任何处理器任何操作系统。 DWARF广泛应用于Unix,Linux和其它操作系统,以及独立的环境中。
  • 为了避免进行stripping操作后调试符号的丢失,你可以使用dwarf-with-dsym选项. DWARF with dSYM 选项在标准的DWARF之外执行一个额外的步骤:创建一个单独的MyApp.app.dSYM文件,这个文件包含你的程序的所有调试符号(这个文件其实是一个包,可以通过右键->显示包内容进行查看)。事实上,DWARF with dSYM选项允许你对你进行单步调试而不管可执行程序是否被剥离了调试信息(stripped)。这是可能的,这是因为gdb将会在你的程序的目录下查找.dSYM文件。它不需要知道对象文件(object files)的名字或者路径。

利用dSYM解析crash log的主要步骤如下:

(1)在调试之前,把xxx.crash、xxx.dSYM、symbolicatecrash三个文件放到一个同一个文件夹中。这里symbolicatecrash是XCode命令行工具中的一个命令,可以把它拷贝过来,也可以建立符号链接。

ln -s /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash /usr/bin/symbolicatecrash
在我的电脑上装的是XCode8,symbolicatecrash的路径为:/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash。如果找不到,可以使用命令:
find /Applications/Xcode.app/ -name symbolicatecrash -type f

(2)验证app和dSYM的UUID是否一致:

dwarfdump --uuid YourApp.app/YourApp
dwarfdump --uuid YourApp.app.dSYM

(3)解析Crash Log

./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash

生成的symbol.crash就是解析后的崩溃日志文件了,里面的符号经过了转换,阅读上变得更加友好。另外,macOS系统上的日志通常存放在如下几个地方:

~/Library/Logs/DiagnosticReports/ (where ~ refers to your Home directory).
~/Library/Logs/CrashReporter/MobileDevice are the crashlogs for your iOS devices (if any).
~/Library/Logs/CrashReporter also has links to items in ~/Library/Logs/DiagnosticReports/
/var/log/system.log

  注意:Build Settings -> Build Options -> Debug Information Format中, 置成 DWARF是不会产生dSYM文件的,必须选择DWARF with dSYM File才会生成符号表文件。

4. Target, Scheme and Group

XCode中的Target类似Visual Studio中的Project,也就是说一个target可以单独进行编译,生成可执行程序。通常在XCode中创建一个项目时,默认会创建一个同名的Target。如果需要新增一个Target,在XCode的工具栏选择:File->New->Target即可。如下图:

创建Target的时候选择需要的项目类型即可。然后,在下图所示位置切换不同的Targets进行编译。

注意:如果要编译不同的Targets一定要记得切换,这个功能如果Visual Studio中的“设置为启动项目”:

如果需要设置不同Targets的项目属性,也需要进行Targets的切换:

编辑Scheme,其实就是设置编译类型:Debug或者Release,以及一些编译动作。XCode里面有Build, Run, Test, Profile, Analysis, Archive这几个编译动作,每个动作都有Debug和Release模式。在这两种模式下设置不同的编译参数。最常用的就是Run和Archive了。

Group在XCode里面的作用非常明确,就是用来在逻辑上对源文件进行分类管理。逻辑上的意思是,它并不会创建物理上的分组,而仅仅是视觉上、逻辑上的划分。所以有时候我们虽然在XCode中看到工程组织的井井有条,可是工程文件夹中的文件实际上是散落一片的。这个功能对于大型的项目功能划分、文件组织非常重要。下图中的New Group和New Group from Selection都是用来创建Group的,后者可以对选中的工程文件创建Group。

5. Misc

  • xcode-select:用于选择不同版本的开发者工具
  • xcodebuild和xcrun是打包时常用的两个命令,xcodebuild负责编译,xcrun负责将app打成ipa。

6. References

XCode日常使用备忘录的更多相关文章

  1. Caffe和py-faster-rcnn日常使用备忘录

    罗列日常使用中遇到的问题和解决办法.包括: { caffe使用中的疑惑和解释: 无法正常执行 train/inference 的情况: Caffe基础工具的微小调整,比如绘loss曲线图: 调试pyt ...

  2. Xcode日常使用

    1.构建输出目录(Preferences->Locations->Locations)当选择为Default时,Derived Data的目录为~/Library/Developer/Xc ...

  3. iOS日常学习 - 每个Xcode开发者应该知道的七个使用技巧

    本文为转载学习使用原文链接 工欲善其事,必先利其器.对一个iOS开发者来说,这就意味着对Xcode的熟练掌握程度.Xcode是一个学习起来有点难度的软件,下面的这些技巧或许可以显著的提高你的编程效率. ...

  4. Xcode插件优缺点对比(推荐20款插件)

    本文大致整理了自己用过的一些插件的使用感想(就是好不好用). 在那之前先简单贴两条插件须知,知道的可以忽略. 1.Alcatraz 类似于管理第三方库的cocoapods,管理插件也有个Alcatra ...

  5. 高效使用你的Xcode

    (via:VongLo's Dev Space  原文:Supercharging Your Xcode Efficiency)   好莱坞电影里经常看到黑客们手指在键盘上飞速跳跃,同时终端上的代码也 ...

  6. Xcode 8 的 Debug 新特性

    Contents OverView Static Analyzer Localizability Instance Cleanup Nullablility Runtime Issue View De ...

  7. Xcode 的正确打开方式——Debugging(转载)

    Xcode 的正确打开方式——Debugging   程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不可避免地需要使用 Xcode.这篇博客就主要介绍了 Xcode 中几种能 ...

  8. 【转】Xcode 插件优缺点对比(推荐 20 款插件)

    [转自]http://www.cnblogs.com/dsxniubility/p/5099191.html 1.Alcatraz 类似于管理第三方库的cocoapods,管理插件也有个Alcatra ...

  9. Xcode 的正确打开方式——Debugging

    程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不可避免地需要使用 Xcode.这篇博客就主要介绍了 Xcode 中几种能够大幅提升代码调试效率的方式. “If debuggi ...

随机推荐

  1. C++文本处理_文件读写

    QT在进行文本读写时和C++一样,是基于文本流操作的. QT在读取全部文本时,相对比较便捷.使用readAll()函数,配合split()进行分隔符的拆分(例如行结束符"\n"), ...

  2. 计数排序和桶排序(Java实现)

    目录 比较和非比较的区别 计数排序 计数排序适用数据范围 过程分析 桶排序 网络流传桶排序算法勘误 桶排序适用数据范围 过程分析 比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比 ...

  3. linux 用户管理(一)

    本节内容梗概: 1.用户管理配置文件 2.用户管理命令 3.用户组管理命令 4.批量添加用户 5.用户授权 学东西先讲原理,所以从配置文件入手 1.用户信息文件  /etc/passwd 存放了用户的 ...

  4. maven web项目中web.xml

    web.xml 不是web工程必须的. web.xml文件用来配置那些东西:欢迎页,servlet,filter等. web.xml文件中定义了多少种标签元素,web.xml 中就可以出现它的模式文件 ...

  5. Android_SQLite数据库增删改查操作

    一:什么是SQLite? 在Android平台上,集成了一个嵌入式关系型轻量级的数据库. 二:什么时候用的数据库? 有大量相似机构的数据需要存储时. 三:如何创建一个数据库? 1.创建一个Sqlite ...

  6. Chrome必备的扩展

    Devtools Terminal ——浏览器终端.牛逼的不得了! LiveReload——为官方 LiveReload 应用程序(Mac 和 Windows)和第三方,例如 guard-livere ...

  7. 如何使用Microsoft技术栈

    Microsoft技术栈最近有大量的变迁,这使得开发人员和领导者都想知道他们到底应该关注哪些技术.Microsoft自己并不想从官方层面上反对Silverlight这样的技术,相对而言他们更喜欢让这种 ...

  8. Android什么时候进行View中Background的加载

    对大多数Android的开发者来说,最经常的操作莫过于对界面进行布局,View中背景图片的加载是最经常做的.但是我们很少关注这个过程,这篇文章主要解析view中背景图片加载的流程.了解view中背景图 ...

  9. java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required

    java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required 严重: Exceptio ...

  10. [大数据之Spark]——Transformations转换入门经典实例

    Spark相比于Mapreduce的一大优势就是提供了很多的方法,可以直接使用:另一个优势就是执行速度快,这要得益于DAG的调度,想要理解这个调度规则,还要理解函数之间的依赖关系. 本篇就着重描述下S ...