@@ -1,17 +1,14 @@
+inherit buildhistory
# Populates LICENSE_DIRECTORY as set in distro config with the license files as set by
# LIC_FILES_CHKSUM.
+# LIC_FILES_CHKSUM.
# TODO:
-# - We should also enable the ability to put the generated license directory onto the
-# rootfs
-# - Gather up more generic licenses
-# - There is a real issue revolving around license naming standards. See license names
-# licenses.conf and compare them to the license names in the recipes. You'll see some
-# differences and that should be corrected.
+# - There is a real issue revolving around license naming standards.
LICENSE_DIRECTORY ??= "${DEPLOY_DIR}/licenses"
LICSSTATEDIR = "${WORKDIR}/license-destdir/"
-addtask populate_lic after do_patch before do_package
+addtask populate_lic after do_patch before do_compile
do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}"
do_populate_lic[cleandirs] = "${LICSSTATEDIR}"
@@ -22,33 +19,124 @@ do_populate_lic[cleandirs] = "${LICSSTATEDIR}"
#
# We should really discuss standardizing this field, but that's a longer term goal.
# For now, we can do this and it should grab the most common LICENSE naming variations.
-
-#GPL variations
-SPDXLICENSEMAP[GPL] = "GPL-1"
-SPDXLICENSEMAP[GPLv2] = "GPL-2"
-SPDXLICENSEMAP[GPLv3] = "GPL-3"
+#
+# Changing GPL mapping to GPL-2 as it's not very likely to be GPL-1
+# We should NEVER have a GPL/LGPL without a version!!!!
+# Any mapping to MPL/LGPL/GPL should be fixed
+# see: https://wiki.yoctoproject.org/wiki/License_Audit
+
+# GPL variations
+SPDXLICENSEMAP[GPL] = "GPL-2.0"
+SPDXLICENSEMAP[GPL-2] = "GPL-2.0"
+SPDXLICENSEMAP[GPLv2] = "GPL-2.0"
+SPDXLICENSEMAP[GPL-3] = "GPL-3.0"
+SPDXLICENSEMAP[GPLv3] = "GPL-3.0"
#LGPL variations
-SPDXLICENSEMAP[LGPL] = "LGPL-2"
-SPDXLICENSEMAP[LGPLv2] = "LGPL-2"
+SPDXLICENSEMAP[LGPL] = "LGPL-2.0"
+SPDXLICENSEMAP[LGPLv2] = "LGPL-2.0"
SPDXLICENSEMAP[LGPL2.1] = "LGPL-2.1"
SPDXLICENSEMAP[LGPLv2.1] = "LGPL-2.1"
-SPDXLICENSEMAP[LGPLv3] = "LGPL-3"
+SPDXLICENSEMAP[LGPLv3] = "LGPL-3.0"
#MPL variations
-SPDXLICENSEMAP[MPL] = "MPL-1"
-SPDXLICENSEMAP[MPLv1] = "MPL-1"
-SPDXLICENSEMAP[MPLv1.1] = "MPL-1"
+SPDXLICENSEMAP[MPL] = "MPL-1.0"
+SPDXLICENSEMAP[MPL-1] = "MPL-1.0"
+SPDXLICENSEMAP[MPLv1] = "MPL-1.0"
+SPDXLICENSEMAP[MPLv1.1] = "MPL-1.1"
#MIT variations
SPDXLICENSEMAP[MIT-X] = "MIT"
+SPDXLICENSEMAP[MIT-style] = "MIT"
#Openssl variations
SPDXLICENSEMAP[openssl] = "OpenSSL"
+#Python variations
+SPDXLICENSEMAP[PSF] = "Python-2.0"
+SPDXLICENSEMAP[PSFv2] = "Python-2.0"
+SPDXLICENSEMAP[Python-2] = "Python-2.0"
+
+#Apache variations
+SPDXLICENSEMAP[Apachev2] = "Apache-2.0"
+SPDXLICENSEMAP[Apache-2] = "Apache-2.0"
+
+#Artistic variations
+SPDXLICENSEMAP[Artistic] = "Artistic-1.0"
+SPDXLICENSEMAP[Artisticv1] = "Artistic-1.0"
+SPDXLICENSEMAP[Artistic-1] = "Artistic-1.0"
+
+#Academic variations
+SPDXLICENSEMAP[AFL-2] = "AFL-2.0"
+SPDXLICENSEMAP[AFL-1] = "AFL-1.2"
+SPDXLICENSEMAP[AFLv2] = "AFL-2.0"
+SPDXLICENSEMAP[AFLv1] = "AFL-1.2"
+
#Other variations
-SPDXLICENSEMAP[AFL2.1] = "AFL-2"
-SPDXLICENSEMAP[EPLv1.0] = "EPL-1"
+SPDXLICENSEMAP[EPLv1.0] = "EPL-1.0"
+
+license_create_manifest() {
+ mkdir -p ${LICENSE_DIRECTORY}/${IMAGE_NAME}
+ # Get list of installed packages
+ list_installed_packages | grep -v "locale" |sort > ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest
+ INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest`
+ # list of installed packages is broken for deb
+ if [ ${IMAGE_PKGTYPE} != "deb" ]; then
+
+ for pkg in ${INSTALLED_PKGS}; do
+ # not the best way to do this but licenses are not arch dependant iirc
+ files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1`
+ for filename in $files; do
+ pkged_pn="$(sed -n 's/^PN: //p' ${filename})"
+ pkged_lic="$(sed -n '/^LICENSE: /{ s/^LICENSE: //; s/[+|&()*]/ /g; s/ */ /g; p }' ${filename})"
+ # check to see if the package name exists in the manifest. if so, bail.
+ if ! grep -q "PACKAGE NAME: ${pkg}" ${filename}; then
+ # exclude local recipes
+ if [ ! ${pkged_pn} == "*locale*" ]; then
+ echo "PACKAGE NAME:" ${pkg} >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ echo "RECIPE NAME:" ${pkged_pn} >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ echo "LICENSE: " >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ for lic in ${pkged_lic}; do
+ if [ -e "${LICENSE_DIRECTORY}/${pkged_pn}/generic_${lic}" ]; then
+ echo ${lic}|sed s'/generic_//'g >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ else
+ echo "WARNING: The license listed, " ${lic} " was not in the licenses collected for " ${pkged_pn}>> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ fi
+ done
+ echo "" >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest
+ fi
+ fi
+ done
+ done
+ fi
+
+ # Two options here:
+ # - Just copy the manifest
+ # - Copy the manifest and the license directories
+ # This will make your image a bit larger, however
+ # if you are concerned about license compliance
+ # and delivery this should cover all your bases
+
+ if [ -n ${COPY_LIC_MANIFEST} ]; then
+ mkdir -p ${IMAGE_ROOTFS}/usr/share/common-licenses/
+ cp ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest ${IMAGE_ROOTFS}/usr/share/common-licenses/license.manifest
+ if [ -n ${COPY_LIC_DIRS} ]; then
+ for pkg in ${INSTALLED_PKGS}; do
+ mkdir -p ${IMAGE_ROOTFS}/usr/share/common-licenses/${pkg}
+ for lic in `ls ${LICENSE_DIRECTORY}/${pkged_pn}`; do
+ # Really don't need to copy the generics as they're
+ # represented in the manifest and in the actual pkg licenses
+ # Doing so would make your image quite a bit larger
+ if [ ! ${lic} == "generic_*" ]; then
+ cp ${LICENSE_DIRECTORY}/${pkged_pn}/${lic} ${IMAGE_ROOTFS}/usr/share/common-licenses/${pkg}/${lic}
+ fi
+ done
+ done
+ fi
+ fi
+
+}
+
python do_populate_lic() {
"""
@@ -59,6 +147,26 @@ python do_populate_lic() {
import shutil
import oe.license
+ # All the license types for the package
+ license_types = d.getVar('LICENSE', True)
+ # All the license files for the package
+ lic_files = d.getVar('LIC_FILES_CHKSUM', True)
+ pn = d.getVar('PN', True)
+ # The base directory we wrangle licenses to
+ destdir = os.path.join(d.getVar('LICSSTATEDIR', True), pn)
+ # The license files are located in S/LIC_FILE_CHECKSUM.
+ srcdir = d.getVar('S', True)
+ # Directory we store the generic licenses as set in the distro configuration
+ generic_directory = d.getVar('COMMON_LICENSE_DIR', True)
+ license_source_dirs = []
+ license_source_dirs.append(generic_directory)
+ try:
+ additional_lic_dirs = d.getVar('LICENSE_DIR', True).split()
+ for lic_dir in additional_lic_dirs:
+ license_source_dirs.append(lic_dir)
+ except:
+ pass
+
class FindVisitor(oe.license.LicenseVisitor):
def visit_Str(self, node):
#
@@ -70,55 +178,42 @@ python do_populate_lic() {
find_license(node.s.replace("+", "").replace("*", ""))
self.generic_visit(node)
- def copy_license(source, destination, file_name):
- try:
- bb.copyfile(os.path.join(source, file_name), os.path.join(destination, file_name))
- except:
- bb.warn("%s: No generic license file exists for: %s at %s" % (pn, file_name, source))
- pass
-
- def link_license(source, destination, file_name):
- try:
- os.symlink(os.path.join(source, file_name), os.path.join(destination, "generic_" + file_name))
- except:
- bb.warn("%s: Could not symlink: %s at %s to %s at %s" % (pn, file_name, source, file_name, destination))
- pass
-
def find_license(license_type):
try:
bb.mkdirhier(gen_lic_dest)
except:
pass
-
+ spdx_generic = ""
+ license_source = ""
# If the generic does not exist we need to check to see if there is an SPDX mapping to it
- if not os.path.isfile(os.path.join(generic_directory, license_type)):
- if d.getVarFlag('SPDXLICENSEMAP', license_type) != None:
- # Great, there is an SPDXLICENSEMAP. We can copy!
- bb.note("We need to use a SPDXLICENSEMAP for %s" % (license_type))
- spdx_generic = d.getVarFlag('SPDXLICENSEMAP', license_type)
- copy_license(generic_directory, gen_lic_dest, spdx_generic)
- link_license(gen_lic_dest, destdir, spdx_generic)
- else:
- # And here is where we warn people that their licenses are lousy
- bb.warn("%s: No generic license file exists for: %s at %s" % (pn, license_type, generic_directory))
- bb.warn("%s: There is also no SPDXLICENSEMAP for this license type: %s at %s" % (pn, license_type, generic_directory))
- pass
- elif os.path.isfile(os.path.join(generic_directory, license_type)):
- copy_license(generic_directory, gen_lic_dest, license_type)
- link_license(gen_lic_dest, destdir, license_type)
-
- # All the license types for the package
- license_types = d.getVar('LICENSE', True)
- # All the license files for the package
- lic_files = d.getVar('LIC_FILES_CHKSUM', True)
- pn = d.getVar('PN', True)
- # The base directory we wrangle licenses to
- destdir = os.path.join(d.getVar('LICSSTATEDIR', True), pn)
- # The license files are located in S/LIC_FILE_CHECKSUM.
- srcdir = d.getVar('S', True)
- # Directory we store the generic licenses as set in the distro configuration
- generic_directory = d.getVar('COMMON_LICENSE_DIR', True)
+ for lic_dir in license_source_dirs:
+ if not os.path.isfile(os.path.join(lic_dir, license_type)):
+ if d.getVarFlag('SPDXLICENSEMAP', license_type) != None:
+ # Great, there is an SPDXLICENSEMAP. We can copy!
+ bb.note("We need to use a SPDXLICENSEMAP for %s" % (license_type))
+ spdx_generic = d.getVarFlag('SPDXLICENSEMAP', license_type)
+ license_source = lic_dir
+ break
+ elif os.path.isfile(os.path.join(lic_dir, license_type)):
+ spdx_generic = license_type
+ license_source = lic_dir
+ break
+
+ if spdx_generic!="" and license_source!="":
+ # we really should copy to generic_ + spdx_generic, however, that ends up messing the manifest
+ # audit up. This should be fixed in emit_pkgdata (or, we actually got and fix all the recipes)
+ ret = bb.copyfile(os.path.join(license_source, spdx_generic), os.path.join(os.path.join(d.getVar('LICSSTATEDIR', True), pn), "generic_" + license_type))
+ # If the copy didn't occur, something horrible went wrong and we fail out
+ if ret is False or ret == 0:
+ bb.warn("%s for %s could not be copied for some reason. It may not exist. WARN for now." % (spdx_generic, pn))
+
+ else:
+ # And here is where we warn people that their licenses are lousy
+ bb.warn("%s: No generic license file exists for: %s in any provider" % (pn, license_type))
+ bb.warn("%s: There is also no SPDXLICENSEMAP for this license type: %s in any provider" % (pn, license_type))
+ pass
+
try:
bb.mkdirhier(destdir)
except:
@@ -142,8 +237,6 @@ python do_populate_lic() {
if ret is False or ret == 0:
bb.warn("%s could not be copied for some reason. It may not exist. WARN for now." % srclicfile)
- gen_lic_dest = os.path.join(d.getVar('LICENSE_DIRECTORY', True), "common-licenses")
-
v = FindVisitor()
try:
v.visit_string(license_types)
@@ -160,4 +253,3 @@ python do_populate_lic_setscene () {
sstate_setscene(d)
}
addtask do_populate_lic_setscene
-
@@ -1065,6 +1065,7 @@ python emit_pkgdata() {
write_if_exists(sf, pkg, 'PR')
write_if_exists(sf, pkg, 'PKGV')
write_if_exists(sf, pkg, 'PKGR')
+ write_if_exists(sf, pkg, 'LICENSE')
write_if_exists(sf, pkg, 'DESCRIPTION')
write_if_exists(sf, pkg, 'SUMMARY')
write_if_exists(sf, pkg, 'RDEPENDS')
@@ -62,6 +62,9 @@ fakeroot rootfs_ipk_do_rootfs () {
package_install_internal_ipk
+ # create license manifest
+ license_create_manifest
+
#post install
export D=${IMAGE_ROOTFS}
export OFFLINE_ROOT=${IMAGE_ROOTFS}
@@ -99,6 +99,9 @@ EOF
package_install_internal_rpm
+ # create license manifest
+ license_create_manifest
+
export D=${IMAGE_ROOTFS}
export OFFLINE_ROOT=${IMAGE_ROOTFS}
export IPKG_OFFLINE_ROOT=${IMAGE_ROOTFS}
@@ -1,5 +1,51 @@
-SRC_DISTRIBUTE_LICENSES += "GPL GPLv2 BSD LGPL Apache-2.0 QPL AFL"
-SRC_DISTRIBUTE_LICENSES += "MIT Sleepycat Classpath Perl PSF PD Artistic"
-SRC_DISTRIBUTE_LICENSES += "bzip2 zlib ntp cron libpng netperf openssl"
-SRC_DISTRIBUTE_LICENSES += "Info-ZIP tcp-wrappers"
+# These aren't actually used anywhere that I can tell
+# They may be in the future (or are used by someone else
+# For completion sake, I've updated them
+SRC_DISTRIBUTE_LICENSES += "AAL Adobe AFL-1.2 AFL-2.0 AFL-2.1 AFL-3.0"
+SRC_DISTRIBUTE_LICENSES += "AGPL-3.0 ANTLR-PD Apache-1.0 Apache-1.1 Apache-2.0"
+SRC_DISTRIBUTE_LICENSES += "APL-1.0 APSL-1.0 APSL-1.1 APSL-1.2 APSL-2.0"
+SRC_DISTRIBUTE_LICENSES += "Artistic-1.0 Artistic-2.0 BitstreamVera BSD"
+SRC_DISTRIBUTE_LICENSES += "BSD-2-Clause BSD-3-Clause BSD-4-Clause BSL-1.0"
+SRC_DISTRIBUTE_LICENSES += "CATOSL-1.1 CC0-1.0 CC-BY-1.0 CC-BY-2.0 CC-BY-2.5"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-3.0 CC-BY-NC-1.0 CC-BY-NC-2.0 CC-BY-NC-2.5"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-NC-3.0 CC-BY-NC-ND-1.0 CC-BY-NC-ND-2.0"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-NC-ND-2.5 CC-BY-NC-ND-3.0 CC-BY-NC-SA-1.0"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-NC-SA-2.0 CC-BY-NC-SA-2.5 CC-BY-NC-SA-3.0"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-ND-1.0 CC-BY-ND-2.0 CC-BY-ND-2.5 CC-BY-ND-3.0"
+SRC_DISTRIBUTE_LICENSES += "CC-BY-SA-1.0 CC-BY-SA-2.0 CC-BY-SA-2.5 CC-BY-SA-3.0"
+SRC_DISTRIBUTE_LICENSES += "CDDL-1.0 CECILL-1.0 CECILL-2.0 CECILL-B CECILL-C"
+SRC_DISTRIBUTE_LICENSES += "ClArtistic CPAL-1.0 CPL-1.0 CUA-OPL-1.0 DSSSL"
+SRC_DISTRIBUTE_LICENSES += "ECL-1.0 ECL-2.0 eCos-2.0 EDL-1.0 EFL-1.0 EFL-2.0"
+SRC_DISTRIBUTE_LICENSES += "Elfutils-Exception Entessa EPL-1.0 ErlPL-1.1"
+SRC_DISTRIBUTE_LICENSES += "EUDatagrid EUPL-1.0 EUPL-1.1 Fair Frameworx-1.0"
+SRC_DISTRIBUTE_LICENSES += "FreeType GFDL-1.1 GFDL-1.2 GFDL-1.3 GPL-1.0"
+SRC_DISTRIBUTE_LICENSES += "GPL-2.0 GPL-2.0-with-autoconf-exception"
+SRC_DISTRIBUTE_LICENSES += "GPL-2.0-with-classpath-exception"
+SRC_DISTRIBUTE_LICENSES += "GPL-2.0-with-font-exception"
+SRC_DISTRIBUTE_LICENSES += "GPL-2.0-with-GCC-exception"
+SRC_DISTRIBUTE_LICENSES += "GPL-2-with-bison-exception GPL-3.0"
+SRC_DISTRIBUTE_LICENSES += "GPL-3.0-with-autoconf-exception"
+SRC_DISTRIBUTE_LICENSES += "GPL-3.0-with-GCC-exception"
+SRC_DISTRIBUTE_LICENSES += "gSOAP-1 gSOAP-1.3b HPND IPA IPL-1.0 ISC LGPL-2.0"
+SRC_DISTRIBUTE_LICENSES += "LGPL-2.1 LGPL-3.0 Libpng LPL-1.02 LPPL-1.0 LPPL-1.1"
+SRC_DISTRIBUTE_LICENSES += "LPPL-1.2 LPPL-1.3c MirOS MIT Motosoto MPL-1.0"
+SRC_DISTRIBUTE_LICENSES += "MPL-1.1 MS-PL MS-RL Multics NASA-1.3 Nauman NCSA"
+SRC_DISTRIBUTE_LICENSES += "NGPL Nokia NPOSL-3.0 NTP OASIS OCLC-2.0 ODbL-1.0"
+SRC_DISTRIBUTE_LICENSES += "OFL-1.1 OGTSL OLDAP-2.8 OpenSSL OSL-1.0 OSL-2.0"
+SRC_DISTRIBUTE_LICENSES += "OSL-3.0 PD PHP-3.0 PostgreSQL Proprietary"
+SRC_DISTRIBUTE_LICENSES += "Python-2.0 QPL-1.0 RHeCos-1 RHeCos-1.1 RPL-1.5"
+SRC_DISTRIBUTE_LICENSES += "RPSL-1.0 RSCPL Ruby SAX-PD Simple-2.0 Sleepycat"
+SRC_DISTRIBUTE_LICENSES += "SPL-1.0 SugarCRM-1 SugarCRM-1.1.3 UCB VSL-1.0 W3C
+SRC_DISTRIBUTE_LICENSES += "Watcom-1.0 WXwindows XFree86-1.1 Xnet YPL-1.1"
+SRC_DISTRIBUTE_LICENSES += "Zimbra-1.3 Zlib ZPL-1.1 ZPL-2.0 ZPL-2.1"
+
+# Additional license directories. Add your custom licenses directories this path.
+# LICENSE_PATH += "${COREBASE}/custom-licenses"
+
+# Set if you want the license.manifest copied to the image
+#COPY_LIC_MANIFEST = "1"
+
+# If you want the pkg licenses copied over as well you must set
+# both COPY_LIC_MANIFEST and COPY_LIC_DIRS
+#COPY_LIC_DIRS = "1"