aboutsummaryrefslogtreecommitdiffstats
path: root/host/cmake/Modules/UHDBoost.cmake
blob: 5ebb4acefbdae07f8467d91a793606346e47c846 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#
# Copyright 2019 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#

# The following variables can be defined external to this script.
#
# ENABLE_STATIC_LIBS : whether to enable static libraries, which will
# require static Boost libraries too. If not using static libraries,
# shared libraries will be used. The default is to use shared
# libraries, and this default will be used if this variable is not
# defined or if is it NO/OFF/FALSE.
#
# UHD_BOOST_REQUIRED_COMPONENTS : Boost components that are required
# for Boost_FOUND to be true. The linkage (shared or static) must be
# correct and the library must also be found.
#
# UHD_BOOST_OPTIONAL_COMPONENTS : Boost components that are
# optional. They do not impact Boost_FOUND. The linkage will still be
# honored, and the library must still be found for the return
# variables to be set.
#
# NOTE: If neither UHD_BOOST_REQUIRED_COMPONENTS and
# UHD_BOOST_OPTIONAL_COMPONENTS are defined and/or are empty, then
# this script just checked to see if the minimum required version of
# Boost can be found, and sets Boost_FOUND accordingly; all of the
# other return variables will be unset / undefined.
#
# UHD_BOOST_REQUIRED : Whether to set Boost required components as
# "required" during finding. If not specified, then defaults to
# TRUE. If REQUIRED is TRUE and Boost is not found, then this script
# will error out. Otherwise this script will not error out, and the
# variable Boost_FOUND will indicate whether a compatible version
# Boost was found or not.
#
# Upon find returning, the following variables will be set upon return
# of this script:
#
# Boost_FOUND : will be TRUE if all of the required Boost components
# are found with the correct linkage (static or shared); otherwise
# this variable will be FALSE unless there are no components specified
# in which case this variable will be unset.
#
# Boost_INCLUDE_DIRS : directories to use with 'include_directories',
# where the top-level "boost" directory is located for headers.
#
# Boost_LIBRARY_DIRS : directories for use in finding libraries; this
# variable is generally not used in favor of either (1) defining
# library names with the full path; or (2) using targets where the
# full path is defined already. This variable is probably deprecated.
#
# Boost_LIBRARIES : a list of found Boost libraries, each of which can
# be either (1) or (2) above; either will work with modern CMake.
#
########################################################################
message(STATUS "")
message(STATUS "Checking for Boost version ${BOOST_MIN_VERSION} or greater")

# unset return variables
unset(Boost_FOUND)
unset(Boost_INCLUDE_DIRS)
unset(Boost_LIBRARY_DIRS)
unset(Boost_LIBRARIES)

# check whether to set REQUIRED or not
# if not set, default is to require Boost
if(NOT UHD_BOOST_REQUIRED)
    # UHD_BOOST_REQUIRED is not set; use the default
    set(UHD_BOOST_REQUIRED "REQUIRED")
elseif(UHD_BOOST_REQUIRED)
    # UHD_BOOST_REQUIRED is set to TRUE/ON/1
    set(UHD_BOOST_REQUIRED "REQUIRED")
else()
    # UHD_BOOST_REQUIRED is not set to TRUE/ON/1
    unset(UHD_BOOST_REQUIRED)
endif()

# set this for verbosity during 'find'
# set(Boost_DEBUG TRUE)

# verify we're looking for something
list(LENGTH UHD_BOOST_OPTIONAL_COMPONENTS UHD_BOOST_OPTIONAL_COMPONENTS_LEN)
list(LENGTH UHD_BOOST_REQUIRED_COMPONENTS UHD_BOOST_REQUIRED_COMPONENTS_LEN)
if(UHD_BOOST_OPTIONAL_COMPONENTS_LEN EQUAL 0 AND
   UHD_BOOST_REQUIRED_COMPONENTS_LEN EQUAL 0)
    # just see if Boost can be found
    find_package(Boost ${BOOST_MIN_VERSION} QUIET ${UHD_BOOST_REQUIRED})
    if(Boost_FOUND)
        message(STATUS "Boost version ${BOOST_MIN_VERSION} or greater - found")
    else()
        message(STATUS "Boost version ${BOOST_MIN_VERSION} or greater - not found")
    endif()
    return()
endif()

# if the OS is MINGW and if 'thread' is in the list, change its name
if(MINGW)
    list(FIND UHD_BOOST_REQUIRED_COMPONENTS "thread" THREAD_NDX)
    if(NOT ${THREAD_NDX} EQUAL -1)
        list(REMOVE_AT UHD_BOOST_REQUIRED_COMPONENTS ${THREAD_NDX})
        list(INSERT UHD_BOOST_REQUIRED_COMPONENTS ${THREAD_NDX} thread_win32)
    endif()
endif()

# if 'system' is in the list, make sure it comes last; sometimes this
# linkage makes a difference
list(FIND UHD_BOOST_REQUIRED_COMPONENTS "system" SYSTEM_NDX)
if(NOT ${SYSTEM_NDX} EQUAL -1)
    list(REMOVE_AT UHD_BOOST_REQUIRED_COMPONENTS ${SYSTEM_NDX})
    list(APPEND UHD_BOOST_REQUIRED_COMPONENTS "system")
endif()

# special library directory that's used by some Linux
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
    list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")

# special Microsoft Visual C handling
if(MSVC)
    set(BOOST_ALL_DYN_LINK "${BOOST_ALL_DYN_LINK}" CACHE BOOL "boost enable dynamic linking")
    if(BOOST_ALL_DYN_LINK)
        add_definitions(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc
    else(BOOST_ALL_DYN_LINK)
        set(UHD_BOOST_REQUIRED_COMPONENTS) #empty components list for static link
    endif(BOOST_ALL_DYN_LINK)
endif(MSVC)

# Starting in CMake 3.15.0, if policy 'CMP0093' is available and set
# to 'NEW', then the Boost_VERSION will be returned as X.Y.Z (e.g.,
# 1.70.0) instead of XXYYZZ (107000). The OLD policy is the default
# for now, but is deprecated and relevant code should be updated to
# the NEW policy format. This change matches the version format
# returned by Boost's CMake scripts. See also:
# https://cmake.org/cmake/help/v3.15/policy/CMP0093.html#policy:CMP0093
# Tell FindBoost, if used, to report Boost_VERSION in X.Y.Z format.
# NOTE: This must be set -before- calling "find_package(Boost ...)".
# NOTE: This setting is for CMake scripts only; each language (e.g.,
# C++) that uses Boost maintains its current format for the Boost
# version variable.
if(POLICY CMP0093)
    cmake_policy(SET CMP0093 NEW)
endif()

# if no CXX STANDARD is set, default to that required by UHD: c++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
  message(WARNING "\nC++ standard not yet set; setting to C++14.\n")
endif()

# tell boost the linkage required
set(Boost_USE_STATIC_LIBS ${ENABLE_STATIC_LIBS})
# temporarily explicitly enable or disable shared libraries,
# build-wise; this can be disabled on a case by case basis for each
# library built.
if(BUILD_SHARED_LIBS)
    set(BUILD_SHARED_LIBS_SET TRUE)
    set(OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
else()
    set(BUILD_SHARED_LIBS_SET FALSE)
endif()
if(ENABLE_STATIC_LIBS)
    set(BUILD_SHARED_LIBS FALSE)
else()
    set(BUILD_SHARED_LIBS TRUE)
endif()

if(${UHD_BOOST_OPTIONAL_COMPONENTS_LEN} GREATER 0)
    message(STATUS "  Looking for optional Boost components...")
    find_package(Boost ${BOOST_MIN_VERSION} QUIET
        OPTIONAL_COMPONENTS ${UHD_BOOST_OPTIONAL_COMPONENTS})
endif()

if(${UHD_BOOST_REQUIRED_COMPONENTS_LEN} GREATER 0)
    message(STATUS "  Looking for required Boost components...")
    find_package(Boost ${BOOST_MIN_VERSION} QUIET
        COMPONENTS ${UHD_BOOST_REQUIRED_COMPONENTS} ${UHD_BOOST_REQUIRED})
endif()

# restore BUILD_SHARED_LIBS, if set
if(BUILD_SHARED_LIBS_SET)
    set(BUILD_SHARED_LIBS ${OLD_BUILD_SHARED_LIBS})
    unset(OLD_BUILD_SHARED_LIBS)
else()
    unset(BUILD_SHARED_LIBS)
endif()

if(NOT Boost_FOUND)
    # Boost was not found
    # clear out return variables, just in case
    unset(Boost_VERSION)
    unset(Boost_INCLUDE_DIRS)
    unset(Boost_LIBRARY_DIRS)
    unset(Boost_LIBRARIES)
else()
    # Boost was found; do fixups and related tests / checks

    # fix the Boost_VERSION to be X.Y.Z if CMake version < 3.15
    if(CMAKE_VERSION VERSION_LESS 3.15)
        set(Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
    endif()

    # generic fix for some linking issues with Boost 1.68.0 or newer.
    if(NOT ${Boost_VERSION} VERSION_LESS 1.68.0)
        message(STATUS "  Enabling Boost Error Code Header Only")
        add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
    endif()

    # test for std::string_view in boost::asio only if we're using
    # c++17 or later and Boost 1.68.0 or later. The default is to not
    # use this feature. Boost 1.67.0 and earlier at best checked for
    # and used std::experimental::string_view, which causes issues for
    # some Boost & C++ versions ... so, just don't use it!
    set(USE_STD_STRING_VIEW_IN_BOOST_ASIO FALSE)
    if((NOT ${CMAKE_CXX_STANDARD} VERSION_LESS 17) AND
       (NOT ${Boost_VERSION} VERSION_LESS 1.68.0))
        # boost::asio::string_view can fail in compiling or linking simple
        # c++. This situation generally happens on for Boost 1.66 - 1.68
        # and macOS using Clang and -std=c++14 ... but it can occur in
        # other situations, so just do a generic check. This issue seems
        # to be fixed in Boost 1.70.0.
        message(STATUS "  Checking whether std::string_view works in boost::asio")
        # unset the return variable, otherwise the compile doesn't take place!
        unset(USE_STD_STRING_VIEW_IN_BOOST_ASIO)
        # set various CheckCXXSourceCompiles variables
        include(CheckCXXSourceCompiles)
        # FindBoost compatibility variables: Boost_INCLUDE_DIRS
        if(NOT Boost_INCLUDE_DIRS OR "${Boost_INCLUDE_DIRS}" STREQUAL "")
            get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
        endif()
        # set the c++ standard to test using
        set(CMAKE_REQUIRED_FLAGS "-std=c++${CMAKE_CXX_STANDARD} -I${Boost_INCLUDE_DIRS}")
        # make this compile quite
        set(CMAKE_REQUIRED_QUIET TRUE)
        # disable Boost's use of std::experimental::string_view
        set(CMAKE_REQUIRED_DEFINITIONS -DBOOST_ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)
        # Check if std::string_view works in boost::asio
        check_cxx_source_compiles(
            "#include <boost/asio/detail/string_view.hpp>
            int main()
            { boost::asio::string_view sv; }"
            USE_STD_STRING_VIEW_IN_BOOST_ASIO
        )
        # clear the various CheckCXXSourceCompiles variables
        unset(CMAKE_REQUIRED_FLAGS)
        unset(CMAKE_REQUIRED_QUIET)
        unset(CMAKE_REQUIRED_DEFINITIONS)
    endif()
    # use std::string_view in boost::asio?
    if(USE_STD_STRING_VIEW_IN_BOOST_ASIO)
        message(STATUS "    Enabling boost::asio use of std::string_view")
        add_definitions(-DBOOST_ASIO_HAS_STD_STRING_VIEW)
    else()
        message(STATUS "    Disabling boost::asio use of std::string_view")
        add_definitions(-DBOOST_ASIO_DISABLE_STD_STRING_VIEW)
    endif()
    unset(USE_STD_STRING_VIEW_IN_BOOST_ASIO)

    # disable Boost's use of std::experimental::string_view
    # works for Boost 1.67.0 and newer & doesn't hurt older
    add_definitions(-DBOOST_ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)

    # Boost 1.70.0's find cmake scripts don't always set the expected
    # return variables. Replicate the commit that fixes that issue here:
    # https://github.com/boostorg/boost_install/commit/cfa8d55250dfc2635e907e42da423e4eb540dee5
    if(Boost_FOUND AND (${Boost_VERSION} VERSION_EQUAL 1.70.0))
        message(STATUS "  Enabling possible Boost 1.70.0 Fixes")

        # FindBoost compatibility variables: Boost_LIBRARIES, Boost_<C>_LIBRARY
        if(NOT Boost_LIBRARIES OR "${Boost_LIBRARIES}" STREQUAL "")
            set(Boost_LIBRARIES "")
            foreach(dep IN LISTS UHD_BOOST_REQUIRED_COMPONENTS UHD_BOOST_OPTIONAL_COMPONENTS)
                string(TOUPPER ${dep} _BOOST_DEP)
                if(NOT Boost_${_BOOST_DEP}_FOUND)
                    status(WARNING "  Boost component '${dep}' should have been found but somehow isn't listed as found. Ignoring and hoping for the best!")
                endif()
                list(APPEND Boost_LIBRARIES Boost::${dep})
                set(Boost_${_BOOST_DEP}_LIBRARY Boost::${dep})
            endforeach()
        endif()

        # FindBoost compatibility variables: Boost_INCLUDE_DIRS
        if(NOT Boost_INCLUDE_DIRS OR "${Boost_INCLUDE_DIRS}" STREQUAL "")
            get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
        endif()

        # FindBoost compatibility variables: Boost_LIBRARY_DIRS
        if(NOT Boost_LIBRARY_DIRS OR "${Boost_LIBRARY_DIRS}" STREQUAL "")
            set(Boost_LIBRARY_DIRS "")
            foreach(dep IN LISTS UHD_BOOST_REQUIRED_COMPONENTS UHD_BOOST_OPTIONAL_COMPONENTS)
                string(TOUPPER ${dep} _BOOST_DEP)
                if(NOT Boost_${_BOOST_DEP}_FOUND)
                    status(WARNING "  Boost component '${dep}' should have been found but somehow isn't listed as found. Ignoring and hoping for the best!")
                endif()
                if(Boost_USE_DEBUG_LIBS)
                    get_target_property(Boost_${dep}_LIBRARY Boost::${dep} IMPORTED_LOCATION_DEBUG)
                else()
                    get_target_property(Boost_${dep}_LIBRARY Boost::${dep} IMPORTED_LOCATION_RELEASE)
                endif()
                get_filename_component(Boost_${dep}_LIBRARY_DIR ${Boost_${dep}_LIBRARY} DIRECTORY ABSOLUTE)
                list(FIND Boost_LIBRARY_DIRS ${Boost_${dep}_LIBRARY_DIR} Boost_${dep}_LIBRARY_DIR_FOUND)
                if(${Boost_${dep}_LIBRARY_DIR_FOUND} EQUAL -1)
                    list(APPEND Boost_LIBRARY_DIRS ${Boost_${dep}_LIBRARY_DIR})
                endif()
            endforeach()
        endif()
        list(SORT Boost_LIBRARY_DIRS)
    endif()

    message(STATUS "  Boost version: ${Boost_VERSION}")
    message(STATUS "  Boost include directories: ${Boost_INCLUDE_DIRS}")
    message(STATUS "  Boost library directories: ${Boost_LIBRARY_DIRS}")
    message(STATUS "  Boost libraries: ${Boost_LIBRARIES}")
endif()

if(Boost_FOUND)
    message(STATUS "Looking for Boost version ${BOOST_MIN_VERSION} or greater - found")
else()
    message(STATUS "Looking for Boost version ${BOOST_MIN_VERSION} or greater - not found")
endif()

# unset some internal variables, if set
unset(Boost_LIBRARY_DIR)
unset(Boost_INCLUDE_DIR)