~unity-api-team/unity-scopes-api/child-scopes-option

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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
cmake_minimum_required(VERSION 2.8.10)

# Default install location. Must be set here, before setting the project.
if (NOT DEFINED CMAKE_INSTALL_PREFIX)
    set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "" FORCE)
endif()

set(PROJECT unity-scopes-api)
project(${PROJECT} C CXX)

if(${PROJECT_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
   message(FATAL_ERROR "In-tree build attempt detected, aborting. Set your build dir outside your source dir, delete CMakeCache.txt from source root and try again.")
endif()

include(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("#ifdef __clang__\n#else\n#error \"Not clang.\"\n#endif\nint main(int argc, char **argv) { return 0; }" IS_CLANG)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)

if(IS_CLANG)
  message(STATUS "Compiling with Clang, disabling lttng.")
endif()

string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_lower) # Build types should always be lowercase but sometimes they are not.

set(ACCEPTED_BUILD_TYPES "" none release debug relwithdebinfo coverage)
list(FIND ACCEPTED_BUILD_TYPES "${cmake_build_type_lower}" IS_BUILD_TYPE_ACCEPTED)
if(${IS_BUILD_TYPE_ACCEPTED} EQUAL -1)
  message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\nValid types are: ${ACCEPTED_BUILD_TYPES}")
endif()

# Static C++ checks

find_program(CPPCHECK_COMMAND NAMES cppcheck)
if (CPPCHECK_COMMAND)
    set(CPPCHECK_COMMAND_OPTIONS --check-config --inline-suppr --enable=all -q --error-exitcode=2)
    set(CPPCHECK_COMMAND_OPTIONS ${CPPCHECK_COMMAND_OPTIONS} --template "'{file}({line}): {severity} ({id}): {message}'")
    add_custom_target(cppcheck COMMAND ${CPPCHECK_COMMAND} ${CPPCHECK_COMMAND_OPTIONS}
        ${CMAKE_SOURCE_DIR}/src
        ${CMAKE_SOURCE_DIR}/test
        ${CMAKE_BINARY_DIR}/test
    )
else()
    message(WARNING "Cannot find cppcheck: cppcheck target will not be available")
endif()

#
# Definitions for testing with valgrind.
#

configure_file(CTestCustom.cmake.in CTestCustom.cmake) # Tests in CTestCustom.cmake are skipped for valgrind

find_program(MEMORYCHECK_COMMAND NAMES valgrind)
if (MEMORYCHECK_COMMAND)
    set(MEMORYCHECK_COMMAND_OPTIONS
        "--suppressions=${CMAKE_SOURCE_DIR}/valgrind-suppress --leak-check=full --num-callers=40 --error-exitcode=3"
    )
    add_custom_target(valgrind DEPENDS NightlyMemCheck)
else()
    message(WARNING "Cannot find valgrind: valgrind target will not be available")
endif()

include(FindPkgConfig)
find_package(Boost COMPONENTS system filesystem regex serialization REQUIRED)
pkg_check_modules(UNITY_API libunity-api>=0.1.3 REQUIRED)
pkg_check_modules(PROCESS_CPP process-cpp>=1.0.1 REQUIRED)
pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED)
pkg_check_modules(LTTNG_UST lttng-ust REQUIRED)
pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED)
pkg_check_modules(JSONCPP jsoncpp REQUIRED)
pkg_check_modules(LIBACCOUNTS REQUIRED libaccounts-glib)
pkg_check_modules(LIBSIGNON REQUIRED libsignon-glib)

find_program(LTTNG_EXECUTABLE lttng)
if (NOT LTTNG_EXECUTABLE)
    message(SEND_ERROR "Cannot find LTTng executable: ensure that lttng-tools is installed")
endif()

#
# Code style fixer. We put the code through astyle first because it makes some fixes that
# clang-format won't do (such as "char *p" -> "char* p"). But astyle messes up other things
# (particularly lambdas and assembly-style comments), which clang-format does right.
# So, we run clang-format after running astyle, which undoes the damage done by astyle
# without reverting desirable astyle fixes.
#

find_program(ASTYLE_COMMAND NAMES astyle)
if (NOT ASTYLE_COMMAND)
    message(WARNING "Cannot find astyle: formatcode target will not be available")
else()
    # astyle 2.03 creates DOS line endings, so we need to fix its output
    find_program(DOS2UNIX_COMMAND NAMES dos2unix)
    if (NOT DOS2UNIX_COMMAND)
        message(WARNING "Cannot find dos2unix: formatcode target will not be available")
    else()
        find_program(CLANG_FORMAT_COMMAND NAMES clang-format-3.5)
        if (NOT CLANG_FORMAT_COMMAND)
            message(WARNING "Cannot find clang-format >= clang-format-3.5: formatcode target will not be available")
        endif()
    endif()
endif()

if (ASTYLE_COMMAND AND DOS2UNIX_COMMAND AND CLANG_FORMAT_COMMAND)
set(UNITY_SCOPES_LIB_HDRS ${UNITY_SCOPES_LIB_HDRS} ${fmt_h})
    add_custom_target(formatcode
                      ${PROJECT_SOURCE_DIR}/tools/format-files.sh ${PROJECT_SOURCE_DIR} ${ASTYLE_COMMAND} ${CLANG_FORMAT_COMMAND})
endif()

find_program(CAPNPC_BIN capnpc)
if(NOT CAPNPC_BIN)
  message(FATAL_ERROR "Capnp compiler not found.")
endif()
set(CAPNPC_FLAGS "" CACHE STRING "Extra flags for capnpc.")

set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
                       ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS}
                       ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS})
set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} ${LIBSIGNON_LIBRARIES})

# Standard install paths
include(GNUInstallDirs)

include_directories(
    include/
    ${CMAKE_BINARY_DIR}/include
    ${CMAKE_BINARY_DIR}/src
    ${OTHER_INCLUDE_DIRS}
)

# We require g++ 4.9, to avoid ABI breakage with earlier version.
# Note that this must match what is specifed in debian/control.
set(cxx_version_required 4.9)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    if (NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${cxx_version_required}")
        message(FATAL_ERROR "g++ version must be ${cxx_version_required}, found ${CMAKE_CXX_COMPILER_VERSION}!")
    endif()
endif()

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wno-variadic-macros -Wextra -fPIC")

# By default, all symbols are visible in the library. We strip out things we don't
# want at link time, by running a version script (see unity-scopes.map and the
# setting of LINK_FLAGS below).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Wextra") # Can't use -std=c++11 with C compiler

# -fno-permissive causes warnings with clang, so we only enable it for gcc
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-permissive")
endif()

if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo")
    option(Werror "Treat warnings as errors" ON)
else()
    option(Werror "Treat warnings as errors" OFF)
endif()

# Some tests are slow, so make it possible not to run them
# during day-to-day development.
option(slowtests "Run slow tests" ON)

if (${Werror})
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
    if ("${cmake_build_type_lower}" STREQUAL "release" OR "${cmake_build_type_lower}" STREQUAL "relwithdebinfo")
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations")
    endif()
endif()

set(SANITIZER "" CACHE STRING "Build with -fsanitize=<value> (legal values: thread, address)")

if ("${SANITIZER}" STREQUAL "")
    # Do nothing
elseif (${SANITIZER} STREQUAL "thread")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer")
elseif (${SANITIZER} STREQUAL "address")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
else()
    message(FATAL_ERROR "Invalid SANITIZER setting: ${SANITIZER}")
endif()

option(IPC_MONITORING "Enable IPC traffic monitoring")

if(IPC_MONITORING)
    add_definitions(-DENABLE_IPC_MONITOR)
endif()

# Scopes library name. Also used as a prefix in various places, and as a subdirectory
# name for installed files. Changing this will also require corresponding changes
# to the debian files.
set(UNITY_SCOPES_LIB unity-scopes)

# API version
set(UNITY_SCOPES_MAJOR 0)
set(UNITY_SCOPES_MINOR 6)
set(UNITY_SCOPES_MICRO 8)
set(UNITY_SCOPES_SOVERSION 3)

# Version for testing, with all symbols visible
set(UNITY_SCOPES_TEST_LIB ${UNITY_SCOPES_LIB}-test)

find_library(ZMQLIB zmq)
if(NOT ZMQLIB)
  message(FATAL_ERROR "Zmq lib not found.")
endif()

find_library(ZMQPPLIB zmqpp)
if(NOT ZMQPPLIB)
  message(FATAL_ERROR "Zmqpp lib not found.")
endif()

find_library(CAPNPLIB capnp)
if(NOT CAPNPLIB)
  message(FATAL_ERROR "Cap'n Proto lib not found.")
endif()

find_library(KJLIB kj)
if(NOT KJLIB)
  message(FATAL_ERROR "Kj lib not found.")
endif()

find_library(DLLIB dl)
if(NOT DLLIB)
  message(FATAL_ERROR "Dl lib not found.")
endif()


# Other libraries we depend on
set(OTHER_LIBS
    ${OTHER_LIBS}
    ${Boost_LIBRARIES}
    ${JSONCPP_LDFLAGS}
    ${PROCESS_CPP_LDFLAGS}
    ${ZMQPPLIB}
    ${ZMQLIB}
    ${CAPNPLIB}
    ${KJLIB}
    ${DLLIB}
    pthread
    smartscopes
)

# All the libraries we need to link a normal executable that uses Unity scopes
set(LIBS ${UNITY_SCOPES_LIB})

# Test version of ${UNITY_SCOPES_LIB}, with internal symbols visible
set(TESTLIBS ${UNITY_SCOPES_TEST_LIB})

# Library install prefix
set(LIB_INSTALL_PREFIX lib/${CMAKE_LIBRARY_ARCHITECTURE})
set(LIBDIR ${CMAKE_INSTALL_LIBDIR})

set(LIBSUBDIR ${LIBDIR}/${UNITY_SCOPES_LIB}})
set(HDR_INSTALL_DIR include/${UNITY_SCOPES_LIB}-${UNITY_SCOPES_MAJOR})

#####################################################################
# Enable code coverage calculation with gcov/gcovr/lcov
# Usage:
#  * Switch build type to coverage (use ccmake or cmake-gui)
#  * Invoke make, make test, make coverage (or ninja if you use that backend)
#  * Find html report in subdir coveragereport
#  * Find xml report suitable for jenkins in coverage.xml
#####################################################################
if(cmake_build_type_lower MATCHES coverage)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -g")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -g")
    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage -g")
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage -g")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage -g")
endif()
include(EnableCoverageReport)

# Tests
include(CTest)
enable_testing()

# Add subdirectories.
add_subdirectory(include)
add_subdirectory(src)
add_subdirectory(scoperegistry)
add_subdirectory(scoperunner)
add_subdirectory(smartscopesproxy)
add_subdirectory(data)
add_subdirectory(test)
add_subdirectory(demo)
add_subdirectory(tools)

# Custom rules to compile .capnp files
foreach(file ${CAPNPROTO_FILES})

    string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" build_dir ${file})
    get_filename_component(build_dir ${build_dir} PATH)

    get_filename_component(proto_file ${file} NAME)
    string(REPLACE ".capnp" ".capnp.c++" src_file ${proto_file})
    string(REPLACE ".capnp" ".capnp.h" hdr_file ${proto_file})

    set(src_file ${build_dir}/${src_file})
    set(hdr_file ${build_dir}/${hdr_file})

    set(CAPNPROTO_HDRS ${CAPNPROTO_HDRS} ${hdr_file})
    set(CAPNPROTO_SRC ${CAPNPROTO_SRC} ${src_file})
endforeach()

# cmake cannot analyze include file dependencies of .capnproto files, so the easiest option is to recompile
# all files if any one of them changes
add_custom_command(OUTPUT ${CAPNPROTO_SRC} ${CAPNPROTO_HDRS}
                   DEPENDS ${CAPNPROTO_FILES}
                   COMMAND ${CAPNPC_BIN} ${CAPNPC_FLAGS} -oc++:${CMAKE_BINARY_DIR} --src-prefix=${CMAKE_SOURCE_DIR} ${CAPNPROTO_FILES})

# Pseudo-library of object files. We need a version of the library for normal clients
# that does not expose symbols in the unity::scopes::internal namespace, and another
# version for whitebox tests, so we can write unit tests for classes in the internal namespaces.
# Here, we create an object library that then is used to link the normal and the test libraries.

set(UNITY_SCOPES_LIB_OBJ ${UNITY_SCOPES_LIB}-obj)
add_library(${UNITY_SCOPES_LIB_OBJ} OBJECT ${UNITY_SCOPES_LIB_SRC} ${CAPNPROTO_SRC})
set_target_properties(${UNITY_SCOPES_LIB_OBJ} PROPERTIES COMPILE_FLAGS "-fPIC")

# Use the object files to make the normal library.
add_library(${UNITY_SCOPES_LIB} SHARED $<TARGET_OBJECTS:${UNITY_SCOPES_LIB_OBJ}>)
set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES
    VERSION "${UNITY_SCOPES_MAJOR}.${UNITY_SCOPES_MINOR}.${UNITY_SCOPES_MICRO}"
    SOVERSION ${UNITY_SCOPES_SOVERSION}
)

# Use the object files to make the test library.
add_library(${UNITY_SCOPES_TEST_LIB} SHARED $<TARGET_OBJECTS:${UNITY_SCOPES_LIB_OBJ}>)
set_target_properties(${UNITY_SCOPES_TEST_LIB} PROPERTIES
    VERSION "${UNITY_SCOPES_MAJOR}.${UNITY_SCOPES_MINOR}.${UNITY_SCOPES_MICRO}"
    SOVERSION ${UNITY_SCOPES_SOVERSION}
)

set(ldflags "")

# Clang sanitizers don't work if --no-undefined is given as a linker argument.
if(NOT IS_CLANG)
    set(ldflags "-Wl,--no-undefined")
endif()

set_target_properties(${UNITY_SCOPES_TEST_LIB} PROPERTIES LINK_FLAGS "${ldflags}")

# We compile with all symbols visible by default. For the shipping library, we strip
# out all symbols that (recursively) are in the unity::scopes::internal namespace,
# except for a few exceptions that are needed by the scoperegistry, scoperunner,
# smartscopesproxy, and any other binaries that reach into the internal namespace.
set(symbol_map "${CMAKE_SOURCE_DIR}/${UNITY_SCOPES_LIB}.map")
set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES
                      LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}")
set_target_properties(${UNITY_SCOPES_LIB} PROPERTIES LINK_DEPENDS ${symbol_map})

target_link_libraries(${UNITY_SCOPES_LIB} ${OTHER_LIBS})
target_link_libraries(${UNITY_SCOPES_TEST_LIB} ${OTHER_LIBS})

# Only the normal library gets installed.
install(TARGETS ${UNITY_SCOPES_LIB} LIBRARY DESTINATION ${LIB_INSTALL_PREFIX})

# Enable coverage testing

if (cmake_build_type_lower MATCHES coverage)
  ENABLE_COVERAGE_REPORT(TARGETS ${UNITY_SCOPES_LIB} smartscopes
                         FILTER /usr/include
                                ${CMAKE_SOURCE_DIR}/test/*
                                ${CMAKE_SOURCE_DIR}/debian/tests/*
                                ${CMAKE_SOURCE_DIR}/demo/*
                                ${CMAKE_BINARY_DIR}/*)
endif()

#
# Documentation
#
# Pass -DDEVEL_DOCS=ON to cmake for more detailed documentation

option(DEVEL_DOCS "Enable detailed Doxygen documentation")

find_package(Doxygen)
find_program(DOT_EXECUTABLE dot /usr/bin)
if (NOT DOXYGEN_FOUND OR NOT DOT_EXECUTABLE)
    message(WARNING "Cannot generate documentation: doxygen and/or graphviz not found")
else()
    if (DEVEL_DOCS)
      message(STATUS "Creating devel documentation")
      configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile-devel.in ${PROJECT_BINARY_DIR}/doc/Doxyfile @ONLY IMMEDIATE)
    else()
      configure_file(${PROJECT_SOURCE_DIR}/doc/Doxyfile.in ${PROJECT_BINARY_DIR}/doc/Doxyfile @ONLY IMMEDIATE)
    endif()
    configure_file(${PROJECT_SOURCE_DIR}/doc/index.html ${PROJECT_BINARY_DIR}/doc/index.html COPYONLY)
    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${UNITY_SCOPES_LIB}/index.html
                       COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/doc/Doxyfile
                       DEPENDS ${PROJECT_BINARY_DIR}/doc/Doxyfile
                               ${PROJECT_SOURCE_DIR}/doc/tutorial.dox
                               ${UNITY_SCOPES_LIB_SRC}
                               ${UNITY_SCOPES_LIB_HDRS})
    add_custom_target(doc ALL
                       DEPENDS ${PROJECT_BINARY_DIR}/doc/${UNITY_SCOPES_LIB}/index.html)
    install(DIRECTORY ${PROJECT_BINARY_DIR}/doc/${UNITY_SCOPES_LIB}
            DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/doc)
endif()