也是座谈哪些在xcode中展开调治将养的,在编写翻

2019-10-01 13:17 来源:未知

原文出自这里

oclint自定义规则的编写,一般我们会生成xcode工程,然后进行编码,build之后会输出dylib。如果我们要验证规则的正确性,只能把dylib拷贝到rules的目录中,然后在进行测试。这样实在是很麻烦,也只能通过log来输出信息,然而clang的方法那么多,单靠log方式也不便于调试。于是在想如何在XCode中进行调试。但搜了很多方法,一直没成功。

#include

#include 是预处理指令,在编译之前的预处理期执行。它的作用是将引入文件中的内容拷贝到当前文件的 #include指令后面,并删除这一行;

//header.h
char *test (void),

//program.c
int x;
#include "header.h"
int main (void) {
  puts (test ());
}

//编译器看到的 program.c
int x;
char *test (void);
int main (void) {
  puts (test ());
}

如果两次 #include 同一个文件,相当于拷贝了两份相同的头文件内容,所以编译时就会报重复定义的错误。

// file.m
#include "header.h"
#inclure "header.h"
//duplicate interface definition for class 'header'

这时就需要引入头文件保护:

#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN
//the entire file
#endif

当头文件再次被引入的时候,条件判断为 false,因为 FILE_FOO_SEEN 已经被定义过了。预处理器会跳过该文件的全部内容,编译器编译时就不会看到两个重复的引用。

#include 不一定要写在文件最开头位置,拷贝内容紧跟在它后面。

#include 后面不一定跟文件名,也可以直接跟路径(相对路径/绝对路径)。

  1. 下载ffmpeg源码 编译ffmpeg 依赖 yasm组件

这里有一个方案:OCLint自定义规则的调试方法,但是不知道他的oclintexe是怎么写的,我自己尝试新建Command Line Tool的工程,然后用NSTask调起oclint的命令,还是没能断点到,可能是我的实现有问题。

#import

#import 不会造成重复引用,它会自己检查是否已经引用过,也可以防止递归包含。

后来又发现了一个答案,How to launch OCLint in xcode with debug model.,也是讨论如何在xcode中进行调试的。一开始没明白答案中步骤的意思,一直无果,突然有一天开窍了。used the cmake tool, create xcode project with each module,看到了each module。然后就想到,在创建rule的时候,不也是通过以下cmake命令生成的xcode工程,LLVM_ROOT指向的是oclint-rules。

<> and ""

filename is optionally preceded by a directory specification. The file name must name an existing file. The difference between the two syntax forms is the order in which the preprocessor searches for the type library files when the path is incompletely specified.

也就是说,""<>的区别在于未指定 filename 路径的情况下,预编译搜寻路径的方式。

除了系统目录外,还可以通过 -I, -isystem, -idirafter, -iquote 选项在预处理阶段添加头文件的搜索路径,他们之间可以任意选项,任意数量的进行组合,中间以空格符分隔;其中指定为 -iquote 选项的目录仅适用于 #import "file" 指令,其它选项同时适用两个指令。

#import <file> 引入头文件时:

1. 所有指定为 `-I` 选项的目录从左往右的依次扫描;
2. 所有指定为 `-system` 选项的目录从左往右依次扫描;
3. 扫描系统目录;
4. 所有指定为 `-idirafter` 选项的目录从左往右依次扫描;

#import "file" 引入头文件时:

1. 首先在当前文件(`#import "file"` 代码所在文件)的目录下进行搜索;
2. 所有指定为 `-iquote` 选项的目录从左往右依次扫描;
3. 所有指定为 `-I` 选项的目录从左往右的依次扫描;
4. 所有指定为 `-system` 选项的目录从左往右的依次扫描;
5. 扫描系统目录;
6. 所有指定为 `-idirafter` 选项的目录从左往右依次扫描;
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"brew install gitbrew install yasm
#! /bin/sh -ecmake -G Xcode  -D CMAKE_CXX_COMPILER=../build/llvm-install/bin/clang++  -D CMAKE_C_COMPILER=../build/llvm-install/bin/clang  -D OCLINT_BUILD_DIR=../build/oclint-core  -D OCLINT_SOURCE_DIR=../oclint-core  -D OCLINT_METRICS_SOURCE_DIR=../oclint-metrics  -D OCLINT_METRICS_BUILD_DIR=../build/oclint-metrics  -D LLVM_ROOT=../build/llvm-install/ ../oclint-rules

Search Paths

PROJECT -> Build SettingsTARGETS -> Build Settings 中 都包含了 Search Paths 这一栏,Xcode 将上面的命令行选项可视化的展示给我们;

image.png

PROJECT 中的设置默认不被 TARGETS 继承,只有当 TARGETS 的设置中加入了 $(inherited) 时,才被继承。

Xcode 中的 TARGETS 和 PROJECTS

  1. 编译ffmpeg

后来发现oclint目录下还有好几个文件夹,oclint-core,oclint-driver,oclint-metrics,oclint-reporters,countly等,是都可以生成xcode工程的。然后,按照步骤,一个个生成了xcode工程,然后进行编译。发现oclint-driver这个工程是可以直接跑起oclint的,大喜。

多个 -I 扫描顺序

目录结构:

/Build/ -> /directory/  -> MyClass.h
                        -> ViewController.h
        -> /directory2/ -> MyClass.h
        -> /directory3/ -> MyClass.h

分别在 /directory, /directory2, /directory3 文件夹下创建相同文件 MyClass.h,文件中都定义了相同变量 static NSString *classKey = @"<dir>/MyClass.h"用来输出上层目录名;

#import <MyClass.h>

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"MyClass.h: %@", classKey);
}
@end

Search Paths:

image.png

编译 ViewController.m

image.png

最终输出:

//Build[] MyClass.h: directory3/MyClass.h
  • 指定为 -I 选项的目录从左往右的依次扫描。

不过最终也不需要答案中的那么复杂,只需要生成oclint-driver的xcode工程编译即可。

#import <file> 目录扫描顺序

在工程 Build 下,新建 Target Build2

/Build2/ -> /directory/  -> math.h //#define MAXFLOAT    0.1f
                         -> ViewController.h
         -> /directory2/ -> math.h //#define MAXFLOAT    0.2f

/user/include/ -> math.h //#define MAXFLOAT    0x1.fffffep+127f

为了验证和系统目录的顺序关系,我们将头文件命名为 math.h,同时分别重定义宏 #MAXFLOAT 的值。

cd FFmpeg./configure -–enable-debug./configure --disable-optimizations--disable-asmmake -j8

下面来具体说下调试的步骤。

-isystem

Search Paths:

image.png

编译 ViewController.m

image.png

最终输出:

//Build2[] MAXFLOAT: 0.200000 
  • 指定为 -isystem 选项的目录扫描顺序在系统路径之前。
  1. 创建Xcode新项目

调试步骤

如果有不清楚oclint如何编写自定义规则的,请看这里:Code Review-OCLint系列开篇

写的比较详细,一步步操作下来就好。不过在编译源码之前,需要安装好所需的环境。两个命令就好。

brew install subversion git cmake lcov opensslbrew install ninja

首先生成oclint-xcoderules的xcode工程。按上面的教程来。 生成oclint-driver的xcode工程,只需把脚本改成LLVM_ROOT = oclint_drivers的目录。

cd oclintmkdir oclint-xcodedrivercd oclint-xcodedrivertouch create.shchmod +x create.sh

create.sh脚本内容如下:

#! /bin/sh -ecmake -G Xcode  -D CMAKE_CXX_COMPILER=../build/llvm-install/bin/clang++  -D CMAKE_C_COMPILER=../build/llvm-install/bin/clang  -D OCLINT_BUILD_DIR=../build/oclint-core  -D OCLINT_SOURCE_DIR=../oclint-core  -D OCLINT_METRICS_SOURCE_DIR=../oclint-metrics  -D OCLINT_METRICS_BUILD_DIR=../build/oclint-metrics  -D LLVM_ROOT=../build/llvm-install/ ../oclint_drivers

最后执行./create.sh,即可生成oclint-driver的xcode工程。

但是在xcode中编译oclint-driver的时候,我这边出现了报错问题。如果你也碰到同样的问题,可以这样解决。

  • 在编译OCLintDriver.a库的时候,报错。<countly/Countly.h>找不到。是因为Header Search Paths没配置countly头文件的路径。

    切到OCLintDriver target的build settings--->Header Search Paths,添加/Users/liusilan/Documents/workspace/my/opensource/oclint/countly/include,这里改成自己的路径。

  • 在编译oclint-0.13的target时,出现-lcountly找不到的情况。这是因为Library path没有配置countly的路径。

    同样在build settings->Library Search Paths,添加lib路径。/Users/liusilan/Documents/workspace/my/opensource/oclint/build/countly/lib,这里改成自己的路径。

    然后build,就可以成功的跑起oclint了。

由于我们需要调试自定义规则,就需要在刚能跑起来的oclint中调起规则,oclint有个参数-R,表示rule所在文件夹路径。通过Arguments Passed On Lanunch的方式,可以添加参数。

自定义rule的dylib的输出路径是

/Users/liusilan/Documents/workspace/my/opensource/oclint/oclint-xcoderules/rules.dl/Debug

把这个参数传进去就可以。然后再添加需要检查的文件,输出格式,系统头文件路径等。

图片 1QQ20171209-1.png

总的参数如下:

-R=/Users/liusilan/Documents/workspace/my/opensource/oclint/oclint-xcoderules/rules.dl/Debug -report-type html -o /Users/liusilan/Documents/workspace/my/demo/Demo/reporter.html /Users/liusilan/Documents/workspace/my/demo/Demo/Demo/Test.m -- -x objective-c -isystem /Users/liusilan/Documents/workspace/my/opensource/oclint/build/oclint-release/lib/clang/5.0.0/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks -isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include

注意:如果出现'stdarg.h' file not found的报错,则需要添加clang的头文件路径。

-isystem /Users/liusilan/Documents/workspace/my/opensource/oclint/build/oclint-release/lib/clang/5.0.0/include

按照这种方式的话,需要把自定义的规则先生成好。但每次改动了,都要去oclint-rule的工程中去跑一遍,稍显麻烦。可以直接把oclint-rule的xcode工程作为oclint-driver的子工程,然后设置target依赖于你要调试的rule的target即可。这样,在跑oclint的时候,就会先编译好自定义的规则了。

图片 2QQ20171209-2.png

一切都配置好之后,在自定义规则里打好断点,run起来,又出现了一个问题

TAG标签:
版权声明:本文由www.129028.com-澳门金沙唯一官网www129028com发布于编程新闻,转载请注明出处:也是座谈哪些在xcode中展开调治将养的,在编写翻