1## ---------------------------------------------------------------------
2##
3## Copyright (C) 2012 - 2019 by the deal.II authors
4##
5## This file is part of the deal.II library.
6##
7## The deal.II library is free software; you can use it, redistribute
8## it, and/or modify it under the terms of the GNU Lesser General
9## Public License as published by the Free Software Foundation; either
10## version 2.1 of the License, or (at your option) any later version.
11## The full text of the license can be found in the file LICENSE.md at
12## the top level directory of deal.II.
13##
14## ---------------------------------------------------------------------
15
16#
17# This file implements the DEAL_II_SETUP_TARGET macro, which is
18# part of the deal.II library.
19#
20# Usage:
21#       DEAL_II_SETUP_TARGET(target)
22#       DEAL_II_SETUP_TARGET(target DEBUG|RELEASE)
23#
24# This appends necessary include directories, linker flags, compile flags
25# and compile definitions and the deal.II library link interface to the
26# given target. In particular:
27#
28# INCLUDE_DIRECTORIES is appended with
29#   "${DEAL_II_INCLUDE_DIRS}"
30#
31# COMPILE_FLAGS is appended with
32#   "${DEAL_II_CXX_FLAGS} ${DEAL_II_CXX_FLAGS_<build type>}"
33#
34# LINK_FLAGS is appended with
35#   "${DEAL_II_LINKER_FLAGS ${DEAL_II_LINKER_FLAGS_<build type>}"
36#
37# COMPILE_DEFINITIONS is appended with
38#   "${DEAL_II_USER_DEFINITIONS};${DEAL_II_USER_DEFINITIONS_<build type>}"
39#
40# If no "DEBUG" or "RELEASE" keyword is specified after the target, the
41# current CMAKE_BUILD_TYPE is used instead. A CMAKE_BUILD_TYPE "Debug" is
42# equivalent to the DEBUG keyword, a CMAKE_BUILD_TYPE "Release" is
43# equivalent to the RELEASE keyword.
44#
45# This macro throws a FATAL_ERROR in case no DEBUG/RELEASE keyword is set
46# and the build type is different from "Debug", or "Release".
47#
48# If the requested build type is not available (e.g. DEBUG request but
49# deal.II was compiled with release mode only), the macro throws a
50# FATAL_ERROR.
51#
52
53MACRO(DEAL_II_SETUP_TARGET _target)
54
55  IF(NOT DEAL_II_PROJECT_CONFIG_INCLUDED)
56    MESSAGE(FATAL_ERROR
57      "\nDEAL_II_SETUP_TARGET can only be called in external projects after "
58      "the inclusion of deal.IIConfig.cmake. It is not intended for "
59      "internal use.\n\n"
60      )
61  ENDIF()
62
63  IF(NOT DEAL_II_TARGET_CONFIG_INCLUDED)
64    INCLUDE(${DEAL_II_TARGET_CONFIG})
65    SET(DEAL_II_TARGET_CONFIG_INCLUDED TRUE)
66  ENDIF()
67
68  # Necessary for setting INCLUDE_DIRECTORIES via SET_PROPERTY
69  CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
70
71  #
72  # Set build type with the help of the specified keyword, or
73  # CMAKE_BUILD_TYPE:
74  #
75  IF("${ARGN}" MATCHES "^(DEBUG|RELEASE)$")
76    SET(_build "${ARGN}")
77  ELSEIF("${ARGN}" STREQUAL "")
78    IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
79      SET(_build "DEBUG")
80    ELSEIF(CMAKE_BUILD_TYPE STREQUAL "Release")
81      SET(_build "RELEASE")
82    ELSE()
83      MESSAGE(FATAL_ERROR
84        "\nDEAL_II_SETUP_TARGET cannot determine DEBUG, or RELEASE flavor "
85        "for target. CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\" is neither "
86        "equal to \"Debug\", nor \"Release\"\n"
87        "Set CMAKE_BUILD_TYPE accordingly, or use an explicit annotation: "
88        "  DEAL_II_SETUP_TARGET(<target> DEBUG|RELEASE)\n\n"
89        )
90    ENDIF()
91  ELSE()
92    MESSAGE(FATAL_ERROR
93      "\nDEAL_II_SETUP_TARGET called with invalid second argument. "
94      "Valid arguments are (empty), DEBUG, or RELEASE\n\n"
95      )
96  ENDIF()
97
98  #
99  # We can only append DEBUG link flags and compile definitions if deal.II
100  # was built with the Debug or DebugRelease build type. So test for this:
101  #
102  IF("${_build}" STREQUAL "DEBUG" AND NOT DEAL_II_BUILD_TYPE MATCHES "Debug")
103    SET(_build "RELEASE")
104  ENDIF()
105
106  IF(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
107    # Intel (at least up to 19.0.5) confuses an external TBB installation with
108    # our selected one if we use -Isystem includes. Work around this by using
109    # normal includes.
110    # See https://github.com/dealii/dealii/issues/8374 for details.
111    TARGET_INCLUDE_DIRECTORIES(${_target} PRIVATE ${DEAL_II_INCLUDE_DIRS})
112  ELSE()
113    TARGET_INCLUDE_DIRECTORIES(${_target} SYSTEM PRIVATE ${DEAL_II_INCLUDE_DIRS})
114  ENDIF()
115
116  SET_PROPERTY(TARGET ${_target} APPEND_STRING PROPERTY
117    LINK_FLAGS " ${DEAL_II_LINKER_FLAGS} ${DEAL_II_LINKER_FLAGS_${_build}}"
118    )
119
120  IF(CMAKE_VERSION VERSION_LESS 3.9 OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
121    SET_PROPERTY(TARGET ${_target} APPEND_STRING PROPERTY
122      COMPILE_FLAGS " ${DEAL_II_CXX_FLAGS} ${DEAL_II_CXX_FLAGS_${_build}}"
123      )
124    SET_PROPERTY(TARGET ${_target} APPEND PROPERTY
125      COMPILE_DEFINITIONS "${DEAL_II_USER_DEFINITIONS};${DEAL_II_USER_DEFINITIONS_${_build}}"
126      )
127
128  ELSE()
129
130    SET(_flags "${DEAL_II_CXX_FLAGS} ${DEAL_II_CXX_FLAGS_${_build}}")
131    SEPARATE_ARGUMENTS(_flags)
132    TARGET_COMPILE_OPTIONS(${_target} PUBLIC
133      $<$<COMPILE_LANGUAGE:CXX>:${_flags}>
134      )
135
136    TARGET_COMPILE_DEFINITIONS(${_target}
137      PUBLIC ${DEAL_II_USER_DEFINITIONS} ${DEAL_II_USER_DEFINITIONS_${_build}}
138      )
139
140    IF(DEAL_II_WITH_CUDA)
141      #
142      # Add cxx compiler and cuda compilation flags to cuda source files:
143      #
144
145      SET(_cuda_flags "${DEAL_II_CUDA_FLAGS} ${DEAL_II_CUDA_FLAGS_${_build}}")
146      SEPARATE_ARGUMENTS(_cuda_flags)
147
148      #
149      # Workaround: cuda will split every compiler option with a comma
150      # (','), so remove all compiler flags that contain a comma:
151      #
152      STRING(REGEX REPLACE "[^ ]*,[^ ]*" "" _cxx_flags
153        "${DEAL_II_CXX_FLAGS} ${DEAL_II_CXX_FLAGS_${_build}}"
154        )
155
156      TARGET_COMPILE_OPTIONS(${_target} PUBLIC
157        $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler ${_cxx_flags}>
158        $<$<COMPILE_LANGUAGE:CUDA>:${_cuda_flags}>
159        )
160
161      SET_TARGET_PROPERTIES(${_target} PROPERTIES
162        CUDA_SEPARABLE_COMPILATION FALSE
163        )
164    ENDIF()
165  ENDIF()
166
167  #
168  # Set up the link interface:
169  #
170  GET_PROPERTY(_type TARGET ${_target} PROPERTY TYPE)
171  IF(NOT "${_type}" STREQUAL "OBJECT_LIBRARY")
172    TARGET_LINK_LIBRARIES(${_target} ${DEAL_II_TARGET_${_build}})
173  ENDIF()
174
175  #
176  # If DEAL_II_STATIC_EXECUTABLE is set, switch the final link type to
177  # static:
178  #
179  IF(DEAL_II_STATIC_EXECUTABLE)
180    SET_PROPERTY(TARGET ${_target} PROPERTY
181      LINK_SEARCH_END_STATIC TRUE
182      )
183  ENDIF()
184
185ENDMACRO()
186