CMake

Compilation timing

set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")

Stripping debug information

# Strip and install debug information
function(myproject_install_debug_syms target component dest_lib dest_bin)
    if (MSVC)
        install(FILES "$<TARGET_PDB_FILE:${target}>"
            DESTINATION ${dest_bin}
            CONFIGURATIONS Debug RelWithDebInfo
            COMPONENT ${component} 
            OPTIONAL EXCLUDE_FROM_ALL)
    elseif (CMAKE_STRIP AND CMAKE_OBJCOPY)
        set(DEBUG_FILE "$<TARGET_FILE_NAME:${target}>.debug")
        add_custom_command(TARGET ${target} POST_BUILD
            COMMAND "${CMAKE_STRIP}" "--only-keep-debug" "$<TARGET_FILE:${target}>" "-o" "${DEBUG_FILE}"
            COMMAND "${CMAKE_STRIP}" "--strip-debug" "$<TARGET_FILE:${target}>"
            COMMAND "${CMAKE_OBJCOPY}" "--add-gnu-debuglink=${DEBUG_FILE}" "$<TARGET_FILE:${target}>"
            COMMAND "${CMAKE_COMMAND}" "-E" "echo" "Stripped into ${DEBUG_FILE}"
            WORKING_DIRECTORY $<TARGET_FILE_DIR:${target}>)
        install(FILES "$<TARGET_FILE_DIR:${target}>/${DEBUG_FILE}"
            DESTINATION ${dest_lib}
            CONFIGURATIONS Debug RelWithDebInfo
            COMPONENT ${component}
            EXCLUDE_FROM_ALL)
    endif()
endfunction()

# Usage
include(GNUInstallDirs)
foreach(target IN LISTS MYPROJECT_INSTALL_TARGETS)
    get_target_property(target_TYPE ${target} TYPE)
    if (${target_TYPE} STREQUAL "SHARED_LIBRARY")
        myproject_install_debug_syms(${target} debug
                                     ${CMAKE_INSTALL_LIBDIR}
                                     ${CMAKE_INSTALL_BINDIR})
    endif()
endforeach()

Hiding symbols with default visibility in shared library

function(configure_visibility target)
    set_target_properties(${target} PROPERTIES CXX_VISIBILITY_PRESET "hidden"
                                               VISIBILITY_INLINES_HIDDEN true)
    if (CMAKE_SYSTEM_NAME MATCHES "Linux")
        target_link_options(${target} PRIVATE "LINKER:--exclude-libs,ALL")
    endif()
endfunction()

The target properties ensure that the source files comprising the given target are compiled with the visibility set to hidden, which means that unless a symbol is explicitly marked “export”, it won't be exported in the shared library.

The linker option ensures that symbols with default visibility in any static libraries the target depends on are not exported in the shared library either.
From man ld(1):

--exclude-libs lib,lib,...
    Specifies a list of archive libraries from which symbols should not
    be automatically exported.  The library names may be delimited by
    commas or colons.  Specifying "--exclude-libs ALL" excludes symbols
    in all archive libraries from automatic export.

For explicitly exporting symbols that are part of the public API, see GenerateExportHeader.

Linux compilation and development

Inspecting binaries

# Dependencies and dynamic section of a shared library
readelf -d libfile.so
# List of symbols in shared library (1)
nm -CD --defined-only --size-sort libfile.so
# List of symbols in shared library (2)
readelf --wide --symbols --demangle libfile.so
# Filter symbols and prevent line wrapping
readelf --wide --symbols --demangle libfile.so | grep name | bat --wrap=never

Checking a debug link

# Dependencies and dynamic section of a shared library
objcopy -O binary --dump-section .gnu_debuglink=>(cut -d '' -f 1 -) libfile.so

Check the GLIBC version requirements of an ELF file

# Print private headers containing version references
objdump -p libfile.so

C++

Reversing a linked list

#include <utility> // std::exchange

struct Node {
    Node *next = nullptr;
};

Node *reverse_linked_list(Node *fwd) {
    Node *rev = nullptr;
    while (fwd)
        rev = std::exchange(fwd, std::exchange(fwd->next, rev));
    return rev;
}

BlueZ

Send and receive MIDI over BLE

bluetoothctl
scan le
scan off
pair F4:12:FA:E3:47:51
connect F4:12:FA:E3:47:51
menu gatt
list-attributes
select-attribute /org/bluez/hci0/dev_F4_12_FA_E3_47_51/service000a/char000b
notify on
read
write "0x80 0x80 0x90 0x12 0x13" 0 command
back
disconnect