make-rules/ips.mk
changeset 26 8a9f4e791832
parent 22 b89eb90ac9c5
child 27 4daa72fdac4c
--- a/make-rules/ips.mk	Tue Jun 15 12:36:26 2010 -0700
+++ b/make-rules/ips.mk	Fri Jul 16 00:58:56 2010 -0500
@@ -35,47 +35,148 @@
 # This set of rules makes the "publish" target the default target for make(1)
 #
 
-PKGSEND =	/usr/bin/pkgsend
+PKGDEPEND =	/usr/bin/pkgdepend
+PKGFMT =	/usr/bin/pkgfmt
 PKGMOGRIFY =	/usr/bin/pkgmogrify
-PKGDEPEND =	/usr/bin/pkgdepend
+PKGSEND =	/usr/bin/pkgsend
+
+# Package headers should all pretty much follow the same format
+METADATA_TEMPLATE =		$(WS_TOP)/transforms/manifest-metadata-template
+COPYRIGHT_TEMPLATE =		$(WS_TOP)/transforms/copyright-template
+
+# order is important
+GENERATE_TRANSFORMS +=		$(WS_TOP)/transforms/generate-cleanup
+GENERATE_TRANSFORMS +=		$(WS_TOP)/transforms/variant.arch
+
+COMPARISON_TRANSFORMS +=	$(WS_TOP)/transforms/comparison-cleanup
+COMPARISON_TRANSFORMS +=	$(PKGMOGRIFY_TRANSFORMS)
+
+# order is important
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/defaults
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/actuators
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/devel
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/docs
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/locale
+PUBLISH_TRANSFORMS +=	$(PKGMOGRIFY_TRANSFORMS)
+PUBLISH_TRANSFORMS +=	$(WS_TOP)/transforms/publish-cleanup
 
-# Add some default transforms that should apply to everyone
-PKGMOGRIFY_TRANSFORMS +=	$(WS_TOP)/transforms/defaults
-PKGMOGRIFY_TRANSFORMS +=	$(WS_TOP)/transforms/actuators
-PKGMOGRIFY_TRANSFORMS +=	$(WS_TOP)/transforms/devel
-PKGMOGRIFY_TRANSFORMS +=	$(WS_TOP)/transforms/docs
-PKGMOGRIFY_TRANSFORMS +=	$(WS_TOP)/transforms/locale
+PKG_MACROS +=		MACH=$(MACH)
+PKG_MACROS +=		ARCH=$(MACH)
+PKG_MACROS +=		MACH32=$(MACH32)
+PKG_MACROS +=		MACH64=$(MACH64)
+PKG_MACROS +=		IPS_PKG_NAME=$(IPS_PKG_NAME)
+PKG_MACROS +=		PUBLISHER=$(PUBLISHER)
+PKG_MACROS +=		CONSOLIDATION=$(CONSOLIDATION)
+PKG_MACROS +=		BUILD_VERSION=$(BUILD_VERSION)
+PKG_MACROS +=		SOLARIS_VERSION=$(SOLARIS_VERSION)
+PKG_MACROS +=		OS_VERSION=$(OS_VERSION)
+PKG_MACROS +=		IPS_COMPONENT_VERSION=$(IPS_COMPONENT_VERSION)
+PKG_MACROS +=		COMPONENT_PROJECT_URL=$(COMPONENT_PROJECT_URL)
+PKG_MACROS +=		COMPONENT_ARCHIVE_URL=$(COMPONENT_ARCHIVE_URL)
 
-MANIFEST =	manifest-$(MACH)
+PKG_OPTIONS +=		$(PKG_MACROS:%=-D %)
+# multi-word macros get broken up, so we handle them "specially"
+PKG_OPTIONS +=		-D COMPONENT_SUMMARY=\"$(COMPONENT_SUMMARY)\"
+PKG_OPTIONS +=		-D COMPONENT_DESCRIPTION=\"$(COMPONENT_DESCRIPTION)\"
+PKG_OPTIONS +=		-D COMPONENT_CLASSIFICATION=\"$(COMPONENT_CLASSIFICATION)\"
+
+MANIFEST_BASE =		$(COMPONENT_SRC)/manifest-$(MACH)
 
-.DEFAULT:	publish
+CANONICAL_MANIFESTS =	$(wildcard *.ips)
+GENERATED =		$(MANIFEST_BASE)-generated
+COMBINED =		$(MANIFEST_BASE)-combined
+MANIFESTS =		$(CANONICAL_MANIFESTS:%=$(MANIFEST_BASE)-%)
 
-publish:	$(COMPONENT_SRC)/.published
+
+MOGRIFIED=$(CANONICAL_MANIFESTS:%.ips=$(MANIFEST_BASE)-%.resolved)
+PUBLISHED=$(MOGRIFIED:%.resolved=%.published)
 
 COPYRIGHT_FILE =	$(COMPONENT_NAME)-$(COMPONENT_VERSION).copyright
+IPS_PKG_NAME =		$(COMPONENT_NAME)
 IPS_COMPONENT_VERSION =	$(COMPONENT_VERSION)
 
-$(PROTO_DIR)/$(COPYRIGHT_FILE):	$(COMPONENT_COPYRIGHT)
-	$(CP) $< $@
+.DEFAULT:		publish
+
+.SECONDARY:		$(GENERATED).fdeps
+
+publish:		install $(COMPONENT_SRC)/.published
+
+sample-manifest:	$(GENERATED).ips
+
+#
+# Rules for generating a manifest automatically.  Generated manifests will
+# contain the following:
+#    copyright - template copyright information
+#    metadata  - mogrified template metadata
+#    actions   - "normalized" actions for the paths to be installed.
+#    depends   - automatically generated dependencies
+#
 
-$(COMPONENT_SRC)/$(MANIFEST):	install
-	pkgsend generate $(PROTO_DIR) >$@
+# transform template metadata into slightly more package specific metadata.
+$(GENERATED).metadata:	$(METADATA_TEMPLATE) install
+	$(PKGMOGRIFY) -D IPS_PKG_NAME=$(IPS_PKG_NAME) $< | \
+		sed -e '/^$$/d' -e '/^#.*$$/d' | $(PKGFMT) >$@
+
+# generate actions from the proto dir
+$(GENERATED).generate:	install
+	$(PKGSEND) generate $(PKG_HARDLINKS:%=--target %) $(PROTO_DIR) >$@
+
+# convert actions to a "normalized" format
+$(GENERATED).actions:	$(GENERATED).generate
+	$(PKGMOGRIFY) $(PKG_OPTIONS) $< $(GENERATE_TRANSFORMS) | \
+		sed -e '/^$$/d' -e '/^#.*$$/d' | $(PKGFMT) >$@
+
+# generate dependencies
+$(MANIFEST_BASE)-%.fdeps:	$(MANIFEST_BASE)-%.generate
+	$(PKGDEPEND) generate $(PKG_OPTIONS) $< $(PROTO_DIR) >$@
+
+$(MANIFEST_BASE)-%.depend:	$(MANIFEST_BASE)-%.fdeps
+	$(PKGDEPEND) resolve -o $< | sed -e '1d' >$@
 
-$(COMPONENT_SRC)/$(MANIFEST).mog:	$(COMPONENT_SRC)/$(MANIFEST) $(PROTO_DIR)/$(COPYRIGHT_FILE)
-	echo "set name=pkg.fmri value=pkg:/$(PUBLISHER)/$(COMPONENT_NAME)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)" >$@
-	echo "set name=pkg.description value=\"$(COMPONENT_DESCRIPTION)\"" >>$@
-	echo "set name=pkg.name value=\"$(COMPONENT_DESCRIPTION)\"" >>$@
-	echo "set name=org.opensolaris.consolidation value=$(CONSOLIDATION)" >>$@
-	echo "license $(COPYRIGHT_FILE) license=$(COPYRIGHT_FILE)" >>$@
-	pkgmogrify $(PKGMOGRIFY_MACROS:%=-D %) $(PKGMOGRIFY_TRANSFORMS) $< >>$@
+# generate a complete manifest from the pieces
+$(GENERATED).ips:	$(GENERATED).metadata $(GENERATED).actions \
+			$(GENERATED).depend
+	cat $(COPYRIGHT_TEMPLATE) $(GENERATED).metadata $(GENERATED).actions \
+	    $(GENERATED).depend >$@
+
+#
+# Rules to generate a combined manifest from the canonical manifest(s) checked
+# into the workspace.
+#
+
+# Combine the canonical manifest(s) for this component and "normalize" them
+# for comparison.
+$(COMBINED).ips:	canonical-manifests
+	cat $(CANONICAL_MANIFESTS) | $(PKGMOGRIFY) $(PKG_OPTIONS) /dev/fd/0 | \
+ 		sed -e '/^$$/d' -e '/^#.*$$/d' | sort -u | $(PKGFMT) >$@
+
+$(MANIFEST_BASE)-%.compare:		$(MANIFEST_BASE)-%.ips
+	$(PKGMOGRIFY) $(PKG_OPTIONS) $(COMPARISON_TRANSFORMS) $< >$@
+
+manifest-compare:	$(COMBINED).compare $(GENERATED).compare
+	@echo "Manifest comparison"
+	@pkgdiff $(GENERATED).compare $(COMBINED).compare
 
-$(COMPONENT_SRC)/$(MANIFEST).fdeps:	$(COMPONENT_SRC)/$(MANIFEST).mog
-	pkgdepend generate -m $< $(PROTO_DIR) >$@
+# mogrify the canonical manifest(s) 
+#
+$(MANIFEST_BASE)-%.resolved:	%.ips manifest-compare
+	$(PKGMOGRIFY) $(PKG_OPTIONS) $< $(PUBLISH_TRANSFORMS) >$@
+
+$(MANIFEST_BASE)-%.published:	$(MANIFEST_BASE)-%.resolved
+	$(PKGSEND) -s $(PKG_REPO) publish --fmri-in-manifest \
+		-d $(PROTO_DIR) -d . $<
+	$(TOUCH) $@
 
-$(COMPONENT_SRC)/$(MANIFEST).fdeps.res:	$(COMPONENT_SRC)/$(MANIFEST).fdeps
-	pkgdepend resolve -m $<
+$(COMPONENT_SRC)/.published:	manifest-compare $(PUBLISHED)
+	$(TOUCH) $@
 
-$(COMPONENT_SRC)/.published:	$(COMPONENT_SRC)/$(MANIFEST).fdeps.res
-	pkgsend -s $(PKG_REPO) publish --fmri-in-manifest \
-		-d $(PROTO_DIR) $<
-	$(TOUCH) $@
+canonical-manifests:	$(CANONICAL_MANIFESTS)
+ifeq	($(strip $(CANONICAL_MANIFESTS)),)
+	# If there were no canonical manifests in the workspace, nothing will
+	# be published and we should fail.  A sample manifest can be generated
+	# with
+	#   $ gmake sample-manifest
+	# Once created, it will need to be reviewed, edited, and added to the
+	# workspace.
+	$(error Missing canonical manifest(s))
+endif