-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Mac .pkg installer #1312
feat: Mac .pkg installer #1312
Conversation
let build_dir_target = TempDir::new()?; | ||
let build_dir = build_dir_target.path(); | ||
let bindir = build_dir.join("bin"); | ||
fs::create_dir_all(&bindir)?; | ||
let libdir = build_dir.join("lib"); | ||
fs::create_dir_all(&libdir)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please no raw io errors, I really want to remove that error variant from DistError, because it's awful to slam a user with that.
We have several places where we do tempdirs we should be reusing, and axoasset APIs for others. Also camino.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Promoted the tempdir thing to a public method; making me wonder if we just want this to be in axoasset.
Converted the rest into axoasset calls except the symlinks, which axoasset doesn't know about yet. I can add that though, feels in scope.
/// Configuration specific to Mac .pkg installers | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
#[serde(default)] | ||
pub mac_pkg_config: Option<MacPkgConfig>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
glossing over this as something we can freely rejig in config 1.0...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, like I mentioned elsewhere this is something I wanted to check in with you about wrt handling before/after config 1.0.
cargo-dist/src/init.rs
Outdated
return Err(DistError::MacPkgBundleIdentifierMissing {}); | ||
} | ||
|
||
let prompt = r#"Please enter the installation prefix this .pkg should use."#; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should probably specify the default, or we shouldn't even ask? Not sure how typical it is to overload this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overloading it is pretty common. Many people are going to want the default /usr/local
, which is in the PATH
but shared with other software. Other people are going to prefer, say, /opt/mypkg
, which is out of the default PATH
but a prefix fully owned by them, etc.
I was going for an "accept NULL, unwrap to /usr/local
later" approach. But I guess that means the default could shift under the user, which maybe isn't ideal - I guess "inline a default if not specified" is probably better.
let binaries = variant.binaries.clone(); | ||
let target = &variant.target; | ||
if !target.contains("darwin") { | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally we warn here, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was following the pattern from the MSI, which doesn't warn here.
// Compute which package we're actually building, based on the binaries | ||
let mut package_info: Option<(String, PackageIdx)> = None; | ||
for &binary_idx in &binaries { | ||
let binary = self.binary(binary_idx); | ||
if let Some((existing_spec, _)) = &package_info { | ||
// we haven't set ourselves up to bundle multiple packages yet | ||
if existing_spec != &binary.pkg_spec { | ||
return Err(DistError::MultiPackage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...wild why was this logic exclusive to msi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right I think it's because I needed to enforce this for the sake of calling into cargo-wix, but I don't think the pkg stuff has that limitation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, so the goal wasn't to create a single MSI containing every package but rather just that cargo-wix can't understand what to do when given multiple packages? I think I misunderstood the purpose of this guard then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see now why we've got a separate conflict here. We're fetching some package-level metadata to pass to the package build - specifically, the identifier field is package-level metadata. We don't have the package directly accessible to us - just on the binaries - and if we did end up with a conflict of which package they resolve to, I don't know if I could get a better answer than the MSI path does.
aa75c73
to
ebabd6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(also we need to disable the init code temporarily to land this)
cargo-dist/src/init.rs
Outdated
let mut new_table = toml_edit::table(); | ||
if let Some(new_table) = new_table.as_table_mut() { | ||
new_table.insert("identifier", toml_edit::value(&mac_pkg_config.identifier)); | ||
if let Some(location) = &mac_pkg_config.install_location { | ||
new_table.insert("install-location", toml_edit::value(location)); | ||
} | ||
new_table.decor_mut().set_prefix(desc); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason these can't call into apply_optional and friends?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, right, I guess I didn't really consider that this is also a table we could just apply_optional_*
into.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like me to break this init commit out into a separate PR? Then we can land the rest with the init stuff missing.
5db9799
to
5b7bcd5
Compare
This adds support for building Mac .pkg installers. This current implementation is intentionally a bit simplistic: it produces one .pkg per package in the user's workspace, without any special branding applied. We currently only allow the app identifier and install location to be configured, but we can consider adding further customization in the future.
dbd6f62
to
7b34136
Compare
This adds support for building Mac .pkg installers. This current implementation is intentionally a bit simplistic: it produces one .pkg per package in the user's workspace, without any special branding applied. We currently only allow the app identifier and install location to be configured, but we can consider adding further customization in the future.
Although I added support for configuring this in
init
, I ran into a bit of trouble serializing that value since the new config is set up as a struct rather than two separate fields.Here's sample config from one app:
And here's the No Name / Sans nom installer it produces: