`
反求诸己
  • 浏览: 543396 次
  • 性别: Icon_minigender_1
  • 来自: 湖南娄底
社区版块
存档分类
最新评论

How to create static library

 
阅读更多

原文地址:

http://www.amateurinmotion.com/articles/2009/02/08/creating-a-static-library-for-iphone.html

 

Apple iPhone Developer agreement forbids using Frameworks in iPhone applications. The main reasons Apple does not allow using them is performance considerations and that developer-private frameworks won’t be reused in memory between iPhone applications anyway. But this doesn’t prohibit 3rd party iPhone developers to create static libraries for reusable code and possibly even distribute them for other developers while not providing source-code.

In this blog post I’ll try to describe the process of:

  • creating a static library for iPhone OS platform in Xcode
  • setting static library project as “Direct Dependency” for dependent project’s Target
  • including static library public (and only public) headers in dependent project’s “Header Search Path”
  • linking against created static library in another iPhone targeted application

Nearly everything in the following applies to Mac OS X static libraries and projects too. I’ll indicated the differences.

Create a static library

Although Xcode doesn’t have iPhone OS Static Library template as it do for Mac OS X, we can use Static Library → Cocoa Static Library template and switch SDK for it or we can create iPhone application project based on iPhone OS → Window-Based Application template and then create new iPhone OS Static Library Target what Xcode has for iPhone projects.

I’ve chosen to use iPhone OS template because created for us iPhone app Target will come in handy anyway, for example as a demo project or for some real-world testing of static library.

So, let’s create a project what a bit later will be the home of our new static library. I’ll name it “LibDemo”.

Select File → New Project… → iPhone OS → Window-Based Application.

static/1.png

Next, let’s create a Static Library Target. Right click on Targets,
Add → New Target… → Cocoa Touch → Static Library

static/2.png

I’ll name the Target “libDemo” (with lower “l”).

Now we have two Targets:

static/3.png

and two Products:

static/4.png

  • LibDemo.app
  • liblibDemo.a

liblibDemo.a certainly doesn’t sound right but it’s easy to fix. Xcode names Products based on Target setting “Product Name”, so let’s go and change it.

Right click on libDemo Target, select “Get Info”, click on “Build” tab. Search for “Product Name” and be shure to use “All Configurations” configuration. Set Product name to “Demo”, Xcode adds standard static library lib prefix:

static/5.png

Fine, now we have following Products:

  • LibDemo.app
  • libDemo.a

Next we can create some dummy class what will be compiled in our static library and what we will use in dependent project.

Create a class for libDemo

I’ll create AMZeeba class with header file what will expose -greet method.

Select File → New File… → Cocoa Touch Classes → NSObject subclass

This class should be compiled in libDemo so select both LibDemo and libDemo Targets.

static/6.png

Static library headers

Fine, now we have a class with a header and in dependent project (depending on setup) we have the choice of using all static library headers or just subset of them what we declare as “public” here (like when creating Frameworks).

I’ve chosen to use only public headers so I can be sure I’m not using anything I consider private from static library. So, if I’m distributing static library in binary form with public headers only I can be confident I haven’t anything forgotten to add to them.

To declare header public, we need to set it’s Role to “public”. Select Targets → libDemo and set “public” as Role for AMZeeba.h:

static/7.png

..and build our library.

Built static library

Xcode creates the following structure in librarie’s build folder:

ampatspell:~/Cocoa/static/LibDemo/build/Debug-iphonesimulator$ tree
.
|-- libDemo.a
`-- usr
    `-- local
        `-- include
            `-- AMZeeba.h

And while we’re here, let’s look at library symbol table:

ampatspell:~/Cocoa/static/LibDemo/build/Debug-iphonesimulator$ nm libDemo.a

libDemo.a(AMZeeba.o):
00000042 t -[AMZeeba greet]
00000000 t -[AMZeeba init]
00000000 A .objc_class_name_AMZeeba
         U .objc_class_name_NSObject
         U ___CFConstantStringClassReference
         U _objc_msgSendSuper

As we can see, the public headers are copied to usr/local/include and libDemo.a actually has AMZeeba class (.objc_class_name_AMZeeba ) and methods (symbols) defined.

Everything looks fine, we can continue with libDemo.a client.

libDemo Client Application

In general there are (at least) two ways how to include code from static library project in dependent application. The simplest is just dragging headers and implementation files to dependent project and adding them to desired Target. Other way is actually to link against static library and it’s preferred way from code organisation point of view.

I’ll start with linking and then, in next section, briefly describe “dragging way” with it’s benefits and drawbacks.

Before we start setting-up linking against our static library, we need to create “Client” iPhone project.

Select File → New Project… → iPhone OS → Application → Window-Based Application

I’ll name this project “Client”. Build & Run. We should see blank, white window background in iPhone Simulator or on actual device.

Linking against static library

To link against a static library while continuing to work with both dependent application and static library we need to:

  • Add a cross-project reference to static library in dependent project
  • Add project to dependent project Target
  • Add static library Product to “Link Binary With Libraries” Build Phase
  • Set static library project as direct dependency to dependent project’s Target
  • Add custom “Header Search Path” to point to static library build output folder

Quite a list of tasks to create this setup but fortunately it’s easy to do. We will start with first.

Cross-Project Reference

We need to start with a cross-project reference to static library project. This is Xcode specific feature what allows us to use Products and set build dependencies between projects.

Drag blue LibDemo project icon from “Groups & Files” and drop it inside Client project. Check “Client” in “Add To Targets” table, do not check “Copy items into destination group’s folder” in the sheet what will appear:

static/8.png

Press Add, the result should look like this:

static/9.png

As you can see, there’s LibDemo.xcodeproj reference what lists two Products — libDemo.a and LibDemo.app. We’re not interested in LibDemo.app what eventually will be just a demo of libDemo.a functionality (or just disappear). But libDemo.a is the product we will use by linking against it.

Link binary, Direct dependency

To link binary with a static library we need to add it to “Linked Libraries” list for binary Target.

Unfold LibDemo.xcodeproj and Targets → Client → Link Binary With Libraries. Drag libDemo.a to Link build phase.

static/10.png

Now we’re linking Client binary against our staric library but it doesn’t mean the library is automatically rebuilt if we make changes in it’s code. To inform Xcode we want to keep library up-to-date and link against newest version in this Target, we need to set library as direct dependency for Target.

To set libDemo library Target as dependency for Client Target, right click on Client Target, select Get Info then click on General tab. Click add button under Direct Dependencies list, select libDemo.

static/11.png

As you can see, this panel consists of two parts:

  • Direct Dependencies
  • Linked Libraries

Actually we could use Add button under Linked Libraries to link against libDemo.a as we could just drag dependent Target under Target we want it depend to. Just two ways of doing it, both yields the same result.

To make sure our direct dependency setting works, let’s clean both projects then build only Client. This should trigger building of libDemo.a too.

Select Build → Clean (⇧⌘K ) and click “Also Clean Dependencies”

Select Build → Build (⌘B ) and Build → Build Results (⇧⌘B )

We should see that two Targets are built successfully:

static/12.png

But before we can start actually using library, we need to tell Xcode where to find library headers.

Public Headers

First I want to show the problem. Let’s add #import "AMZeeba.h" in ClientAppDelegate.m , build and examine build results:

static/13.png

Of course, Client’s app project has no idea where to look for AMZeeba.h 1 .

External headers in Xcode are searched using “Header Search Path” (and “User Header Search Path”) build variables. We need to add libDemo.a public header location to it.

Open “Client” Target info panel (Select Targets → Client and press ⌘I ), type “header search” in search field under “Build” tab.

static/14.png

Double-click on “Header Search Path” and add:

${PROJECT_DIR}/../libDemo/build/${BUILD_STYLE}-${PLATFORM_NAME}/usr/local/include

The variables are:

PROJECT_DIR Client project’s root directory
BUILD_STYLE Debug or Release
PLATFORM_NAME iphonesimulator or iphoneos

Note: For Mac OS X Static libraries the search path value is:

${PROJECT_DIR}/../libDemo/build/${BUILD_STYLE}/usr/local/include

Grand finale

Now we can build Client and it should find AMZeeba.h .

static/15.png

…and this is the result we where looking for.

Download LibDemo & Client (36Kb)

Dragging thing

Creating a static library is not the only way how to create reusable code “bundles” for iPhone and for Cocoa development in general. On Mac OS X the preferred way is creating Frameworks but this is not an option for iPhone but there’s third way — dragging and dropping group of files from one project into another and adding them to desired Targets. This way we’re cross-project referencing source code. This has some benefits and drawbacks.

The benefit is simpler setup — we don’t need to create a static library Target, no header search pathes to set.

The drawbacks to name a few are:

  • when Group is cross-project referenced it’s contents are not automatically updated. So if we create a new header or class, this addition needs to be added to dependent project manually
  • library content is a part of dependent project’s source tree — no control over cleaning and rebuilding library versus dependent project.

In conclusion I must mention that it’s possible to mix static library approach with code cross-project references. It may be beneficial to start with static library by using drag-and-drop referencing and when library grows or there’s need to distribute static library in binary form, switch to static linking.

分享到:
评论

相关推荐

    How to create your library

    本篇文章将详细介绍如何创建一个Windows 32位静态C库(Win32 Static C Library)。这不仅有助于提高代码的可维护性和可重用性,还能帮助开发者更好地管理项目中的各个模块。 #### 创建静态库类型 首先,我们需要...

    Program Library Howto

    This HOWTO for programmers discusses how to create and use program libraries on Linux. This includes static libraries, shared libraries, and dynamically loaded libraries.

    QGIS Python Programming Cookbook

    Build a library of reusable scripts with ScriptRunner Create, import, and edit geospatial data on disk or in memory Get to know more about dynamic mapping Create and add features to static maps ...

    OPC UA 客户端 服务器 标准库源码

    How to create self signed certificates for the sample applications On Windows 1. Open a command prompt in the root folder of your repository 2. Run the script CreateAllCerts.cmd in the root folder of ...

    Python 2.6 Graphics Cookbook.pdf

    Chapter 10, GUI Construction: Part 1: This chapter provides basic examples of how to create buttons, data entry boxes, drop-down menus, list-boxes, and text labels. It also covers how to customize ...

    Django.Unleashed.0321985079.epub

    Define how your data is organized and create a SQLite database to manage it Quickly produce HTML with Django templates Create dynamic webpages with Django’s URL patterns and views, including function...

    Dart in Action

    The book explains how to define and use libraries, as well as the privacy rules that govern access to library members. - **Classes and Interfaces**: Dart's object-oriented features are explored in ...

    C Programming

    - **Defining Your Own Types**: Explanation of how to create custom data types using `typedef`. #### Files The document explains file handling in C, which involves reading from and writing to files: ...

    Python for data analysis

    features, Get started with data analysis tools in the pandas library, Use high-performance tools to load, clean, transform, merge, and reshape data, Create scatter plots and static or interactive ...

    Python for Data Analysis

    features, Get started with data analysis tools in the pandas library, Use high-performance tools to load, clean, transform, merge, and reshape data, Create scatter plots and static or interactive ...

    sqlite3在Visual studio 2012下的编译

    Under "Code Generation" for "Runtime Library" make sure to pick static linking. /MTd (release) or /MTd (debug) Make a .DEF file A .def file should be placed in the project directory. Get the def ...

    Java邮件开发Fundamentals of the JavaMail API

    You use the package to create Mail User Agent (MUA) type programs, similar to Eudora, pine, and Microsoft Outlook. The API's main purpose is not for transporting, delivering, and forwarding ...

    Python4DelphiPart-1-7139726.pdf

    - **Access to Python Libraries**: Delphi developers can tap into Python’s vast library ecosystem to enhance their applications with advanced features. - **Using Python as a Scripting Language**: ...

    CSharp 3.0 With the .NET Framework 3.5 Unleashed(english)

    - **Instance and Static Members**: Instance members belong to each instance of a class, while static members are shared among all instances. - **Fields**: Fields store data in objects. - **Methods**: ...

    android-viewflow

    if instead you have a static numbers of views you ought to look at Fragments and the ViewPager in the Compatibility Library instead. Usage In your layout android:id="@+id/viewflow" app:...

    Packt.Mastering.Csharp.and.NET.Programming

    - **Creating Custom Generic Types and Methods**: Shows how to create generic classes and methods. - **Lambda Expressions and Anonymous Types**: - **Lambda Expressions**: Concise way to define ...

    Turbo C 2.00[DISK]

    static variable or a variable that is local to a static function. o Because of the limited memory available in the Tiny model, it no longer supports graphics functions. o The Version 1.5 ...

    ElementsBrowserCreator

    After searching and browsing through the elements of an application, users can select useful elements to create automation classes and test cases. This feature streamlines the automation process, ...

Global site tag (gtag.js) - Google Analytics