I have created two separate static libraries in Xcode for usage on iOS, A and B. A uses methods that are defined in B.
When creating a new Xcode project where both A and B are needed, I can include them separately. However, for simplicity of integration I prefer to create a Universal Framework that contains both A and B.
Is it possible in Xcode to merge 2 static libraries into 1, without merging the code of the 2 libraries in 1 project. In other words. Can I somehow link the compiled static library B into static library A when I am compiling/Linking static library A?
If this is possible, how can I accomplish this?
I've just run some quick tests and it seems to be happening automatically. This is what I did:
<LibX/Header.h>
.After this basic setup, I imported classes from B to A with something similar to <LibB/Header.h>
and wrote some code that actually made use of B. Then, I imported A and B to the main project with <LibA/Header.h>
and <LibB/Header.h>
and wrote code that made use of A and B. Finally, I went to the DerivedData folder with the terminal and navigated to the location where A is built. I checked if LibA.a contains objects from LibB with:
nm LibA.a
And yes, it contains objects from LibB. So, to sum up, with this simple dependency setup you should be able to get what you asked for.
EDIT To make B direct dependency of A and link A against B do this:
Having A open in the XCode, go to Finder and drag&drop B project file into A. Then, choose the root element in A, go to Build Phases, expand Target Dependencies, press '+' button, choose B and confirm. then expand Link Binary With Libraries, press '+' button, choose B.a (or whatever the product name is) and confirm.
Important There is a bug in XCode that prevents you from properly dropping B project file into A workspace. Instead, you are left with B project file in A workspace, but you cannot expand B and do anything with it. To work around this problem, remove the faulty B project file reference from A, close A, close B if you have it open. Then reopen A and use Finder to navigate to B project file, then drag&drop B inside A workspace. If didn't work, repeat.
EDIT2 I case you don't have access to the sources of B (and possibly A), making this work is just a matter of copying the required headers in the proper place. Then in you main project, you don't make the A direct dependency, instead you link against static libA.a that you have. If A uses B, then the symbols from B are already in the libA.a. You can check this with nm tool like I do above. So we are down to exposing those symbols to the main application with B headers. There are a couple of ways to do it, I remember that I simply copied the headers to the Copy Headers destination path of the library that is in the middle of the dependency chain. After that, by linking against A and adding A headers to User Header Search Paths I was able to access B directly. What is the best way to do it for you depends on if you have access to the sources of A. If you have, there are two options to consider:
In both cases, you end up with LibA.a which holds compiled sources of A and B, and the headers folder which holds headers from A and B. You can then link your main project agains LibA.a and add the headers folder path to the User Headers Search Path in you main project, and you should be good to go.
Important
If, in your libraries, you have files that hold only category code in them, make sure to link this library with -force_load, or your category symbols will not be packed properly.
I've done it with libtool, as per this answer.
To do so, in Xcode 5.0.2, I've added a script to A (Editor -> Add Build Phase -> Add Run Script Build Phase
) that
figures out the architecture for which A is being built:
LIPO_ARCH=$(lipo -info ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} | awk 'END{ print $NF }')
creates a thin version of B, with only the architecture being built
lipo -thin ${LIPO_ARCH} ${FULLPATH_OF_B} -output ${FULLPATH_OF_THIN_B}
joins A and B into a new A
mv ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} ${FULLPATH_OF_THIN_A}
libtool -static -o ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} ${FULLPATH_OF_THIN_A} ${FULLPATH_OF_THIN_B}
removes the temp files
rm ${FULLPATH_OF_THIN_A}
rm ${FULLPATH_OF_THIN_B}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With