summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-11-17 11:03:51 +0800
committerGitHub <[email protected]>2023-11-17 11:03:51 +0800
commitcf3afe37b546efb93079fd6314c0769884ca0fb1 (patch)
tree732f74fe2fd2922f3c95e8542de82cb6ee108f1c
parentb6bb372d19bd2f6ac931d3e0e096b4fa07024cfb (diff)
parente0f074c79be1f712d09df9f7b4b32245ba95f1c9 (diff)
Merge pull request #4392 from xmake-io/emptydirs
improve os.rm to support remove emptydirs
-rw-r--r--core/src/demo/xmake.lua19
-rw-r--r--core/xpack.lua1
-rw-r--r--xmake/core/base/os.lua30
-rw-r--r--xmake/core/sandbox/modules/os.lua8
-rw-r--r--xmake/includes/xpack/xmake.lua4
-rw-r--r--xmake/modules/private/action/clean/remove_files.lua10
-rw-r--r--xmake/modules/private/utils/batchcmds.lua26
-rw-r--r--xmake/plugins/pack/nsis/main.lua72
-rw-r--r--xmake/scripts/xpack/nsis/makensis.nsi143
9 files changed, 215 insertions, 98 deletions
diff --git a/core/src/demo/xmake.lua b/core/src/demo/xmake.lua
index 02466b31f..a45c82693 100644
--- a/core/src/demo/xmake.lua
+++ b/core/src/demo/xmake.lua
@@ -68,3 +68,22 @@ target("demo")
add_installfiles("$(projectdir)/../scripts/xrepo.sh", {prefixdir = "bin", filename = "xrepo"})
end
+ before_installcmd(function (target, batchcmds, opt)
+ -- we need to avoid some old files interfering with xmake's module import.
+ if target:is_plat("windows") then
+ batchcmds:rmdir("actions")
+ batchcmds:rmdir("core")
+ batchcmds:rmdir("includes")
+ batchcmds:rmdir("languages")
+ batchcmds:rmdir("modules")
+ batchcmds:rmdir("platforms")
+ batchcmds:rmdir("plugins")
+ batchcmds:rmdir("repository")
+ batchcmds:rmdir("rules")
+ batchcmds:rmdir("templates")
+ batchcmds:rmdir("scripts")
+ batchcmds:rmdir("themes")
+ batchcmds:rmdir("toolchains")
+ end
+ end)
+
diff --git a/core/xpack.lua b/core/xpack.lua
index 5cbff58e8..280b1365a 100644
--- a/core/xpack.lua
+++ b/core/xpack.lua
@@ -5,6 +5,7 @@ xpack("xmake")
add_targets("demo")
set_bindir(".")
set_iconfile("src/demo/xmake.ico")
+ set_nsis_displayname("Xmake build utility ($(arch))")
on_load(function (package)
local arch = package:arch()
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index 7ae34ccc2..ed5490b7d 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -159,6 +159,19 @@ function os._rm(filedir)
return true
end
+-- remove empty parent directories of this file path
+function os._rm_empty_parentdirs(filepath)
+ local parentdir = path.directory(filepath)
+ while parentdir and os.isdir(parentdir) and os.emptydir(parentdir) do
+ local ok, errors = os._rm(parentdir)
+ if not ok then
+ return false, errors
+ end
+ parentdir = path.directory(parentdir)
+ end
+ return true
+end
+
-- get the ramdisk root directory
-- https://github.com/xmake-io/xmake/issues/3408
function os._ramdir()
@@ -464,7 +477,7 @@ function os.mv(srcpath, dstpath, opt)
end
-- remove files or directories
-function os.rm(filepath)
+function os.rm(filepath, opt)
-- check arguments
if not filepath then
@@ -472,16 +485,29 @@ function os.rm(filepath)
end
-- remove file or directories
+ opt = opt or {}
filepath = tostring(filepath)
local filepathes = os._match_wildcard_pathes(filepath)
if type(filepathes) == "string" then
- return os._rm(filepathes)
+ local ok, errors = os._rm(filepathes)
+ if not ok then
+ return false, errors
+ end
+ if opt.emptydirs then
+ return os._rm_empty_parentdirs(filepathes)
+ end
else
for _, _filepath in ipairs(filepathes) do
local ok, errors = os._rm(_filepath)
if not ok then
return false, errors
end
+ if opt.emptydirs then
+ ok, errors = os._rm_empty_parentdirs(filepath)
+ if not ok then
+ return false, errors
+ end
+ end
end
end
return true
diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua
index c23ffb261..9004f66ee 100644
--- a/xmake/core/sandbox/modules/os.lua
+++ b/xmake/core/sandbox/modules/os.lua
@@ -152,12 +152,12 @@ function sandbox_os.vmv(srcpath, dstpath, opt)
end
-- remove file or directory with the verbose info
-function sandbox_os.vrm(filepath)
+function sandbox_os.vrm(filepath, opt)
assert(filepath)
if option.get("verbose") then
utils.cprint("${dim}> remove %s", filepath)
end
- return sandbox_os.rm(filepath)
+ return sandbox_os.rm(filepath, opt)
end
-- link file or directory with the verbose info
@@ -182,9 +182,9 @@ function sandbox_os.trymv(srcpath, dstpath)
end
-- try to remove files or directories
-function sandbox_os.tryrm(filepath)
+function sandbox_os.tryrm(filepath, opt)
assert(filepath)
- return os.rm(vformat(filepath))
+ return os.rm(vformat(filepath), opt)
end
-- change to directory
diff --git a/xmake/includes/xpack/xmake.lua b/xmake/includes/xpack/xmake.lua
index f7198600d..9021404f7 100644
--- a/xmake/includes/xpack/xmake.lua
+++ b/xmake/includes/xpack/xmake.lua
@@ -49,7 +49,9 @@ local apis = {
-- set installed library directory, e.g. lib
"xpack.set_libdir",
-- set installed include directory, e.g. include
- "xpack.set_includedir"
+ "xpack.set_includedir",
+ -- set nsis display name
+ "xpack.set_nsis_displayname"
},
paths = {
-- set the spec file path, support the custom variable pattern, e.g. set_specfile("", {pattern = "%${([^\n]-)}"})
diff --git a/xmake/modules/private/action/clean/remove_files.lua b/xmake/modules/private/action/clean/remove_files.lua
index 606bb405d..3d62c6b78 100644
--- a/xmake/modules/private/action/clean/remove_files.lua
+++ b/xmake/modules/private/action/clean/remove_files.lua
@@ -25,14 +25,6 @@ import("core.base.option")
function main(filedirs, opt)
opt = opt or {}
for _, filedir in ipairs(filedirs) do
- os.tryrm(filedir)
- if option.get("all") or opt.emptydir then
- -- remove it if the parent directory is empty
- local parentdir = path.directory(filedir)
- while parentdir and os.isdir(parentdir) and os.emptydir(parentdir) do
- os.tryrm(parentdir)
- parentdir = path.directory(parentdir)
- end
- end
+ os.tryrm(filedir, {emptydirs = option.get("all") or opt.emptydir})
end
end
diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua
index fe518cbec..eda3887c8 100644
--- a/xmake/modules/private/utils/batchcmds.lua
+++ b/xmake/modules/private/utils/batchcmds.lua
@@ -140,15 +140,7 @@ end
function _runcmd_rm(cmd, opt)
local filepath = cmd.filepath
if not opt.dryrun then
- os.tryrm(filepath)
- end
-end
-
--- run command: os.tryrm
-function _runcmd_tryrm(cmd, opt)
- local filepath = cmd.filepath
- if not opt.dryrun then
- os.tryrm(filepath)
+ os.tryrm(filepath, opt)
end
end
@@ -156,7 +148,7 @@ end
function _runcmd_rmdir(cmd, opt)
local dir = cmd.dir
if not opt.dryrun and os.isdir(dir) then
- os.tryrm(dir)
+ os.tryrm(dir, opt)
end
end
@@ -197,7 +189,6 @@ function _runcmd(cmd, opt)
rmdir = _runcmd_rmdir,
cd = _runcmd_cd,
rm = _runcmd_rm,
- tryrm = _runcmd_tryrm,
cp = _runcmd_cp,
mv = _runcmd_mv,
ln = _runcmd_ln
@@ -352,18 +343,13 @@ function batchcmds:mkdir(dir)
end
-- add command: os.rmdir
-function batchcmds:rmdir(dir)
- table.insert(self:cmds(), {kind = "rmdir", dir = dir})
+function batchcmds:rmdir(dir, opt)
+ table.insert(self:cmds(), {kind = "rmdir", dir = dir, opt = opt})
end
-- add command: os.rm
-function batchcmds:rm(filepath)
- table.insert(self:cmds(), {kind = "rm", filepath = filepath})
-end
-
--- add command: os.tryrm
-function batchcmds:tryrm(filepath)
- table.insert(self:cmds(), {kind = "tryrm", filepath = filepath})
+function batchcmds:rm(filepath, opt)
+ table.insert(self:cmds(), {kind = "rm", filepath = filepath, opt = opt})
end
-- add command: os.cp
diff --git a/xmake/plugins/pack/nsis/main.lua b/xmake/plugins/pack/nsis/main.lua
index 02d31ac48..3c4fa3bbd 100644
--- a/xmake/plugins/pack/nsis/main.lua
+++ b/xmake/plugins/pack/nsis/main.lua
@@ -25,6 +25,7 @@ import("lib.detect.find_tool")
import("private.utils.batchcmds")
import("private.action.require.impl.packagenv")
import("private.action.require.impl.install_packages")
+import(".filter")
-- get the makensis
function _get_makensis()
@@ -59,9 +60,9 @@ function _get_unique_tag(content)
end
-- get command string
-function _get_command_strings(package, cmd)
+function _get_command_strings(package, cmd, opt)
+ opt = table.join(cmd.opt or {}, opt)
local result = {}
- local opt = cmd.opt or {}
local kind = cmd.kind
if kind == "cp" then
-- https://nsis.sourceforge.io/Reference/File
@@ -84,25 +85,16 @@ function _get_command_strings(package, cmd)
end
elseif kind == "rm" then
local filepath = path.normalize(path.join("$InstDir", cmd.filepath))
- table.insert(result, string.format("Delete \"%s\"", filepath))
- elseif kind == "tryrm" then
- --[[
- IfFileExists "$InstDir\file" file_found file_not_found_or_end
- file_found:
- Delete "$InstDir\file"
- goto file_not_found_or_end
- file_not_found_or_end:
- --]]
- local filepath = path.normalize(path.join("$InstDir", cmd.filepath))
- local tag = _get_unique_tag(filepath)
- table.insert(result, string.format("IfFileExists \"%s\" file_found_%s file_not_found_or_end_%s", filepath, tag, tag))
- table.insert(result, string.format("file_found_%s:", tag))
- table.insert(result, string.format(" Delete \"%s\"", filepath))
- table.insert(result, string.format(" goto file_not_found_or_end_%s", tag))
- table.insert(result, string.format("file_not_found_or_end_%s:", tag))
+ table.insert(result, string.format("${%s} \"%s\"", opt.install and "RMFileIfExists" or "unRMFileIfExists", filepath))
+ if opt.emptydirs then
+ table.insert(result, string.format("${%s} \"%s\"", opt.install and "RMEmptyParentDirs" or "unRMEmptyParentDirs", filepath))
+ end
elseif kind == "rmdir" then
local dir = path.normalize(path.join("$InstDir", cmd.dir))
- table.insert(result, string.format("RMDir /r \"%s\"", dir))
+ table.insert(result, string.format("${%s} \"%s\"", opt.install and "RMDirIfExists" or "unRMDirIfExists", dir))
+ if opt.emptydirs then
+ table.insert(result, string.format("${%s} \"%s\"", opt.install and "RMEmptyParentDirs" or "unRMEmptyParentDirs", dir))
+ end
elseif kind == "mv" then
local srcpath = path.normalize(path.join("$InstDir", cmd.srcpath))
local dstpath = path.normalize(path.join("$InstDir", cmd.dstpath))
@@ -118,10 +110,10 @@ function _get_command_strings(package, cmd)
end
-- get commands string
-function _get_commands_string(package, cmds)
+function _get_commands_string(package, cmds, opt)
local cmdstrs = {}
for _, cmd in ipairs(cmds) do
- table.join2(cmdstrs, _get_command_strings(package, cmd))
+ table.join2(cmdstrs, _get_command_strings(package, cmd, opt))
end
return table.concat(cmdstrs, "\n ")
end
@@ -173,7 +165,7 @@ end
function _uninstall_headers(target, batchcmds_, includedir)
local _, dstheaders = target:headerfiles(includedir, {installonly = true})
for _, dstheader in ipairs(dstheaders) do
- batchcmds_:rm(dstheader)
+ batchcmds_:rm(dstheader, {emptydirs = true})
end
end
@@ -182,7 +174,7 @@ function _uninstall_shared_for_package(target, pkg, batchcmds_, outputdir)
for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do
if dllpath:endswith(".dll") then
local dllname = path.filename(dllpath)
- batchcmds_:rm(path.join(outputdir, dllname))
+ batchcmds_:rm(path.join(outputdir, dllname), {emptydirs = true})
end
end
end
@@ -311,14 +303,14 @@ function _on_target_uninstallcmd_binary(target, batchcmds_, opt)
local bindir = package:bindir()
-- uninstall target file
- batchcmds_:rm(path.join(bindir, target:filename()))
- batchcmds_:tryrm(path.join(bindir, path.filename(target:symbolfile())))
+ batchcmds_:rm(path.join(bindir, target:filename()), {emptydirs = true})
+ batchcmds_:rm(path.join(bindir, path.filename(target:symbolfile())), {emptydirs = true})
-- remove the dependent shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/961
for _, dep in ipairs(target:orderdeps()) do
if dep:is_shared() then
- batchcmds_:rm(path.join(bindir, path.filename(dep:targetfile())))
+ batchcmds_:rm(path.join(bindir, path.filename(dep:targetfile())), {emptydirs = true})
end
_uninstall_shared_for_packages(dep, batchcmds_, bindir)
end
@@ -335,13 +327,13 @@ function _on_target_uninstallcmd_shared(target, batchcmds_, opt)
local includedir = package:includedir()
-- uninstall target file
- batchcmds_:rm(path.join(bindir, target:filename()))
- batchcmds_:tryrm(path.join(bindir, path.filename(target:symbolfile())))
+ batchcmds_:rm(path.join(bindir, target:filename()), {emptydirs = true})
+ batchcmds_:rm(path.join(bindir, path.filename(target:symbolfile())), {emptydirs = true})
-- remove *.lib for shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/714
local targetfile = target:targetfile()
- batchcmds_:rm(path.join(libdir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")))
+ batchcmds_:rm(path.join(libdir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")), {emptydirs = true})
-- remove headers from the include directory
_uninstall_headers(target, batchcmds_, includedir)
@@ -357,8 +349,8 @@ function _on_target_uninstallcmd_static(target, batchcmds_, opt)
local includedir = package:includedir()
-- uninstall target file
- batchcmds_:rm(path.join(libdir, target:filename()))
- batchcmds_:tryrm(path.join(libdir, path.filename(target:symbolfile())))
+ batchcmds_:rm(path.join(libdir, target:filename()), {emptydirs = true})
+ batchcmds_:rm(path.join(libdir, path.filename(target:symbolfile())), {emptydirs = true})
-- remove headers from the include directory
_uninstall_headers(target, batchcmds_, includedir)
@@ -389,7 +381,7 @@ function _on_target_uninstallcmd(target, batchcmds_, opt)
-- uninstall target files
local _, dstfiles = target:installfiles(".")
for _, dstfile in ipairs(dstfiles) do
- batchcmds_:rm(dstfile)
+ batchcmds_:rm(dstfile, {emptydirs = true})
end
end
@@ -474,7 +466,7 @@ end
function _on_uninstallcmd(package, batchcmds_)
local _, dstfiles = package:installfiles(".")
for _, dstfile in ipairs(dstfiles) do
- batchcmds_:rm(dstfile)
+ batchcmds_:rm(dstfile, {emptydirs = true})
end
for _, target in ipairs(package:targets()) do
_get_target_uninstallcmds(target, batchcmds_, {package = package})
@@ -499,7 +491,7 @@ function _get_installcmds(package)
end
-- generate command string
- return _get_commands_string(package, batchcmds_:cmds())
+ return _get_commands_string(package, batchcmds_:cmds(), {install = true})
end
-- get uninstall commands
@@ -520,7 +512,16 @@ function _get_uninstallcmds(package)
end
-- generate command string
- return _get_commands_string(package, batchcmds_:cmds())
+ return _get_commands_string(package, batchcmds_:cmds(), {install = false})
+end
+
+-- get value and filter it
+function _get_filter_value(package, name)
+ local value = package:get(name)
+ if type(value) == "string" then
+ value = filter.handle(value, package)
+ end
+ return value
end
-- get specvars
@@ -535,6 +536,7 @@ function _get_specvars(package)
specvars.PACKAGE_UNINSTALLCMDS = function ()
return _get_uninstallcmds(package)
end
+ specvars.PACKAGE_NSIS_DISPLAY_NAME = _get_filter_value(package, "nsis_displayname") or package:name()
specvars.PACKAGE_NSIS_INSTALL_SECTIONS = function ()
local result = {}
local cmds = package:get("nsis_installcmds")
diff --git a/xmake/scripts/xpack/nsis/makensis.nsi b/xmake/scripts/xpack/nsis/makensis.nsi
index 5d1a99dc0..ffcb39c7c 100644
--- a/xmake/scripts/xpack/nsis/makensis.nsi
+++ b/xmake/scripts/xpack/nsis/makensis.nsi
@@ -120,40 +120,128 @@ VIAddVersionKey /LANG=0 ProductVersion "${VERSION_FULL}"
; helper functions
Function TrimQuote
- Exch $R1 ; Original string
- Push $R2
+ Exch $R1 ; Original string
+ Push $R2
Loop:
- StrCpy $R2 "$R1" 1
- StrCmp "$R2" "'" TrimLeft
- StrCmp "$R2" "$\"" TrimLeft
- StrCmp "$R2" "$\r" TrimLeft
- StrCmp "$R2" "$\n" TrimLeft
- StrCmp "$R2" "$\t" TrimLeft
- StrCmp "$R2" " " TrimLeft
- GoTo Loop2
+ StrCpy $R2 "$R1" 1
+ StrCmp "$R2" "'" TrimLeft
+ StrCmp "$R2" "$\"" TrimLeft
+ StrCmp "$R2" "$\r" TrimLeft
+ StrCmp "$R2" "$\n" TrimLeft
+ StrCmp "$R2" "$\t" TrimLeft
+ StrCmp "$R2" " " TrimLeft
+ GoTo Loop2
TrimLeft:
- StrCpy $R1 "$R1" "" 1
- Goto Loop
+ StrCpy $R1 "$R1" "" 1
+ Goto Loop
Loop2:
- StrCpy $R2 "$R1" 1 -1
- StrCmp "$R2" "'" TrimRight
- StrCmp "$R2" "$\"" TrimRight
- StrCmp "$R2" "$\r" TrimRight
- StrCmp "$R2" "$\n" TrimRight
- StrCmp "$R2" "$\t" TrimRight
- StrCmp "$R2" " " TrimRight
- GoTo Done
+ StrCpy $R2 "$R1" 1 -1
+ StrCmp "$R2" "'" TrimRight
+ StrCmp "$R2" "$\"" TrimRight
+ StrCmp "$R2" "$\r" TrimRight
+ StrCmp "$R2" "$\n" TrimRight
+ StrCmp "$R2" "$\t" TrimRight
+ StrCmp "$R2" " " TrimRight
+ GoTo Done
TrimRight:
- StrCpy $R1 "$R1" -1
- Goto Loop2
+ StrCpy $R1 "$R1" -1
+ Goto Loop2
Done:
- Pop $R2
- Exch $R1
+ Pop $R2
+ Exch $R1
FunctionEnd
+; remove directory if it exists
+Function RMDirIfExists
+!define RMDirIfExists '!insertmacro RMDirIfExistsCall'
+!macro RMDirIfExistsCall _PATH
+ push '${_PATH}'
+ Call RMDirIfExists
+!macroend
+ Exch $0
+ IfFileExists "$0" 0 fileDoesNotExist
+ RMDir /r "$0"
+ fileDoesNotExist:
+FunctionEnd
+
+Function unRMDirIfExists
+!define unRMDirIfExists '!insertmacro un.RMDirIfExistsCall'
+!macro unRMDirIfExistsCall _PATH
+ push '${_PATH}'
+ Call un.RMDirIfExists
+!macroend
+ Exch $0
+ IfFileExists "$0" 0 fileDoesNotExist
+ RMDir /r "$0"
+ fileDoesNotExist:
+FunctionEnd
+
+; remove file if it exists
+Function RMFileIfExists
+!define RMFileIfExists '!insertmacro RMFileIfExistsCall'
+!macro RMFileIfExistsCall _PATH
+ push '${_PATH}'
+ Call RMFileIfExists
+!macroend
+ Exch $0
+ IfFileExists "$0" 0 fileDoesNotExist
+ Delete "$0"
+ fileDoesNotExist:
+FunctionEnd
+
+Function un.RMFileIfExists
+!define unRMFileIfExists '!insertmacro unRMFileIfExistsCall'
+!macro unRMFileIfExistsCall _PATH
+ push '${_PATH}'
+ Call un.RMFileIfExists
+!macroend
+ Exch $0
+ IfFileExists "$0" 0 fileDoesNotExist
+ Delete "$0"
+ fileDoesNotExist:
+FunctionEnd
+
+; remove it's parent directories if they are empty
+Function RMEmptyParentDirs
+!define RMEmptyParentDirs '!insertmacro RMEmptyParentDirsCall'
+!macro RMEmptyParentDirsCall _PATH
+ push '${_PATH}'
+ Call RMEmptyParentDirs
+!macroend
+ ClearErrors
+
+ Exch $0
+ RMDir "$0\.."
+
+ IfErrors Skip
+ ${RMEmptyParentDirs} "$0\.."
+ Skip:
+
+ Pop $0
+FunctionEnd
+
+Function un.RMEmptyParentDirs
+!define unRMEmptyParentDirs '!insertmacro unRMEmptyParentDirsCall'
+!macro unRMEmptyParentDirsCall _PATH
+ push '${_PATH}'
+ Call un.RMEmptyParentDirs
+!macroend
+ ClearErrors
+
+ Exch $0
+ RMDir "$0\.."
+
+ IfErrors Skip
+ ${unRMEmptyParentDirs} "$0\.."
+ Skip:
+
+ Pop $0
+FunctionEnd
+
+
; setup installer
Var BinDir
Var NoAdmin
@@ -208,7 +296,7 @@ Section "${PACKAGE_NAME} (required)" InstallExeutable
; Write the uninstall keys for Windows
!macro AddReg RootKey
WriteRegStr ${RootKey} ${RegUninstall} "NoAdmin" "$NoAdmin"
- WriteRegStr ${RootKey} ${RegUninstall} "DisplayName" "${PACKAGE_NAME} (${PACKAGE_ARCH})"
+ WriteRegStr ${RootKey} ${RegUninstall} "DisplayName" "${PACKAGE_NSIS_DISPLAY_NAME}"
WriteRegStr ${RootKey} ${RegUninstall} "DisplayIcon" '"$InstDir\${PACKAGE_BINDIR}\${PACKAGE_FILENAME}"' ; TODO
WriteRegStr ${RootKey} ${RegUninstall} "Comments" "${PACKAGE_DESCRIPTION}"
WriteRegStr ${RootKey} ${RegUninstall} "Publisher" "${PACKAGE_COPYRIGHT}"
@@ -282,7 +370,6 @@ Function un.onInit
!else
StrCpy $BinDir "$InstDir\${PACKAGE_BINDIR}"
!endif
-
FunctionEnd
Section "Uninstall"
@@ -304,6 +391,8 @@ Section "Uninstall"
${EndIf}
; remove uninstall.exe
- Delete "$InstDir\uninstall.exe"
+ ${unRMFileIfExists} "$InstDir\uninstall.exe"
+ ${unRMEmptyParentDirs} "$InstDir\uninstall.exe"
+
SectionEnd