CMake

From Crypto++ Wiki
Jump to: navigation, search

Crypto++ 5.6.3 through 5.6.5 provided some Cmake support. The three library versions can be built using CMake with some cautions. The cautions are CMake does not use the library's recommended flags and options, and it could lead to problems later, like CVE-2016-7420. The CMake support files of interest are CMakeFile.txt and cryptopp-config.cmake.

CMake supports various platforms, including Windows desktops and servers, Windows Phone, Windows Store, Linux, OS X, Android, iOS, Solaris, Unix and others. Its appealing to use CMake because it supports so many platforms, but keep in mind you are responsible for selecting the proper flags and options.

Note: CMake was removed from the library prior to the release of Crypto++ 6.0. The mailing list discussion is at Remove CMake from GitHub; add it to Patch Page on wiki?, and the check-in of interest is Commit 913a9e60d375e458.

Note: The CMake project files are now maintained by the community, and not the library. If you want to use CMake then download it from GitHub | cryptopp-cmake. It is a separate project to ensure folks don't accidentally use it. If you have an improvement, then make the change and submit a pull request.

Many thanks to the folks who contributed to the CMake task. Special thanks to GamePad64, who made early contributions and wrote the initial wiki page. Additional thanks go to Anonimal, who also provided patches.

Create a build directory

First, create a directory outside the source directory, for example /home/user/cryptopp-build, then cd into it.

$ mkdir /home/user/cryptopp-build
$ cd /home/user/cryptopp-build

This step is optional, but recommended. CMake creates out-of-source builds, so all the build artifacts are created in a separate directory, leaving the original source directory untouched. You can read more at CMake FAQ.

Select Options

The Crypto++ library can be configured to suit your particular needs. For example, it can be configured for a dbug build or a release build. To select a library configuration, use CMake options to control the library configuration. Multiple options can be selected.

To set an option, simply pass it to CMake using -D. For example, to enable a debeg configuration, perform the following.

cmake ... -DCMAKE_BUILD_TYPE=Release -DDISABLE_ASM=OFF

The table below provides CMake options to control library configurations.

Library Configuration Options
Define Values Default Comments
BUILD_TESTING ON/OFF ON Enables building the test drive program (cryptest.exe).
BUILD_DOCUMENTATION ON/OFF OFF Enables building documentation using Doxygen.
DISABLE_ASM ON/OFF OFF Disables assembler and intrinsic code. This is a fail safe option and it should not be needed. Also see the wiki page config.h | assembly defines.
DISABLE_SSSE3 ON/OFF OFF Disables SSSE3 instructions. This option is needed for some older Binutils due to downlevel assemblers. Also see the wiki page config.h | assembly defines.
DISABLE_SSE4 ON/OFF OFF Disables SSE4.1 and SSE4.2 instructions. This option is needed for some older Binutils due to downlevel assemblers. Also see the wiki page config.h | assembly defines.
DISABLE_AESNI ON/OFF OFF Disables AES-NI instructions. This option is needed for some older Binutils due to downlevel assemblers. Also see the wiki page config.h | assembly defines.
DISABLE_SHA ON/OFF OFF Disables SHA instructions. This option is needed for some Binutils due to downlevel assemblers. Also see the wiki page config.h | assembly defines.
CRYPTOPP_NATIVE_ARCH ON/OFF OFF Enables the addition of -march=native (IA32), -march=armv7-a -mfpu=neon (AMRv7a) or -march=armv8-a (AMRv8a) to CXXFLAGS.
CRYPTOPP_DATA_DIR - "" Sets the Crypto++ test data directory. The default value is an empty string. For more information see Issue #82: Add Debian-style Data Directory patch.
CMAKE_INSTALL_PREFIX - - Sets the install prefix (similar to --prefix in Autotools). The default value is platform dependent.
CMAKE_BUILD_TYPE See below Debug Sets the build type. The value can be one of Debug/Release/MinSizeRel/RelWithDebInfo. You should explicitly set this value.

Note: the library's CRYPTOPP_DISABLE_ASM is a fail-safe. It should not be needed under any configurations, from X86 or X64 through ARM or MIPS. If its needed, then please report it on the mailing list or bug tracker so the issue can be fixed.

DISABLE_SSSE3, DISABLE_SSE4, DISABLE_AESNI, and DISABLE_SHA are automatically engaged if the assembler is too old to assemble an object file with the respective instruction. DISABLE_SHA is new, and it may miss the mark. If its needed, then please report it on the mailing list or bug tracker so the issue can be fixed.

If given a choice you should enable CRYPTOPP_NATIVE_ARCH by configuring CMake with -DCRYPTOPP_NATIVE_ARCH=1. On modern processors it will engage CPU features like AVX, AVX2, BMI and BMI2. AVX-based memcpy is often translated into 32-byte vmovdqa/vmovdqu and it is lightening fast. The library will usually perform much better with CRYPTOPP_NATIVE_ARCH.

The table below discusses values for CMAKE_BUILD_TYPE.

Library Configuration Options
Value Comments
Debug This option is similar to similar to -O0 -g.
Release This option is similar to similar to -O2 -DNDEBUG.
MinSizeRel This option is similar to similar to -O2 -DNDEBUG.
RelWithDebInfo This option is similar to similar to -O2 -DNDEBUG -g. This is mostly used to strip symbols into a separate file after building. For example, for building -dbg packages in Debian.

Generate Makefiles

Next, generate the makefiles. Be sure to use the source directory as argument; and not the build directory. It may be either absolute or relative path.

$ cmake /home/user/cryptopp

Building the Library

Once the Makefiles are generated, you only have to run make to compile and link the library and test program.

$ make

This step builds static and shared versions of the library + tests binary (cryptest). If you want to build only shared or static version, then make cryptopp-static or cryptopp-shared targets. Like so: $ make cryptopp-static.

A more cross-platform way to build is to invoke $ cmake --build . (notice the dot) instead of make. It can be used, if we use non-Makefile generator (Ninja or Visual Studio, for example).

CMake hides the output of the compilation process by default. You can use VERBOSE=1 to display it. Please use VERBOSE=1 if you are asking for help on the mailing list or filing a bug report.

Testing the Library

Once the library is built, it should be tested to ensure operational correctness.

TODO: talk about how to run cryptest.exe v and cryptest.exe tv all

Installing the library

To install the library after building invoke

# make install

If you want to change installation prefix, you can do it using -DCMAKE_INSTALL_PREFIX=YOUR_INSTALL_PREFIX as described in CMake Options. Note, that you may need root privileges if you install it in a system location.

Importing Crypto++

For example, you have a project, that uses Crypto++ and CMake, and you want to add Crypto++ as a dependency. Include directories will be added automatically.

On Linux add these lines to CMakeLists.txt in your project directory:

find_package(CryptoPP REQUIRED)
target_link_libraries(YOUR_TARGET_NAME cryptopp-shared)

If you want to link with static version of the library, then use cryptopp-static instead of cryptopp-shared. On Windows you must use cryptopp-static because the dynamic link library is the FIPS DLL (which is something you should avoid).

IDE Generators

CMake includes built-in support for a number of command line and IDE environments, including Nmake, Unix, VC++, Visual Studio 2002-2013 and Xcode. You can enlist a Generator with the -G option:

# Visual Studio 2013
cmake -G "Visual Studio 12"

#Xcode
cmake -G "Xcode"

Sometimes the output artifacts don't work as expected. For example, CMake does not generate a functioning set of Xcode project files; see Issue 355: CMake-based Xcode build fails to build any library, Issue 374: CMake XCode build on macOS fails and Cmake generated Xcode project does not produce library artifacts? on Stack Overflow.

CMake Removal

CMake was added to the library at Crypto++ 5.6.3. The CMake project files never achieved a good state and no one was available with the necessary skills to move them into a good state (or maybe, no one was available to perform the work). CMake was a failed experiment and removed from the library prior to the release of Crypto++ 6.0. The mailing list discussion is at Remove CMake from GitHub; add it to Patch Page on wiki?, and the check-in of interest is Commit 913a9e60d375e458.

The experiment failed for several reasons. First, CMake is a redundant build system because the Makefile is used on Unix & Linux; and Visual Studio & MSBuild are used on Windows. CMake users could integrate the library by using ExternalProject_Add. There was no reason for us to provide CMake to create Makefiles and MSBuild files we were already providing. We were doing over twice the amount of work than we needed to be doing.

Second, CMake was consuming disproportionate amounts of our time. It accounted for over 18% of bug reports in the issue tracker. When an issue was encountered, it was often non-trivial to find a solution. Even simple workflows, like "add a flag to CXXFLAGS" or "add a flag to LDFLAGS" were complicated. Based on Current Status below there was no end in sight.

Third, CMake uses an insecure configuration for release builds. All CMake projects are vulnerable to CVE-2016-7420 -like findings if the project uses the default options provided by CMake. Secrets that Crypto++ may protect could be egressed because of the CMake's insecure configuration (which have nothing to do with the Crypto++ configuration). Additionally, CMake does not use required platform flags, like -mfloat-abi=softfp for armeabi builds on Android.

Fourth, CMake did not provide a cross platform way to get a shell for testing. We had to prepare arguments for a call to exec or CreateProcess. It also meant we could not do thing like assign sh -c to a variable and call through it. Also see Avoid egrep when possible, remove egrep from DumpMachine in the Crypto++ issue tracker.

Fifth, CMake makes it difficult to impossible to change flags it wants to use, like -O2. Vectorization gained widespread support in the mid-2000's. The library has a lot of code and patterns to take advantage of it. To engage vectorizations we need -O3 for compilers like Clang, GCC and Intel ICC. Unfortunately, CMake has forced us to use their poor selection.

Sixth, CMake lacked good native support for AIX, Android, iOS, PowerPC, Solaris, Windows Phone, Windows Store, SSE, ARMv7, ARMv8 and Power8. We had to do nearly everything manually, and it placed too much of a burden on the library maintainers.

Seventh, we could not query CMake and user options in a particular configuration to further tune our use of flags and options. Also see Difference between add_compile_options and SET(CMAKE_CXX_FLAGS…) on Stack Overflow.

Eighth, CMake had too many bugs that went unfixed and required too many work-arounds. For example, we were never able to set project(cryptopp, CXX) because CMake could not perform its tests with a C++ compiler. Two years later the bug was still not fixed. Also see Tell CMake to use C++ compiler for C files coming from CMake? on Stack Overflow. Another example is How to have CHECK_CXX_COMPILER_FLAG fail on illegal value? on Stack Overflow, where the compiler would report an illegal option but CMake would report success. Yet another example is How to strip trailing whitespace in CMake variable?, where STRIP does not strip whitespace.

Ninth, CMake uses anti-patterns, like not driving link through the compiler. Best practice dictates using the compiler driver for link. The compiler driver will pass necessary options and libraries to the linker. CMake failed to honor the practice or supply the equivalent functionality. Also see Instruct CMake to use CXX and CXXFLAGS when driving link? on Stack Overflow.

Tenth, CMake hides output that is necessary for users to confirm their configuration and report bugs to the library. Nearly every bug report received had 1%, 2%, 3%, etc. Nearly every report lacked information we request, like a typical compile command and the link command. Its yet another example of making the "common case" difficult.

Eleventh, its impossible to comply with best practices and policies. For example, we started catching policy violations for quoting CMake variables. We removed the quotes to comply with policy, which subsequently broke Windows because of spaces in pathnames. Also see How to use variables and avoid CMP0054 policy violations? on Stack Overflow.

Twelfth, the documentation sucks. We did not know how to approach many workflows or treat most problems. Simple workflows, like "change release optimizations from -O2 to -O3" , were not documented and lacked exemplary code. When we experienced a problem it was hard to find a solution. We spent hours in their manuals without learning how to do much of anything.

Thirteenth, no one stepped up to maintain it. Part of the agreement in adding CMake support was the community would maintain it. Once the initial files were added the Cmake supporters mostly disappeared. The library maintainers then had to field the bugs.

Also see Remove CMake from GitHub; add it to Patch Page on wiki? (mailing list), Commit 1c740b0a097aecaa (warning message) and Commit 913a9e60d375e458 (library removal).

Crypto++ was not the only project to suffer chronic CMake problems. See, for example, Monero Issue 771, Windows not bundling OpenSSL statically.

Current Status

The table below lists the state of the CMake project files before they were removed. As can be seen there are many gaps in the project files. Nearly all platforms have problems with their linker flags due to Instruct CMake to use CXX and CXXFLAGS when driving link? which means all the sanitzers are broken. JW takes full responsibility for the problems with the project files.

Including the project files in their current state would be like adding a cipher that produces incorrect results. It would harm users who believe they are using well maintained source files from the Crypto++ project.

Platform Status Comments
Windows x86 Not using library options
Windows x64 Not using library options
Windows Phone Not using library options
Windows Store Unknown
MinGW Don't care Abandoned by its authors
MinGW-64 Unknown
Cygwin Unknown
Cygwin-64 Unknown
Linux i686 Mostly using library settings
Linux x86_64 Mostly using library settings
OS X i386 Unknown
OS X x86_64 Unknown
OS X PPC Unknown
iOS ARM Unknown
iOS ARM64 Unknown
iOS TV Unknown
iOS Watch Unknown
Linux ARM A-32 Mostly using library settings
Linux Aarch32 Mostly using library settings
Linux Aarch64 Mostly using library settings
Linux MIPS Not using library options
Linux MIPS64 Not using library options
Linux PPC Not using library options
Linux PPC64 Not using library options
AIX PPC Not using library options
AIX PPC64 Not using library options
Solaris i386 Mostly using library options Linker flags missing -xarch options
Solaris x86_64 Mostly using library options Linker flags missing -xarch options
Solaris Sparc Using some library options Linker flags missing -xarch options
Solaris Sparc64 Using some library options Linker flags missing -xarch options
Android armeabi Not using library options Not using Android options
Android armv7a Not using library options Not using Android options
Android armv7a+NEON Not using library options Not using Android options
Android armv8a Not using library options Not using Android options
Android i686 Not using library options Not using Android options
Android x86_64 Not using library options Not using Android options

Downloads

GitHub | cryptopp-cmake - GitHub with the latest CMake sources.