summaryrefslogtreecommitdiffstats
path: root/cmake/Modules/FindCRYPTO.cmake
blob: 25846f3ca093b2abc03f6a127ca0f6b416eab2dd (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
#
# Try to find libcrypto.
#

#
# Were we told where to look for libcrypto?
#
if(NOT CRYPTO_ROOT)
  #
  # No.
  #
  # First, try looking for it with pkg-config, if we have it.
  #
  find_package(PkgConfig)

  #
  # Homebrew's pkg-config does not, by default, look for
  # pkg-config files for packages it has installed.
  # Furthermore, at least for OpenSSL, they appear to be
  # dumped in package-specific directories whose paths are
  # not only package-specific but package-version-specific.
  #
  # So the only way to find openssl is to get the value of
  # PKG_CONFIG_PATH from "brew --env openssl" and add that
  # to PKG_CONFIG_PATH.  (No, we can't just assume it's under
  # /usr/local; Homebrew have conveniently chosen to put it
  # under /opt/homebrew on ARM.)
  #
  # That's the nice thing about Homebrew - it makes things easier!
  # Thanks!
  #
  find_program(BREW brew)
  if(BREW)
    #
    # We have Homebrew.
    # Get the pkg-config directory for openssl.
    #
    execute_process(COMMAND "${BREW}" "--env" "--plain" "openssl"
      RESULT_VARIABLE BREW_RESULT
      OUTPUT_VARIABLE BREW_OUTPUT
      OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    if(BREW_RESULT EQUAL 0)
      #
      # brew --env --plain openssl succeeded.
      # Split its output into a list, one entry per line.
      #
      string(REGEX MATCHALL "[^\n\r]+" BREW_OUTPUT_LINES "${BREW_OUTPUT}")

      #
      # Find the line that begins with "PKG_CONFIG_PATH: ", and extract
      # the path following that.
      #
      foreach(LINE IN LISTS BREW_OUTPUT_LINES)
        if(LINE MATCHES "PKG_CONFIG_PATH: \(.*\)")
          string(REGEX REPLACE "PKG_CONFIG_PATH: \(.*\)"
              "\\1" OPENSSL_PKGCONFIG_DIR
              ${LINE})
        endif()
      endforeach()
    endif()
  endif()

  #
  # Save the current value of the PKG_CONFIG_PATH environment
  # variable.
  #
  set(SAVE_PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH})

  #
  # If we got an additional pkg-config directory from Homebrew, add
  # it to the PKG_CONFIG_PATH environment variable.
  #
  if(OPENSSL_PKGCONFIG_DIR)
    set(ENV{PKG_CONFIG_PATH} "${OPENSSL_PKGCONFIG_DIR}:$ENV{PKG_CONFIG_PATH}")
  endif()

  #
  # Use pkg-config to find libcrypto.
  #
  pkg_check_modules(CRYPTO libcrypto)

  #
  # Revert the change to PKG_CONFIG_PATH.
  #
  set(ENV{PKG_CONFIG_PATH} "${SAVE_PKG_CONFIG_PATH}")

  #
  # Did pkg-config find it?
  #
  if(CRYPTO_FOUND)
    #
    # This "helpfully" supplies CRYPTO_LIBRARIES as a bunch of
    # library names - not paths - and CRYPTO_LIBRARY_DIRS as
    # a bunch of directories.
    #
    # CMake *really* doesn't like the notion of specifying "here are
    # the directories in which to look for libraries" except in
    # find_library() calls; it *really* prefers using full paths to
    # library files, rather than library names.
    #
    # Find the libraries and add their full paths.
    #
    set(CRYPTO_LIBRARY_FULLPATHS)
    foreach(_lib IN LISTS CRYPTO_LIBRARIES)
      #
      # Try to find this library, so we get its full path.
      #
      find_library(_libfullpath ${_lib} HINTS ${CRYPTO_LIBRARY_DIRS})
      list(APPEND CRYPTO_LIBRARY_FULLPATHS ${_libfullpath})
    endforeach()
    set(CRYPTO_LIBRARIES "${CRYPTO_LIBRARY_FULLPATHS}")
  else()
    #
    # No.  If we have Homebrew installed, see if it's in Homebrew.
    #
    if(BREW)
      #
      # The brew man page lies when it speaks of
      # $BREW --prefix --installed <formula>
      # outputting nothing.  In Homebrew 3.3.16,
      # it produces output regardless of whether
      # the formula is installed or not, so we
      # send the standard output and error to
      # the bit bucket.
      #
      # libcrypto isn't a formula, openssl is a formula.
      #
      execute_process(COMMAND "${BREW}" "--prefix" "--installed" "openssl"
        RESULT_VARIABLE BREW_RESULT
        OUTPUT_QUIET
      )
      if(BREW_RESULT EQUAL 0)
        #
        # Yes.  Get the include directory and library
        # directory.  (No, we can't just assume it's
        # under /usr/local; Homebrew have conveniently
        # chosen to put it under /opt/homebrew on ARM.)
        #
        execute_process(COMMAND "${BREW}" "--prefix" "openssl"
          RESULT_VARIABLE BREW_RESULT
          OUTPUT_VARIABLE OPENSSL_PATH
          OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        set(CRYPTO_INCLUDE_DIRS "${OPENSSL_PATH}/include")

        #
        # Search for the libcrypto library under lib.
        #
        find_library(CRYPTO_LIBRARIES crypto
            PATHS "${OPENSSL_PATH}/lib"
            NO_DEFAULT_PATH)
      endif()
    endif()
  endif()
endif()

#
# Have we found it with pkg-config or Homebrew?
#
if(NOT CRYPTO_INCLUDE_DIRS)
  #
  # No.
  # Try to find the openss/evp.h header.
  # We search for that header to make sure that it's installed (if
  # it's just a shared library for the benefit of existing
  # programs, that's not useful).
  #
  find_path(CRYPTO_INCLUDE_DIRS openssl/evp.h)

  #
  # Try to find the library.
  #
  find_library(CRYPTO_LIBRARIES crypto)
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CRYPTO
  DEFAULT_MSG
  CRYPTO_INCLUDE_DIRS
  CRYPTO_LIBRARIES
)

mark_as_advanced(
  CRYPTO_INCLUDE_DIRS
  CRYPTO_LIBRARIES
)