The only change in meta.yaml compared to the previous recipe is the mkl-devel dependency. The challenge from the CMake perspective is to locate the MKL libraries that are installed by Anaconda. Fortunately, we know that they are located in ${CMAKE_INSTALL_PREFIX}. The Intel MKL link line advisor available online (https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor/) can be used to look up how to link MKL into our project depending on the platform and compiler chosen. We have decided to wrap this information into an INTERFACE library. This solution is ideal for the case of MKL: the library is not a target created by our project, or any subproject, but it still needs to be dealt with in a possibly very convoluted manner; that is: setting compiler flags, include directories, and link libraries. CMake INTERFACE libraries are targets in the build system, but do not create any build output, at least directly. However, since they are targets, we may set their properties on them. Just as "real" targets, they can also be installed, exported, and imported.
First of all, we declare a new library called IntelMKL with the INTERFACE attribute. We then need to set properties as needed and we follow the pattern of calling the appropriate CMake command on the target with the INTERFACE attribute, using the following:
- target_compile_options, to set INTERFACE_COMPILE_OPTIONS. In our case, -m64 has to be set, but only if using the GNU or AppleClang compilers. Note that we do this with a generator expression.
- target_include_directories, to set the INTERFACE_INCLUDE_DIRECTORIES. These can be set after finding the mkl.h header file on the system. This was done with the find_path CMake command.
- target_link_libraries, to set the INTERFACE_LINK_LIBRARIES. We decided to link against the single dynamic library libmkl_rt.so and searched for it with the find_library CMake command. The GNU or AppleClang compilers will also need to link the executable to the native threading and mathematical libraries. Once again, these cases are elegantly handled with generator expressions.
The properties we have just set on the IntelMKL target can be printed out for the user by means of the cmake_print_properties command. Finally, we link against the IntelMKL target. As expected, this will set compiler flags, include directories, and link libraries as necessary to compile successfully:
target_link_libraries(dgemm-example
PRIVATE
IntelMKL
)