BashCompletion.cmake (4163B)
1 # A wrapper around pkg-config-provided and cmake-provided bash completion that 2 # will have dynamic behavior at INSTALL() time to allow both root-level 3 # INSTALL() as well as user-level INSTALL(). 4 # 5 # See also https://github.com/scop/bash-completion 6 # 7 # Copyright (c) 2018, Tres Finocchiaro, <tres.finocchiaro@gmail.com> 8 # Redistribution and use is allowed according to the terms of the BSD license. 9 # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 10 # 11 # Usage: 12 # INCLUDE(BashCompletion) 13 # BASHCOMP_INSTALL(foo) 14 # ... where "foo" is a shell script adjacent to the CMakeLists.txt 15 # 16 # How it determines BASHCOMP_PKG_PATH, in order: 17 # 1. Uses BASHCOMP_PKG_PATH if already set (e.g. -DBASHCOMP_PKG_PATH=...) 18 # a. If not, uses pkg-config's PKG_CHECK_MODULES to determine path 19 # b. Fallback to cmake's FIND_PACKAGE(bash-completion) path 20 # c. Fallback to hard-coded /usr/share/bash-completion/completions 21 # 2. Final fallback to ${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions if 22 # detected path is unwritable. 23 24 # - Windows does not support bash completion 25 # - macOS support should eventually be added for Homebrew (TODO) 26 IF(WIN32) 27 MESSAGE(STATUS "Bash completion is not supported on this platform.") 28 ELSEIF(APPLE) 29 MESSAGE(STATUS "Bash completion is not yet implemented for this platform.") 30 ELSE() 31 INCLUDE(FindUnixCommands) 32 # Honor manual override if provided 33 IF(NOT BASHCOMP_PKG_PATH) 34 # First, use pkg-config, which is the most reliable 35 FIND_PACKAGE(PkgConfig QUIET) 36 IF(PKGCONFIG_FOUND) 37 PKG_CHECK_MODULES(BASH_COMPLETION bash-completion) 38 PKG_GET_VARIABLE(BASHCOMP_PKG_PATH bash-completion completionsdir) 39 ELSE() 40 # Second, use cmake (preferred but less common) 41 FIND_PACKAGE(bash-completion QUIET) 42 IF(BASH_COMPLETION_FOUND) 43 SET(BASHCOMP_PKG_PATH "${BASH_COMPLETION_COMPLETIONSDIR}") 44 ENDIF() 45 ENDIF() 46 47 # Third, use a hard-coded fallback value 48 IF("${BASHCOMP_PKG_PATH}" STREQUAL "") 49 SET(BASHCOMP_PKG_PATH "/usr/share/bash-completion/completions") 50 ENDIF() 51 ENDIF() 52 53 # Always provide a fallback for non-root INSTALL() 54 SET(BASHCOMP_USER_PATH "${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions") 55 56 # Cmake doesn't allow easy use of conditional logic at INSTALL() time 57 # this is a problem because ${BASHCOMP_PKG_PATH} may not be writable and we 58 # need sane fallback behavior for bundled INSTALL() (e.g. .AppImage, etc). 59 # 60 # The reason this can't be detected by cmake is that it's fairly common to 61 # run "cmake" as a one user (i.e. non-root) and "make install" as another user 62 # (i.e. root). 63 # 64 # - Creates a script called "install_${SCRIPT_NAME}_completion.sh" into the 65 # working binary directory and invokes this script at install. 66 # - Script handles INSTALL()-time conditional logic for sane ballback behavior 67 # when ${BASHCOMP_PKG_PATH} is unwritable (i.e. non-root); Something cmake 68 # can't handle on its own at INSTALL() time) 69 MACRO(BASHCOMP_INSTALL SCRIPT_NAME) 70 # A shell script for wrapping conditionl logic 71 SET(BASHCOMP_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_${SCRIPT_NAME}_completion.sh") 72 73 FILE(WRITE ${BASHCOMP_SCRIPT} "\ 74 #!${BASH}\n\ 75 set -e\n\ 76 BASHCOMP_PKG_PATH=\"${BASHCOMP_USER_PATH}\"\n\ 77 if [ -n \"${BASHCOMP_PKG_PATH}\" ]; then\n\ 78 BASHCOMP_PKG_PATH=\"${BASHCOMP_PKG_PATH}\"\n\ 79 fi\n\ 80 echo -e \"\\nInstalling bash completion...\\n\"\n\ 81 mkdir -p \"\${DESTDIR}/$BASHCOMP_PKG_PATH\"\n\ 82 cp \"${CMAKE_CURRENT_BINARY_DIR}/${SCRIPT_NAME}\" \"\${DESTDIR}/$BASHCOMP_PKG_PATH\"\n\ 83 chmod a+r \"\${DESTDIR}/$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ 84 echo -e \"Bash completion for ${SCRIPT_NAME} has been installed to \${DESTDIR}/$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\ 85 ") 86 INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x \"install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") 87 INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"./install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )") 88 89 MESSAGE(STATUS "Bash completion script for ${SCRIPT_NAME} will be installed to ${DESTDIR}/${BASHCOMP_PKG_PATH} or fallback to ${BASHCOMP_USER_PATH} if unwritable.") 90 ENDMACRO() 91 ENDIF() 92