Issue
I am using CPack module in CMake to generate the product installer on macOS. I am trying to install a 3rd party macOS installer package as a prerequisite to our product installer. I tried -
add_executable(
XYZ
IMPORTED
)
set_property(
TARGET XYZ PROPERTY
IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/import/redist/XYZ.pkg
)
install(
IMPORTED_RUNTIME_ARTIFACTS
XYZ
COMPONENT
XYZ
)
However, this doesn't install the XYZ.pkg though it is part of my final product installer pkg file. Is this the correct way to embed and install 3rd party installer package from my product package installer ?
Edit: Instead of executing the XYZ.pkg installer to install it's components, my product installer is copying it to my product's destination folder. I was expecting to chain the install instead.
Solution
Looking at CPack IMPORTED_RUNTIME_ARTIFACTS
, I see it is designed for copying files, not executing them. That means the approach you have taken will not execute the XYZ.pkg
package installer, but will package it into your product's .pkg
installer.
If you wish to chain installers, you would typically use a post-install script that is executed once your package is installed. That script would then run the XYZ.pkg
installer.
You can specify a post-install script (for instance, postflight.sh
+ chmod 755
) using the CPACK_POSTFLIGHT_SCRIPT
variable in CMake, as seen in this thread. Below is a simplified example.
#!/bin/bash
installer -pkg $PWD/XYZ.pkg -target /
In your CMakeLists.txt
, set the CPACK_POSTFLIGHT_SCRIPT
variable to point to your script.
...
include(CPack)
# specify your postflight script
set(CPACK_POSTFLIGHT_SCRIPT "/path/to/postflight.sh")
...
Do copy the XYZ.pkg
into a location that the postflight.sh
script can reference, or modify the postflight.sh
script to locate XYZ.pkg
appropriately.
Once your package is installed, the postflight.sh
script should be executed, and it will run the XYZ.pkg
installer. That should achieve the chained installation behavior you are looking for.
I had a slightly different solution where post install script of my product installs the dependency using the exact command you mentioned. Unfortunately, our team was looking for a more standard solution.
We ended up doing:
- Modify our package distribution.xml to include
XYZ.pkg
info.- CPack builds our package (i.e.,
PRODUCT.pkg
).- From post build script (
CPACK_POST_BUILD_SCRIPTS
), expand thePRODUCT.pkg
usingpkgutil
. 4. Using theproductbuild
, include the expandedPRODUCT.pkg, XYZ.pkg
.
Indeed, manipulating the package directly provides a more "native" approach for handling macOS installer packages.
By altering the distribution.xml
and rebuilding the package using productbuild
, you are essentially creating a "meta-package" that encompasses both your own product and the third-party dependency (XYZ.pkg
). That ensures a more streamlined installation process and is generally more robust than relying on post-install scripts to install additional packages.
The use of pkgutil
to expand the PRODUCT.pkg
and productbuild
to reassemble it, along with the third-party package, is a particularly effective way to achieve this. That approach has the advantage of integrating tightly with the macOS installer system, making it more predictable and potentially less prone to errors compared to a script-based approach.
Answered By - VonC Answer Checked By - Willingham (WPSolving Volunteer)