|
| 1 | +cmake_policy(VERSION 3.15) |
| 2 | + |
| 3 | +if(NOT CMAKE_SCRIPT_MODE_FILE) |
| 4 | + # We are being included from within a project, so we should generate the install rules |
| 5 | + # The script name is "uninstall" by default: |
| 6 | + if(NOT DEFINED UNINSTALL_SCRIPT_NAME) |
| 7 | + set(UNINSTALL_SCRIPT_NAME "uninstall") |
| 8 | + endif() |
| 9 | + # We need a directory where we should install the script: |
| 10 | + if(NOT UNINSTALL_PROG_DIR) |
| 11 | + message(SEND_ERROR "We require an UNINSTALL_PROG_DIR to be defined") |
| 12 | + endif() |
| 13 | + # Platform dependent values: |
| 14 | + if(WIN32) |
| 15 | + set(_script_ext "cmd") |
| 16 | + set(_script_runner cmd.exe /c) |
| 17 | + else() |
| 18 | + set(_script_ext "sh") |
| 19 | + set(_script_runner sh -e -u) |
| 20 | + endif() |
| 21 | + # The script filename and path: |
| 22 | + set(_script_filename "${UNINSTALL_SCRIPT_NAME}.${_script_ext}") |
| 23 | + get_filename_component(_uninstaller_script "${CMAKE_CURRENT_BINARY_DIR}/${_script_filename}" ABSOLUTE) |
| 24 | + # Code that will do the work at install-time: |
| 25 | + string(CONFIGURE [==[ |
| 26 | + function(__generate_uninstall) |
| 27 | + set(UNINSTALL_IS_WIN32 "@WIN32@") |
| 28 | + set(UNINSTALL_WRITE_FILE "@_uninstaller_script@") |
| 29 | + set(UNINSTALL_SCRIPT_SELF "@UNINSTALL_PROG_DIR@/@_script_filename@") |
| 30 | + include("@CMAKE_CURRENT_LIST_FILE@") |
| 31 | + endfunction() |
| 32 | + __generate_uninstall() |
| 33 | + ]==] code @ONLY ESCAPE_QUOTES) |
| 34 | + install(CODE "${code}") |
| 35 | + # Add a rule to install that file: |
| 36 | + install( |
| 37 | + FILES "${_uninstaller_script}" |
| 38 | + DESTINATION "${UNINSTALL_PROG_DIR}" |
| 39 | + PERMISSIONS |
| 40 | + OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| 41 | + GROUP_READ GROUP_EXECUTE |
| 42 | + WORLD_READ WORLD_EXECUTE |
| 43 | + ) |
| 44 | + |
| 45 | + # If applicable, generate an "uninstall" target to run the uninstaller: |
| 46 | + if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR OR PROJECT_IS_TOP_LEVEL) |
| 47 | + add_custom_target( |
| 48 | + uninstall |
| 49 | + COMMAND ${_script_runner} "${_uninstaller_script}" |
| 50 | + COMMENT Uninstalling... |
| 51 | + ) |
| 52 | + endif() |
| 53 | + # Stop here: The rest of the file is for install-time |
| 54 | + return() |
| 55 | +endif() |
| 56 | + |
| 57 | +# We get here if running in script mode (e.g. at CMake install-time) |
| 58 | +if(NOT DEFINED CMAKE_INSTALL_MANIFEST_FILES) |
| 59 | + message(FATAL_ERROR "This file is only for use with CMake's install(CODE/SCRIPT) command") |
| 60 | +endif() |
| 61 | +if(NOT DEFINED UNINSTALL_WRITE_FILE) |
| 62 | + message(FATAL_ERROR "Expected a variable “UNINSTALL_WRITE_FILE” to be defined") |
| 63 | +endif() |
| 64 | + |
| 65 | +# Clear out the uninstall script before we begin writing: |
| 66 | +file(WRITE "${UNINSTALL_WRITE_FILE}" "") |
| 67 | + |
| 68 | +# Append a line to the uninstall script file. Single quotes will be replaced with doubles, |
| 69 | +# and an appropriate newline will be added. |
| 70 | +function(append_line line) |
| 71 | + string(REPLACE "'" "\"" line "${line}") |
| 72 | + file(APPEND "${UNINSTALL_WRITE_FILE}" "${line}\n") |
| 73 | +endfunction() |
| 74 | + |
| 75 | +# The copyright header: |
| 76 | +set(header [[ |
| 77 | +Mongo C Driver uninstall program, generated with CMake |
| 78 | + |
| 79 | +Copyright 2018-present MongoDB, Inc. |
| 80 | + |
| 81 | +Licensed under the Apache License, Version 2.0 (the \"License\"); |
| 82 | +you may not use this file except in compliance with the License. |
| 83 | +You may obtain a copy of the License at |
| 84 | + |
| 85 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 86 | + |
| 87 | +Unless required by applicable law or agreed to in writing, software |
| 88 | +distributed under the License is distributed on an \"AS IS\" BASIS, |
| 89 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 90 | +See the License for the specific language governing permissions and |
| 91 | +limitations under the License. |
| 92 | +]]) |
| 93 | +string(STRIP header "${header}") |
| 94 | +string(REPLACE "\n" ";" header_lines "${header}") |
| 95 | + |
| 96 | +# Prefix for the Batch script: |
| 97 | +set(bat_preamble [[ |
| 98 | +call :init |
| 99 | + |
| 100 | +:print |
| 101 | +<nul set /p_=%~1 |
| 102 | +exit /b |
| 103 | + |
| 104 | +:rmfile |
| 105 | +set f=%__prefix%\%~1 |
| 106 | +call :print "Remove file %f% " |
| 107 | +if EXIST "%f%" ( |
| 108 | + del /Q /F "%f%" || exit /b %errorlevel% |
| 109 | + call :print " - ok" |
| 110 | +) else ( |
| 111 | + call :print " - skipped: not present" |
| 112 | +) |
| 113 | +echo( |
| 114 | +exit /b |
| 115 | + |
| 116 | +:rmdir |
| 117 | +set f=%__prefix%\%~1 |
| 118 | +call :print "Remove directory: %f% " |
| 119 | +if EXIST "%f%" ( |
| 120 | + rmdir /Q "%f%" 2>nul |
| 121 | + if ERRORLEVEL 0 ( |
| 122 | + call :print "- ok" |
| 123 | + ) else ( |
| 124 | + call :print "- skipped (non-empty?)" |
| 125 | + ) |
| 126 | +) else ( |
| 127 | + call :print " - skipped: not present" |
| 128 | +) |
| 129 | +echo( |
| 130 | +exit /b |
| 131 | + |
| 132 | +:init |
| 133 | +setlocal EnableDelayedExpansion |
| 134 | +setlocal EnableExtensions |
| 135 | +if /i "%~dp0" NEQ "%TEMP%\" ( |
| 136 | + set tmpfile=%TEMP%\mongoc-%~nx0 |
| 137 | + copy "%~f0" "!tmpfile!" >nul |
| 138 | + call "!tmpfile!" & del "!tmpfile!" |
| 139 | + exit /b |
| 140 | +) |
| 141 | +]]) |
| 142 | + |
| 143 | +# Prefix for the shell script: |
| 144 | +set(sh_preamble [[ |
| 145 | +set -eu |
| 146 | + |
| 147 | +__rmfile() { |
| 148 | + set -eu |
| 149 | + abs=$__prefix/$1 |
| 150 | + printf "Remove file %s: " "$abs" |
| 151 | + if test -f "$abs" || test -L "$abs" |
| 152 | + then |
| 153 | + rm -- "$abs" |
| 154 | + echo "ok" |
| 155 | + else |
| 156 | + echo "skipped: not present" |
| 157 | + fi |
| 158 | +} |
| 159 | + |
| 160 | +__rmdir() { |
| 161 | + set -eu |
| 162 | + abs=$__prefix/$1 |
| 163 | + printf "Remove directory %s: " "$abs" |
| 164 | + if test -d "$abs" |
| 165 | + then |
| 166 | + list=$(ls --almost-all "$abs") |
| 167 | + if test "$list" = "" |
| 168 | + then |
| 169 | + rmdir -- "$abs" |
| 170 | + echo "ok" |
| 171 | + else |
| 172 | + echo "skipped: not empty" |
| 173 | + fi |
| 174 | + else |
| 175 | + echo "skipped: not present" |
| 176 | + fi |
| 177 | +} |
| 178 | +]]) |
| 179 | + |
| 180 | +# Convert the install prefix to an absolute path with the native path format: |
| 181 | +get_filename_component(install_prefix "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) |
| 182 | +file(TO_NATIVE_PATH "${install_prefix}" install_prefix) |
| 183 | +# Handling DESTDIR requires careful handling of root path redirection: |
| 184 | +set(root_path) |
| 185 | +set(relative_prefix "${install_prefix}") |
| 186 | +if(COMMAND cmake_path) |
| 187 | + cmake_path(GET install_prefix ROOT_PATH root_path) |
| 188 | + cmake_path(GET install_prefix RELATIVE_PART relative_prefix) |
| 189 | +endif() |
| 190 | + |
| 191 | +# The first lines that will be written to the script: |
| 192 | +set(init_lines) |
| 193 | + |
| 194 | +if(UNINSTALL_IS_WIN32) |
| 195 | + # Comment the header: |
| 196 | + list(TRANSFORM header_lines PREPEND "rem ") |
| 197 | + # Add the preamble |
| 198 | + list(APPEND init_lines |
| 199 | + "@echo off" |
| 200 | + "${header_lines}" |
| 201 | + "${bat_preamble}" |
| 202 | + "if \"%DESTDIR%\"==\"\" (" |
| 203 | + " set __prefix=${install_prefix}" |
| 204 | + ") else (" |
| 205 | + " set __prefix=!DESTDIR!\\${relative_prefix}" |
| 206 | + ")" |
| 207 | + "") |
| 208 | + set(__rmfile "call :rmfile") |
| 209 | + set(__rmdir "call :rmdir") |
| 210 | +else() |
| 211 | + # Comment the header: |
| 212 | + list(TRANSFORM header_lines PREPEND "# * ") |
| 213 | + # Add the preamble |
| 214 | + list(APPEND init_lines |
| 215 | + "#!/bin/sh" |
| 216 | + "${header_lines}" |
| 217 | + "${sh_preamble}" |
| 218 | + "__prefix=\${DESTDIR:-}${install_prefix}" |
| 219 | + "") |
| 220 | + set(__rmfile "__rmfile") |
| 221 | + set(__rmdir "__rmdir") |
| 222 | +endif() |
| 223 | + |
| 224 | +# Add the first lines to the file: |
| 225 | +string(REPLACE ";" "\n" init "${init_lines}") |
| 226 | +append_line("${init}") |
| 227 | + |
| 228 | +# Generate a "remove a file" command |
| 229 | +function(add_rmfile filename) |
| 230 | + file(TO_NATIVE_PATH "${filename}" native) |
| 231 | + append_line("${__rmfile} '${native}'") |
| 232 | +endfunction() |
| 233 | + |
| 234 | +# Generate a "remove a directory" command |
| 235 | +function(add_rmdir dirname) |
| 236 | + file(TO_NATIVE_PATH "${dirname}" native) |
| 237 | + append_line("${__rmdir} '${native}'") |
| 238 | +endfunction() |
| 239 | + |
| 240 | +set(script_self "${install_prefix}/${UNINSTALL_SCRIPT_SELF}") |
| 241 | +set(dirs_to_remove) |
| 242 | +foreach(installed IN LISTS CMAKE_INSTALL_MANIFEST_FILES script_self) |
| 243 | + # Get the relative path from the prefix (the uninstaller will fix it up later) |
| 244 | + file(RELATIVE_PATH relpath "${install_prefix}" "${installed}") |
| 245 | + # Add a removal: |
| 246 | + add_rmfile("${relpath}") |
| 247 | + # Climb the path and collect directories: |
| 248 | + while("1") |
| 249 | + get_filename_component(installed "${installed}" DIRECTORY) |
| 250 | + file(TO_NATIVE_PATH "${installed}" installed) |
| 251 | + get_filename_component(parent "${installed}" DIRECTORY) |
| 252 | + file(TO_NATIVE_PATH "${parent}" parent) |
| 253 | + # Don't account for the prefix or direct children of the prefix: |
| 254 | + if(installed STREQUAL install_prefix OR parent STREQUAL install_prefix) |
| 255 | + break() |
| 256 | + endif() |
| 257 | + # Keep track of this directory for later: |
| 258 | + list(APPEND dirs_to_remove "${installed}") |
| 259 | + endwhile() |
| 260 | +endforeach() |
| 261 | + |
| 262 | +# Now generate commands to remove (empty) directories: |
| 263 | +list(REMOVE_DUPLICATES dirs_to_remove) |
| 264 | +# Order them by depth so that we remove subdirectories before their parents: |
| 265 | +list(SORT dirs_to_remove ORDER DESCENDING) |
| 266 | +foreach(dir IN LISTS dirs_to_remove) |
| 267 | + file(RELATIVE_PATH relpath "${install_prefix}" "${dir}") |
| 268 | + add_rmdir("${relpath}") |
| 269 | +endforeach() |
| 270 | + |
| 271 | +message(STATUS "Generated uninstaller: ${UNINSTALL_WRITE_FILE}") |
0 commit comments