1# Module to find OpenEXR and Imath.
2#
3# I'm afraid this is a mess, due to needing to support a wide range of
4# OpenEXR versions.
5#
6# For OpenEXR & Imath 3.0, this will establish the following imported
7# targets:
8#
9#    Imath::Imath
10#    Imath::Half
11#    OpenEXR::OpenEXR
12#    OpenEXR::Iex
13#    OpenEXR::IlmThread
14#
15# For OpenEXR 2.4 & 2.5, it will establish the following imported targets:
16#
17#    IlmBase::Imath
18#    IlmBase::Half
19#    IlmBase::Iex
20#    IlmBase::IlmThread
21#    OpenEXR::IlmImf
22#
23# For all versions -- but for OpenEXR < 2.4 the only thing this sets --
24# are the following CMake variables:
25#
26#   OPENEXR_FOUND          true, if found
27#   OPENEXR_INCLUDES       directory where OpenEXR headers are found
28#   OPENEXR_LIBRARIES      libraries for OpenEXR + IlmBase
29#   OPENEXR_VERSION        OpenEXR version (accurate for >= 2.0.0,
30#                              otherwise will just guess 1.6.1)
31#   IMATH_INCLUDES         directory where Imath headers are found
32#   ILMBASE_INCLUDES       directory where IlmBase headers are found
33#   ILMBASE_LIBRARIES      libraries just IlmBase
34#
35#
36
37# First, try to fine just the right config files
38find_package(Imath CONFIG)
39if (NOT TARGET Imath::Imath)
40    # Couldn't find Imath::Imath, maybe it's older and has IlmBase?
41    find_package(IlmBase CONFIG)
42endif ()
43find_package(OpenEXR CONFIG)
44
45if (TARGET OpenEXR::OpenEXR AND TARGET Imath::Imath)
46    # OpenEXR 3.x if both of these targets are found
47    set (FOUND_OPENEXR_WITH_CONFIG 1)
48    if (NOT OpenEXR_FIND_QUIETLY)
49        message (STATUS "Found CONFIG for OpenEXR 3 (OPENEXR_VERSION=${OpenEXR_VERSION})")
50    endif ()
51
52    # Mimic old style variables
53    set (OPENEXR_VERSION ${OpenEXR_VERSION})
54    get_target_property(IMATH_INCLUDES Imath::Imath INTERFACE_INCLUDE_DIRECTORIES)
55    get_target_property(ILMBASE_INCLUDES Imath::Imath INTERFACE_INCLUDE_DIRECTORIES)
56    get_target_property(ILMBASE_IMATH_LIBRARY Imath::Imath INTERFACE_LINK_LIBRARIES)
57    get_target_property(IMATH_LIBRARY Imath::Imath INTERFACE_LINK_LIBRARIES)
58    get_target_property(OPENEXR_IEX_LIBRARY OpenEXR::Iex INTERFACE_LINK_LIBRARIES)
59    get_target_property(OPENEXR_ILMTHREAD_LIBRARY OpenEXR::IlmThread INTERFACE_LINK_LIBRARIES)
60    set (ILMBASE_LIBRARIES ${ILMBASE_IMATH_LIBRARY})
61    set (ILMBASE_FOUND true)
62
63    get_target_property(OPENEXR_INCLUDES OpenEXR::OpenEXR INTERFACE_INCLUDE_DIRECTORIES)
64    get_target_property(OPENEXR_ILMIMF_LIBRARY OpenEXR::OpenEXR INTERFACE_LINK_LIBRARIES)
65    set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ILMBASE_LIBRARIES})
66    set (OPENEXR_FOUND true)
67
68    # Link with pthreads if required
69    find_package (Threads)
70    if (CMAKE_USE_PTHREADS_INIT)
71        list (APPEND ILMBASE_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
72    endif ()
73
74elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
75        (OPENEXR_VERSION VERSION_GREATER_EQUAL 2.4 OR OpenEXR_VERSION VERSION_GREATER_EQUAL 2.4))
76    # OpenEXR 2.4 or 2.5 with exported config
77    set (FOUND_OPENEXR_WITH_CONFIG 1)
78    if (NOT OpenEXR_FIND_QUIETLY)
79        message (STATUS "Found CONFIG for OpenEXR 2 (OPENEXR_VERSION=${OpenEXR_VERSION})")
80    endif ()
81
82    # Mimic old style variables
83    get_target_property(ILMBASE_INCLUDES IlmBase::IlmBaseConfig INTERFACE_INCLUDE_DIRECTORIES)
84    get_target_property(IMATH_INCLUDES IlmBase::IlmBaseConfig INTERFACE_INCLUDE_DIRECTORIES)
85    get_target_property(ILMBASE_Imath_LIBRARY IlmBase::Imath INTERFACE_LINK_LIBRARIES)
86    get_target_property(ILMBASE_IMATH_LIBRARY IlmBase::Imath INTERFACE_LINK_LIBRARIES)
87    get_target_property(ILMBASE_HALF_LIBRARY IlmBase::Half INTERFACE_LINK_LIBRARIES)
88    get_target_property(OPENEXR_IEX_LIBRARY IlmBase::Iex INTERFACE_LINK_LIBRARIES)
89    get_target_property(OPENEXR_ILMTHREAD_LIBRARY IlmBase::IlmThread INTERFACE_LINK_LIBRARIES)
90    set (ILMBASE_LIBRARIES ${ILMBASE_IMATH_LIBRARY} ${ILMBASE_HALF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY})
91    set (ILMBASE_FOUND true)
92
93    get_target_property(OPENEXR_INCLUDES OpenEXR::IlmImfConfig INTERFACE_INCLUDE_DIRECTORIES)
94    get_target_property(OPENEXR_ILMIMF_LIBRARY OpenEXR::IlmImf INTERFACE_LINK_LIBRARIES)
95    set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${ILMBASE_LIBRARIES})
96    set (OPENEXR_FOUND true)
97
98    # Link with pthreads if required
99    find_package (Threads)
100    if (CMAKE_USE_PTHREADS_INIT)
101        list (APPEND ILMBASE_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
102    endif ()
103
104    # Correct for how old OpenEXR config exports set the directory one
105    # level lower than we prefer it.
106    string(REGEX REPLACE "include/OpenEXR$" "include" ILMBASE_INCLUDES "${ILMBASE_INCLUDES}")
107    string(REGEX REPLACE "include/OpenEXR$" "include" IMATH_INCLUDES "${IMATH_INCLUDES}")
108    string(REGEX REPLACE "include/OpenEXR$" "include" OPENEXR_INCLUDES "${OPENEXR_INCLUDES}")
109
110else ()
111    # OpenEXR 2.x older versions without a config or whose configs we don't
112    # trust.
113
114    set (FOUND_OPENEXR_WITH_CONFIG 0)
115
116# Other standard issue macros
117include (FindPackageHandleStandardArgs)
118include (SelectLibraryConfigurations)
119
120find_package (ZLIB REQUIRED)
121
122# Link with pthreads if required
123find_package (Threads)
124if (CMAKE_USE_PTHREADS_INIT)
125    set (ILMBASE_PTHREADS ${CMAKE_THREAD_LIBS_INIT})
126endif ()
127
128# Attempt to find OpenEXR with pkgconfig
129find_package(PkgConfig)
130if (PKG_CONFIG_FOUND)
131    if (NOT Ilmbase_ROOT AND NOT ILMBASE_ROOT
132        AND NOT DEFINED ENV{Ilmbase_ROOT} AND NOT DEFINED ENV{ILMBASE_ROOT})
133        pkg_check_modules(_ILMBASE QUIET IlmBase>=2.0.0)
134    endif ()
135    if (NOT OpenEXR_ROOT AND NOT OPENEXR_ROOT
136        AND NOT DEFINED ENV{OpenEXR_ROOT} AND NOT DEFINED ENV{OPENEXR_ROOT})
137        pkg_check_modules(_OPENEXR QUIET OpenEXR>=2.0.0)
138    endif ()
139endif (PKG_CONFIG_FOUND)
140
141# List of likely places to find the headers -- note priority override of
142# ${OPENEXR_ROOT}/include.
143# ILMBASE is needed in case ilmbase an openexr are installed in separate
144# directories, like NixOS does
145set (GENERIC_INCLUDE_PATHS
146    ${OPENEXR_ROOT}/include
147    $ENV{OPENEXR_ROOT}/include
148    ${ILMBASE_ROOT}/include
149    $ENV{ILMBASE_ROOT}/include
150    ${_ILMBASE_INCLUDEDIR}
151    ${_OPENEXR_INCLUDEDIR}
152    /usr/local/include
153    /usr/include
154    /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
155    /sw/include
156    /opt/local/include )
157
158# Find the include file locations.
159find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h
160           HINTS ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}
161                 ${GENERIC_INCLUDE_PATHS} )
162find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
163           HINTS ${OPENEXR_INCLUDE_DIR}
164                 ${GENERIC_INCLUDE_PATHS} )
165
166# Try to figure out version number
167if (DEFINED _OPENEXR_VERSION AND NOT "${_OPENEXR_VERSION}" STREQUAL "")
168    set (OPENEXR_VERSION "${_OPENEXR_VERSION}")
169    string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OPENEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
170    string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OPENEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
171elseif (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
172    # Must be at least 2.0
173    file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_STRING .*$")
174    string (REGEX MATCHALL "[0-9]+[.0-9]+" OPENEXR_VERSION ${TMP})
175    file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MAJOR .*$")
176    string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MAJOR ${TMP})
177    file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MINOR .*$")
178    string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MINOR ${TMP})
179else ()
180    # Assume an old one, predates 2.x that had versions
181    set (OPENEXR_VERSION 1.6.1)
182    set (OPENEXR_MAJOR 1)
183    set (OPENEXR_MINOR 6)
184endif ()
185
186
187# List of likely places to find the libraries -- note priority override of
188# ${OPENEXR_ROOT}/lib.
189set (GENERIC_LIBRARY_PATHS
190    ${OPENEXR_ROOT}/lib
191    ${ILMBASE_ROOT}/lib
192    ${OPENEXR_INCLUDE_PATH}/../lib
193    ${ILMBASE_INCLUDE_PATH}/../lib
194    ${_ILMBASE_LIBDIR}
195    ${_OPENEXR_LIBDIR}
196    /usr/local/lib
197    /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
198    /usr/lib
199    /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
200    /sw/lib
201    /opt/local/lib
202    $ENV{PROGRAM_FILES}/OpenEXR/lib/static )
203
204# message (STATUS "Generic lib paths: ${GENERIC_LIBRARY_PATHS}")
205
206# Handle request for static libs by altering CMAKE_FIND_LIBRARY_SUFFIXES.
207# We will restore it at the end of this file.
208set (_openexr_orig_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
209if (OpenEXR_USE_STATIC_LIBS)
210    if (WIN32)
211        set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
212    else ()
213        set (CMAKE_FIND_LIBRARY_SUFFIXES .a)
214    endif ()
215endif ()
216
217# Look for the libraries themselves, for all the components.
218# This is complicated because the OpenEXR libraries may or may not be
219# built with version numbers embedded.
220set (_openexr_components IlmThread IlmImf Imath Iex Half)
221foreach (COMPONENT ${_openexr_components})
222    string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
223    # First try with the version embedded
224    find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY
225                  NAMES ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}
226                        ${COMPONENT}
227                        ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}_d
228                        ${COMPONENT}_d
229                  HINTS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
230                        ${GENERIC_LIBRARY_PATHS} )
231endforeach ()
232
233find_package_handle_standard_args (OpenEXR
234    REQUIRED_VARS ILMBASE_INCLUDE_PATH OPENEXR_INCLUDE_PATH
235                  OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY
236                  OPENEXR_IEX_LIBRARY OPENEXR_HALF_LIBRARY
237    )
238
239if (OPENEXR_FOUND)
240    set (OpenEXR_VERSION ${OPENEXR_VERSION})
241    set (ILMBASE_FOUND TRUE)
242    set (ILMBASE_INCLUDES ${ILMBASE_INCLUDE_PATH})
243    set (IMATH_INCLUDES ${ILMBASE_INCLUDE_PATH})
244    set (OPENEXR_INCLUDES ${OPENEXR_INCLUDE_PATH})
245    set (ILMBASE_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
246    set (IMATH_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
247    set (OPENEXR_INCLUDE_DIR ${OPENEXR_INCLUDE_PATH})
248    set (ILMBASE_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ILMBASE_PTHREADS} CACHE STRING "The libraries needed to use IlmBase")
249    set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${ILMBASE_LIBRARIES} ${ZLIB_LIBRARIES} CACHE STRING "The libraries needed to use OpenEXR")
250    set (FINDOPENEXR_FALLBACK TRUE)
251endif ()
252
253mark_as_advanced(
254    OPENEXR_ILMIMF_LIBRARY
255    OPENEXR_IMATH_LIBRARY
256    OPENEXR_IEX_LIBRARY
257    OPENEXR_HALF_LIBRARY
258    OPENEXR_VERSION)
259
260# Restore the original CMAKE_FIND_LIBRARY_SUFFIXES
261set (CMAKE_FIND_LIBRARY_SUFFIXES ${_openexr_orig_suffixes})
262
263endif ()
264