👨 🏻 💻 making Demo

Easy to remember:

  • Compiler languages: OC and Swift are compiled based on Clang and LLVM (Clang front-end, LLVM back-end)
  • Features: Faster Clang, low memory footprint, GCC-compatible, simple design, modular library (GCC supports JAVA and more platforms)
  • Compilation: Clang syntax analysis, semantic analysis, generation of intermediate code; LLVM machine independent code optimization to generate machine language
  • Complete compilation: dSYM file storage function address mapping is generated, Fabric, friendship and other crash parsing
  • Compile insert: preprocessing — macro, insert script — cocoapod
  • Compile time optimization:
    • Code layer – optimize @class for precompilation instead of #import, packaged libraries, headers;
    • Compiler layer – Debug mode does not generate DSYM and enables Build Active Architecture and disables compiler optimization Only

Sort out a series of articles about learning iOS Principle, and summarize the knowledge points at the beginning of each article to help memorize


I. Related concepts

Historical reasons

In 2000, Chris Lattner of the University of Illinois at Urbana-Champaign (UIUC), one of the world’s leading public research universities, tweeted Clattner_llvm (@clattner_llVM) developed a compiler development tool suite called Low Level Virtual Machine. Later, it covers an increasingly wide range and can be used for general compilers, JIT compilers, assemblers, debuggers, static analysis tools and a series of programming language related work. So the abbreviation LLVM became the official name. Chris Lattner later developed Clang, allowing LLVM to directly challenge GCC. In 2012, LLVM won the ACM Software System Award, along with UNIX, WWW, TCP/IP, Tex, JAVA, etc.

Chris Lattner, born in 1978, joined Apple in 2005 to fully convert GCC, which Apple uses, to LLVM. In 2010, I began to lead the development of Swift language.

Objective-c for iOS development is compiled by Clang/LLVM.

Swift is Swift/LLVM, where the SIL Optimizer is added to the Swift front end, which generates.swift as intermediate code. SIL is a high-level IR because Swift completes method binding at compile time. Direct calls from addresses are strongly typed languages, and method calls are no longer messages sent like OC, so compilation can obtain more information for later back-end optimizations.

LLVM is a collection of modular and reusable compiler and toolchain technologies. Clang, a subproject of LLVM, is a C, C++, and Objective-C compiler designed to provide surprisingly fast compilation, up to 3 times faster than GCC, Clang Static Analyzer does syntactic analysis, semantic analysis, and intermediate code generation. Of course, this process checks the code and flags errors and warnings. The LLVM core library provides an optimizer that supports code generation for popular cpus. LLD is the built-in linker for Clang/LLVM, which Clang must call to produce the executable.

Welcome to Clang’s documentation! – 4.0 documentation Clang

This is an overview of The LLVM Architecture: The Architecture of Open Source Applications

It is also important to understand the history of the compiler before it is compiled. For example, to answer the question, what is the compiler program compiled with? Just look at the book Linkers and Loaders.


Introduction to LLVM and Clang

LLVM is short for Low Level Virtual Machine. This library provides compiler – related support, including compile-time optimization, link optimization, online compilation optimization, and code generation for programming languages. In short, it can be used as a background for multiple language compilers. If that’s a bit abstract, here’s Clang: Clang is a C/C++/Objective C/Objective C++ compiler written in C++, based on LLVM and published under the LLVM BSD license with the goal (among other things) to surpass GCC.

Clang was developed for a number of reasons.

Apple uses LLVM to generate code (JIT) on gpus (Intel low-end graphics cards) that don’t support all of OpenGL’s features, so the program still works. The subsequent integration of LLVM with GCC caused some discomfort, as the GCC system was large and cumbersome, and Objective-C, which Was heavily used by Apple, had low priority in GCC. In addition, GCC, as a pure compilation system, does not work well with the IDE. In addition to licensing requirements, Apple could not use a modified version of GCC to close the source. So Apple decided to write the front end of C Family, known as LLVM-based Clang, from scratch.

Clang features:

  • Fast: By compiling carbon-h tests on OS X that contain almost all C header files, including Preprocess, lex, parse, Semantic Analysis, Clang is 2.5x faster than Apple GCC 4.0 in Abstract Syntax Tree generation time. (2007-7-25)
  • Small memory footprint: Clang memory footprint is 130% of the source code, Apple GCC memory footprint is over 10x.
  • The diagnostic information is readable: I don’t know how to type it, so I recommend going to the website. In contrast to GCC, the error syntax has a source code prompt as well as ~~~~~ and ^ prompts below the error call and associated context.
  • GCC compatibility.
  • The design is clear and simple, easy to understand, and easy to expand and enhance. Compared to GCC, with its older code base, the learning curve is flat.
  • Library-based modular design facilitates IDE integration and reuse for other purposes. Because of its history, GCC is a single executable compiler that does everything internally, from pre-processing to final code generation, and much of the information in between cannot be reused by other programs. Clang breaks the compilation process into separate phases, and AST information can be serialized. With library support, programs can access AST level information, which greatly enhances their ability to manipulate code. Code completion and refactoring are important features for an IDE, but without the underlying support, using tags analysis or regular expression matching is difficult to achieve.

Of course, GCC also has its advantages:

  • Support JAVA/ADA/FORTRAN
  • The current C++ support for Clang lags behind GCC, see. (Clang has recently become self-compiled, see)
  • GCC supports more platforms
  • GCC is more popular, widely used, and fully supported
  • GCC is based on C and does not require a C++ compiler to compile

IOS development purposes

Programming languages can generally be divided into two types, compiled languages and literal languages.

  • Compiled languages: Like C++,Objective C are compiled languages. When a compiled language is executed, it must first generate machine code through the compiler. Machine code can be executed directly on the CPU, so the execution efficiency is high.
  • Literal languages: Like JavaScript,Python is a literal language. A literal language does not need to go through the compilation process, but instead interprets the code into code that the CPU can execute through an intermediate interpreter at execution time. So, literal languages are less efficient than compiled languages, but they are more flexible to write, which is why JS is better.

The most common languages for iOS development are Objective and Swift. Both are compiled languages, in other words, they need to be compiled to execute. Compilation of both relies on Clang + LLVM.


Compile iOS

Both OC and Swift adopt Clang as compiler front-end and LLVM(Low Level Vritual Machine) as compiler backend. So the simple compilation process is shown here


Compiler front end

The front end of the compiler performs: parsing, semantic analysis, and generating intermediate representation. During this process, type checking is performed to indicate which line is highlighted if errors or warnings are found.


Compiler back end

The compiler back end performs machine-independent code optimizations, generates machine language, and performs machine-dependent code optimizations. In the iOS compilation process, the back-end processing is as follows

  • LVVM optimizer does BitCode generation, link period optimization, and so on.

  • The LLVM machine code generator generates different machine codes for different architectures such as ARM64.


Execute the XCode Build process once

When you select Build in XCode (command+B), the following process is performed

  • Compile information is written to auxiliary files to create the compiled file schema (name.app)
  • Process file packaging information, for example in debug
Entitlements:
{
   "application-identifier" = "App bundleid." ";
   "aps-environment" = development;
}
Copy the code
  • Execute CocoaPod pre-compile scripts (such as CheckPods manifest.lock for projects using CocoaPod)
  • Compile each. M file using CompileC and clang.
CompileC ClassName.o ClassName.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
export LANG=en_US.US-ASCII
export PATH="..."clang -x objective-c -arch x86_64 -fmessage-length=0 -fobjc-arc... -Wno-missing-field-initializers ... -DDEBUG=1 ... - isysroot iPhoneSimulator10.1. SDK - fasm - blocks... -i file mentioned above -f required Framework -iquote required Framework... -c ClassName.c -o ClassName.oCopy the code

With this compiled command, we can see that

  • Clang is the actual compile command
  • X Objective-C specifies the compiled language
  • Arch X86_64 specifies the compiled architecture, as well as ARM7 and so on
  • Fobjc-arc Some columns start with -f, specifying information such as using ARC. This is why you can do non-ARC programming for a single.m file.
  • Wno-mission-field-initializers are a series of warning options that start with -w and allow you to customize your build options
  • DDEBUG=1 some columns starting with -d, referring to precompiled macros through which conditional compilation can be implemented
  • Iphonesimulator10.1. SDK specifies the iOS SDK version used for compilation
  • I writes compilation information to the specified auxiliary file
  • F Link the required Framework
  • C Classname. c Compiles files
  • O classname. o Compilation product

The working process

  • Links need Framework, such as the Foundation Framework, AFNetworking. Framework, ALiPay. Fframework
  • Compile xiB files
  • Copy xiB, image and other resource files to the result directory
  • Compile ImageAssets
  • To deal with the info. Plist
  • Run the CocoaPod script
  • Copy the Swift standard library
  • Create an.app file and sign it

DSYM file

We generate a DSYM file after each compilation. Dsym files store the hexadecimal function address map.

In the binary that the App actually executes, the method is called by address. When the App crashed, third-party tools (Fabric, Friendship, etc.) would help us catch the crashed call stack, which would contain the call information of the crash address. Then, with the dSYM file, we can map the address to the specific function location.

In XCode, select Window -> Organizer to see the archier file we generated

IOS how to debug a third party statistics to the collapse of the report (http://blog.csdn.net/hello_hwc/article/details/50036323)


attribute

At some point, you’ve seen attributes in a third-party library or in an iOS header file.

Such as

__attribute__ ((warn_unused_result)) // If no return value is used, a warning is given at compile timeCopy the code

Attribtue is an advanced compiler directive that allows developers to specify more compile checks and some advanced compile-time optimizations.

There are three kinds:

  • Function attributes
  • Variable Attributes
  • Type Attributes

Grammatical structure

Attribute syntax format: attribute ((attribute-list))

Put the declaration semicolon “;” The front.

For example, declaring a property or method is deprecated in the current version, which is most common in tripartite libraries

@property (strong,nonatomic)CLASSNAME * property __deprecated;
Copy the code

This has the advantage of giving developers a transitional version that lets them know the attribute is deprecated and should use the latest API, but the deprecated attribute can still be used normally. If deprecated, the code will not run when the developer updates the Pod.

There are many scenarios for __attribtue__ to be used, and this article only lists a few that are commonly used in iOS development:

// Deprecate API for API updates#define __deprecated __attribute__((deprecated))// Deprecate with description#define __deprecated_msg(_msg) __attribute__((deprecated(_msg)))// When an __unavailable variable/method is encountered, the compiler simply throws an Error#define __unavailable __attribute__((unavailable))// Tell the compiler not to throw a warning even if the variable/method is not being used#define __unused __attribute__((unused))// The opposite of __unused#define __used __attribute__((used))// Warn if the method return value is not used#define __result_use_check __attribute__((__warn_unused_result__))The OC method is not available in Swift#define __swift_unavailable(_msg) __attribute__((__availability__(swift, unavailable, message=_msg)))
Copy the code

Clang warning processing

You’ve no doubt seen code like this:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"/ / / code#pragma clang diagnostic pop
Copy the code

What this code does is

  • Compacting the current compilation environment
  • Ignore -wundeclared -selector(undeclared) selector warning
  • Compile the code
  • Unstack the compile environment

With Clang Diagnostic Push/POP, you have the flexibility to control the compilation options of your code blocks.

  • IOS reasonable use Clang warned to improve the quality of the code (http://blog.csdn.net/Hello_Hwc/article/details/46425503)

pretreatment

Preprocessing is processing before compilation. Preprocessing allows you to define compiler variables and implement conditional compilation.

For example, such code is common

#ifdef DEBUG/ /...#else/ /...#endif
Copy the code

Also, we can define other preprocessing variables as well. In XCode- select target-Build Settings, search for Proprecess. Then click the blue plus sign to set the preprocessor macros for both debug and Release modes.

For example, we add: TestServer to indicate that the code in this macro is running on the TestServer

Then, with multiple Targets (right-click Target and select Duplicate), a single Target is responsible for testing the server. This way we don’t have to change the code every time we switch test servers.

#ifdef TESTMODE// Test server-related code#else// Production server code#endif
Copy the code

Insert the script

In general, if you’re using CocoaPod to manage third-party libraries, your Build Phase looks like this:

[CP] is the script inserted by CocoaPod.

  • Check Pods manifest.lock to Check whether the third-party libraries managed by Cocoapod need to be updated
  • Embed Pods Framework, runs scripts to link tripartite libraries to static/dynamic libraries
  • Copy Pods Resources, run the script to Copy the resource files of the third party library

The configuration information is stored in this file (.xcodeProg)

At this point, CocoaPod works by modifying XCodeProject and then configuring compile-time scripts to ensure that the third-party libraries compile connections correctly.

Also, we can insert our own scripts to do extra things. For example, every time we archive, we have to manually adjust the build version of target, and if we are not careful, we will forget. This process can be automated by inserting scripts.

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
Copy the code

The script is as simple as reading the build version number of the current pist, then adding one to it and rewriting.

It’s also easy to use:

  • Xcode — Select Target — Select Build Phase
  • Select add Run Script Phase

Then copy the Script in and check Run Script Only When installing to ensure that we Only execute the Script When it is installed on the device. Rename the script to Auto Increase Build number

Then, drag the script into the Link Binary With Libraries


Script compilation packaging

Scripted compilation packaging is very useful for CI(continuous integration). In iOS development, the two commands required for compiling and packaging are:

// Compile to.app xcodebuild-workspace$projectName.xcworkspace -scheme $projectName  -configuration $buildConfig clean build SYMROOT=$buildAppToDir// Pack xcRun - SDK iphoneOS PackageApplication -v$appDir/$projectName.app -o $appDir/$ipaNameIpa You can run the info command to view the detailed document info xcodebuildCopy the code

Before writing a compiled based on the Python scripts packaging (https://github.com/ReverseScale/AutoBuildScript/blob/master/autobuild.py)


Improve project compilation speed

Usually, when the project is large and the source code and third-party libraries are introduced in large numbers, we find that the compilation is slow. After understanding the compilation process of XCode, we can optimize the compilation speed from the following aspects:

1) Check the compile time

We need a way to see compilation times so we can compare and see if our optimizations are working.

For XCode 8, turn off XCode and the terminal enters the following command

defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
Copy the code

Then, restart XCode and compile, and you’ll see the compile time here.

2) Optimization at code level

2.1) forward declaration

The forward declaration is @class CLASSNAME instead of #import classname.h. In this way, the compiler can greatly speed up #import substitution.

2.2) Package common utility classes (Framework/.a)

Package it into a Framework or static library so that it doesn’t need to be recompiled at compile time.

2.3) Put common header files into precompiled files

XCode’s PCH files are precompiled files, where the content is precompiled before the XCode build is executed and imported into every.m file.

3) Compiler options optimization

3.1) In Debug mode, no DSYM file is generated

As mentioned above, the dysm file stores debugging information. In Debug mode, we can use XCode and LLDB to Debug. Therefore, there is no need to generate additional DSYM files to slow down compilation.

3.2)Debug Enables Build Active Architecture Only

In XCode -> Build Settings -> Build Active Architecture Only change to YES. By doing this, you can only build the current version of arm7/arm64, and remember to only enable Debug mode. This option is automatically turned on in older versions of XCode.

3.3) Disable compiler optimization in Debug mode

Compiler optimization


More in-depth learning

Clang LLVM for iOS


Copyright statement

This series of articles is mostly about online information. At the end of the article, there will be a reference link. If there is any mistake, please discuss 🤗

The above articles are compiled from: https://my.oschina.net/u/2345393/blog/820141, https://linuxtoy.org/archives/llvm-and-clang.html, https://blog.csdn.net/hello_hwc/article/details/53557308, https://github.com/ming1016/study/wiki/ – iOS – compile – deep insight into Clang – LLVM