IOS (Xcode)

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.

Note well: The script to build the library from the command line is called setenv-ios.sh, and it was added to the library sources in March 2016. It is available in Master and library ZIP files after 5.6.3. Also see Commit a78b9dfa0840f92f, Added iOS environment and test script.

Note well: Crypto++ 5.6.4 and later added code to take advantage of NEON, CRC and Crypto extensions. You should use Crypto++ 5.6.4 or later if possible. You should also avoid -DCRYPTOPP_DISABLE_ASM for Crypto++ 5.6.4 or later. If you experience missing symbols for AlignedAllocate and AlignedDeallocate, then be sure you are using Crypto++ 5.6.4 or later. Also see Missing AlignedAllocate/AlignedDeallocate iOS/ARM64 on the mailing list.

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.

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.

$ git clone https://github.com/weidai11/cryptopp
Cloning into 'cryptopp'...
remote: Counting objects: 9116, done.
remote: Total 9116 (delta 0), reused 0 (delta 0), pack-reused 9116
Receiving objects: 100% (9116/9116), 8.05 MiB | 6.53 MiB/s, done.
Resolving deltas: 100% (6406/6406), done.
Checking connectivity... done.

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.'

You only need to add Library Sources into the project. You don't need to add test sources to the project. You can get a list of library sources using the makefile's sources target. You can use the formula "Library sources = All sources - Test sources".

$ make -f GNUmakefile-cross sources
Library sources: cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algpara
m.cpp arc4.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2.cp
p blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp 
channels.cpp cmac.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp
 eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.
cpp filters.cpp fips140.cpp fipstest.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cp
p gost.cpp gzip.cpp hex.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp keccak.cpp 
luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp n
btheory.cpp network.cpp oaep.cpp osrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cp
p pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp 
rdtables.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp seal.cpp s
eed.cpp serpent.cpp sha.cpp sha3.cpp shacal2.cpp shark.cpp sharkbox.cpp skipjack.cpp socke
tft.cpp sosemanuk.cpp square.cpp squaretb.cpp strciphr.cpp tea.cpp tftables.cpp tiger.cpp 
tigertab.cpp trdlocal.cpp ttmac.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp xt
r.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp

Test sources: adhoc.cpp test.cpp bench1.cpp bench2.cpp validat0.cpp validat1.cpp validat2.
cpp validat3.cpp datatest.cpp regtest.cpp fipsalgt.cpp dlltest.cpp
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. 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".

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.

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, then you are probably using an old version of the library. You can fix it in one of two ways. First, use Crypto++ 5.6.4 or above. Second, add CRYPTOPP_DISABLE_ASM to all configurations under Preprocessor Macros. We recommend the first option.

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

/Users/jeffrey/cryptopp/cryptopp-r521/integer.cpp:4232:   instantiated from here
/Users/jeffrey/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

setenv-ios.sh.zip - Script to set the environment for iOS cross-compiles. Added to the library at Crypto++ 5.6.3.

GNUmakefile-cross.zip - Makefile for cross-compiling the library. Added to the library at Crypto++ 5.6.3.