| 1 |
project(Phonon) |
| 2 |
|
| 3 |
cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR) |
| 4 |
|
| 5 |
# CMP0002: we have multiple targets with the same name for the unit tests |
| 6 |
cmake_policy(SET CMP0002 OLD) |
| 7 |
|
| 8 |
# enable unit tests |
| 9 |
option(PHONON_BUILD_TESTS "Build the tests") |
| 10 |
option(PHONON_BUILD_EXAMPLES "Build the examples") |
| 11 |
|
| 12 |
if (PHONON_BUILD_TESTS) |
| 13 |
enable_testing() |
| 14 |
endif (PHONON_BUILD_TESTS) |
| 15 |
|
| 16 |
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") |
| 17 |
|
| 18 |
include(PhononMacros) |
| 19 |
|
| 20 |
include(MacroLogFeature) |
| 21 |
include(MacroOptionalFindPackage) |
| 22 |
|
| 23 |
set(QT_MIN_VERSION 4.4.0) |
| 24 |
find_package(Qt4 REQUIRED) |
| 25 |
if (NOT QT_QTDBUS_FOUND) |
| 26 |
message(STATUS "Warning: Phonon won't be compiled with DBus support.") |
| 27 |
endif(NOT QT_QTDBUS_FOUND) |
| 28 |
|
| 29 |
find_package(Automoc4 REQUIRED) |
| 30 |
include (CheckCXXCompilerFlag) |
| 31 |
include (MacroEnsureVersion) |
| 32 |
|
| 33 |
if (NOT AUTOMOC4_VERSION) |
| 34 |
set(AUTOMOC4_VERSION "0.9.83") |
| 35 |
endif (NOT AUTOMOC4_VERSION) |
| 36 |
macro_ensure_version("0.9.86" "${AUTOMOC4_VERSION}" _automoc4_version_ok) |
| 37 |
if (NOT _automoc4_version_ok) |
| 38 |
message(FATAL_ERROR "Your version of automoc4 is too old. You have ${AUTOMOC4_VERSION}, you need at least 0.9.86") |
| 39 |
endif (NOT _automoc4_version_ok) |
| 40 |
|
| 41 |
if (CMAKE_COMPILER_IS_GNUCXX) |
| 42 |
set (KDE4_ENABLE_EXCEPTIONS -fexceptions) |
| 43 |
# Select flags. |
| 44 |
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") |
| 45 |
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG -DQT_NO_DEBUG") |
| 46 |
set(CMAKE_CXX_FLAGS_DEBUG "-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline") |
| 47 |
set(CMAKE_CXX_FLAGS_DEBUGFULL "-g3 -fno-inline") |
| 48 |
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs") |
| 49 |
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") |
| 50 |
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG -DQT_NO_DEBUG") |
| 51 |
set(CMAKE_C_FLAGS_DEBUG "-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline") |
| 52 |
set(CMAKE_C_FLAGS_DEBUGFULL "-g3 -fno-inline") |
| 53 |
set(CMAKE_C_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs") |
| 54 |
|
| 55 |
if (CMAKE_SYSTEM_NAME MATCHES Linux) |
| 56 |
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -std=iso9899:1990 -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common") |
| 57 |
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -fno-check-new -fno-common") |
| 58 |
add_definitions (-D_BSD_SOURCE -DQT_NO_EXCEPTIONS) |
| 59 |
endif (CMAKE_SYSTEM_NAME MATCHES Linux) |
| 60 |
|
| 61 |
# gcc under Windows |
| 62 |
if (MINGW) |
| 63 |
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-all-symbols -Wl,--disable-auto-import") |
| 64 |
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--export-all-symbols -Wl,--disable-auto-import") |
| 65 |
|
| 66 |
# we always link against the release version of QT with mingw |
| 67 |
# (even for debug builds). So we need to define QT_NO_DEBUG |
| 68 |
# or else QPluginLoader rejects plugins because it thinks |
| 69 |
# they're built against the wrong QT. |
| 70 |
add_definitions(-DQT_NO_DEBUG) |
| 71 |
endif (MINGW) |
| 72 |
|
| 73 |
if (QT_USE_FRAMEWORKS) |
| 74 |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F${QT_LIBRARY_DIR}") |
| 75 |
endif (QT_USE_FRAMEWORKS) |
| 76 |
|
| 77 |
check_cxx_compiler_flag(-fPIE HAVE_FPIE_SUPPORT) |
| 78 |
if(KDE4_ENABLE_FPIE) |
| 79 |
if(HAVE_FPIE_SUPPORT) |
| 80 |
set (KDE4_CXX_FPIE_FLAGS "-fPIE") |
| 81 |
set (KDE4_PIE_LDFLAGS "-pie") |
| 82 |
else(HAVE_FPIE_SUPPORT) |
| 83 |
message(STATUS "Your compiler doesn't support PIE flag") |
| 84 |
endif(HAVE_FPIE_SUPPORT) |
| 85 |
endif(KDE4_ENABLE_FPIE) |
| 86 |
|
| 87 |
check_cxx_compiler_flag(-Woverloaded-virtual __KDE_HAVE_W_OVERLOADED_VIRTUAL) |
| 88 |
if(__KDE_HAVE_W_OVERLOADED_VIRTUAL) |
| 89 |
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual") |
| 90 |
endif(__KDE_HAVE_W_OVERLOADED_VIRTUAL) |
| 91 |
|
| 92 |
# visibility support |
| 93 |
check_cxx_compiler_flag(-fvisibility=hidden __KDE_HAVE_GCC_VISIBILITY) |
| 94 |
set( __KDE_HAVE_GCC_VISIBILITY ${__KDE_HAVE_GCC_VISIBILITY} CACHE BOOL "GCC support for hidden visibility") |
| 95 |
|
| 96 |
# get the gcc version |
| 97 |
exec_program(${CMAKE_C_COMPILER} ARGS ${CMAKE_C_COMPILER_ARG1} --version OUTPUT_VARIABLE _gcc_version_info) |
| 98 |
|
| 99 |
string (REGEX MATCH "[345]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}") |
| 100 |
# gcc on mac just reports: "gcc (GCC) 3.3 20030304 ..." without the patch level, handle this here: |
| 101 |
if (NOT _gcc_version) |
| 102 |
string (REGEX REPLACE ".*\\(GCC\\).* ([34]\\.[0-9]) .*" "\\1.0" _gcc_version "${_gcc_version_info}") |
| 103 |
endif (NOT _gcc_version) |
| 104 |
|
| 105 |
macro_ensure_version("4.1.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_1) |
| 106 |
macro_ensure_version("4.2.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_2) |
| 107 |
macro_ensure_version("4.3.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_3) |
| 108 |
|
| 109 |
# save a little by making local statics not threadsafe |
| 110 |
# ### do not enable it for older compilers, see |
| 111 |
# ### http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31806 |
| 112 |
if (GCC_IS_NEWER_THAN_4_3) |
| 113 |
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics") |
| 114 |
endif (GCC_IS_NEWER_THAN_4_3) |
| 115 |
|
| 116 |
set(_GCC_COMPILED_WITH_BAD_ALLOCATOR FALSE) |
| 117 |
if (GCC_IS_NEWER_THAN_4_1) |
| 118 |
exec_program(${CMAKE_C_COMPILER} ARGS -v OUTPUT_VARIABLE _gcc_alloc_info) |
| 119 |
string(REGEX MATCH "(--enable-libstdcxx-allocator=mt)" _GCC_COMPILED_WITH_BAD_ALLOCATOR "${_gcc_alloc_info}") |
| 120 |
endif (GCC_IS_NEWER_THAN_4_1) |
| 121 |
|
| 122 |
if (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32) |
| 123 |
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") |
| 124 |
set (KDE4_C_FLAGS "-fvisibility=hidden") |
| 125 |
# check that Qt defines Q_DECL_EXPORT as __attribute__ ((visibility("default"))) |
| 126 |
# if it doesn't and KDE compiles with hidden default visibiltiy plugins will break |
| 127 |
set(_source "#include <QtCore/QtGlobal>\n int main()\n {\n #ifdef QT_VISIBILITY_AVAILABLE \n return 0;\n #else \n return 1; \n #endif \n }\n") |
| 128 |
set(_source_file ${CMAKE_BINARY_DIR}/CMakeTmp/check_qt_visibility.cpp) |
| 129 |
file(WRITE "${_source_file}" "${_source}") |
| 130 |
set(_include_dirs "-DINCLUDE_DIRECTORIES:STRING=${QT_INCLUDES}") |
| 131 |
|
| 132 |
try_run(_run_result _compile_result ${CMAKE_BINARY_DIR} ${_source_file} CMAKE_FLAGS "${_include_dirs}") |
| 133 |
|
| 134 |
if(NOT _compile_result) |
| 135 |
message(FATAL_ERROR "Could not compile simple test program:\n ${_source}") |
| 136 |
endif(NOT _compile_result) |
| 137 |
if(_run_result) |
| 138 |
message(FATAL_ERROR "Qt compiled without support for -fvisibility=hidden. This will break plugins and linking of some applications. Please fix your Qt installation.") |
| 139 |
endif(_run_result) |
| 140 |
|
| 141 |
if (GCC_IS_NEWER_THAN_4_2) |
| 142 |
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") |
| 143 |
endif (GCC_IS_NEWER_THAN_4_2) |
| 144 |
else (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32) |
| 145 |
set (__KDE_HAVE_GCC_VISIBILITY 0) |
| 146 |
endif (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32) |
| 147 |
|
| 148 |
endif (CMAKE_COMPILER_IS_GNUCXX) |
| 149 |
|
| 150 |
set(CMAKE_INCLUDE_CURRENT_DIR ON) |
| 151 |
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) |
| 152 |
set(CMAKE_COLOR_MAKEFILE ON) |
| 153 |
|
| 154 |
set(PHONON_LIB_MAJOR_VERSION "4") |
| 155 |
set(PHONON_LIB_MINOR_VERSION "4") |
| 156 |
set(PHONON_LIB_PATCH_VERSION "0") |
| 157 |
set(PHONON_LIB_VERSION "${PHONON_LIB_MAJOR_VERSION}.4.0") |
| 158 |
set(PHONON_LIB_SOVERSION ${PHONON_LIB_MAJOR_VERSION}) |
| 159 |
|
| 160 |
add_definitions(${QT_DEFINITIONS}) |
| 161 |
remove_definitions(-DQT3_SUPPORT_WARNINGS -DQT3_SUPPORT) |
| 162 |
if(MSVC) |
| 163 |
add_definitions( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS ) |
| 164 |
endif(MSVC) |
| 165 |
|
| 166 |
# for including config.h and for includes like <kparts/foo.h> |
| 167 |
include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/includes ${CMAKE_CURRENT_SOURCE_DIR}/phonon ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/phonon) |
| 168 |
|
| 169 |
macro(_SET_FANCY _var _value _comment) |
| 170 |
if (KDESupport_SOURCE_DIR) |
| 171 |
# when building inside kdesupport other subprojects write crap into our variables |
| 172 |
set(${_var} "${_value}") |
| 173 |
else (KDESupport_SOURCE_DIR) |
| 174 |
if (NOT DEFINED ${_var}) |
| 175 |
set(${_var} "${_value}") |
| 176 |
else (NOT DEFINED ${_var}) |
| 177 |
set(${_var} "${${_var}}" CACHE PATH "${_comment}") |
| 178 |
endif (NOT DEFINED ${_var}) |
| 179 |
endif (KDESupport_SOURCE_DIR) |
| 180 |
endmacro(_SET_FANCY) |
| 181 |
|
| 182 |
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) |
| 183 |
|
| 184 |
if (WIN32) |
| 185 |
_set_fancy(EXEC_INSTALL_PREFIX "." "Base directory for executables and libraries") |
| 186 |
else(WIN32) |
| 187 |
_set_fancy(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Base directory for executables and libraries") |
| 188 |
endif(WIN32) |
| 189 |
_set_fancy(SHARE_INSTALL_PREFIX "${EXEC_INSTALL_PREFIX}/share" "Base directory for files which go to share/") |
| 190 |
_set_fancy(INCLUDE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/include" "The subdirectory to the header prefix") |
| 191 |
_set_fancy(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" "The install dir for executables (default ${EXEC_INSTALL_PREFIX}/bin)") |
| 192 |
_set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" "The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})") |
| 193 |
_set_fancy(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/kde4" "The subdirectory relative to the install prefix where plugins will be installed (default is ${LIB_INSTALL_DIR}/kde4)") |
| 194 |
_set_fancy(ICON_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/icons" "The icon install dir (default ${SHARE_INSTALL_PREFIX}/share/icons/)") |
| 195 |
_set_fancy(SERVICES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/kde4/services" "The install dir for service (desktop, protocol, ...) files") |
| 196 |
_set_fancy(DBUS_INTERFACES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/interfaces" "The dbus interfaces install dir (default: ${SHARE_INSTALL_PREFIX}/dbus-1/interfaces)") |
| 197 |
_set_fancy(DBUS_SERVICES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/services" "The dbus services install dir (default: ${SHARE_INSTALL_PREFIX}/dbus-1/services)") |
| 198 |
|
| 199 |
set(INSTALL_TARGETS_DEFAULT_ARGS RUNTIME DESTINATION "${BIN_INSTALL_DIR}" |
| 200 |
LIBRARY DESTINATION "${LIB_INSTALL_DIR}" |
| 201 |
ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" COMPONENT Devel ) |
| 202 |
|
| 203 |
# on the Mac support an extra install directory for application bundles |
| 204 |
if(APPLE) |
| 205 |
set(INSTALL_TARGETS_DEFAULT_ARGS ${INSTALL_TARGETS_DEFAULT_ARGS} |
| 206 |
BUNDLE DESTINATION "${BUNDLE_INSTALL_DIR}" ) |
| 207 |
set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined dynamic_lookup") |
| 208 |
set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace -undefined dynamic_lookup") |
| 209 |
endif(APPLE) |
| 210 |
|
| 211 |
if (CMAKE_SYSTEM_NAME MATCHES Linux) |
| 212 |
if (CMAKE_COMPILER_IS_GNUCXX) |
| 213 |
set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_SHARED_LINKER_FLAGS}") |
| 214 |
set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_MODULE_LINKER_FLAGS}") |
| 215 |
|
| 216 |
set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_SHARED_LINKER_FLAGS}") |
| 217 |
set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_MODULE_LINKER_FLAGS}") |
| 218 |
set ( CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_EXE_LINKER_FLAGS}") |
| 219 |
|
| 220 |
# we profile... |
| 221 |
if(CMAKE_BUILD_TYPE_TOLOWER MATCHES profile) |
| 222 |
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") |
| 223 |
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") |
| 224 |
endif(CMAKE_BUILD_TYPE_TOLOWER MATCHES profile) |
| 225 |
endif (CMAKE_COMPILER_IS_GNUCXX) |
| 226 |
if (CMAKE_C_COMPILER MATCHES "icc") |
| 227 |
set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_SHARED_LINKER_FLAGS}") |
| 228 |
set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_MODULE_LINKER_FLAGS}") |
| 229 |
endif (CMAKE_C_COMPILER MATCHES "icc") |
| 230 |
endif (CMAKE_SYSTEM_NAME MATCHES Linux) |
| 231 |
|
| 232 |
set(PHONON_LIBS phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) |
| 233 |
if(QT_QTDBUS_FOUND) |
| 234 |
list(APPEND PHONON_LIBS phonon ${QT_QTDBUS_LIBRARY}) |
| 235 |
endif(QT_QTDBUS_FOUND) |
| 236 |
|
| 237 |
set(EXECUTABLE_OUTPUT_PATH ${Phonon_BINARY_DIR}/bin) |
| 238 |
if (WIN32) |
| 239 |
set(LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH}) |
| 240 |
else (WIN32) |
| 241 |
set(LIBRARY_OUTPUT_PATH ${Phonon_BINARY_DIR}/lib) |
| 242 |
endif (WIN32) |
| 243 |
|
| 244 |
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc") |
| 245 |
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-check-new -fno-common") |
| 246 |
endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc") |
| 247 |
|
| 248 |
# Set up RPATH handling, so the libs are found if they are installed to a non-standard location. |
| 249 |
# By default cmake builds the targets with full RPATH to everything in the build directory, |
| 250 |
# but then removes the RPATH when installing. |
| 251 |
# These two options below make it set the RPATH of the installed targets to all |
| 252 |
# RPATH directories outside the current CMAKE_BINARY_DIR and also the library |
| 253 |
# install directory. Alex |
| 254 |
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) |
| 255 |
set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}" ) |
| 256 |
|
| 257 |
if(APPLE) |
| 258 |
set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR}) |
| 259 |
endif(APPLE) |
| 260 |
|
| 261 |
|
| 262 |
add_subdirectory(phonon) |
| 263 |
add_subdirectory(includes) |
| 264 |
if (Q_WS_MAC AND BUILD_PHONON_QT7) |
| 265 |
add_subdirectory(qt7) |
| 266 |
endif (Q_WS_MAC AND BUILD_PHONON_QT7) |
| 267 |
if (Q_WS_WIN) |
| 268 |
add_subdirectory(ds9) |
| 269 |
endif (Q_WS_WIN) |
| 270 |
|
| 271 |
if (Q_WS_X11) |
| 272 |
add_subdirectory(gstreamer) |
| 273 |
add_subdirectory(xine) |
| 274 |
endif (Q_WS_X11) |
| 275 |
|
| 276 |
if(NOT WIN32) # pkgconfig file |
| 277 |
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/phonon.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/phonon.pc @ONLY) |
| 278 |
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/phonon.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) |
| 279 |
endif(NOT WIN32) |
| 280 |
|
| 281 |
macro_display_feature_log() |