Patchwork [v3,01/22] legal-info: infrastructure to collect legally-relevant material

login
register
mail settings
Submitter Luca Ceresoli
Date May 7, 2012, 8:12 p.m.
Message ID <1336421563-5986-1-git-send-email-luca@lucaceresoli.net>
Download mbox | patch
Permalink /patch/157389/
State Superseded
Headers show

Comments

Luca Ceresoli - May 7, 2012, 8:12 p.m.
This allows to automatically collect material that may be needed to comply with
the license of packages that Buildroot prepares for the target device.

The core of the implementation is made by the following parts:
 - in package/pkg-utils.mk some helper functions are defined for common actions
   such as generating a warning, producing info about a package etc;
 - in package/pkg-gentargets.mk, within the GENTARGETS framework, a new
   <PKG>-legal-info target produces all the info for a given package;
 - Makefile implements the top-level targets:
   - legal-info-prepare creates the output directory and produces legal info
     about Buildroot itself and the toolchain, which mostly means just warning
     the user that this is not implemented;
   - legal-info, the only target that is supposed to be used directly, depends
     on all of the above and finishes things by producing the README files from
     the various pieces.

Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
---
 Makefile                                  |   42 +++++++++++++++++-
 package/pkg-gentargets.mk                 |   65 +++++++++++++++++++++++++++++
 package/pkg-utils.mk                      |   25 +++++++++++
 support/legal-info/README.header          |   24 +++++++++++
 support/legal-info/README.warnings-header |    4 ++
 5 files changed, 157 insertions(+), 3 deletions(-)
 create mode 100644 support/legal-info/README.header
 create mode 100644 support/legal-info/README.warnings-header
Arnout Vandecappelle - May 12, 2012, 11:10 p.m.
On 05/07/12 22:12, Luca Ceresoli wrote:
> This allows to automatically collect material that may be needed to comply with
> the license of packages that Buildroot prepares for the target device.
>
> The core of the implementation is made by the following parts:
>   - in package/pkg-utils.mk some helper functions are defined for common actions
>     such as generating a warning, producing info about a package etc;
>   - in package/pkg-gentargets.mk, within the GENTARGETS framework, a new
>     <PKG>-legal-info target produces all the info for a given package;
>   - Makefile implements the top-level targets:
>     - legal-info-prepare creates the output directory and produces legal info
>       about Buildroot itself and the toolchain, which mostly means just warning
>       the user that this is not implemented;
>     - legal-info, the only target that is supposed to be used directly, depends
>       on all of the above and finishes things by producing the README files from
>       the various pieces.
>
> Signed-off-by: Luca Ceresoli<luca@lucaceresoli.net>

  Looks great!

  Any chance that this can still go into the 2012.05 release?  I have one customer
who would be really pleased with that...

  Except for the dirs dependency, I think it can go in as it is.  But of course I
do have some optional remarks :-)

> +TARGETS_LEGAL_INFO:=$(patsubst %,%-legal-info,\
> +		$(filter-out host-makedevs,\
> +		$(TARGETS) $(BASE_TARGETS) $(TARGETS_HOST_DEPS) $(HOST_DEPS))))

  I guess host-makedevs is filtered out here because it has no tar file?
In that case, the same should be done for makedevs and mcookie.  But maybe
it's better to define the SITE_METHOD of these packages as local.  Then they
will be registered as "not saved" in the manifest.

[snip]
> +legal-info-clean:
> +	@rm -fr $(LEGAL_INFO_DIR)

  We usually use '$(RM) -r', I think.

> +
> +legal-info-prepare: $(LEGAL_INFO_DIR)

  I would add an announcement here:
	@$(call MESSAGE,"Collecting legal info")

> +	@$(call legal-license-file,buildroot,COPYING,COPYING)
> +	@$(call legal-manifest,package,version,license,license files,source archive)

  I would Capitalize the titles.

> +	@$(call legal-manifest,buildroot,$(BR2_VERSION_FULL),GPLv2+,COPYING,not saved)
> +	@$(call legal-warning,the Buildroot source code has not been saved)
> +	@$(call legal-warning,the toolchain has not been saved)
> +	@cp $(CONFIG_DIR)/.config $(LEGAL_INFO_DIR)/buildroot.config
[snip]
> +$(2)_RAWNAME			=  $(patsubst host-%,%,$(1))

  Not for this patch, but it would be better to add an argument to
GENTARGETS for the lowercase non-host name.

  Also, the %/.stamp_patched target could reuse this variable.

>
>
> +ifneq ($$($(3)_LICENSE),PROPRIETARY)
> +ifneq ($$($(3)_SITE_METHOD),local)
> +ifneq ($$($(3)_SITE_METHOD),override)
> +# Packages that have a tarball need it downloaded and extracted beforehand
> +$(1)-legal-info:	$(1)-extract $(REDIST_SOURCES_DIR)
> +endif
> +endif
> +endif

  I would combine these conditions with the ones below for setting
_MANIFEST_TARBALL.  Or you could put it as

ifneq ($$($(2)_MANIFEST_TARBALL),not saved)
$(1)-legal-info:	$(1)-extract $(REDIST_SOURCES_DIR)
endif

  BTW, why is it $(3)_LICENSE here and $(2)_LICENSE below?

> +
>   $(1)-show-depends:
>   			@echo $$($(2)_DEPENDENCIES)
>
> @@ -412,6 +436,47 @@ else
>   $(2)_KCONFIG_VAR = BR2_PACKAGE_$(2)
>   endif
>
> +# Set values used later for legal-info manifest
> +ifneq ($$($(2)_LICENSE),PROPRIETARY)
> +ifneq ($$($(2)_SITE_METHOD),local)
> +ifneq ($$($(2)_SITE_METHOD),override)
> +$(2)_MANIFEST_TARBALL = $$($(2)_SOURCE)
> +ifneq ($(call qstrip,$$($(2)_LICENSE_FILES)),)

  Why is there a qstrip here?  The variable is defined in a .mk
file so doesn't contain quotes, right?

> +$(2)_MANIFEST_LICENSE_FILES = $$($(2)_LICENSE_FILES)
> +endif
> +endif
> +endif
> +endif
> +# defaults for packages without tarball or license files
> +$(2)_MANIFEST_TARBALL ?= not saved
> +$(2)_MANIFEST_LICENSE_FILES ?= not saved
> +
> +# legal-info: produce legally relevant info.
> +$(1)-legal-info:
> +ifeq ($$($(2)_LICENSE),PROPRIETARY)
> +# Proprietary packages: nothing to save
> +else ifeq ($$($(2)_SITE_METHOD),local)
> +# Packages without a tarball: don't save and warn
> +	@$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),local)
> +else ifeq ($$($(2)_SITE_METHOD),override)
> +	@$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),override)
> +else
> +# Other packages
> +# Save license files if defined
> +ifeq ($(call qstrip,$$($(2)_LICENSE_FILES)),)
> +	@$(call legal-license-nofiles,$$($(2)_RAWNAME))
> +	@$(call legal-warning-pkg,$$($(2)_RAWNAME),cannot save license ($(2)_LICENSE_FILES not defined))
> +else
> +	@for F in $$($(2)_LICENSE_FILES); do \
> +		$(call legal-license-file,$$($(2)_RAWNAME),$$$${F},$$($(2)_DIR)/$$$${F}); \
> +		done
> +endif
> +# Copy the source tarball (just hardlink if possible)
> +	@cp -l $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR) 2>/dev/null || \
> +	   cp $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR)

  Genius!

> +endif
> +	@$(call legal-manifest,$$($(2)_RAWNAME),$$($(2)_VERSION),$$($(2)_LICENSE),$$($(2)_MANIFEST_LICENSE_FILES),$$($(2)_MANIFEST_TARBALL))
> +

  I'm not sure if it would work, but maybe this could be moved out
of the GENTARGETS and defined as a pattern rule, like all the other
stuff.  That saves a lot of double $$.

[snip]

  Regards,
  Arnout
Luca Ceresoli - May 14, 2012, 4:54 p.m.
Hi Arnout,
thanks for your review.

Arnout Vandecappelle wrote:
> On 05/07/12 22:12, Luca Ceresoli wrote:
>> This allows to automatically collect material that may be needed to 
>> comply with
>> the license of packages that Buildroot prepares for the target device.
>>
>> The core of the implementation is made by the following parts:
>>   - in package/pkg-utils.mk some helper functions are defined for 
>> common actions
>>     such as generating a warning, producing info about a package etc;
>>   - in package/pkg-gentargets.mk, within the GENTARGETS framework, a new
>> <PKG>-legal-info target produces all the info for a given package;
>>   - Makefile implements the top-level targets:
>>     - legal-info-prepare creates the output directory and produces 
>> legal info
>>       about Buildroot itself and the toolchain, which mostly means 
>> just warning
>>       the user that this is not implemented;
>>     - legal-info, the only target that is supposed to be used 
>> directly, depends
>>       on all of the above and finishes things by producing the README 
>> files from
>>       the various pieces.
>>
>> Signed-off-by: Luca Ceresoli<luca@lucaceresoli.net> 
>
>  Looks great!
>
>  Any chance that this can still go into the 2012.05 release?  I have 
> one customer
> who would be really pleased with that...
>
>  Except for the dirs dependency, I think it can go in as it is.  But 
> of course I
> do have some optional remarks :-)
>
>> +TARGETS_LEGAL_INFO:=$(patsubst %,%-legal-info,\
>> +        $(filter-out host-makedevs,\
>> +        $(TARGETS) $(BASE_TARGETS) $(TARGETS_HOST_DEPS) $(HOST_DEPS)))) 
>
>  I guess host-makedevs is filtered out here because it has no tar file?
> In that case, the same should be done for makedevs and mcookie.  But 
> maybe
> it's better to define the SITE_METHOD of these packages as local.  
> Then they
> will be registered as "not saved" in the manifest. 

My ignorance, I didn't know about the existence of mcookie in Buildroot.
I would like to omit entirely these packages from the legal-info list, 
as they are
actually a part of Buildroot.
But since using filter-out is pretty dirty, I think a clean 
implementation would be
to exclude from legal-info processing all packages with an empyt _SOURCE 
variable.
The assumption here is that if they don't have an external source, they 
are part of
Buildroot.

Do you think this is a good idea?

$ git grep -E '_SOURCE[^A-Z_]*=[^A-Za-z]*$' package/
package/makedevs/makedevs.mk:MAKEDEVS_SOURCE =
package/makedevs/makedevs.mk:HOST_MAKEDEVS_SOURCE =
package/x11r7/mcookie/mcookie.mk:MCOOKIE_SOURCE =

Look, they turned out to be makedevs and mcookie! :)

>
> [snip]
>> +legal-info-clean:
>> +    @rm -fr $(LEGAL_INFO_DIR) 
>
>  We usually use '$(RM) -r', I think. 

Apparently not (although that might be nice).

>
>
>> +
>> +legal-info-prepare: $(LEGAL_INFO_DIR) 
>
>  I would add an announcement here:
>     @$(call MESSAGE,"Collecting legal info") 

Fine, will do.

>
>> +    @$(call legal-license-file,buildroot,COPYING,COPYING)
>> +    @$(call legal-manifest,package,version,license,license 
>> files,source archive) 
>
>  I would Capitalize the titles.

That's sound, will do.

>
>> +    @$(call 
>> legal-manifest,buildroot,$(BR2_VERSION_FULL),GPLv2+,COPYING,not saved)
>> +    @$(call legal-warning,the Buildroot source code has not been saved)
>> +    @$(call legal-warning,the toolchain has not been saved)
>> +    @cp $(CONFIG_DIR)/.config $(LEGAL_INFO_DIR)/buildroot.config 
> [snip]
>> +$(2)_RAWNAME            =  $(patsubst host-%,%,$(1)) 
>
>  Not for this patch, but it would be better to add an argument to
> GENTARGETS for the lowercase non-host name.
>
>  Also, the %/.stamp_patched target could reuse this variable.
>
>>
>> +ifneq ($$($(3)_LICENSE),PROPRIETARY)
>> +ifneq ($$($(3)_SITE_METHOD),local)
>> +ifneq ($$($(3)_SITE_METHOD),override)
>> +# Packages that have a tarball need it downloaded and extracted 
>> beforehand
>> +$(1)-legal-info:    $(1)-extract $(REDIST_SOURCES_DIR)
>> +endif
>> +endif
>> +endif 
>
>  I would combine these conditions with the ones below for setting
> _MANIFEST_TARBALL.  Or you could put it as 

This was to keep dependencies where all other dependencies live, and the
"implementation" in its own place. But the number of extra lines is actually
ugly. I will move the one dependency line below unless there are voices 
against.

> ifneq ($$($(2)_MANIFEST_TARBALL),not saved)
> $(1)-legal-info:    $(1)-extract $(REDIST_SOURCES_DIR)
> endif
>
>  BTW, why is it $(3)_LICENSE here and $(2)_LICENSE below? 

Good catch, these should both be $(2) indeed. Will be fixed in the next 
patchset.

>
>> +
>>   $(1)-show-depends:
>>               @echo $$($(2)_DEPENDENCIES)
>>
>> @@ -412,6 +436,47 @@ else
>>   $(2)_KCONFIG_VAR = BR2_PACKAGE_$(2)
>>   endif
>>
>> +# Set values used later for legal-info manifest
>> +ifneq ($$($(2)_LICENSE),PROPRIETARY)
>> +ifneq ($$($(2)_SITE_METHOD),local)
>> +ifneq ($$($(2)_SITE_METHOD),override)
>> +$(2)_MANIFEST_TARBALL = $$($(2)_SOURCE)
>> +ifneq ($(call qstrip,$$($(2)_LICENSE_FILES)),) 
>
>  Why is there a qstrip here?  The variable is defined in a .mk
> file so doesn't contain quotes, right?

Right. Will fix.

>
>> +$(2)_MANIFEST_LICENSE_FILES = $$($(2)_LICENSE_FILES)
>> +endif
>> +endif
>> +endif
>> +endif
>> +# defaults for packages without tarball or license files
>> +$(2)_MANIFEST_TARBALL ?= not saved
>> +$(2)_MANIFEST_LICENSE_FILES ?= not saved
>> +
>> +# legal-info: produce legally relevant info.
>> +$(1)-legal-info:
>> +ifeq ($$($(2)_LICENSE),PROPRIETARY)
>> +# Proprietary packages: nothing to save
>> +else ifeq ($$($(2)_SITE_METHOD),local)
>> +# Packages without a tarball: don't save and warn
>> +    @$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),local)
>> +else ifeq ($$($(2)_SITE_METHOD),override)
>> +    @$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),override)
>> +else
>> +# Other packages
>> +# Save license files if defined
>> +ifeq ($(call qstrip,$$($(2)_LICENSE_FILES)),)
>> +    @$(call legal-license-nofiles,$$($(2)_RAWNAME))
>> +    @$(call legal-warning-pkg,$$($(2)_RAWNAME),cannot save license 
>> ($(2)_LICENSE_FILES not defined))
>> +else
>> +    @for F in $$($(2)_LICENSE_FILES); do \
>> +        $(call 
>> legal-license-file,$$($(2)_RAWNAME),$$$${F},$$($(2)_DIR)/$$$${F}); \
>> +        done
>> +endif
>> +# Copy the source tarball (just hardlink if possible)
>> +    @cp -l $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR) 
>> 2>/dev/null || \
>> +       cp $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR) 
>
>  Genius!
>
>> +endif
>> +    @$(call 
>> legal-manifest,$$($(2)_RAWNAME),$$($(2)_VERSION),$$($(2)_LICENSE),$$($(2)_MANIFEST_LICENSE_FILES),$$($(2)_MANIFEST_TARBALL))
>> + 
>
>  I'm not sure if it would work, but maybe this could be moved out
> of the GENTARGETS and defined as a pattern rule, like all the other
> stuff.  That saves a lot of double $$. 

When I tried to do this change, it turned out that it would add more lines
than the dollars it removes, so I reverted everything.
I can't exclude it might be done in a better way that I was able to do,
anyway.

Luca
Peter Korsgaard - May 14, 2012, 7:16 p.m.
>>>>> "Arnout" == Arnout Vandecappelle <arnout@mind.be> writes:

Hi,

 Arnout>  Looks great!

 Arnout>  Any chance that this can still go into the 2012.05 release?  I
 Arnout> have one customer who would be really pleased with that...

Sorry, but I think it's getting too late for that. We can merge it to
-next pretty soon once the remining issues are worked out though.
Arnout Vandecappelle - May 15, 2012, 8:02 p.m.
On 05/14/12 18:54, Luca Ceresoli wrote:
> Arnout Vandecappelle wrote:
>> On 05/07/12 22:12, Luca Ceresoli wrote:
[snip]
>>> +TARGETS_LEGAL_INFO:=$(patsubst %,%-legal-info,\
>>> + $(filter-out host-makedevs,\
>>> + $(TARGETS) $(BASE_TARGETS) $(TARGETS_HOST_DEPS) $(HOST_DEPS))))
>>
>> I guess host-makedevs is filtered out here because it has no tar file?
>> In that case, the same should be done for makedevs and mcookie. But maybe
>> it's better to define the SITE_METHOD of these packages as local. Then they
>> will be registered as "not saved" in the manifest.
>
> My ignorance, I didn't know about the existence of mcookie in Buildroot.
> I would like to omit entirely these packages from the legal-info list, as they are
> actually a part of Buildroot.
> But since using filter-out is pretty dirty, I think a clean implementation would be
> to exclude from legal-info processing all packages with an empyt _SOURCE variable.
> The assumption here is that if they don't have an external source, they are part of
> Buildroot.
>
> Do you think this is a good idea?

  Good plan!

[snip]
>> I'm not sure if it would work, but maybe this could be moved out
>> of the GENTARGETS and defined as a pattern rule, like all the other
>> stuff. That saves a lot of double $$.
>
> When I tried to do this change, it turned out that it would add more lines
> than the dollars it removes, so I reverted everything.
> I can't exclude it might be done in a better way that I was able to do,
> anyway.

  I can take a shot at it once this stuff gets committed.

  Regards,
  Arnout

Patch

diff --git a/Makefile b/Makefile
index a7625ba..21c30b9 100644
--- a/Makefile
+++ b/Makefile
@@ -247,6 +247,14 @@  TARGET_DIR:=$(BASE_DIR)/target
 TOOLCHAIN_DIR=$(BASE_DIR)/toolchain
 TARGET_SKELETON=$(TOPDIR)/fs/skeleton
 
+LEGAL_INFO_DIR=$(BASE_DIR)/legal-info
+REDIST_SOURCES_DIR=$(LEGAL_INFO_DIR)/sources
+LICENSE_FILES_DIR=$(LEGAL_INFO_DIR)/licenses
+LEGAL_MANIFEST_CSV=$(LEGAL_INFO_DIR)/manifest.csv
+LEGAL_LICENSES_TXT=$(LEGAL_INFO_DIR)/licenses.txt
+LEGAL_WARNINGS=$(LEGAL_INFO_DIR)/.warnings
+LEGAL_REPORT=$(LEGAL_INFO_DIR)/README
+
 ifeq ($(BR2_CCACHE),y)
 CCACHE:=$(HOST_DIR)/usr/bin/ccache
 CCACHE_CACHE_DIR=$(HOME)/.buildroot-ccache
@@ -321,6 +329,10 @@  HOST_DEPS = $(sort $(foreach dep,\
 		$($(dep))))
 HOST_SOURCE += $(addsuffix -source,$(sort $(TARGETS_HOST_DEPS) $(HOST_DEPS)))
 
+TARGETS_LEGAL_INFO:=$(patsubst %,%-legal-info,\
+		$(filter-out host-makedevs,\
+		$(TARGETS) $(BASE_TARGETS) $(TARGETS_HOST_DEPS) $(HOST_DEPS))))
+
 # all targets depend on the crosscompiler and it's prerequisites
 $(TARGETS_ALL): __real_tgt_%: $(BASE_TARGETS) %
 
@@ -337,8 +349,9 @@  prepare: $(BUILD_DIR)/buildroot-config/auto.conf
 world: prepare dirs dependencies $(BASE_TARGETS) $(TARGETS_ALL)
 
 .PHONY: all world dirs clean distclean source outputmakefile \
+	legal-info legal-info-prepare legal-info-clean \
 	$(BASE_TARGETS) $(TARGETS) $(TARGETS_ALL) \
-	$(TARGETS_CLEAN) $(TARGETS_DIRCLEAN) $(TARGETS_SOURCE) \
+	$(TARGETS_CLEAN) $(TARGETS_DIRCLEAN) $(TARGETS_SOURCE) $(TARGETS_LEGAL_INFO) \
 	$(DL_DIR) $(TOOLCHAIN_DIR) $(BUILD_DIR) $(STAGING_DIR) $(TARGET_DIR) \
 	$(HOST_DIR) $(BINARIES_DIR) $(STAMP_DIR)
 
@@ -348,7 +361,7 @@  world: prepare dirs dependencies $(BASE_TARGETS) $(TARGETS_ALL)
 # dependencies anywhere else
 #
 #############################################################
-$(DL_DIR) $(TOOLCHAIN_DIR) $(BUILD_DIR) $(HOST_DIR) $(BINARIES_DIR) $(STAMP_DIR):
+$(DL_DIR) $(TOOLCHAIN_DIR) $(BUILD_DIR) $(HOST_DIR) $(BINARIES_DIR) $(STAMP_DIR) $(LEGAL_INFO_DIR) $(REDIST_SOURCES_DIR):
 	@mkdir -p $@
 
 $(STAGING_DIR):
@@ -451,6 +464,27 @@  source: dirs $(TARGETS_SOURCE) $(HOST_SOURCE)
 external-deps:
 	@$(MAKE) -Bs DL_MODE=SHOW_EXTERNAL_DEPS $(EXTRAMAKEARGS) source | sort -u
 
+legal-info-clean:
+	@rm -fr $(LEGAL_INFO_DIR)
+
+legal-info-prepare: $(LEGAL_INFO_DIR)
+	@$(call legal-license-file,buildroot,COPYING,COPYING)
+	@$(call legal-manifest,package,version,license,license files,source archive)
+	@$(call legal-manifest,buildroot,$(BR2_VERSION_FULL),GPLv2+,COPYING,not saved)
+	@$(call legal-warning,the Buildroot source code has not been saved)
+	@$(call legal-warning,the toolchain has not been saved)
+	@cp $(CONFIG_DIR)/.config $(LEGAL_INFO_DIR)/buildroot.config
+
+legal-info: legal-info-clean legal-info-prepare $(REDIST_SOURCES_DIR) \
+		$(TARGETS_LEGAL_INFO)
+	@cat support/legal-info/README.header >>$(LEGAL_REPORT)
+	@if [ -r $(LEGAL_WARNINGS) ]; then \
+		cat support/legal-info/README.warnings-header \
+			$(LEGAL_WARNINGS) >>$(LEGAL_REPORT); \
+		cat $(LEGAL_WARNINGS); fi
+	@echo "Legal info produced in $(LEGAL_INFO_DIR)"
+	@rm -f $(LEGAL_WARNINGS)
+
 show-targets:
 	@echo $(TARGETS)
 
@@ -572,7 +606,8 @@  endif
 
 clean:
 	rm -rf $(STAGING_DIR) $(TARGET_DIR) $(BINARIES_DIR) $(HOST_DIR) \
-		$(STAMP_DIR) $(BUILD_DIR) $(TOOLCHAIN_DIR) $(BASE_DIR)/staging
+		$(STAMP_DIR) $(BUILD_DIR) $(TOOLCHAIN_DIR) $(BASE_DIR)/staging \
+		$(LEGAL_INFO_DIR)
 
 distclean: clean
 ifeq ($(DL_DIR),$(TOPDIR)/dl)
@@ -640,6 +675,7 @@  endif
 	@echo '  source                 - download all sources needed for offline-build'
 	@echo '  source-check           - check all packages for valid download URLs'
 	@echo '  external-deps          - list external packages used'
+	@echo '  legal-info             - generate info about license compliance'
 	@echo
 	@echo '  make V=0|1             - 0 => quiet build (default), 1 => verbose build'
 	@echo '  make O=dir             - Locate all output files in "dir", including .config'
diff --git a/package/pkg-gentargets.mk b/package/pkg-gentargets.mk
index 1c9b458..11d83c4 100644
--- a/package/pkg-gentargets.mk
+++ b/package/pkg-gentargets.mk
@@ -180,6 +180,7 @@  define GENTARGETS_INNER
 
 $(2)_TYPE                       =  $(5)
 $(2)_NAME			=  $(1)
+$(2)_RAWNAME			=  $(patsubst host-%,%,$(1))
 
 # Keep the package version that may contain forward slashes in the _DL_VERSION
 # variable, then replace all forward slashes ('/') by underscores ('_') to
@@ -245,6 +246,20 @@  $(2)_OVERRIDE_SRCDIR = $($(2)_SITE)
 endif
 endif
 
+ifndef $(2)_LICENSE
+ ifdef $(3)_LICENSE
+  $(2)_LICENSE = $($(3)_LICENSE)
+ endif
+endif
+
+ifndef $(2)_LICENSE_FILES
+ ifdef $(3)_LICENSE_FILES
+  $(2)_LICENSE_FILES = $($(3)_LICENSE_FILES)
+ endif
+endif
+
+$(2)_LICENSE			?= unknown
+
 $(2)_DEPENDENCIES ?= $(patsubst host-host-%,host-%,$(addprefix host-,$($(3)_DEPENDENCIES)))
 
 $(2)_INSTALL_STAGING		?= NO
@@ -354,6 +369,15 @@  $(1)-rsync:		$$($(2)_TARGET_RSYNC)
 $(1)-source:		$$($(2)_TARGET_RSYNC_SOURCE)
 endif
 
+ifneq ($$($(3)_LICENSE),PROPRIETARY)
+ifneq ($$($(3)_SITE_METHOD),local)
+ifneq ($$($(3)_SITE_METHOD),override)
+# Packages that have a tarball need it downloaded and extracted beforehand
+$(1)-legal-info:	$(1)-extract $(REDIST_SOURCES_DIR)
+endif
+endif
+endif
+
 $(1)-show-depends:
 			@echo $$($(2)_DEPENDENCIES)
 
@@ -412,6 +436,47 @@  else
 $(2)_KCONFIG_VAR = BR2_PACKAGE_$(2)
 endif
 
+# Set values used later for legal-info manifest
+ifneq ($$($(2)_LICENSE),PROPRIETARY)
+ifneq ($$($(2)_SITE_METHOD),local)
+ifneq ($$($(2)_SITE_METHOD),override)
+$(2)_MANIFEST_TARBALL = $$($(2)_SOURCE)
+ifneq ($(call qstrip,$$($(2)_LICENSE_FILES)),)
+$(2)_MANIFEST_LICENSE_FILES = $$($(2)_LICENSE_FILES)
+endif
+endif
+endif
+endif
+# defaults for packages without tarball or license files
+$(2)_MANIFEST_TARBALL ?= not saved
+$(2)_MANIFEST_LICENSE_FILES ?= not saved
+
+# legal-info: produce legally relevant info.
+$(1)-legal-info:
+ifeq ($$($(2)_LICENSE),PROPRIETARY)
+# Proprietary packages: nothing to save
+else ifeq ($$($(2)_SITE_METHOD),local)
+# Packages without a tarball: don't save and warn
+	@$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),local)
+else ifeq ($$($(2)_SITE_METHOD),override)
+	@$(call legal-warning-pkg-savednothing,$$($(2)_RAWNAME),override)
+else
+# Other packages
+# Save license files if defined
+ifeq ($(call qstrip,$$($(2)_LICENSE_FILES)),)
+	@$(call legal-license-nofiles,$$($(2)_RAWNAME))
+	@$(call legal-warning-pkg,$$($(2)_RAWNAME),cannot save license ($(2)_LICENSE_FILES not defined))
+else
+	@for F in $$($(2)_LICENSE_FILES); do \
+		$(call legal-license-file,$$($(2)_RAWNAME),$$$${F},$$($(2)_DIR)/$$$${F}); \
+		done
+endif
+# Copy the source tarball (just hardlink if possible)
+	@cp -l $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR) 2>/dev/null || \
+	   cp $(DL_DIR)/$$($(2)_SOURCE) $(REDIST_SOURCES_DIR)
+endif
+	@$(call legal-manifest,$$($(2)_RAWNAME),$$($(2)_VERSION),$$($(2)_LICENSE),$$($(2)_MANIFEST_LICENSE_FILES),$$($(2)_MANIFEST_TARBALL))
+
 # add package to the general list of targets if requested by the buildroot
 # configuration
 ifeq ($$($$($(2)_KCONFIG_VAR)),y)
diff --git a/package/pkg-utils.mk b/package/pkg-utils.mk
index 953dbc9..43cc76c 100644
--- a/package/pkg-utils.mk
+++ b/package/pkg-utils.mk
@@ -83,3 +83,28 @@  define sep
 
 
 endef
+
+#
+# legal-info helper functions
+#
+LEGAL_INFO_SEPARATOR="::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
+legal-warning=echo "WARNING: $(1)" >>$(LEGAL_WARNINGS)
+legal-warning-pkg=echo "WARNING: $(1): $(2)" >>$(LEGAL_WARNINGS)
+define legal-warning-pkg-savednothing # pkg, {local|override}
+	$(call legal-warning-pkg,$(1),sources and license files not saved ($(2) packages not handled))
+endef
+legal-manifest=echo "$(1),$(2),$(3),$(4),$(5)" >>$(LEGAL_MANIFEST_CSV)
+define legal-license-header
+	echo -e "$(LEGAL_INFO_SEPARATOR)\n\t$(1):" \
+		"$(2)\n$(LEGAL_INFO_SEPARATOR)\n\n" >>$(LEGAL_LICENSES_TXT)
+endef
+define legal-license-nofiles
+	$(call legal-license-header,$(1),unknown license file(s))
+endef
+define legal-license-file # pkg, filename, file-fullpath
+	$(call legal-license-header,$(1),$(2) file) && \
+	cat $(3) >>$(LEGAL_LICENSES_TXT) && \
+	echo >>$(LEGAL_LICENSES_TXT) && \
+	mkdir -p $(LICENSE_FILES_DIR)/$(1)/ && \
+	cp $(3) $(LICENSE_FILES_DIR)/$(1)/
+endef
diff --git a/support/legal-info/README.header b/support/legal-info/README.header
new file mode 100644
index 0000000..3321adb
--- /dev/null
+++ b/support/legal-info/README.header
@@ -0,0 +1,24 @@ 
+Most of the packages that were used by Buildroot to produce the image files,
+including Buildroot itself, have open-source licenses. It is your
+responsibility to comply to the requirements of these licenses.
+To make this easier for you, Buildroot collected in this directory some
+material you may need to get it done.
+
+This material is composed of the following items.
+ * The scripts used to control compilation of the packages and the generation
+   of image files, i.e. the Buildroot sources.
+   Note: this has not been saved due to technical limitations, you must
+   collect it manually.
+ * The Buildroot configuration file; this has been saved in buildroot.config.
+ * The toolchain (cross-compiler and related tools) used to generate all the
+   compiled programs.
+   Note: this has not been saved due to technical limitations, you must
+   collect it manually.
+ * The source code for all packages; this has been saved in the sources/
+   subdirectory (except for the proprietary packages, which have not been
+   saved); patches applied to some packages by Buildroot are included in the
+   Buildroot sources and were not duplicated in the sources/ subdirectory.
+ * A manifest file listing the configured packages and related information.
+ * The license text of the packages; they have been saved in the licenses/
+   subdirectory.
+
diff --git a/support/legal-info/README.warnings-header b/support/legal-info/README.warnings-header
new file mode 100644
index 0000000..cd08290
--- /dev/null
+++ b/support/legal-info/README.warnings-header
@@ -0,0 +1,4 @@ 
+Due to technical limitations or lack of license definition in the package
+makefile, some of the material listed above could not been saved, as the
+following list details.
+