1# - Find jsoncpp - Overarching find module 2# This is a over-arching find module to find older jsoncpp versions and those sadly built 3# without JSONCPP_WITH_CMAKE_PACKAGE=ON, as well as those built with the cmake config file. 4# It also wraps the different versions of the module. 5# 6# On CMake 3.0 and newer: 7# JsonCpp::JsonCpp - Imported target (possibly an interface/alias) to use: 8# if anything is populated, this is. If both shared and static are found, then 9# this will be the static version on DLL platforms and shared on non-DLL platforms. 10# JsonCpp::JsonCppShared - Imported target (possibly an interface/alias) for a 11# shared library version. 12# JsonCpp::JsonCppStatic - Imported target (possibly an interface/alias) for a 13# static library version. 14# 15# On all CMake versions: (Note that on CMake 2.8.10 and earlier, you may need to use JSONCPP_INCLUDE_DIRS) 16# JSONCPP_LIBRARY - wraps JsonCpp::JsonCpp or equiv. 17# JSONCPP_LIBRARY_IS_SHARED - if we know for sure JSONCPP_LIBRARY is shared, this is true-ish. We try to "un-set" it if we don't know one way or another. 18# JSONCPP_LIBRARY_SHARED - wraps JsonCpp::JsonCppShared or equiv. 19# JSONCPP_LIBRARY_STATIC - wraps JsonCpp::JsonCppStatic or equiv. 20# JSONCPP_INCLUDE_DIRS - Include directories - should (generally?) not needed if you require CMake 2.8.11+ since it handles target include directories. 21# 22# JSONCPP_FOUND - True if JsonCpp was found. 23# 24# Original Author: 25# 2016 Ryan Pavlik <ryan.pavlik@gmail.com> 26# Incorporates work from the module contributed to VRPN under the same license: 27# 2011 Philippe Crassous (ENSAM ParisTech / Institut Image) p.crassous _at_ free.fr 28# 29# Copyright Philippe Crassous 2011. 30# Copyright Sensics, Inc. 2016. 31# Distributed under the Boost Software License, Version 1.0. 32# (See accompanying file LICENSE_1_0.txt or copy at 33# http://www.boost.org/LICENSE_1_0.txt) 34 35set(__jsoncpp_have_namespaced_targets OFF) 36set(__jsoncpp_have_interface_support OFF) 37if(NOT ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 3.0)) 38 set(__jsoncpp_have_namespaced_targets ON) 39 set(__jsoncpp_have_interface_support ON) 40elseif(("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" EQUAL 2.8) AND "${CMAKE_PATCH_VERSION}" GREATER 10) 41 set(__jsoncpp_have_interface_support ON) 42endif() 43 44# sets __jsoncpp_have_jsoncpplib based on whether or not we have a real imported jsoncpp_lib target. 45macro(_jsoncpp_check_for_real_jsoncpplib) 46 set(__jsoncpp_have_jsoncpplib FALSE) 47 if(TARGET jsoncpp_lib) 48 get_property(__jsoncpp_lib_type TARGET jsoncpp_lib PROPERTY TYPE) 49 #message(STATUS "__jsoncpp_lib_type ${__jsoncpp_lib_type}") 50 # We make interface libraries. If an actual config module made it, it would be an imported library. 51 if(NOT __jsoncpp_lib_type STREQUAL "INTERFACE_LIBRARY") 52 #message("have jsoncpp_lib and we didn't invent it ourselves") 53 set(__jsoncpp_have_jsoncpplib TRUE) 54 endif() 55 endif() 56endmacro() 57 58include(FindPackageHandleStandardArgs) 59# Ensure that if this is TRUE later, it's because we set it. 60set(JSONCPP_FOUND FALSE) 61 62# See if we find a CMake config file - there is no harm in calling this more than once, 63# and we need to call it at least once every CMake invocation to create the original 64# imported targets, since those don't stick around like cache variables. 65find_package(jsoncpp QUIET NO_MODULE) 66 67if(jsoncpp_FOUND) 68 # Build a string to help us figure out when to invalidate our cache variables. 69 # start with where we found jsoncpp 70 set(__jsoncpp_info_string "[${jsoncpp_DIR}]") 71 72 # part of the string to indicate if we found a real jsoncpp_lib (and what kind) 73 _jsoncpp_check_for_real_jsoncpplib() 74 if(__jsoncpp_have_jsoncpplib) 75 list(APPEND __jsoncpp_info_string "[${__jsoncpp_lib_type}]") 76 else() 77 list(APPEND __jsoncpp_info_string "[]") 78 endif() 79 # part of the string to indicate if we found jsoncpp_lib_static 80 if(TARGET jsoncpp_lib_static) 81 list(APPEND __jsoncpp_info_string "[T]") 82 else() 83 list(APPEND __jsoncpp_info_string "[]") 84 endif() 85endif() 86 87 88# If we found something, and it's not the exact same as what we've found before... 89# NOTE: The contents of this "if" block update only (internal) cache variables! 90# (since this will only get run the first CMake pass that finds jsoncpp or that finds a different/updated install) 91if(jsoncpp_FOUND AND NOT __jsoncpp_info_string STREQUAL "${JSONCPP_CACHED_JSONCPP_DIR_DETAILS}") 92 #message("Updating jsoncpp cache variables! ${__jsoncpp_info_string}") 93 set(JSONCPP_CACHED_JSONCPP_DIR_DETAILS "${__jsoncpp_info_string}" CACHE INTERNAL "" FORCE) 94 unset(JSONCPP_IMPORTED_LIBRARY_SHARED) 95 unset(JSONCPP_IMPORTED_LIBRARY_STATIC) 96 unset(JSONCPP_IMPORTED_LIBRARY) 97 unset(JSONCPP_IMPORTED_INCLUDE_DIRS) 98 unset(JSONCPP_IMPORTED_LIBRARY_IS_SHARED) 99 100 # if(__jsoncpp_have_jsoncpplib) is equivalent to if(TARGET jsoncpp_lib) except it excludes our 101 # "invented" jsoncpp_lib interface targets, made for convenience purposes after this block. 102 103 if(__jsoncpp_have_jsoncpplib AND TARGET jsoncpp_lib_static) 104 105 # A veritable cache of riches - we have both shared and static! 106 set(JSONCPP_IMPORTED_LIBRARY_SHARED jsoncpp_lib CACHE INTERNAL "" FORCE) 107 set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) 108 if(WIN32 OR CYGWIN OR MINGW) 109 # DLL platforms: static library should be default 110 set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_STATIC} CACHE INTERNAL "" FORCE) 111 set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) 112 else() 113 # Other platforms - might require PIC to be linked into shared libraries, so safest to prefer shared. 114 set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_SHARED} CACHE INTERNAL "" FORCE) 115 set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED TRUE CACHE INTERNAL "" FORCE) 116 endif() 117 118 elseif(TARGET jsoncpp_lib_static) 119 # Well, only one variant, but we know for sure that it's static. 120 set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) 121 set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib_static CACHE INTERNAL "" FORCE) 122 set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) 123 124 elseif(__jsoncpp_have_jsoncpplib AND __jsoncpp_lib_type STREQUAL "STATIC_LIBRARY") 125 # We were able to figure out the mystery library is static! 126 set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib CACHE INTERNAL "" FORCE) 127 set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) 128 set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) 129 130 elseif(__jsoncpp_have_jsoncpplib AND __jsoncpp_lib_type STREQUAL "SHARED_LIBRARY") 131 # We were able to figure out the mystery library is shared! 132 set(JSONCPP_IMPORTED_LIBRARY_SHARED jsoncpp_lib CACHE INTERNAL "" FORCE) 133 set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) 134 set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED TRUE CACHE INTERNAL "" FORCE) 135 136 elseif(__jsoncpp_have_jsoncpplib) 137 # One variant, and we have no idea if this is just an old version or if 138 # this is shared based on the target name alone. Hmm. 139 set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) 140 endif() 141 142 # Now, we need include directories. Can't just limit this to old CMakes, since 143 # new CMakes might be used to build projects designed to support older ones. 144 if(__jsoncpp_have_jsoncpplib) 145 get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES) 146 if(__jsoncpp_interface_include_dirs) 147 set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) 148 endif() 149 endif() 150 if(TARGET jsoncpp_lib_static AND NOT JSONCPP_IMPORTED_INCLUDE_DIRS) 151 get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib_static PROPERTY INTERFACE_INCLUDE_DIRECTORIES) 152 if(__jsoncpp_interface_include_dirs) 153 set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) 154 endif() 155 endif() 156endif() 157 158# As a convenience... 159if(TARGET jsoncpp_lib_static AND NOT TARGET jsoncpp_lib) 160 add_library(jsoncpp_lib INTERFACE) 161 target_link_libraries(jsoncpp_lib INTERFACE jsoncpp_lib_static) 162endif() 163 164if(JSONCPP_IMPORTED_LIBRARY) 165 if(NOT JSONCPP_IMPORTED_INCLUDE_DIRS) 166 # OK, so we couldn't get it from the target... maybe we can figure it out from jsoncpp_DIR. 167 168 # take off the jsoncpp component 169 get_filename_component(__jsoncpp_import_root "${jsoncpp_DIR}/.." ABSOLUTE) 170 set(__jsoncpp_hints "${__jsoncpp_import_root}") 171 # take off the cmake component 172 get_filename_component(__jsoncpp_import_root "${__jsoncpp_import_root}/.." ABSOLUTE) 173 list(APPEND __jsoncpp_hints "${__jsoncpp_import_root}") 174 # take off the lib component 175 get_filename_component(__jsoncpp_import_root "${__jsoncpp_import_root}/.." ABSOLUTE) 176 list(APPEND __jsoncpp_hints "${__jsoncpp_import_root}") 177 # take off one more component in case of multiarch lib 178 get_filename_component(__jsoncpp_import_root "${__jsoncpp_import_root}/.." ABSOLUTE) 179 list(APPEND __jsoncpp_hints "${__jsoncpp_import_root}") 180 181 # Now, search. 182 find_path(JsonCpp_INCLUDE_DIR 183 NAMES 184 json/json.h 185 PATH_SUFFIXES include jsoncpp include/jsoncpp 186 HINTS ${__jsoncpp_hints}) 187 if(JsonCpp_INCLUDE_DIR) 188 mark_as_advanced(JsonCpp_INCLUDE_DIR) 189 # Note - this does not set it in the cache, in case we find it better at some point in the future! 190 set(JSONCPP_IMPORTED_INCLUDE_DIRS ${JsonCpp_INCLUDE_DIR}) 191 endif() 192 endif() 193 194 find_package_handle_standard_args(JsonCpp 195 DEFAULT_MSG 196 jsoncpp_DIR 197 JSONCPP_IMPORTED_LIBRARY 198 JSONCPP_IMPORTED_INCLUDE_DIRS) 199endif() 200 201if(JSONCPP_FOUND) 202 # Create any missing namespaced targets from the config module. 203 if(__jsoncpp_have_namespaced_targets) 204 if(JSONCPP_IMPORTED_LIBRARY AND NOT TARGET JsonCpp::JsonCpp) 205 add_library(JsonCpp::JsonCpp INTERFACE IMPORTED) 206 set_target_properties(JsonCpp::JsonCpp PROPERTIES 207 INTERFACE_INCLUDE_DIRECTORIES "${JSONCPP_IMPORTED_INCLUDE_DIRS}" 208 INTERFACE_LINK_LIBRARIES "${JSONCPP_IMPORTED_LIBRARY}") 209 endif() 210 211 if(JSONCPP_IMPORTED_LIBRARY_SHARED AND NOT TARGET JsonCpp::JsonCppShared) 212 add_library(JsonCpp::JsonCppShared INTERFACE IMPORTED) 213 set_target_properties(JsonCpp::JsonCppShared PROPERTIES 214 INTERFACE_INCLUDE_DIRECTORIES "${JSONCPP_IMPORTED_INCLUDE_DIRS}" 215 INTERFACE_LINK_LIBRARIES "${JSONCPP_IMPORTED_LIBRARY_SHARED}") 216 endif() 217 218 if(JSONCPP_IMPORTED_LIBRARY_STATIC AND NOT TARGET JsonCpp::JsonCppStatic) 219 add_library(JsonCpp::JsonCppStatic INTERFACE IMPORTED) 220 set_target_properties(JsonCpp::JsonCppStatic PROPERTIES 221 INTERFACE_INCLUDE_DIRECTORIES "${JSONCPP_IMPORTED_INCLUDE_DIRS}" 222 INTERFACE_LINK_LIBRARIES "${JSONCPP_IMPORTED_LIBRARY_STATIC}") 223 endif() 224 225 # Hide the stuff we didn't, and no longer, need. 226 if(NOT JsonCpp_LIBRARY) 227 unset(JsonCpp_LIBRARY CACHE) 228 endif() 229 if(NOT JsonCpp_INCLUDE_DIR) 230 unset(JsonCpp_INCLUDE_DIR CACHE) 231 endif() 232 endif() 233 234 set(JSONCPP_LIBRARY ${JSONCPP_IMPORTED_LIBRARY}) 235 set(JSONCPP_INCLUDE_DIRS ${JSONCPP_IMPORTED_INCLUDE_DIRS}) 236 if(DEFINED JSONCPP_IMPORTED_LIBRARY_IS_SHARED) 237 set(JSONCPP_LIBRARY_IS_SHARED ${JSONCPP_IMPORTED_LIBRARY_IS_SHARED}) 238 else() 239 unset(JSONCPP_LIBRARY_IS_SHARED) 240 endif() 241 242 if(JSONCPP_IMPORTED_LIBRARY_SHARED) 243 set(JSONCPP_LIBRARY_SHARED ${JSONCPP_IMPORTED_LIBRARY_SHARED}) 244 endif() 245 246 if(JSONCPP_IMPORTED_LIBRARY_STATIC) 247 set(JSONCPP_LIBRARY_STATIC ${JSONCPP_IMPORTED_LIBRARY_STATIC}) 248 endif() 249endif() 250 251# Still nothing after looking for the config file: must go "old-school" 252if(NOT JSONCPP_FOUND) 253 # Invoke pkgconfig for hints 254 find_package(PkgConfig QUIET) 255 set(_JSONCPP_INCLUDE_HINTS) 256 set(_JSONCPP_LIB_HINTS) 257 if(PKG_CONFIG_FOUND) 258 pkg_search_module(_JSONCPP_PC QUIET jsoncpp) 259 if(_JSONCPP_PC_INCLUDE_DIRS) 260 set(_JSONCPP_INCLUDE_HINTS ${_JSONCPP_PC_INCLUDE_DIRS}) 261 endif() 262 if(_JSONCPP_PC_LIBRARY_DIRS) 263 set(_JSONCPP_LIB_HINTS ${_JSONCPP_PC_LIBRARY_DIRS}) 264 endif() 265 if(_JSONCPP_PC_LIBRARIES) 266 set(_JSONCPP_LIB_NAMES ${_JSONCPP_PC_LIBRARIES}) 267 endif() 268 endif() 269 270 if(NOT _JSONCPP_LIB_NAMES) 271 # OK, if pkg-config wasn't able to give us a library name suggestion, then we may 272 # have to resort to some intense old logic. 273 set(_JSONCPP_LIB_NAMES jsoncpp) 274 set(_JSONCPP_PATHSUFFIXES) 275 276 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 277 list(APPEND _JSONCPP_PATHSUFFIXES 278 linux-gcc) # bit of a generalization but close... 279 endif() 280 if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_NAME STREQUAL "Linux") 281 list(APPEND 282 _JSONCPP_LIB_NAMES 283 json_linux-gcc-${CMAKE_CXX_COMPILER_VERSION}_libmt 284 json_linux-gcc_libmt) 285 list(APPEND _JSONCPP_PATHSUFFIXES 286 linux-gcc-${CMAKE_CXX_COMPILER_VERSION}) 287 288 elseif(MSVC) 289 if(MSVC_VERSION EQUAL 1200) 290 list(APPEND _JSONCPP_LIB_NAMES json_vc6_libmt) 291 list(APPEND _JSONCPP_PATHSUFFIXES msvc6) 292 elseif(MSVC_VERSION EQUAL 1300) 293 list(APPEND _JSONCPP_LIB_NAMES json_vc7_libmt) 294 list(APPEND _JSONCPP_PATHSUFFIXES msvc7) 295 elseif(MSVC_VERSION EQUAL 1310) 296 list(APPEND _JSONCPP_LIB_NAMES json_vc71_libmt) 297 list(APPEND _JSONCPP_PATHSUFFIXES msvc71) 298 elseif(MSVC_VERSION EQUAL 1400) 299 list(APPEND _JSONCPP_LIB_NAMES json_vc8_libmt) 300 list(APPEND _JSONCPP_PATHSUFFIXES msvc80) 301 elseif(MSVC_VERSION EQUAL 1500) 302 list(APPEND _JSONCPP_LIB_NAMES json_vc9_libmt) 303 list(APPEND _JSONCPP_PATHSUFFIXES msvc90) 304 elseif(MSVC_VERSION EQUAL 1600) 305 list(APPEND _JSONCPP_LIB_NAMES json_vc10_libmt) 306 list(APPEND _JSONCPP_PATHSUFFIXES msvc10 msvc100) 307 endif() 308 309 elseif(MINGW) 310 list(APPEND _JSONCPP_LIB_NAMES 311 json_mingw_libmt) 312 list(APPEND _JSONCPP_PATHSUFFIXES mingw) 313 314 else() 315 list(APPEND _JSONCPP_LIB_NAMES 316 json_suncc_libmt 317 json_vacpp_libmt) 318 endif() 319 endif() # end of old logic 320 321 # Actually go looking. 322 find_path(JsonCpp_INCLUDE_DIR 323 NAMES 324 json/json.h 325 PATH_SUFFIXES jsoncpp 326 HINTS ${_JSONCPP_INCLUDE_HINTS}) 327 find_library(JsonCpp_LIBRARY 328 NAMES 329 ${_JSONCPP_LIB_NAMES} 330 PATHS libs 331 PATH_SUFFIXES ${_JSONCPP_PATHSUFFIXES} 332 HINTS ${_JSONCPP_LIB_HINTS}) 333 334 find_package_handle_standard_args(JsonCpp 335 DEFAULT_MSG 336 JsonCpp_INCLUDE_DIR 337 JsonCpp_LIBRARY) 338 339 if(JSONCPP_FOUND) 340 # We already know that the target doesn't exist, let's make it. 341 # TODO don't know why we get errors like: 342 # error: 'JsonCpp::JsonCpp-NOTFOUND', needed by 'bin/osvr_json_to_c', missing and no known rule to make it 343 # when we do the imported target commented out below. So, instead, we make an interface 344 # target with an alias. Hmm. 345 346 #add_library(JsonCpp::JsonCpp UNKNOWN IMPORTED) 347 #set_target_properties(JsonCpp::JsonCpp PROPERTIES 348 # IMPORTED_LOCATION "${JsonCpp_LIBRARY}" 349 # INTERFACE_INCLUDE_DIRECTORIES "${JsonCpp_INCLUDE_DIR}" 350 # IMPORTED_LINK_INTERFACE_LANGUAGES "CXX") 351 352 set(JSONCPP_LIBRARY "${JsonCpp_LIBRARY}") 353 set(JSONCPP_INCLUDE_DIRS "${JsonCpp_INCLUDE_DIR}") 354 unset(JSONCPP_LIBRARY_IS_SHARED) 355 356 if(__jsoncpp_have_interface_support AND NOT TARGET jsoncpp_interface) 357 add_library(jsoncpp_interface INTERFACE) 358 set_target_properties(jsoncpp_interface PROPERTIES 359 INTERFACE_LINK_LIBRARIES "${JsonCpp_LIBRARY}" 360 INTERFACE_INCLUDE_DIRECTORIES "${JsonCpp_INCLUDE_DIR}") 361 endif() 362 if(__jsoncpp_have_namespaced_targets) 363 if(NOT TARGET JsonCpp::JsonCpp) 364 add_library(JsonCpp::JsonCpp ALIAS jsoncpp_interface) 365 endif() 366 endif() 367 endif() 368endif() 369 370if(JSONCPP_FOUND) 371 mark_as_advanced(jsoncpp_DIR JsonCpp_INCLUDE_DIR JsonCpp_LIBRARY) 372endif() 373