File: leatherman.cmake.in

package info (click to toggle)
leatherman 1.4.2%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,944 kB
  • sloc: cpp: 14,555; python: 3,105; sh: 45; makefile: 9; ruby: 1
file content (361 lines) | stat: -rw-r--r-- 14,453 bytes parent folder | download | duplicates (4)
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
# This file contains utilities used by both leatherman and consuming
# projects.

include(GNUInstallDirs)

# Save the directory containing other cmake script files.
# If we're top-level, this file is generated and dropped
# in a different directory from the other script files.
if(LEATHERMAN_TOPLEVEL)
    set(LEATHERMAN_CMAKE_DIR ${CMAKE_SOURCE_DIR}/cmake)
else()
    set(LEATHERMAN_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR})
endif()

# Usage: leatherman_logging_namespace("namespace")
#
# Sets the LEATHERMAN_LOGGING_NAMESPACE preprocessor definition to the
# value passed as "namespace".
macro(leatherman_logging_namespace namespace)
    add_definitions("-DLEATHERMAN_LOGGING_NAMESPACE=\"${namespace}\"")
endmacro()

# Usage: leatherman_logging_line_numbers()
#
# Sets the LEATHERMAN_LOGGING_LINE_NUMBERS preprocessor definition.
macro(leatherman_logging_line_numbers)
    add_definitions("-DLEATHERMAN_LOGGING_LINE_NUMBERS")
endmacro()

# Usage: debug("Something cool is happening")
#
# Print message if LEATHERMAN_DEBUG is set. Used to introspect macro
# logic.
macro(debug str)
    if (LEATHERMAN_DEBUG)
        message(STATUS ${str})
    endif()
endmacro(debug)

# Usage: export_var("foobar")
#
# Sets variable "foobar" in the parent scope to the same value as
# "foobar" in the invoking scope. Remember that a macro does not
# create a new scope, but a function does.
macro(export_var varname)
    if (NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
        debug("Exporting ${varname}")
        set(${varname} ${${varname}} PARENT_SCOPE)
    else()
        debug("Skipping export of ${varname} because I'm top-level")
    endif()
    debug("It's value is: ${${varname}}")
endmacro(export_var)

# Usage: defoption(VARNAME "Documentation String" ${DEFAULT_VALUE}")
#
# Define an option that will only be set to DEFAULT_VALUE if it does
# not already exist in this scope. If the variable is available in the
# scope, the option will keep the current value. This works around a
# weird CMake behavior where set(OPTION_VAR TRUE) does not cause
# option() to ignore its default.
macro(defoption name doc default)
    if(DEFINED ${name})
        debug("${name} is already set, using it")
        set(enabled ${${name}})
    else()
        debug("${name} unset, using default")
        set(enabled ${default})
    endif()
    option(${name} ${doc} ${enabled})
endmacro()

# Usage: leatherman_install(TARGETS)
#
# Installs targets using common cross-platform configuration.
# On Windows shared libraries go in bin, import and archive libraries
# go in lib. On Linux shared libraries go in lib. Binaries go in bin.
macro(leatherman_install)
    install(TARGETS ${ARGV}
        RUNTIME DESTINATION bin
	LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
	ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endmacro()

# Usage: add_cppcheck_dirs(dir1 dir2)
#
# Add the listed directories to the set that cppcheck will be run
# against
macro(add_cppcheck_dirs)
    list(APPEND CPPCHECK_DIRS ${ARGV})
    export_var(CPPCHECK_DIRS)
endmacro()

# Usage: add_cpplint_files(file1 file2)
#
# Add the listed files to the set that cpplint will be run against
macro(add_cpplint_files)
    list(APPEND CPPLINT_FILES ${ARGV})
    export_var(CPPLINT_FILES)
endmacro()

# Usage: enable_cppcheck()
#
# Create the cppcheck custom target with all the directories specified
# in previous calls to `add_cppcheck_dirs`
macro(enable_cppcheck)
    add_custom_target(cppcheck COMMAND cppcheck --enable=warning,performance --error-exitcode=2 --quiet --inline-suppr ${CPPCHECK_DIRS})
endmacro()

# We set this here so that enable_cpplint() can find it
set(LEATHERMAN_CPPLINT_PATH "${LEATHERMAN_CMAKE_DIR}/../scripts/cpplint.py")

# Usage: enable_cpplint()
#
# Create the cpplint custom target with all the specified in previous
# calls to `add_cpplint_files`
macro(enable_cpplint)
    include(FindPythonInterp)
    if (NOT PYTHONINTERP_FOUND)
        message(STATUS "Python not found; 'cpplint' target will not be available")
    else()
        set(CPPLINT_FILTER
            "-build/c++11"            # <thread>, <condvar>, etc...
            "-whitespace/indent"      # We use 4 space indentation
            "-build/include"          # Why?
            "-build/namespaces"       # What's a namespace to do
            "-legal/copyright"        # Not yet
            "-runtime/references"     # Not sure about this religion
            "-readability/streams"    # What?
            "-readability/namespace"  # Ignore nested namespace comment formatting
            "-whitespace/braces"      # Is there a k&r setting?
            "-whitespace/line_length" # Well yeah, but ... not just now
            "-runtime/arrays"         # Sizing an array with a 'const int' doesn't make it variable sized
            "-readability/todo"       # Seriously? todo comments need to identify an owner? pffft
            "-whitespace/empty_loop_body" # Can't handle do { ... } while(expr);
            "-runtime/int"            # Some C types are needed for library interop
            "-runtime/explicit"       # Using implicit conversion from string to regex for regex calls.
            "-build/header_guard"     # Disable header guards (cpplint doesn't yet support enforcing #pragma once)
            "-runtime/indentation_namespace" # Our namespace indentation is not consistent
            "-readability/inheritance" # virtual/override sometimes used together
            "-whitespace/operators"   # Expects spaces around perfect forwarding (&&)
        )

        set(CPPLINT_ARGS "--extensions=cc,cpp,hpp,h")
        if (CPPLINT_FILTER)
            string(REPLACE ";" "," CPPLINT_FILTER "${CPPLINT_FILTER}")
            set(CPPLINT_ARGS "${CPPLINT_ARGS};--filter=${CPPLINT_FILTER}")
        endif()
        if (MSVC)
            set(CPPLINT_ARGS "${CPPLINT_ARGS};--output=vs7")
        endif()

        add_custom_target(cpplint
            COMMAND ${PYTHON_EXECUTABLE} ${LEATHERMAN_CPPLINT_PATH} ${CPPLINT_ARGS} ${CPPLINT_FILES}
            VERBATIM
        )
    endif()
endmacro()

# Usage: gettext_templates(dir)
#
# Create templates for gettext in `dir` from the source files specified as additional arguments.
# Creates a custom target `translation`.
macro(gettext_templates dir)
    # Don't even try to find gettext on AIX or Solaris, we don't want it.
    if (LEATHERMAN_USE_LOCALES AND LEATHERMAN_GETTEXT)
        find_program(XGETTEXT_EXE xgettext)
    endif()

    if (XGETTEXT_EXE)
        set(TRANSLATION_DIR "${dir}")
        file(MAKE_DIRECTORY ${TRANSLATION_DIR})

        set(ALL_PROJECT_SOURCES ${ARGN})
        set(lang_template ${TRANSLATION_DIR}/${PROJECT_NAME}.pot)
        add_custom_command(OUTPUT ${lang_template}
            COMMAND ${XGETTEXT_EXE}
                --sort-by-file
                --copyright-holder "Puppet \\<docs@puppet.com\\>"
                --package-name=${PROJECT_NAME} --package-version=${PROJECT_VERSION}
                --msgid-bugs-address "docs@puppet.com"
                -d ${PROJECT_NAME} -o ${lang_template}
                --keyword=LOG_DEBUG:1,\\"debug\\"
                --keyword=LOG_INFO:1,\\"info\\"
                --keyword=LOG_WARNING:1,\\"warning\\"
                --keyword=LOG_ERROR:1,\\"error\\"
                --keyword=LOG_FATAL:1,\\"fatal\\"
                --keyword=log:2,\\"log\\"
                --keyword=translate:1
                --keyword=translate_n:1,2
                --keyword=translate_p:1c,2
                --keyword=translate_np:1c,2,3
                --keyword=format:1
                --keyword=format_n:1,2
                --keyword=format_p:1c,2
                --keyword=format_np:1c,2,3
                --keyword=_:1
                --keyword=n_:1,2
                --keyword=p_:1c,2
                --keyword=np_:1c,2,3
                --add-location=file
                --add-comments=LOCALE
                ${ALL_PROJECT_SOURCES}
            COMMAND ${CMAKE_COMMAND}
                -DPOT_FILE=${lang_template}
                -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
                -P ${LEATHERMAN_CMAKE_DIR}/normalize_pot.cmake
            DEPENDS ${ALL_PROJECT_SOURCES})

        add_custom_target(${PROJECT_NAME}.pot ALL DEPENDS ${lang_template})

        find_program(MSGINIT_EXE msginit)
        find_program(MSGMERGE_EXE msgmerge)
        if (MSGINIT_EXE AND MSGMERGE_EXE)
            foreach(lang ${LEATHERMAN_LOCALES})
                set(lang_file ${TRANSLATION_DIR}/${lang}.po)
                add_custom_command(OUTPUT ${lang_file}
                    COMMAND ${CMAKE_COMMAND}
                        -DPOT_FILE=${lang_template}
                        -DLANG_FILE=${lang_file}
                        -DLANG=${lang}
                        -DMSGMERGE_EXE=${MSGMERGE_EXE}
                        -DMSGINIT_EXE=${MSGINIT_EXE}
                        -P ${LEATHERMAN_CMAKE_DIR}/generate_translations.cmake
                    DEPENDS ${lang_template})
                add_custom_target(${PROJECT_NAME}-${lang}.pot ALL DEPENDS ${lang_file})
            endforeach()
        endif()
    else()
        message(STATUS "Could not find gettext executables, skipping gettext_templates.")
    endif()
endmacro()

# Usage: gettext_compile(dir inst)
#
# Compile gettext .po files into .mo files and configure installing to inst
# Creates a custom target `translations`.
#
# Does nothing if msgfmt (part of gettext) isn't found. Sets GETTEXT_ENABLED
# to ON if we can compile .mo files, otherwise sets to OFF. This variable can
# be used to disable functionality (such as testing) that requires gettext
# translation files.
macro(gettext_compile dir inst)
    # Don't even try to find gettext on AIX or Solaris, we don't want it.
    if (LEATHERMAN_USE_LOCALES AND LEATHERMAN_GETTEXT)
        find_program(MSGFMT_EXE msgfmt)
    endif()

    if (MSGFMT_EXE)
        file(GLOB TRANSLATIONS ${dir}/*.po)
        if (NOT TARGET translations)
            add_custom_target(translations ALL)
        endif()

        # Add LEATHERMAN_LOCALES, as they may not have been generated yet.
        foreach(locale ${LEATHERMAN_LOCALES})
            set(fpath ${dir}/${locale}.po)
            list(FIND TRANSLATIONS ${fpath} FOUND)
            if (${FOUND} EQUAL -1)
                list(APPEND TRANSLATIONS ${fpath})
            endif()
        endforeach()

        foreach(fpath ${TRANSLATIONS})
            get_filename_component(lang ${fpath} NAME_WE)
            set(mo ${CMAKE_BINARY_DIR}/${lang}/LC_MESSAGES/${PROJECT_NAME}.mo)
            add_custom_command(OUTPUT ${mo}
                COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/${lang}/LC_MESSAGES
                COMMAND ${MSGFMT_EXE} -c -v -o ${mo} ${fpath} 2>&1
                DEPENDS ${fpath})
            add_custom_target(${lang}-${PROJECT_NAME} DEPENDS ${mo})
            add_dependencies(translations ${lang}-${PROJECT_NAME})
            if(LEATHERMAN_LOCALE_INSTALL)
                install(FILES ${mo} DESTINATION "@CMAKE_INSTALL_PREFIX@/${LEATHERMAN_LOCALE_INSTALL}/${lang}/LC_MESSAGES")
            else()
                install(FILES ${mo} DESTINATION "@CMAKE_INSTALL_PREFIX@/share/locale/${lang}/LC_MESSAGES")
            endif()
        endforeach()
        set(GETTEXT_ENABLED ON)
    else()
        message(STATUS "Could not find gettext executables, skipping gettext_compile.")
        set(GETTEXT_ENABLED OFF)
    endif()
endmacro()

include(GetGitRevisionDescription)
# Usage: get_commit_string(VARNAME)
#
# Sets VARNAME to the git commit revision string, i.e. (commit SHA1)
function(get_commit_string varname)
    get_git_head_revision(GIT_REFSPEC GIT_SHA1)
    debug("Git SHA1 is ${GIT_SHA1}")
    if ("${GIT_SHA1}" STREQUAL "" OR "${GIT_SHA1}" STREQUAL "GITDIR-NOTFOUND")
        set(${varname} "" PARENT_SCOPE)
    else()
        set(${varname} " (commit ${GIT_SHA1})" PARENT_SCOPE)
    endif()
endfunction()

include(GenerateExportHeader)
# Usage: symbol_exports(TARGET HEADER)
#
# Generate the export header for restricting symbols exported from the library,
# and configure the compiler. Restricting symbols has several advantages, noted
# at https://gcc.gnu.org/wiki/Visibility.
macro(symbol_exports target header)
    generate_export_header(${target} EXPORT_FILE_NAME "${header}")
    # Export on Apple resulted in issues finding symbols from library dependencies
    # that we haven't solved. For now avoid the problem.
    # AIX doesn't support inline headers, and CMake warns if you try to apply the
    # option on static libraries.
    get_target_property(target_type ${target} TYPE)
    if ((NOT APPLE) AND (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") AND
        (${target_type} STREQUAL SHARED_LIBRARY))
        set_target_properties(${target} PROPERTIES VISIBILITY_INLINES_HIDDEN ON)
    endif()
    # If the target name is not a C identifier, generate_export_header will
    # convert it to one. Fix the define to do the same.
    string(MAKE_C_IDENTIFIER ${target} target_c_name)
    string(TOLOWER ${target_c_name} target_name_lower)
    target_compile_definitions(${target} PRIVATE "-D${target_name_lower}_EXPORTS")
endmacro()

# Usage: append_new(VARNAME VAR1 VAR2 ...)
#
# Append ARGN items to VARNAME list if not already present. Accounts for
# optimized/debug flags.
function(append_new varname)
    set(prefix "")
    foreach(DEP ${ARGN})
        if ((${DEP} STREQUAL optimized) OR (${DEP} STREQUAL debug))
            set(prefix ${DEP})
        else()
            list(FIND ${varname} ${DEP} found)
            if (${found} EQUAL -1)
                if (prefix)
                    list(APPEND ${varname} ${prefix})
                endif()
                list(APPEND ${varname} ${DEP})
            endif()
            set(prefix "")
        endif()
    endforeach()
    set(${varname} ${${varname}} PARENT_SCOPE)
endfunction()

# Usage: unpack_vendored("pkg.zip" "pkg" SOURCE_DIR)
#
# Unpacks a compressed pkg.zip in the vendor directory to
# ${PROJECT_BINARY_DIR}/src/pkg and saves the unpacked location to a variable.
macro(unpack_vendored pkg extracted_dir dir)
    set(pkgfile ${PROJECT_SOURCE_DIR}/vendor/${pkg})
    set(${dir} ${PROJECT_BINARY_DIR}/src/${extracted_dir})

    message(STATUS "Unpacking ${pkgfile} into ${${dir}}")
    file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/src)
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/vendor/${pkg}
        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src
        )
endmacro(unpack_vendored)