iOS C/C++ Static Library Sizes

There is often alarm at the size of the Chilkat static libraries (.a) for iOS. This should not be of too much concern, because after building your app in Release mode, your app’s executable will NOT grow by the size of the static library. It will only grow by a very small fraction of the total size of the .a

There are some common misunderstandings about static libraries that should be cleared up.

  1. You do NOT include the static library (.a) in the package you submit to the app store.
  2. When building your program, Xcode only pulls in the library code that is directly or indirectly used.   (This is true for any C/C++ linker.)   If, for example, Chilkat added functionality for SNMP, Jabber, and Bitcoin, and if this new code caused growth in the .a by 100MB, then it would only cause an increase in your app’s size if your app actually uses the new code.
  3. You may be unaware of the vast number of already-existing system libs (.a) and the vast sizes if all of these were summed up.  Obviously, these are not included in their entirety in your app’s executable.  The same applies to the Chilkat static libs.
  4. You can always check to see how much your app’s executable actually grows in size after linking with Chilkat by examining the size of the executable after linking.
  5. The Chilkat universal lib is composed of both the simulator static libs (x86 + x86_64), and the device libs (arm64, armv7, armv7s).   Your application built for the App Store would not be including alternatives for the simulator.
  6. This Apple Technical Q&A discusses general techniques for reducing the size of an app:  https://developer.apple.com/library/ios/qa/qa1795/_index.html

Linking “C” Programs with the Chilkat C/C++ Libs

The Chilkat C/C++ libs are (internally) written in C++.  Therefore, when linking a “C” program with the Chilkat libs, the C++ runtime libs must be included.  This is true regardless of the operating system, whether it be Windows, MAC OS X, IOS, Linux, etc.    Different build environments will have different ways of accomplishing the task.  For example, with XCode (on Mac OS X), simply adding an empty source file having a filename with the extension “.cpp” is all that is needed.  This blog post will show how to link a “C” program on Linux with the Chilkat C/C++ static library.  The solution is to use “g++” for the link phase instead of “gcc”.  The telltale indicator that the C++ runtime libs are missing is when you see errors involving “__cxxabiv1”, such as the following:

undefined reference to `vtable for __cxxabiv1::__class_type_info'

Here is a simple C program with a simple shell script to build it correctly.

buildTest.sh (This is for 64-bit Linux. Notice that g++ is used for linking, not gcc.)

#!/bin/bash -ev

gcc -m64 -Werror -c -fmessage-length=0 -fno-stack-protector -fPIC -o"cTest.o" "cTest.c"

g++ -g0 -m64 -L"/home/chilkat/workspace/chilkat/lib64_static" ./cTest.o -o"cTest"  
    -lchilkat-9.3.0 -lpthread -lresolv

cTest.c

#include <stdio.h>
#include "../chilkat/include/C_CkFtp2.h"

void testFtp2Create(void)
    {
    HCkFtp2 ftp;
    BOOL success;

    ftp = CkFtp2_Create();

    //  Any string unlocks the component for the 1st 30-days.
    success = CkFtp2_UnlockComponent(ftp,"Anything for 30-day trial");
    if (success != TRUE) {
        printf("%s\n",CkFtp2_lastErrorText(ftp));
    }

    CkFtp2_Dispose(ftp);
    }


int main(int argc, char *argv[])
{
	testFtp2Create();
	printf("Hello World!\n");
	return 0;
}

IOS / Mac OS X Link Problems involving symbols such as __ZTVN10__cxxabiv121__vmi_class_type_infoE

If linking produces undefined symbols involving the following:

  • __ZTVN10__cxxabiv121__vmi_class_type_infoE
  • __Znwm
  • __ZdlPv
  • ___gxx_personality_sj0
  • ___cxa_begin_catch
  • __ZTVN10__cxxabiv120__si_class_type_infoE
  • ___cxa_end_catch
  • __ZdaPv
  • __ZTVN10__cxxabiv117__class_type_infoE
  • etc.

It means you’re NOT linking with the C++ runtime libs.  To link with the C++ runtime libs, include an empty source file having a file extension of “.cpp”.   For more information, see the IOS Objective-C linking notes

Undefined symbol: _res_9_query

Question:

I had some IMAP code working with Chilkat iOS 9.2.1 version. Tried upgrading to 9.3.0 (wanted to use the new attachments functionality) and got the following error:

Undefined symbols for architecture i386:
“_res_9_query”, referenced from:
ChilkatResolve::mxLookup(char const*, ScoredStrings&, LogBase&, bool) in libchilkatIos.a(ChilkatResolve.o)
ChilkatResolve::dkimLookup(char const*, StringBuffer&, LogBase&, bool) in libchilkatIos.a(ChilkatResolve.o)
ChilkatResolve::bestMxLookup(char const*, StringBuffer&, LogBase&, bool) in libchilkatIos.a(ChilkatResolve.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

It is building fine for Device scheme, and only fails for Simulator scheme.
Any advice?

Answer:

Add “-lresolv” to your list of link libraries.

(A quick way to find a solution for unresolved externals such as this is to Google “Undefined symbol _res_9_query”.   

XCode Linker will automatically choose dylib over static libs

A note about building (linking) a project in XCode:

If a static lib’s corresponding dylib is in a library search path during linking, Xcode will link to the dylib instead of the static lib.

The solution is to move the dylib somewhere else.
(from a Chilkat customer) “I created chilkat-9.2.1-macosx-10.5/lib/dylib and moved the dylibs into it.  Since my library search path in the project settings is not recursive, Xcode can’t find the dylib and links to the static lib.  It’s quirky and slightly hackish but you might want to consider structuring your download the same way to prevent other Xcode users from running into the problem.”

Note: The next version of the Chilkat Objective-C libs will be structured such that the dylibs and static libs are in separate directories.  Hopefully this will prevent this pitfall (where a user *thinks* the static lib is being linked, but in fact XCode is linking against the dylib).

Common IOS undefined symbols error

Link Error:

Undefined symbols for architecture i386:

“operator new(unsigned long)”, referenced from:
-[CkoMailMan init] in libchilkatIos.a(CkoMailMan.o)
“operator delete(void*)”, referenced from:
-[CkoMailMan init] in libchilkatIos.a(CkoMailMan.o)

Solution:
The Chilkat internals are written in C++. Therefore, your Objective-C application will need to link against the C++ runtime libraries. The easiest way to do it is to include an empty source file with the file extension “cpp” in your app target.

VC++ Link problem: fatal error C1047, “Chilkat*.lib’ was created with an older compiler than other objects; rebuild old objects and libraries”

Regarding the following VC++ link problem:

“fatal error C1047: The object or library file 'c:\Chilkat\libs\x64\ChilkatRel_x64.lib' 
was created with an older compiler than other objects; rebuild old objects and libraries”

This can be resolved by building without the /LTCG flag turned on. Unfortunately, it is not possible to use the /LTCG flag if you are using the Chilkat libraries. Compiling and linking your C++ application without using the /LTCG flag should resolve the problem.

Chilkat C++ Libs – Link and Maintain Single EXE?

Question:

I am developing a single EXE in C++ that doesn’t make use of any external libraries and including MFC. Can I add your zip libaries to my application and still maintain the application as a single EXE?

Answer:

Yes, the Chilkat C++ libs may be linked directly into your application.  This results in a single EXE containing the Chilkat library code required to satisfy all direct and indirect references.  (The linker includes only the code needed to resolve all references.)  You may run your EXE on any computer because the licensing is royalty-free.  Internally, Chilkat does not use or reference MFC.   (Note: MFC applications may still use the Chilkat libs.  The point is this: if your application does not use MFC, then linking with Chilkat will not cause MFC to be “pulled-into” your EXE.)

Choosing Correct C++ Library for Linking

When linking with a Chilkat C++ library, you must choose the .lib that matches your project’s “code generation” property setting.

For example, in VC++ 8.0, these are the Chilkat .lib’s:

ChilkatDbg.lib
ChilkatDbgDll.lib
ChilkatRel.lib
ChilkatRelDll.lib

If “Dll” is in the library name, it means that you are *not* statically linking with the C runtime libs. Just because your project produces a .dll does not mean you’ll use the .lib with “DLL” in the name. The choice depends on the “code generation” project setting for each build.

I hope you can figure out the difference between “Dbg” and “Rel” without me explicitly stating it…

Here are screenshots of the VC++ 6.0, VC++ 7.0, and VC++ 8.0 code generation property pages:

ALSO: The names of the libs and the information shown here for VC++ 8.0 are identical for VC++ 9.0 and VC++ 10.0

VC++ 8.0
VC++ 8.0 Code Generation

VC++ 7.0
VC++ 7.0 Code Generation

VC++ 6.0
VC++ 6.0 Code Generation