* [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
@ 2026-03-17 7:49 Shubham Chakraborty
2026-03-17 7:58 ` Thomas Petazzoni via buildroot
0 siblings, 1 reply; 6+ messages in thread
From: Shubham Chakraborty @ 2026-03-17 7:49 UTC (permalink / raw)
To: buildroot, Thomas Petazzoni; +Cc: Shubham Chakraborty
Buildroot currently does not track which files are installed by each
package in output/staging, output/target, output/host, and
output/images directories. This makes it impossible to cleanly remove
a package without performing a full rebuild.
This commit adds:
1. A new Python script (support/scripts/pkg-uninstall.py) that reads
manifest files (.files-list*.txt) tracking package file installations
and removes all files belonging to a specified package from a given
directory.
The script handles:
- Regular files and symlinks (both to files and directories)
- Broken symlinks
- Empty directory cleanup (deepest first)
- Safe removal that prevents deletion outside the base directory
- Graceful handling of missing manifests
2. A new 'make <pkg>-uninstall' target in pkg-generic.mk that:
- Displays an "Uninstalling" message
- Removes the package's install stamp files
- Calls pkg-uninstall.py for each output directory:
* TARGET_DIR (target rootfs)
* STAGING_DIR (staging for libraries/headers)
* HOST_DIR (host tools)
* BINARIES_DIR (images like kernel/bootloader)
- Updates size tracking baselines for each directory
- Cleans up the manifest files after uninstallation
Usage:
make <package-name>-uninstall
This enables selective package removal without requiring a complete
rebuild of the entire system.
Signed-off-by: Shubham Chakraborty <chakrabortyshubham66@gmail.com>
---
package/pkg-generic.mk | 26 +++++++++++-
support/scripts/pkg-uninstall.py | 71 ++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 1 deletion(-)
create mode 100755 support/scripts/pkg-uninstall.py
diff --git a/package/pkg-generic.mk b/package/pkg-generic.mk
index dd440e4062..db058b86a3 100644
--- a/package/pkg-generic.mk
+++ b/package/pkg-generic.mk
@@ -1043,6 +1043,29 @@ $(1)-all-legal-info: $$(foreach p,$$($(2)_FINAL_ALL_DEPENDENCIES),$$(p)-all-lega
$(1)-dirclean: $$($(2)_TARGET_DIRCLEAN)
+$(1)-uninstall: PKG=$(2)
+$(1)-uninstall:
+ @$$(call MESSAGE,"Uninstalling")
+ # Remove stamps first (fault-tolerant ordering)
+ rm -f $$($(2)_TARGET_INSTALL)
+ rm -f $$($(2)_TARGET_INSTALL_STAGING)
+ rm -f $$($(2)_TARGET_INSTALL_TARGET)
+ rm -f $$($(2)_TARGET_INSTALL_IMAGES)
+ rm -f $$($(2)_TARGET_INSTALL_HOST)
+ # Uninstall files from all locations
+ $$(Q)support/scripts/pkg-uninstall.py -p $$($(2)_NAME) -d $$(TARGET_DIR) -l $$($(2)_DIR)/.files-list.txt
+ $$(Q)support/scripts/pkg-uninstall.py -p $$($(2)_NAME) -d $$(STAGING_DIR) -l $$($(2)_DIR)/.files-list-staging.txt
+ $$(Q)support/scripts/pkg-uninstall.py -p $$($(2)_NAME) -d $$(HOST_DIR) -l $$($(2)_DIR)/.files-list-host.txt
+ $$(Q)support/scripts/pkg-uninstall.py -p $$($(2)_NAME) -d $$(BINARIES_DIR) -l $$($(2)_DIR)/.files-list-images.txt
+ # Update baselines to reflect post-uninstall state
+ @$$(call pkg_size_before,$$(TARGET_DIR))
+ @$$(call pkg_size_before,$$(STAGING_DIR),-staging)
+ @$$(call pkg_size_before,$$(HOST_DIR),-host)
+ @$$(call pkg_size_before,$$(BINARIES_DIR),-images)
+ # Clean up manifests
+ rm -f $$($(2)_DIR)/.files-list.txt $$($(2)_DIR)/.files-list-staging.txt $$($(2)_DIR)/.files-list-host.txt $$($(2)_DIR)/.files-list-images.txt
+
+
$(1)-clean-for-reinstall:
ifneq ($$($(2)_OVERRIDE_SRCDIR),)
rm -f $$($(2)_TARGET_RSYNC)
@@ -1304,7 +1327,8 @@ DL_TOOLS_DEPENDENCIES += $$(call extractor-system-dependency,$$($(2)_SOURCE))
$(1)-show-depends \
$(1)-show-info \
$(1)-show-version \
- $(1)-source
+ $(1)-source \
+ $(1)-uninstall
ifneq ($$($(2)_SOURCE),)
ifeq ($$($(2)_SITE),)
diff --git a/support/scripts/pkg-uninstall.py b/support/scripts/pkg-uninstall.py
new file mode 100755
index 0000000000..3ef3f7bd7c
--- /dev/null
+++ b/support/scripts/pkg-uninstall.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import argparse
+
+def main():
+ parser = argparse.ArgumentParser(description="Cleanly uninstall a package's files")
+ parser.add_argument("-p", "--package", required=True, help="Package name")
+ parser.add_argument("-d", "--dir", required=True, help="Base directory (e.g. output/target)")
+ parser.add_argument("-l", "--list", required=True, help="Path to .files-list.txt")
+
+ args = parser.parse_args()
+
+ if not os.path.exists(args.list):
+ # We don't error out because a package might not install files in all locations
+ # (e.g. no staging or no images), but we print a notice for debugging.
+ print(f"Notice: Manifest not found, skipping: {args.list}")
+ return
+
+ with open(args.list, "r") as f:
+ lines = f.readlines()
+
+ directories = set()
+
+ # Remove files
+ for line in lines:
+ line = line.strip()
+ if not line:
+ continue
+
+ parts = line.split(",", 1)
+ if len(parts) != 2:
+ continue
+
+ pkg, rel_path = parts
+ if pkg != args.package:
+ continue
+
+ if rel_path.startswith("./"):
+ rel_path = rel_path[2:]
+
+ full_path = os.path.join(args.dir, rel_path)
+
+ if os.path.lexists(full_path) and (not os.path.isdir(full_path) or os.path.islink(full_path)):
+ try:
+ os.remove(full_path)
+ print(f"Removed: {full_path}")
+ directories.add(os.path.dirname(full_path))
+ except OSError as e:
+ print(f"Failed to remove {full_path}: {e}", file=sys.stderr)
+ elif not os.path.lexists(full_path):
+ # If it doesn't exist, we still might want to clean up its parent dir
+ directories.add(os.path.dirname(full_path))
+
+ # Remove empty directories, deeper first
+ sorted_dirs = sorted(list(directories), key=len, reverse=True)
+ for d in sorted_dirs:
+ # Don't try to remove the base dir or outside it
+ if not d or d == args.dir or not os.path.abspath(d).startswith(os.path.abspath(args.dir)):
+ continue
+ try:
+ # Atomic attempt to remove directory if empty
+ os.rmdir(d)
+ print(f"Removed empty dir: {d}")
+ except OSError:
+ # Directory not empty or other error, safe to ignore
+ pass
+
+if __name__ == "__main__":
+ main()
--
2.53.0
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
2026-03-17 7:49 [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages Shubham Chakraborty
@ 2026-03-17 7:58 ` Thomas Petazzoni via buildroot
2026-03-17 8:11 ` Shubham Chakraborty
0 siblings, 1 reply; 6+ messages in thread
From: Thomas Petazzoni via buildroot @ 2026-03-17 7:58 UTC (permalink / raw)
To: Shubham Chakraborty; +Cc: buildroot
Hello,
On Tue, Mar 17, 2026 at 01:19:19PM +0530, Shubham Chakraborty wrote:
> Buildroot currently does not track which files are installed by each
> package in output/staging, output/target, output/host, and
> output/images directories. This makes it impossible to cleanly remove
> a package without performing a full rebuild.
>
> This commit adds:
>
> 1. A new Python script (support/scripts/pkg-uninstall.py) that reads
> manifest files (.files-list*.txt) tracking package file installations
> and removes all files belonging to a specified package from a given
> directory.
Thanks for your patch. Unfortunately there's a reason why this hasn't
been implemented, because it simply doesn't work. Think about the
following scenario:
1. Make a build with BR2_PACKAGE_NTP=y, BR2_PACKAGE_OPENSSL=y
2. Run "make openssl-uninstall"
3. ntp is now broken on the target, because the ntp binary is linked
against libopenssl.so, but libopenssl.so is no longer on the target
Best regards,
Thomas
--
Thomas Petazzoni, co-owner and CEO, Bootlin
Embedded Linux and Kernel engineering and training
https://bootlin.com
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
2026-03-17 7:58 ` Thomas Petazzoni via buildroot
@ 2026-03-17 8:11 ` Shubham Chakraborty
2026-03-17 9:08 ` Thomas Petazzoni via buildroot
0 siblings, 1 reply; 6+ messages in thread
From: Shubham Chakraborty @ 2026-03-17 8:11 UTC (permalink / raw)
To: Thomas Petazzoni; +Cc: buildroot
[-- Attachment #1.1: Type: text/plain, Size: 2523 bytes --]
Hi Thomas,
Thank you for the quick feedback and for pointing out this critical issue.
I didn't consider reverse dependencies. The scenario you described
(uninstalling openssl breaking ntp) is a
serious problem that makes the current implementation unsafe.
I see a few potential approaches to address this:
1. Add dependency checking that refuses to uninstall if reverse
dependencies exist (similar to package managers like apt/dnf)
2. Implement cascade uninstall (uninstall the package and all its reverse
dependencies)
3. Add a --force flag with clear warnings that this may break other
packages
4. Simply document this as a "use at your own risk" feature for advanced
debugging scenarios
I wanted to ask: would any of these approaches be acceptable for Buildroot?
Or is the fundamental issue that without proper
dependency tracking during uninstall, this feature is too dangerous to
include regardless of warnings/checks?
I'm happy to implement proper dependency checking if that would make this
feature viable,
or I can withdraw the patch if you think the approach is fundamentally
flawed.
Thanks again for your time reviewing this.
Best regards,
Shubham
On Tue, Mar 17, 2026 at 1:29 PM Thomas Petazzoni <
thomas.petazzoni@bootlin.com> wrote:
> Hello,
>
> On Tue, Mar 17, 2026 at 01:19:19PM +0530, Shubham Chakraborty wrote:
> > Buildroot currently does not track which files are installed by each
> > package in output/staging, output/target, output/host, and
> > output/images directories. This makes it impossible to cleanly remove
> > a package without performing a full rebuild.
> >
> > This commit adds:
> >
> > 1. A new Python script (support/scripts/pkg-uninstall.py) that reads
> > manifest files (.files-list*.txt) tracking package file installations
> > and removes all files belonging to a specified package from a given
> > directory.
>
> Thanks for your patch. Unfortunately there's a reason why this hasn't
> been implemented, because it simply doesn't work. Think about the
> following scenario:
>
> 1. Make a build with BR2_PACKAGE_NTP=y, BR2_PACKAGE_OPENSSL=y
>
> 2. Run "make openssl-uninstall"
>
> 3. ntp is now broken on the target, because the ntp binary is linked
> against libopenssl.so, but libopenssl.so is no longer on the target
>
> Best regards,
>
> Thomas
> --
> Thomas Petazzoni, co-owner and CEO, Bootlin
> Embedded Linux and Kernel engineering and training
> https://bootlin.com
>
[-- Attachment #1.2: Type: text/html, Size: 3413 bytes --]
[-- Attachment #2: Type: text/plain, Size: 150 bytes --]
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
2026-03-17 8:11 ` Shubham Chakraborty
@ 2026-03-17 9:08 ` Thomas Petazzoni via buildroot
0 siblings, 0 replies; 6+ messages in thread
From: Thomas Petazzoni via buildroot @ 2026-03-17 9:08 UTC (permalink / raw)
To: Shubham Chakraborty; +Cc: buildroot
Hello,
On Tue, Mar 17, 2026 at 01:41:25PM +0530, Shubham Chakraborty wrote:
> I didn't consider reverse dependencies. The scenario you described
> (uninstalling openssl breaking ntp) is a
> serious problem that makes the current implementation unsafe.
>
> I see a few potential approaches to address this:
>
> 1. Add dependency checking that refuses to uninstall if reverse
> dependencies exist (similar to package managers like apt/dnf)
This would make the feature useless for a significant number of
packages I'd say.
> 2. Implement cascade uninstall (uninstall the package and all its reverse
> dependencies)
This would probably be the logical thing, I guess?
> 4. Simply document this as a "use at your own risk" feature for advanced
> debugging scenarios
>
> I wanted to ask: would any of these approaches be acceptable for Buildroot?
> Or is the fundamental issue that without proper
> dependency tracking during uninstall, this feature is too dangerous to
> include regardless of warnings/checks?
This has so far been the project's opinion on this topic. But nothing
is set in stone forever, so we can always revisit/rediscuss things.
Thomas
--
Thomas Petazzoni, co-owner and CEO, Bootlin
Embedded Linux and Kernel engineering and training
https://bootlin.com
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
[not found] <mailman.9.1773748801.2109898.buildroot@buildroot.org>
@ 2026-03-18 4:43 ` Andreas Ziegler
2026-03-18 7:44 ` Shubham Chakraborty
0 siblings, 1 reply; 6+ messages in thread
From: Andreas Ziegler @ 2026-03-18 4:43 UTC (permalink / raw)
To: buildroot; +Cc: Shubham Chakraborty, Thomas Petazzoni
Hi Thomas, Shubham, ALL,
On 2026-03-17 10:08, Thomas Petazzoni wrote:
>
> Hello,
>
> On Tue, Mar 17, 2026 at 01:41:25PM +0530, Shubham Chakraborty wrote:
>
>> I didn't consider reverse dependencies. The scenario you described
>> (uninstalling openssl breaking ntp) is a
>> serious problem that makes the current implementation unsafe.
>>
>> I see a few potential approaches to address this:
>>
>> 1. Add dependency checking that refuses to uninstall if reverse
>> dependencies exist (similar to package managers like apt/dnf)
>
> This would make the feature useless for a significant number of
> packages I'd say.
In most cases, exactly these reverse dependencies make removal of the
package desirable. Testing with and without sometimes needs manual
intervention. Also I prefer clearing up the mess after testing to doing
a full rebuild: it's less time consuming.
>> 2. Implement cascade uninstall (uninstall the package and all its
>> reverse
>> dependencies)
>
> This would probably be the logical thing, I guess?
>
Nice to have, but is it worth the effort? This is not a tool for
everyday use, and most people will know what they are doing.
>> 4. Simply document this as a "use at your own risk" feature for
>> advanced
>> debugging scenarios
>>
>> I wanted to ask: would any of these approaches be acceptable for
>> Buildroot?
>> Or is the fundamental issue that without proper
>> dependency tracking during uninstall, this feature is too dangerous to
>> include regardless of warnings/checks?
>
> This has so far been the project's opinion on this topic. But nothing
> is set in stone forever, so we can always revisit/rediscuss things.
I used to delete files manually, until I discovered the central
packages-file-list*.txt files, and have been using a similar Python
script for a few years. Shubham's approach to use the package based
lists is better.
Including the script as a build target is optional.
> Thomas
> --
> Thomas Petazzoni, co-owner and CEO, Bootlin
> Embedded Linux and Kernel engineering and training
> https://bootlin.com
Kind regards,
Andreas
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages
2026-03-18 4:43 ` Andreas Ziegler
@ 2026-03-18 7:44 ` Shubham Chakraborty
0 siblings, 0 replies; 6+ messages in thread
From: Shubham Chakraborty @ 2026-03-18 7:44 UTC (permalink / raw)
To: Andreas Ziegler; +Cc: buildroot, Thomas Petazzoni
[-- Attachment #1.1: Type: text/plain, Size: 3098 bytes --]
Hi Thomas, Andreas, all,
Thank you both for the feedback.
Andreas, I'm glad to hear this approach has been working well for you
in practice. That's reassuring.
Based on the discussion, I see a few paths forward:
1. Keep the script as-is with clear documentation that it's for advanced
debugging/testing scenarios and doesn't handle reverse dependencies
2. Add the cascade uninstall feature for safety
3. Ship the script in support/scripts/ but make the make target integration
optional (as Andreas suggested)
I'm inclined toward option 1 or 3 - shipping a useful tool for developers
who understand the caveats, with clear documentation about the reverse
dependency limitation.
What do you think?
Best regards,
Shubham
On Wed, Mar 18, 2026 at 10:13 AM Andreas Ziegler <br025@umbiko.net> wrote:
> Hi Thomas, Shubham, ALL,
>
> On 2026-03-17 10:08, Thomas Petazzoni wrote:
> >
> > Hello,
> >
> > On Tue, Mar 17, 2026 at 01:41:25PM +0530, Shubham Chakraborty wrote:
> >
> >> I didn't consider reverse dependencies. The scenario you described
> >> (uninstalling openssl breaking ntp) is a
> >> serious problem that makes the current implementation unsafe.
> >>
> >> I see a few potential approaches to address this:
> >>
> >> 1. Add dependency checking that refuses to uninstall if reverse
> >> dependencies exist (similar to package managers like apt/dnf)
> >
> > This would make the feature useless for a significant number of
> > packages I'd say.
>
> In most cases, exactly these reverse dependencies make removal of the
> package desirable. Testing with and without sometimes needs manual
> intervention. Also I prefer clearing up the mess after testing to doing
> a full rebuild: it's less time consuming.
>
> >> 2. Implement cascade uninstall (uninstall the package and all its
> >> reverse
> >> dependencies)
> >
> > This would probably be the logical thing, I guess?
> >
>
> Nice to have, but is it worth the effort? This is not a tool for
> everyday use, and most people will know what they are doing.
>
> >> 4. Simply document this as a "use at your own risk" feature for
> >> advanced
> >> debugging scenarios
> >>
> >> I wanted to ask: would any of these approaches be acceptable for
> >> Buildroot?
> >> Or is the fundamental issue that without proper
> >> dependency tracking during uninstall, this feature is too dangerous to
> >> include regardless of warnings/checks?
> >
> > This has so far been the project's opinion on this topic. But nothing
> > is set in stone forever, so we can always revisit/rediscuss things.
>
> I used to delete files manually, until I discovered the central
> packages-file-list*.txt files, and have been using a similar Python
> script for a few years. Shubham's approach to use the package based
> lists is better.
>
> Including the script as a build target is optional.
>
> > Thomas
> > --
> > Thomas Petazzoni, co-owner and CEO, Bootlin
> > Embedded Linux and Kernel engineering and training
> > https://bootlin.com
>
> Kind regards,
> Andreas
>
[-- Attachment #1.2: Type: text/html, Size: 3878 bytes --]
[-- Attachment #2: Type: text/plain, Size: 150 bytes --]
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-18 7:45 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 7:49 [Buildroot] [PATCH] package/pkg-generic: add support for uninstalling packages Shubham Chakraborty
2026-03-17 7:58 ` Thomas Petazzoni via buildroot
2026-03-17 8:11 ` Shubham Chakraborty
2026-03-17 9:08 ` Thomas Petazzoni via buildroot
[not found] <mailman.9.1773748801.2109898.buildroot@buildroot.org>
2026-03-18 4:43 ` Andreas Ziegler
2026-03-18 7:44 ` Shubham Chakraborty
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox