aboutsummaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 6375f9dd8c06f126c92302ada7c7b43f648c4a6e (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
cmake_minimum_required(VERSION 3.3.0)
cmake_policy(SET CMP0048 NEW)

# Specify search path for CMake modules to be loaded by include() 
# and find_package()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")

# Add defaults for cmake
# Those need to be set before the project() call.
include(DefineCMakeDefaults)
include(DefineCompilerFlags)

project(libssh VERSION 0.8.90 LANGUAGES C)

# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME})

# SOVERSION scheme: CURRENT.AGE.REVISION
#   If there was an incompatible interface change:
#     Increment CURRENT. Set AGE and REVISION to 0
#   If there was a compatible interface change:
#     Increment AGE. Set REVISION to 0
#   If the source code was changed, but there were no interface changes:
#     Increment REVISION.
set(LIBRARY_VERSION "4.8.1")
set(LIBRARY_SOVERSION "4")

# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked

# add definitions
include(DefinePlatformDefaults)
include(DefineOptions.cmake)
include(CPackConfig.cmake)
include(GNUInstallDirs)

include(CompilerChecks.cmake)

# disallow in-source build
include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")

# Copy library files to a lib sub-directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

# search for libraries
if (WITH_ZLIB)
    find_package(ZLIB REQUIRED)
endif (WITH_ZLIB)

if (WITH_GCRYPT)
  find_package(GCrypt 1.5.0 REQUIRED)
  if (NOT GCRYPT_FOUND)
    message(FATAL_ERROR "Could not find GCrypt")
  endif (NOT GCRYPT_FOUND)
elseif(WITH_MBEDTLS)
    find_package(MbedTLS REQUIRED)
    if (NOT MBEDTLS_FOUND)
      message(FATAL_ERROR "Could not find mbedTLS")
    endif (NOT MBEDTLS_FOUND)
else (WITH_GCRYPT)
  find_package(OpenSSL)
  if (NOT OPENSSL_FOUND)
    find_package(GCrypt)
    if (NOT GCRYPT_FOUND)
      find_package(MbedTLS)
      if (NOT MBEDTLS_FOUND)
        message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
      endif (NOT MBEDTLS_FOUND)
    endif (NOT GCRYPT_FOUND)
  endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)

if (UNIT_TESTING)
    find_package(CMocka REQUIRED)
endif ()

# Find out if we have threading available
set(CMAKE_THREAD_PREFER_PTHREADS ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)

if (WITH_GSSAPI)
    find_package(GSSAPI)
endif (WITH_GSSAPI)

if (WITH_NACL)
    find_package(NaCl)
    if (NOT NACL_FOUND)
        set(WITH_NACL OFF)
    endif (NOT NACL_FOUND)
endif (WITH_NACL)

if (BSD OR SOLARIS OR OSX)
    find_package(Argp)
endif (BSD OR SOLARIS OR OSX)

# Disable symbol versioning in non UNIX platforms
if (UNIX)
    find_package(ABIMap 0.3.1)
else (UNIX)
    set(WITH_SYMBOL_VERSIONING OFF)
endif (UNIX)

# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)

# check subdirectories
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(src)

# pkg-config file
if (UNIX)
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
install(
  FILES
    ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
  DESTINATION
    ${CMAKE_INSTALL_LIBDIR}/pkgconfig
  COMPONENT
    pkgconfig
)
endif (UNIX)

# CMake config files
include(CMakePackageConfigHelpers)

set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})

# libssh-config-version.cmake
write_basic_package_version_file(libssh-config-version.cmake
                                 VERSION ${PROJECT_VERSION}
                                 COMPATIBILITY SameMajorVersion)

install(
    FILES
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
    DESTINATION
        ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
    COMPONENT
        devel)

if (WITH_EXAMPLES)
    add_subdirectory(examples)
endif (WITH_EXAMPLES)

if (UNIT_TESTING)
    include(AddCMockaTest)
    add_subdirectory(tests)
endif (UNIT_TESTING)

### SOURCE PACKAGE
if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
    # Get the current ABI version from source
    get_filename_component(current_abi_path
                           "${CMAKE_SOURCE_DIR}/src/ABI/current"
                           ABSOLUTE)

    # Check if the ABI version should be updated
    file(READ ${current_abi_path} CURRENT_ABI_CONTENT)
    string(STRIP "${CURRENT_ABI_CONTENT}" CURRENT_ABI_VERSION)

    if (LIBRARY_VERSION VERSION_GREATER CURRENT_ABI_VERSION)
        set(UPDATE_ABI TRUE)
    endif ()

    if (UPDATE_ABI)
        message(STATUS "Library version bumped to ${LIBRARY_VERSION}: Updating ABI")

        # Get the list of header files
        get_file_list(${PROJECT_NAME}_header_list
                      DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libssh"
                      FILES_PATTERNS "*.h")

        # Extract the symbols marked as "LIBSSH_API" from the header files
        extract_symbols(${PROJECT_NAME}.symbols
                        HEADERS_LIST ${PROJECT_NAME}_header_list
                        FILTER_PATTERN "LIBSSH_API"
                        COPY_TO "${CMAKE_SOURCE_DIR}/src/ABI/${PROJECT_NAME}-${LIBRARY_VERSION}.symbols")

        if (WITH_ABI_BREAK)
            set(ALLOW_ABI_BREAK "BREAK_ABI")
        endif()

        # Target we can depend on in 'make dist'
        set(_SYMBOL_TARGET "${PROJECT_NAME}.map")

        # Set the path to the current map file
        set(MAP_PATH "${CMAKE_SOURCE_DIR}/src/${_SYMBOL_TARGET}")

        # Generate the symbol version map file
        generate_map_file(${_SYMBOL_TARGET}
                          SYMBOLS ${PROJECT_NAME}.symbols
                          RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION}
                          CURRENT_MAP ${MAP_PATH}
                          COPY_TO ${MAP_PATH}
                          FINAL
                          ${ALLOW_ABI_BREAK})

        # Write the current version to the source
        file(WRITE ${current_abi_path} ${LIBRARY_VERSION})
    endif(UPDATE_ABI)
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)

add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET})

# Link compile database for clangd
execute_process(COMMAND cmake -E create_symlink
                "${CMAKE_BINARY_DIR}/compile_commands.json"
                "${CMAKE_SOURCE_DIR}/compile_commands.json")

message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} build options : **********")

message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
message(STATUS "libnacl support: ${WITH_NACL}")
message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}")
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
message(STATUS "GEX support : ${WITH_GEX}")
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}")
message(STATUS "Unit testing: ${UNIT_TESTING}")
message(STATUS "Client code testing: ${CLIENT_TESTING}")
message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}")
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
set(_SERVER_TESTING OFF)
if (WITH_SERVER)
    set(_SERVER_TESTING ${SERVER_TESTING})
endif()
message(STATUS "Server code testing: ${_SERVER_TESTING}")
if (WITH_INTERNAL_DOC)
    message(STATUS "Internal documentation generation")
else (WITH_INTERNAL_DOC)
    message(STATUS "Public API documentation generation")
endif (WITH_INTERNAL_DOC)
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
message(STATUS "Release is final: ${WITH_FINAL}")
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
if (WITH_SERVER)
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
endif()
message(STATUS "********************************************")