Xcode other link flags detailed explanation

The other linker flags is unique to Xcode, an integrated development environment, which is designed to allow connector LD to work with links, except for default parameters, and then add additional parameters at the root.

Object-C link properties:

The “selector not recognized” runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) – instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.

The linker for Object-C does not create symbolic tables for each method, but establishes link symbols for each class. In this case the static library defines the classification of existing class, the linker that this class will not exist, classification and core code Association (merger), so in the final executable file, you will not find the methods defined in the classification.

For example, the following error:

Xcode other link flags detailed explanation
Snip20170613_4.png

As you can see, log can be seen that NSString is a classification method, designByOhterLinker can not find the implementation, and this method is indeed a static library inside a classification method.

Xcode other link flags detailed explanation
Snip20170613_5.png

How to solve this problem?

Three Linker parameters:

  • -ObjC
  • -all_load
  • -force_load

-ObjC:

This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application it will allow), the successful creation of effective Objective-C static libraries that contain categories on existing classes.

Join this parameter, the linker will be static library in each class and classification is loaded into the final executable file, of course, this parameter will lead to the executable file is relatively large, the reason is to load additional objects more code to the executable file, but it can solve classification problems existing static library the Objec-C class contains.

The above makes it clear that -ObjC solves the classification problem of classes already in the static library. Then, what if the class is in existence with the static library, but the class is not in the static library?

Important: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -allload or -forceload flags.

It’s clear that using -all_load or -force_load can solve the problem.

The -all_load:
parameter to find the target files are loaded into the executable file, but there is a problem, if the two static libraries, use the same executable file (which is a very common problem, such as we are used to the target file name base64.o ld: duplicate symbol) will sign the conflict, so it’s not recommended.

The -force_load:
parameter with -all_load is the same, but -force_load needs to specify the path to load all the library files, so, as long as the fully loaded a library file, does not affect the remaining library files on-demand loading.

But there is also one of the most headaches, that is, when two static libraries use the same target file

Xcode other link flags detailed explanation
Snip20170613_1.png

Two of the two libMyOtherStaticLibrary.a and libMyStaticLibrary in the figure above conflict with the MyClass.o class in
, so there are two solutions at this time:

1, use -force_load to let the linker specify the target file that compiles one of the static libraries without loading a duplicate target file from another static library

Concrete practice:

Xcode other link flags detailed explanation
Snip20170613_2.png

But it has a disadvantage that if the two static library also uses the classification (basically will use it) if only let the compiler loading one static library file (-force_load), and another in the static library classification with loading to the target file. Also, the running time will lead to the collapse of the problem. But what if the two static libraries in -foce_load will have symbolic conflicts?


2, in simple terms, is to remove a static library of duplicate target files, and then packaged

Specifically:
1) using the compression tool to command ar -t to view the target files in two static library files, which conflict,
, as follows:

Xcode other link flags detailed explanation
-Snip20170613_7.png
Xcode other link flags detailed explanation
Snip20170613_6.png

Symbol conflict is clearly MyClass.o the target file, in fact do not line, anyway, when the compiler Clang compiler will have a symbolic conflict error, the error of the Xcode map is a good example, can read those object files repeated.

2) remove a duplicate target file from one of the static libraries, and then wrap it into a static library again

  • First, use the lipo command to extract one of the iOS static library files (because the static library file of iOS is a package file that combines different CPU schema static libraries).
Xcode other link flags detailed explanation
-Snip20170613_9.png

As you can see, libMyOtherStaticLibrary.a contains the static library files of armv7 and arm64 two architectures

  • The static library files of two different architectures are extracted respectively
Xcode other link flags detailed explanation
-Snip20170613_10.png
Xcode other link flags detailed explanation
-Snip20170613_11.png
  • Using the AR compression tool, the static library files of the two different schemas are eliminated from the target file in another static library file that is in conflict.
Xcode other link flags detailed explanation
-Snip20170613_12.png

From the above command, we see that the MyClass.o has been successfully removed from the static library

  • Using lipo, two static libraries of different architectures are repackaged and encapsulated into iOS static library files
Xcode other link flags detailed explanation
-Snip20170613_13.png
Xcode other link flags detailed explanation
5cac35f4-a80d-4e91-8d23-137d1d946c47.png

Then, in the libMyOtherStaticLibraryOut.a, the static library is re placed into the project to replace the original libMyOtherStaticLibrary.a

Other linker flags just needs -ObjC

Compile, Successful,
running, perfect!