# how to set link flag for specific target (MKL) and deal with the dependence between several libraries

**URL:** <https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645>\
**Category:** Code\
**Created:** [February 17, 2020, 7:07am UTC](https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645 "2020-02-17T07:07:05Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Crownk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/crownk/32/369_2.png) [@Crownk](https://discourse.cmake.org/u/Crownk)\
**Post date:** [February 17, 2020, 7:07am UTC](https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645/1 "2020-02-17T07:07:05Z")

</div>

I write a project which is composed of several libraries and Intel MKL library. I want to use CMake to compile my project and I have two `CMakeLists.txt` as the following.

In the root directory,

```auto
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(MMNET LANGUAGES CXX)

# use the new policy to allow CMake to link target libraries from other directories
cmake_policy(SET CMP0079 NEW)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-o2 -msse -msse2 ${OpenMP_CXX_FLAGS}")

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)

set(MKL_ROOT "/opt/intel/compilers_and_libraries_2019.4.243/linux/mkl")

# In the future modification, I will wirte my own find_package module.
# Now we set this path manually.
set(GSL_LIBRARY_PATH /usr/lib/x86_64-linux-gnu/libgsl.a)
set(DL_LIBRARY_PATH /usr/lib/x86_64-linux-gnu/libdl.a)

set(MKL_LIBRARY_FLAGS "-Wl,--start-group ${MKL_ROOT}/lib/intel64/libmkl_intel_lp64.a") 
set(MKL_LIBRARY_FLAGS "${MKL_LIBRARY_FLAGS} ${MKL_ROOT}/lib/intel64/libmkl_gnu_thread.a")
set(MKL_LIBRARY_FLAGS "${MKL_LIBRARY_FLAGS} ${MKL_ROOT}/lib/intel64/libmkl_core.a -Wl,--end-group -lgomp -lpthread -lm -ldl")

find_package(Boost 1.58.0 COMPONENTS program_options REQUIRED)
find_package(OpenMP REQUIRED)

add_subdirectory(src)

include_directories(${Boost_INCLUDE_DIRS})

add_executable(MMNET ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)

target_link_libraries(dataIO PUBLIC ${Boost_LIBRARIES})
target_link_libraries(Params PUBLIC dataIO)
target_link_libraries(GenoData PUBLIC GenotypeBasis)
target_link_libraries(AuxGenoData PUBLIC GenotypeBasis)
target_link_libraries(GeneticCorr PUBLIC NumericUtils GenoData AuxGenoData)
target_link_libraries(LMMCPU PUBLIC GenoData)

list(APPEND LINK_STATIC_LIBRARIES dataIO Params Timer GenoData MemoryUtils
                                  LMMCPU NumericUtils GeneticCorr GenotypeBasis
                                  AuxGenoData)

target_link_libraries(MMNET PUBLIC ${LINK_STATIC_LIBRARIES} 
                                   ${GSL_LIBRARY_PATH} 
                                   ${DL_LIBRARY_PATH}
                                   ${MKL_LIBRARY_FLAGS})

```

In the subdirectory,

```auto
add_library(dataIO STATIC IOUtils.h
                          IOUtils.cpp)
add_library(Timer STATIC Timer.h
                         Timer.cpp)
add_library(Params STATIC Parameters.h
                          Parameters.cpp)
add_library(MemoryUtils STATIC MemoryUtils.h
                               MemoryUtils.cpp)
add_library(LMMCPU STATIC LMMCPU.h
                          LMMCPU.cpp)
add_library(NumericUtils STATIC NumericUtils.h
                                NumericUtils.cpp)
add_library(GenoData STATIC GenoData.h
                                GenoData.cpp)
add_library(GeneticCorr STATIC GeneticCorr.h
                                GeneticCorr.cpp)     
add_library(GenotypeBasis STATIC GenotypeBasis.h
                GenotypeBasis.cpp)
add_library(AuxGenoData STATIC AuxGenoData.h
                              AuxGenoData.cpp)   

MESSAGE(STATUS "Finish building libraries")

```

In terms of the `CMakeLists.txt` file from the root directory, there are three lines to deal with the Intel MKL library. I am not sure if there is another beautiful way to solve this problem.

```auto
set(MKL_LIBRARY_FLAGS "-Wl,--start-group ${MKL_ROOT}/lib/intel64/libmkl_intel_lp64.a") 
set(MKL_LIBRARY_FLAGS "${MKL_LIBRARY_FLAGS} ${MKL_ROOT}/lib/intel64/libmkl_gnu_thread.a")
set(MKL_LIBRARY_FLAGS "${MKL_LIBRARY_FLAGS} ${MKL_ROOT}/lib/intel64/libmkl_core.a -Wl,--end-group -lgomp -lpthread -lm -ldl")

```

What’s more, in my root `CMakeLists.txt` file, I write several `targe_link_libraries` command to deal with the dependence between libraries. Is there any other better ways to do? Thank you!

---

<div class="post-metadata">

**Author:** ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)\
**Post date:** [February 17, 2020, 1:53pm UTC](https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645/2 "2020-02-17T13:53:07Z")

</div>

Depending on which part of MKL you use you may simply  
set(BLA\_VENDOR Intel10\_64lp)  
find\_package(LAPACK)

see: [https://cmake.org/cmake/help/v3.16/module/FindLAPACK.html](https://cmake.org/cmake/help/v3.16/module/FindLAPACK.html)  
note that you have one for GSL too:  
[https://cmake.org/cmake/help/v3.16/module/FindGSL.html](https://cmake.org/cmake/help/v3.16/module/FindGSL.html)

other remarks:

1. You should avoid using `${Whatever_VAR}` in `TLL` and `include_directories` and use appropriate imported target in `TLL` i.e. `target_link_libraries(dataIO PUBLIC Boost::program_options)`, this will bring appropriate library and include requirement in one usage requirement.
2. You use `OpenMP_CXX_FLAGS` before `find_package(OpenMP REQUIRED)` this won’t work. And you’d better use OpenMP::OpenMP\_CXX imported target and not `OpenMP_CXX_FLAGS` var.
3. `cmake_minimum_required(VERSION 3.5)` 3.5 is ancient
4. I think you’d better write the `target_link_libraries(...)` in the same CMakeLists.txt as the one defining the libs, those requirements are part of the definition of the libraries and should be (I think) near their respective `add_library` statement.

---

<div class="post-metadata">

**Author:** ![Crownk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/crownk/32/369_2.png) [@Crownk](https://discourse.cmake.org/u/Crownk)\
**Post date:** [February 18, 2020, 6:54am UTC](https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645/3 "2020-02-18T06:54:33Z")

</div>

@erk Thank you for your patient instruction. I fully agree with your remark 3 and remark4. I still have several confusion point. First of all, I do not clearly understand your first remark. After I find the Boost package, I want to include the boost header file search path and link it to my library `dataIO`. With respect to your remark2, it is better for me to link the `OpenMP:OpenMP_CXX` directly with my library instead of using compiler flag. Is it right? What’s more, how should I do to make a lot of `target_link_library` command more neat? Thank you so much!

---

<div class="post-metadata">

**Author:** ![erk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/erk/32/114_2.png) [@erk](https://discourse.cmake.org/u/erk)\
**Post date:** [February 18, 2020, 8:07am UTC](https://discourse.cmake.org/t/how-to-set-link-flag-for-specific-target-mkl-and-deal-with-the-dependence-between-several-libraries/645/4 "2020-02-18T08:07:19Z")

</div>

> [@Crownk](#):
>
> First of all, I do not clearly understand your first remark. After I find the Boost package, I want to include the boost header file search path and link it to my library `dataIO` .

Precisely if you  
`target_link_libraries(dataIO PUBLIC Boost::program_options)` you’ll get exactly what you need, because the include search path comes with the imported target `Boost::program_options`.  
Basically with _modern_ CMake your target (library or executable usually **only need** to `target_link_libraries(...)` the libraries they are using. Basically a CMake target shall convey all necessary informations to use it.

> [@Crownk](#):
>
> With respect to your remark2, it is better for me to link the `OpenMP:OpenMP_CXX` directly with my library instead of using compiler flag.

Yes that’s what I meant. For every library which uses OpenMP you do:  
`target_link_libraries(theLib PUBLIC OpenMP::OpenMP_CXX)`  
this will have the benefit to show which library does in fact need OpenMP.

In your current setup, you will have OpenMP FLAGS enabled for every target even though some of them may not need that.
