IOS

From Crypto++ Wiki

Jump to: navigation, search

iOS is Apple's mobile operating system and used by the iPhone, iPad, and iTouch. Apple's mobile devices are popular in many markets, and this wiki article will demonstrate building the Crypto++ library for iOS 4.2 using Xcode 3.2.5 and GCC 4.2. Though iOS supplies and uses dynamic libraries (*.dynlib), developers can only build a static library on iOS. If you are interested in a dynamic library for MAC OS X, please see Uri's mailing list post at Minor patch to compile shared lib on Mac OS X.

Xcode is Apple's free development environment. Apple's mobile development framework is Cocoa Touch and language of choice is Objective-C 2.0. Cocoa Touch is Apple's equivalent of frameworks such as QT and MFC. While Cocoa and Objective C can be a surprise for GUI programmers with a background in MFC, QT, or GTK++, the language causes no hardships for the Crypto++ library.

iOS targets the ARM processor (v6, v7, and v7s), so Crypto++'s CRYPTOPP_DISABLE_ASM and CRYPTOPP_DISABLE_SSE2 should be defined. The macros can be defined in the Xcode environment or the Crypto++ library's config.h. This article will define the macros in the environment (see Project Build Settings).

Xcode currently uses GCC 4.2 as its default compiler. Future versions of Xcode will probably be frozen at GCC 4.2, and may drop GCC support and only offer the LLVM compiler. Check the GCC Mailing List for information on the politics in motion (Apple, iPhone, and GPLv3 troubles and http://www.google.com/#q=apple+gcc+gplv3+site:gnu.org). On Xcode 4.5.2 compilation with optimization appears to break parts of the library. An unoptimized build was usable, however.

Finally, Dr. Ugo Chirico offers an iPhone port of Crypto++ 5.5.2 at www.ugosweb.com/cryptopp.aspx. In addition, a GitHub project script is available here . Note, however, that this will not compile under Xcode 4.5.2.

Contents

Fetch the Crypto++ Library

Download Crypto++ from the website, or fetch the library from Sourceforge. Below, a terminal was used and the project was retrieved from Sourceforge. A terminal can be found from the Dock Bar in Applications → Utilities.

$ svn checkout https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp
A    cryptopp/winpipes.cpp
A    cryptopp/safer.cpp
A    cryptopp/adler32.h
...
A    cryptopp/dlltest.vcproj
A    cryptopp/rijndael.h
 U   cryptopp
Checked out revision 521.

Cocoa Touch Static Library

Figure 1: Xcode Cocoa Touch Library
Figure 2: Cocoa Touch Library Project

In Xcode, select a new Cocoa Touch Static Library as shown in Figure 1. When prompted, name the project cryptopp.

The project files should look similar to Figure 2. By Xcode convention, Objective-C class files are added to the Classes folder, and non-Objective-C files are added to Other Sources. In Figure 2, two folders were added under Other Sources: Header Files and Source Files. Crypto++ header and source files will be added to the new folders below.

Note that libcryptopp.a is in red under the Products group since the library is not yet built - Xcode deems the library missing.

Move Sources into Project

Xcode-3.png
Move the Crypto++ directory into the Xcode project directory. Below, a terminal was used to perform the move.
$ ls
Desktop		Downloads	Movies		Pictures	Sites
Documents	Library		Music		Public		cryptopp
$ mv cryptopp/ Documents/cryptopp/
$ ls Documents/cryptopp/
build			cryptopp.xcodeproj
cryptopp		cryptopp_Prefix.pch

Add the Crypto++ header files to the Header Files folder, and the source files to the Source Files folder. There is no need to check 'Copy items into destination group's folder.' adhoc.cpp.proto or dlltest.cpp can also be removed since the files are used on Windows. In addition, source files such as datatest.cpp, regtest.cpp and validat{1|2|3}.cpp are not needed.

Figure 4: Add Crypto++ files to Project

For those who did not copy the Crypto++ sources into the project's directory, please take some time to research Xcode paths and xconfig files. See Build Configurations in the Xcode Build System Guide and Working with the Xcode Build Settings.

Project Build Settings

With cryptopp highlighted under Groups & Files (the left tree view in Figure 5), click the large blue info button to bring up the project's build settings.

Figure 5: Crypto++ Xcode Project
Figure 6: Crypto++ Xcode Build Settings

Ensure All Configurations is selected as shown in Figure 6. Add CRYPTOPP_DISABLE_ASM and CRYPTOPP_DISABLE_SSE2 to Preprocessor Macros as shown in Figure 7 below. Xcode does not appear to reliably define DEBUG and NDEBUG, so take time to define the symbols also. See GCC_PREPROCESSOR_DEFINITIONS at Xcode Build Setting Reference.


Figure 7: Preprocessor Macros Build Settings

For completeness, the iPhone simulator runs locally using a 32 bit i386 binary, and not an x86_64 binary. Disabling assembly instructions and SSE2 for all available targets keeps things simple.

Another setting which is useful, but not required, is -Wall -Wno-unused -Wno-unknown-pragmas under GCC 4.2 Warnings, Other Warning Flags. Be careful of -Wextra since GCC 4.2 will flag signed/unsigned comparisons due to C++ templates. -Wno-type-limits will suppress the spurious template warnings, but the option is only available in GCC 4.3 and above. See Missing "warning: comparison is always false due to limited range of data type".

config.h

config.h needs to be modified as follows. Scroll down near line 300 and define CRYPTOPP_BOOL_ALIGN16_ENABLED to 0. Using __IPHONE_OS_VERSION_MIN_REQUIRED offers more granularity than __APPLE__. See Apple Preprocessor Macros below.

#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
	#define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
#else
	#define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
#endif

#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) || defined(PRODUCT_iPhone)
# undef CRYPTOPP_BOOL_ALIGN16_ENABLED
# define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
#endif

Build the Library

After building, libcryptopp.a will be displayed in black instead of red since the library is available (contrast to Figure 2).

Figure 9: Successful build of the library
Figure 10: Library Dependencies and Linked Libraries

After building the Crypto++ library, the libcryptopp.a can be added as a Direct Dependency of an executable (meaning the executable is dependent upon the library), and then as a Linked Library (meaning the executable will link against the library). See Figure 10.

Precompiled Headers

Xcode precompiled header
Xcode includes extensive support for precompiled headers. Precompiled header support was added when the Crypto++ library project was created by Xcode.

To take advantage of Xcode's precompiled headers, add Crypto++'s pch.h to Xcode's cryptoppp_Prefix.pch. Then define Crypto++'s USE_PRECOMPILED_HEADERS under Xcode's Preprocessor Macros build settings. Crypto++'s pch.h will pick up the USE_PRECOMPILED_HEADERS define and include additional headers for precompilation.

Preprocessor Macros

Xcode offers three defines of interest for those who are mindful of cross platform source code. __APPLE__ will defined on the platform, and __OBJC__ will be defined when Objective C is available. When using a BSD based kernel, __MACH__ will also be defined. In addition, __IPHONE_OS_VERSION_MIN_REQUIRED is available on both iPhone and iPad when inspecting the Xcode 3.2.5 command line.

cdefs.h includes a few interesting symbols: PRODUCT_AppleTV, PRODUCT_iPhone, PRODUCT_MacOSX. Unfortunately, PRODUCT_iPhone seems to be elusive and probably should not be relied upon.

In addition, Apple offers a number of predifined macros in Availability.h, such as __MAC_10_0, __MAC_10_6, __IPHONE_2_0, and __IPHONE_3_0. Apple discusses conditional compilation at Conditionally Compiling for Different SDKs. The following was taken from Availability.h:

It is also possible to use the *_VERSION_MIN_REQUIRED in source code to make one
source base that can be compiled to target a range of OS versions.  It is best
to not use the _MAC_* and __IPHONE_* macros for comparisons, but rather their values.
That is because you might get compiled on an old OS that does not define a later
OS version macro, and in the C preprocessor undefined values evaluate to zero
in expresssions, which could cause the #if expression to evaluate in an unexpected way.
    
 #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
    // code only compiled when targeting Mac OS X and not iPhone
    // note use of 1050 instead of __MAC_10_5
    #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050
        // code in here might run on pre-Leopard OS
    #else
        // code here can assume Leopard or later
    #endif
 #endif

Xcode Environment

After building the project, expanding a compile results in the following for the Build Results window. The command line below is for integer.cpp, but is representative of all Crypto++ source files. Formatting was applied to two commands to reduce horizontal scrolling.

CompileC build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/Objects-normal/i386/integer.o cryptopp-r521/integer.cpp ↵
    normal i386 c++ com.apple.compilers.gcc.4_2
cd /Users/jeffrey/Documents/cryptopp
setenv LANG en_US.US-ASCII
setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe ↵
    -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable ↵
    -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.2.sdk -fexceptions -mfix-and-continue ↵
    -mmacosx-version-min=10.6 -gdwarf-2 -D__IPHONE_OS_VERSION_MIN_REQUIRED=40200 ↵
    -iquote /Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/cryptopp-generated-files.hmap ↵
    -I/Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/cryptopp-own-target-headers.hmap ↵
    -I/Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/cryptopp-all-target-headers.hma ↵
    -iquote /Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/cryptopp-project-headers.hmap ↵
    -F/Users/jeffrey/Documents/cryptopp/build/Debug-iphonesimulator -I/Users/jeffrey/Documents/cryptopp/build/Debug-iphonesimulator/include ↵
    -I/Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/DerivedSources/i386 ↵
    -I/Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/DerivedSources ↵
    -include /var/folders/dC/dCfs8ij4HeWN-ZqbDcAWyU+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/ ↵
        cryptopp_Prefix-glftuiuqopisxmehyamygkzfneex/cryptopp_Prefix.pch ↵
    -c /Users/jeffrey/Documents/cryptopp/cryptopp-r521/integer.cpp ↵
    -o /Users/jeffrey/Documents/cryptopp/build/cryptopp.build/Debug-iphonesimulator/cryptopp.build/Objects-normal/i386/integer.o

In addition to the environment's settings, iOS has predefined macros available. To determine the predefined vendor macros in play, first locate cpp:

$ find /Developer/ -wholename "*/cpp"
Xcode run script
Next, create a Run Script which runs as a pre-build step using the iOS version of cpp.
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cpp -dM < /dev/null | sort

Results will be similar to below. We see that at least two addition macros of interest exist for the platform: __APPLE_CC__ and OBJEC_NEW_PROPERTIES.

Figure 11: cpp output for the iOS preprocessor

Build Warnings and Errors

If you receive four errors with a message similar to, Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1, you probably did not add CRYPTOPP_DISABLE_ASM and CRYPTOPP_DISABLE_SSE2 to all configurations under Preprocessor Macros.

Expanding the compiler output in the Build Results windows will show similar to the following.

/Users/jeffrey/Documents/cryptopp/cryptopp-r521/integer.cpp:4232:   instantiated from here
/Users/jeffrey/Documents/cryptopp/cryptopp-r521/algparam.h:322: warning: unused variable 'p'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
{standard input}:13639:suffix or operands invalid for `call'
...
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1

If you receive a number of errors which culminate in Symbol(s) not found, ensure Crypto++ is a linked library (see Build the Library), or add -lcryptopp to Other Linker Flags under the executable's Build Settings.

Error: "CryptoPP::BufferedTransformation::ChannelCreatePutSpace(std::basic_string<char, std::char_traits<char>, ↵
          std::allocator<char> > const&, unsigned long&)", referenced from:
      vtable for CryptoPP::Bufferless<CryptoPP::Sink>in cryptotest.o
      vtable for CryptoPP::Sinkin cryptotest.o
      vtable for CryptoPP::StringSourcein cryptotest.o
      vtable for CryptoPP::SourceTemplate<CryptoPP::StringStore>in cryptotest.o
      vtable for CryptoPP::AutoSignaling<CryptoPP::InputRejecting<CryptoPP::BufferedTransformation> >in cryptotest.o
      vtable for CryptoPP::InputRejecting<CryptoPP::BufferedTransformation>in cryptotest.o
      vtable for CryptoPP::InputRejecting<CryptoPP::Filter>in cryptotest.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Downloads

xcode-cryptopp.zip - Xcode 3.2.5 project with Crypto++ 5.6.1 (revision 521) for iOS 4.2 targets This will compile under Xcode 4.5.2 and llvm 4.1, but, with the default optimization settings AES encryption, at a minimum, will NOT function properly. Compilation with no optimization does work.

Personal tools