summaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 0d236f82d4908e24a9295f1f79428fc62d773e5d (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
# https://cmake.org/pipermail/cmake/2011-May/044166.html
IF(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS)
    SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
ENDIF()

cmake_minimum_required(VERSION 3.1)
IF (UNIX)
    OPTION(ADD_ASAN "Use ASAN to show memory issues" FALSE)
    OPTION(ADD_TSAN "Use TSAN to show thread issues" FALSE)
    IF(ADD_ASAN)
        SET(EXTRA_LIBS ${EXTRA_LIBS} asan )
        ADD_COMPILE_OPTIONS(-fsanitize=address -fno-omit-frame-pointer)
    ENDIF()
    IF(ADD_TSAN)
        SET(EXTRA_LIBS ${EXTRA_LIBS} tsan )
        SET(USE_CLANG TRUE)
        ADD_COMPILE_OPTIONS(-fsanitize=thread -fno-omit-frame-pointer -fPIC -g) #use with clang
    ENDIF()
    IF(ADD_TSAN AND ADD_ASAN)
        message(FATAL_ERROR "TSAN and ASAN cannot be used at the same time")
    ENDIF()
ENDIF()

project(libnitrokey LANGUAGES C CXX VERSION 3.5.0)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)


include(GNUInstallDirs)



IF (NOT CMAKE_BUILD_TYPE)
    IF(APPLE)
        # Issues occur when build with enabled optimizations
        set(CMAKE_BUILD_TYPE Debug)
    ELSE()
        set(CMAKE_BUILD_TYPE RelWithDebInfo)
    ENDIF()
ENDIF()
MESSAGE("${PROJECT_NAME}: Build type: ${CMAKE_BUILD_TYPE}")

include_directories(hidapi)
include_directories(libnitrokey)
set(SOURCE_FILES
    libnitrokey/command.h
    libnitrokey/command_id.h
    libnitrokey/cxx_semantics.h
    libnitrokey/device.h
    libnitrokey/device_proto.h
    libnitrokey/dissect.h
    libnitrokey/log.h
    libnitrokey/misc.h
    libnitrokey/NitrokeyManager.h
    libnitrokey/stick10_commands.h
    libnitrokey/stick20_commands.h
    libnitrokey/CommandFailedException.h
    libnitrokey/LibraryException.h
    libnitrokey/LongOperationInProgressException.h
    libnitrokey/stick10_commands_0.8.h
    command_id.cc
    device.cc
    log.cc
    misc.cc
    NitrokeyManager.cc
    NK_C_API.h
    NK_C_API.cc
    DeviceCommunicationExceptions.cpp
    ${CMAKE_CURRENT_BINARY_DIR}/version.cc
    )

set(BUILD_SHARED_LIBS ON CACHE BOOL "Build all libraries as shared")
add_library(nitrokey ${SOURCE_FILES})

IF(APPLE)
    include_directories(hidapi/hidapi)
    add_library(hidapi-libusb STATIC hidapi/mac/hid.c )
    target_link_libraries(hidapi-libusb "-framework CoreFoundation" "-framework IOKit")
    target_link_libraries(nitrokey hidapi-libusb)
ELSEIF(UNIX)
#    add_library(hidapi-libusb STATIC hidapi/libusb/hid.c )
    find_package(PkgConfig)
    IF(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
        pkg_search_module(HIDAPI_LIBUSB REQUIRED hidapi)
    ELSE()
        pkg_search_module(HIDAPI_LIBUSB REQUIRED hidapi-libusb)
    ENDIF()
    target_compile_options(nitrokey PRIVATE ${HIDAPI_LIBUSB_CFLAGS})
    target_link_libraries(nitrokey ${HIDAPI_LIBUSB_LDFLAGS})
ELSEIF(WIN32)
    include_directories(hidapi/hidapi)
    add_library(hidapi-libusb STATIC hidapi/windows/hid.c )
    target_link_libraries(hidapi-libusb setupapi)
    target_link_libraries(nitrokey hidapi-libusb)
ENDIF()

set_target_properties(nitrokey PROPERTIES
	VERSION ${libnitrokey_VERSION}
	SOVERSION ${libnitrokey_VERSION_MAJOR})

OPTION(ERROR_ON_WARNING "Stop compilation on warning found (not supported for MSVC)" OFF)
if (NOT MSVC)
    set(COMPILE_FLAGS "-Wall -Wno-unused-function -Wcast-qual -Woverloaded-virtual -Wsign-compare -Wformat -Wformat-security")
    IF(NOT APPLE)
        if (ERROR_ON_WARNING)
            set(COMPILE_FLAGS "${COMPILE_FLAGS} -Werror")
        endif()
    ENDIF()
    SET_TARGET_PROPERTIES(nitrokey PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} )
endif()

OPTION(NO_LOG "Compile without logging functionality and its strings (decreases size)" OFF)
IF (NO_LOG)
    SET_TARGET_PROPERTIES(nitrokey PROPERTIES COMPILE_DEFINITIONS "NO_LOG")
ENDIF()

OPTION(LOG_VOLATILE_DATA "Log volatile data (debug)" OFF)
IF (LOG_VOLATILE_DATA)
    SET_TARGET_PROPERTIES(nitrokey PROPERTIES COMPILE_DEFINITIONS "LOG_VOLATILE_DATA")
ENDIF()


OPTION(ADD_GIT_INFO "Add information about source code version from Git repository" TRUE)
# generate version.h
IF(ADD_GIT_INFO)
execute_process(
	COMMAND git describe --always --abbrev=4 HEAD
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	RESULT_VARIABLE PROJECT_VERSION_GIT_RETURN_CODE
	OUTPUT_VARIABLE PROJECT_VERSION_GIT
	OUTPUT_STRIP_TRAILING_WHITESPACE
	ERROR_QUIET
)
ENDIF()
# the version.h generation logic is tricky in a number of ways:
# 1. git describe on a release tarball will always fail with
#    a non-zero return code, usually 128
# 2. If git is not installed, PROJECT_VERSION_GIT_RETURN_CODE
#    will contain the string 'No such file or directory'
# Hence fallback to PROJECT_VERSION when the return code is NOT 0.
IF((NOT ${ADD_GIT_INFO}) OR (NOT ${PROJECT_VERSION_GIT_RETURN_CODE} STREQUAL "0"))
	MESSAGE(STATUS "Setting fallback Git library version")
	SET(PROJECT_VERSION_GIT "v${PROJECT_VERSION}")
ENDIF()
MESSAGE(STATUS "Setting Git library version to: " ${PROJECT_VERSION_GIT} )
configure_file("version.cc.in" "version.cc" @ONLY)


file(GLOB LIB_INCLUDES "libnitrokey/*.h" "NK_C_API.h")
install (FILES ${LIB_INCLUDES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
install (TARGETS nitrokey DESTINATION ${CMAKE_INSTALL_LIBDIR})

IF(NOT WIN32)
    # Install Nitrokey udev rules
    IF(NOT DEFINED CMAKE_INSTALL_UDEVRULESDIR)
        set(PKG_GET_UDEV_DIR ${PKG_CONFIG_EXECUTABLE} --variable=udevdir udev)
        execute_process(COMMAND ${PKG_GET_UDEV_DIR} RESULT_VARIABLE ERR OUTPUT_VARIABLE CMAKE_INSTALL_UDEVRULESDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
        IF(${ERR})
            set(CMAKE_INSTALL_UDEVRULESDIR "lib/udev/rules.d")
        ELSE()
            set(CMAKE_INSTALL_UDEVRULESDIR "${CMAKE_INSTALL_UDEVRULESDIR}/rules.d")
        ENDIF()
        string(REGEX REPLACE "^/" "" CMAKE_INSTALL_UDEVRULESDIR "${CMAKE_INSTALL_UDEVRULESDIR}")
        string(REGEX REPLACE "^usr/" "" CMAKE_INSTALL_UDEVRULESDIR "${CMAKE_INSTALL_UDEVRULESDIR}") # usual prefix is usr/local
        message(STATUS "Setting udev rules dir to ${CMAKE_INSTALL_UDEVRULESDIR}")
    ENDIF()

    install(FILES
            ${CMAKE_CURRENT_SOURCE_DIR}/data/41-nitrokey.rules
            DESTINATION ${CMAKE_INSTALL_UDEVRULESDIR}
    )
ENDIF()

# configure and install pkg-config file
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libnitrokey.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libnitrokey-1.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnitrokey-1.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

OPTION(COMPILE_TESTS "Compile tests" FALSE)
OPTION(COMPILE_OFFLINE_TESTS "Compile offline tests" FALSE)

IF(COMPILE_OFFLINE_TESTS OR COMPILE_TESTS)
    find_package(PkgConfig)
    IF(PKG_CONFIG_FOUND)
        pkg_check_modules(CATCH2 catch2)
    ENDIF()

    if (CATCH2_FOUND)
        message(STATUS "Found system Catch2, not using bundled version")
        add_compile_options(${CATCH2_CFLAGS})
    ELSE()
        message(STATUS "Did NOT find system Catch2, instead using bundled version")
        include_directories(unittest/Catch/single_include)
    ENDIF()

    add_library(catch STATIC unittest/catch_main.cpp )
ENDIF()

IF(COMPILE_OFFLINE_TESTS)
    add_executable (test_offline unittest/test_offline.cc)
    target_link_libraries (test_offline ${EXTRA_LIBS} nitrokey catch)
    SET_TARGET_PROPERTIES(test_offline PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} )
    #run with 'make test' or 'ctest'
    include (CTest)
    add_test (runs test_offline)

    add_executable(test_minimal unittest/test_minimal.c)
    target_link_libraries(test_minimal ${EXTRA_LIBS} nitrokey)
    add_test(minimal test_minimal)
ENDIF()

IF (COMPILE_TESTS)
    #needs connected Pro/Storage devices for success
    #WARNING: it may delete data on the device

        SET(TESTS
                unittest/test_C_API.cpp
                unittest/test2.cc
                unittest/test3.cc
                unittest/test_HOTP.cc
                unittest/test1.cc
                unittest/test_issues.cc
		unittest/test_memory.c
                unittest/test_multiple_devices.cc
                unittest/test_strdup.cpp
                unittest/test_safe.cpp
        )

    foreach(testsourcefile ${TESTS} )
        get_filename_component(testname ${testsourcefile} NAME_WE )
        add_executable(${testname} ${testsourcefile} )
        target_link_libraries(${testname} ${EXTRA_LIBS} nitrokey catch )
        SET_TARGET_PROPERTIES(${testname} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} )
    endforeach(testsourcefile)

ENDIF()



#SET(CPACK_GENERATOR
#        "DEB;RPM")
# build a CPack driven installer package
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
        "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set (CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
include (CPack)

# Build Doxygen documentation for the C API
find_package(Doxygen)
if (DOXYGEN_FOUND)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
    add_custom_target(doc ${DOXYGEN_EXECUTABLE} Doxyfile
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
        COMMENT "Generating C API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)