博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Xcode Static Library Subprojects and Submodules[2]
阅读量:7298 次
发布时间:2019-06-30

本文共 8752 字,大约阅读时间需要 29 分钟。

hot3.png

Using the subproject

Well, that’s us with a nice static library set up, we’re home and dry, right? Well, not quite - we’re still not using it. As with setting it up, it’s fairlysimple in Xcode 4, but it does take a few steps.

Create an app superproject

First, we create a new single-view app, called, imaginatively again, SampleSuperproject. We’ll set this app’s project up to refer to our SampleSubproject, building and linking the library from it into the SampleSuperproject app when the app is built. When it’s run, it’ll use some of the SampleSubproject library’s wonderful helloing functionality.

Choose A Template For Your New Project sheet with Single View Application selected and highlighted

Clone the static library into the app superproject’s directory tree

After creating the SampleSuperproject, we need to get the SampleSubproject ‘into’ it somehow. I use Git submodules to do this, but as I mentioned, you could use e.g. Subversion externals or whatever your version control system’s similar alternative is. If you’re not using Git, skip on to .

To include the submodule, make sure your SampleSuperproject is a Git repository (mine already is, since I let Xcode create one for me). We’re going to have to drop down to the terminal to get the submodule into place. Commands I typed are in bold:

lappy8086:SampleSuperproject jamie$ cd SampleSuperprojectlappy8086:SampleSuperproject jamie$ git submodule add git://github.com/th-in-gs/SampleSubproject.gitCloning into 'SampleSubproject'...remote: Counting objects: 21, done.remote: Compressing objects: 100% (14/14), done.remote: Total 21 (delta 6), reused 21 (delta 6)Receiving objects: 100% (21/21), 4.15 KiB, done.Resolving deltas: 100% (6/6), done.

And with that the subproject is set up in the filesystem. Git submodules are slightly strange beasts - the submodule is treated like a single file in the superproject by Git; when you commit it, you commit a reference to a specific version of the subproject. In the filesystem though, the submodule is fully checked out for you to use. If you’re going to be using a subproject from a Git submodule like this, I highly recommend you read up on Git submodules before you do it in earnest, because, like everything with Git, they’re not entirely intuitive. Pro Git has a , as does the official  - although I do think that the official examples are rather complex for an introduction. Anyway, for the purposes of this article, let’s assume we now have a copy of the subproject in a directory inside the superproject’s directory.

Add the static library’s .xcodeproj to the app’s project

Getting the subproject into the superproject’s Xcode project is easy. Just find the SampleSubproject.xcodeproj from the subproject folder in Finder, and drag it into Xcode’s Navigator tree. Alternatively, add it with Xcode’s Add Files File menu item (make sure to add theSampleSubproject.xcodeproj file only, not the entire directory).

After you’ve added the subproject, it’ll appear below the main project in Xcode’s Navigator tree:

Xcode window showing SampleSupreproect project with the SampleSubproject subproject highlighted in the Navigator

Configure the app target to build the static library target

Now, we need to get the SampleSuperproject to build and link to the SampleSubproject library.

First, in the SampleSuperproject app’s target settings, find the Build Phases section. This is where we’ll configure the SampleSuperproject target to automatically build and link to the SampleSubproject library.

Xcode window showing SampleSuperbroject's build phases

Once you’ve found that, open the Target Dependencies block and click the ‘+’ button. In the hierarchy presented to you, the SampleSubprojecttarget from the SampleSubproject project should be listed. Select it and click Add.

Adding a target dependency to the SampleSuperproject target

Configure the app target to link to the static library target

Next, we need to set the app to link to the library when it’s built - just like you would a system framework you wanted to use. Open the Link Binary With Libraries section a bit below the Target Dependencies section, and hit ‘+’ in there too. At the top of the list should be thelibSampleSubproject.a static library that the SampleSubproject target produces. Choose it and hit add.

Adding libSampleSubproject.a to the SampleSuperproject target

Lastly, because we’re using Objective-C, we’ll have to add a couple of linker flags to the SampleSuperproject app’s target to ensure that ObjC static libraries like ours are linked correctly. In the SampleSuperproject target’s Build Settings, find the Other Linker Flags line, and add -ObjC and -all_load. I won’t go in to what makes these extra flags necessary technically here, I’ll just say that if you don’t want at the very least strange runtime errors when you try to use categories defined in static libraries, you’ll need them.

Setting the linker flags on the SampleSuperproject target

We’re almost done! If you hit build now, you’ll see that the SampleSubproject library is built before SampleSuperproject app, and they’re linked together. We haven’t actually used any functionality yet though. In order to do this, there’s one more setting to change - we need to be able to find our library’s public headers. Now, there are some sources on the web that will tell you that Xcode 4 will find these automatically, but I’ve never found that to be true.

Configure the app target to use the static library’s headers when building

Again in the SampleSuperproject target’s Build Settings, find the Header Search Paths line this time, and add two settings:"$(TARGET_BUILD_DIR)/usr/local/lib/include" and "$(OBJROOT)/UninstalledProducts/include". Make sure to include the quotes here - they’re necessary if you have any directories with names containing spaces in your file hierarchy (and make sure they’re regular ‘straight’ quotes, not the fancy things Habari will surely turn them into in this post). Why two paths? The first is the ‘normal’ path, where Xcode puts the headers during a normal build. The second is necessary to make builds specifically triggered by the Archive item in the Project menu work. I’m not sure why Xcode’s internal build procedure seems to vary based on whether you’re doing an Archive build or not - to be honest, it feels like a build system bug to me. If anyone knows, I’d love to hear more about it in the comments.

Setting the Header Search Paths on the SampleSuperproject target

Use the static library in the app

Thats it for the settings! Now, in files compiled by the app target, you can just #import <SampleSubproject/SampleSubproject.h> and use functionality from the library, just as you would from a system framework. In our contrived example, we can call [[[SSHelloer alloc] init] hello]; and get our string back:

Calling [[[SSHelloer alloc] init] hello];

Rather than walk through changing the project to do this, I’ll assume that you already know how do do things like make labels in Interface Builder and set up a simple UI. If you want to run the sample app, it’s also . Remember, it uses Git submodules to include the static library subproject - you need to remember that when cloning it and make sure to also initialise and update the submodules (you did read those Git submodule references I mentioned earlier, right?), like this:

lappy8086:tmp jamie$ git clone git://github.com/th-in-gs/SampleSuperproject.gitCloning into 'SampleSuperproject'...remote: Counting objects: 36, done.remote: Compressing objects: 100% (21/21), done.remote: Total 36 (delta 13), reused 36 (delta 13)Receiving objects: 100% (36/36), 9.91 KiB, done.Resolving deltas: 100% (13/13), done.lappy8086:tmp jamie$ cd SampleSuperproject/lappy8086:SampleSuperproject jamie$ git submodule initSubmodule 'SampleSubproject' (git://github.com/th-in-gs/SampleSubproject.git) registered for path 'SampleSubproject'lappy8086:SampleSuperproject jamie$ git submodule updateCloning into 'SampleSubproject'...remote: Counting objects: 25, done.remote: Compressing objects: 100% (17/17), done.remote: Total 25 (delta 7), reused 25 (delta 7)Receiving objects: 100% (25/25), 4.84 KiB, done.Resolving deltas: 100% (7/7), done.Submodule path 'SampleSubproject': checked out '8a6ac6af716213b91a3714ce7d6039e121b4b610'

And here’s how it looks:

Calling [[[SSHelloer alloc] init] hello];

Recapping

The steps again, in order:

Of course, in reality, you wouldn’t perform these steps in this order. Perhaps you already have app projects, and want to create the subproject to factor out some common code. Or perhaps there’s a library you want to use already that you just need to reconfigure the project for so that you can include it in this way. Hopefully though, now that you’ve seen that it’s not all that hard to get working, you’ll be able to start using library submodules and reap the code-sharing benefits.

I’d love to see more open source projects having static library targets that are set up in the way described above. That way, they’d be ready for app projects to just use directly as submodules without having to keep special, slightly forked, versions of the projects - or worse, but sadly common, including the code directly.

In case you missed the links, here’s the  on GitHub, along with the , referencing the subproject as a submodule.

转载于:https://my.oschina.net/w11h22j33/blog/204443

你可能感兴趣的文章
Spring study notes
查看>>
梯度下降取负梯度的简单证明,挺有意思的mark一下
查看>>
未解决
查看>>
php课程 4-15 数组遍历、超全局数组、表单提交数据(多看学习视频)
查看>>
php实现简单的学生管理系统
查看>>
编程学习资源
查看>>
Android之Handler的postDelayed()方法的用法
查看>>
企业架构研究总结(1)——参考资料列表
查看>>
Vim中自动在程序起始处添加版权和作者信息
查看>>
Linux_LDAP+NFS+autofs
查看>>
读名老中医之路笔记(一)岳美中:无恒难以做医生
查看>>
win7win8一键取得超级管理员权限
查看>>
XML案例(使用JAXP进行DOM解析)
查看>>
Spring MVC 使用MultipartResolver与Commons FileUpload传输文件
查看>>
课堂作业——寻找发帖水王
查看>>
【BZOJ 1084】 [SCOI2005]最大子矩阵(DP)
查看>>
联合文件系统 unionfs
查看>>
【计算几何】【极角序】【前缀和】bzoj1132 [POI2008]Tro
查看>>
【2-sat】Gym - 101201F - Illumination
查看>>
【构造】Codeforces Round #480 (Div. 2) B. Marlin
查看>>