Packaging: give each component its own license-notice directory

Since rc.153 every component package has installed LICENSE,
THIRD_PARTY_NOTICES.md and licenses/*.txt into share/doc/jfjoch, because the
install rule loops over CPACK_COMPONENTS_ALL with one fixed destination. So
jfjoch, jfjoch-writer, and (when built) jfjoch-viewer and jfjoch-driver-dkms all
claim the same paths.

rpm and dpkg only tolerate two installed packages owning one path while the
content matches. That is fine when the packages are installed or upgraded in a
single transaction, and it breaks the moment they are upgraded one after the
other: as soon as a release changes the notices, updating jfjoch alone conflicts
with the still-installed older jfjoch-writer. PSI deployment updates them
sequentially, so in practice jfjoch could never be updated without jfjoch-writer.

Each component now installs into a directory of its own, named after the
package's principal binary: share/doc/jfjoch_broker, jfjoch_writer, jfjoch_viewer
and jfjoch_driver_dkms.

The main package moves too, rather than keeping share/doc/jfjoch, so that no
rc.163 package claims the path the old ones shared. That is what makes the first
sequential update work from any earlier release: upgrading jfjoch to rc.163 can
no longer collide with an rc.153-rc.158 jfjoch-writer that still owns
share/doc/jfjoch with different content. Keeping the main package there would
have left that hop broken - rc.153 and rc.158 ship a different
THIRD_PARTY_NOTICES.md and licenses/traccc.txt from rc.163 - and would have
required a one-off combined update on every such host. When the old sibling is
finally upgraded its claim is dropped, nothing else owns those files, and the
stale share/doc/jfjoch is removed.

These notice files were the only paths any two components had in common. Checked
by extracting every file(INSTALL) rule from the generated cmake_install.cmake
tree per component and intersecting the four packaged components pairwise: 6 of 6
pairs share nothing, where before the fix each pair shared LICENSE,
THIRD_PARTY_NOTICES.md and all of licenses/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPzDRu2tbgFM1cCe3qYjc
This commit is contained in:
2026-08-25 12:59:41 +02:00
co-authored by Claude Opus 5
parent 4dc2534dbf
commit 7b640edf6e
+18 -4
View File
@@ -568,16 +568,30 @@ endif()
# Ship the license notices (top-level LICENSE, the third-party manifest, and the verbatim
# license texts) with every package variant, under share/doc/jfjoch. Installed per component so
# the file lands in whichever component package(s) the current build mode produces.
# license texts) with every package variant. Installed per component so the files land in
# whichever component package(s) the current build mode produces.
#
# Each component gets a directory of its own, named after the package's principal binary:
# share/doc/jfjoch_broker, jfjoch_writer, jfjoch_viewer, jfjoch_driver_dkms. No two components
# may write the same path, and no component writes the plain share/doc/jfjoch these all used to
# share. Deployment updates the packages one at a time (jfjoch first, then jfjoch-writer), so a
# path claimed by two packages blocks the first step as soon as a release changes its content -
# and leaving the main package on the old shared path would keep blocking it for anyone
# upgrading from a release that still had the collision. These notices were the only files any
# two components had in common.
SET(JFJOCH_NOTICE_FILES
${CMAKE_SOURCE_DIR}/LICENSE
${CMAKE_SOURCE_DIR}/THIRD_PARTY_NOTICES.md)
FOREACH(_component IN LISTS CPACK_COMPONENTS_ALL)
IF (_component STREQUAL "jfjoch")
SET(_suffix broker)
ELSE()
STRING(REPLACE "-" "_" _suffix ${_component})
ENDIF()
INSTALL(FILES ${JFJOCH_NOTICE_FILES}
DESTINATION share/doc/jfjoch COMPONENT ${_component})
DESTINATION share/doc/jfjoch_${_suffix} COMPONENT ${_component})
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses/
DESTINATION share/doc/jfjoch/licenses COMPONENT ${_component}
DESTINATION share/doc/jfjoch_${_suffix}/licenses COMPONENT ${_component}
PATTERN "COLLECT.sh" EXCLUDE)
ENDFOREACH()