Skip to content
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

Add Mac Crafter #6830

Merged
merged 54 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
06fb86b
Start working on mac builder script
claucambra Jun 19, 2024
21853da
Add convenience func to run shell command
claucambra Jun 19, 2024
cf83f81
Add convenience func to check if command exists
claucambra Jun 19, 2024
f213959
Install brew through builder if not present
claucambra Jun 19, 2024
b6c09e2
Install inkscape via mac builder script if not present
claucambra Jun 19, 2024
6df8146
Configure xcode command line tools if missing in mac builder
claucambra Jun 19, 2024
19c14d0
Set up python if missing in mac builder script
claucambra Jun 19, 2024
fd0d39f
Deduplicate installation of required tools in macos builder
claucambra Jun 19, 2024
92ed12b
Clone craft in mac builder script
claucambra Jun 19, 2024
70331dd
Clone craft master to craftdir in mac builder script
claucambra Jun 19, 2024
dd943fd
Craft the desktop client in the mac builder script
claucambra Jun 19, 2024
1580382
Add codesign function to macos builder
claucambra Jun 19, 2024
ee7630e
Move build script into dedicated package
claucambra Jun 20, 2024
1290ab4
Add copyright header to main.swift
claucambra Jun 20, 2024
67bcf91
Move functions of mac crafter into different files
claucambra Jun 20, 2024
916f1fb
Implement basic argumentparser in mac crafter
claucambra Jun 20, 2024
9a0095c
Make installIfMissing throwing in mac crafter
claucambra Jun 20, 2024
f60dd6e
Make codesigning throw in mac crafter
claucambra Jun 20, 2024
3362912
Codesign all the crafted libraries with mac crafter
claucambra Jun 20, 2024
86e50ae
Codesign all crafted plugins in mac crafter
claucambra Jun 20, 2024
5a3c1d3
Move library check to separate file in mac crafter
claucambra Jun 20, 2024
79a933f
Make build path adjustable in mac crafter
claucambra Jun 20, 2024
2484b28
Make URLs adjustable in mac crafter
claucambra Jun 20, 2024
7a9cbb9
Fix dependencies for mac-crafter
claucambra Jun 20, 2024
17c7105
Adjust arguments for mac crafter
claucambra Jun 20, 2024
190922e
Fix mac-crafter abstract
claucambra Jun 20, 2024
fdc505a
Fix paths in mac crafter
claucambra Jun 20, 2024
a22ac09
Remove previous craft client builder
claucambra Jun 20, 2024
1562421
Allow setting of build type in mac crafter
claucambra Jun 20, 2024
1dd239e
Allow explicitly skipping code-signing of dependencies in mac crafter
claucambra Jun 20, 2024
e595b9c
Add procedure to codesign app bundle in mac crafter
claucambra Jun 20, 2024
e3866e4
Fix buildtype argument for craft in mac crafter
claucambra Jun 20, 2024
15f6d35
Throw if codesign binary not found in mac crafter
claucambra Jun 20, 2024
e6c7665
Fix unused codesignidentity warning in mac crafter
claucambra Jun 20, 2024
ccb6210
Divide client app dir path construction in mac crafter
claucambra Jun 20, 2024
6e43443
Add option to skip craft configuration in mac crafter
claucambra Jun 20, 2024
b0328a7
Add relevant files to mac crafter gitignore
claucambra Jun 20, 2024
7578546
Directly sign plugins and frameworks within app bundle in mac crafter
claucambra Jun 20, 2024
d5d5365
Extract app bundle codesigning procedure to separate file in mac crafter
claucambra Jun 20, 2024
589f229
Remove unused Build file in mac crafter
claucambra Jun 21, 2024
b554882
Add support for fetching and including Sparkle in mac crafter
claucambra Jun 21, 2024
9f84da1
Make craft blueprint name adjustable in mac crafter
claucambra Jun 22, 2024
0b57046
Use --options as recommended for configuring craft build in mac crafter
claucambra Jun 22, 2024
0513bf5
Always configure craft if first download and set to not reconfigure b…
claucambra Jun 22, 2024
c342db2
Allow setting custom git clone command in mac crafter
claucambra Jun 22, 2024
77062ee
Compile and install instead of full clean rebuild of client in mac cr…
claucambra Jun 22, 2024
00873b7
Throw on failure of any shell commands to complete successfully in ma…
claucambra Jun 22, 2024
17d98d8
Make mac-related build options configurable in mac crafter
claucambra Jun 22, 2024
87fd676
Improve build mode flag handling in mac crafter
claucambra Jun 22, 2024
4ceb7ad
Simplify dylib signing process and ensure resource libs are signed in…
claucambra Jun 22, 2024
c41c03e
When doing a full rebuild in mac crafter, delete old build folder
claucambra Jun 22, 2024
246da6c
Add option to build tests or not in mac crafter
claucambra Jun 23, 2024
ecc0010
Replace bool options with flags in mac crafter
claucambra Jun 24, 2024
f64b80f
Add offline flag to mac crafter
claucambra Jun 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions admin/osx/mac-crafter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
build/
build\downloads
wget-log*
22 changes: 22 additions & 0 deletions admin/osx/mac-crafter/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "mac-crafter",
platforms: [
.macOS(.v11),
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.4.0")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "mac-crafter",
dependencies: [.product(name: "ArgumentParser", package: "swift-argument-parser")]
),
]
)
72 changes: 72 additions & 0 deletions admin/osx/mac-crafter/Sources/Utils/Codesign.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2024 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

import Foundation

enum CodeSigningError: Error {
case failedToCodeSign(String)
}

enum AppBundleSigningError: Error {
case couldNotEnumerate(String)
}

func isLibrary(_ path: String) -> Bool {
path.hasSuffix(".dylib") || path.hasSuffix(".framework")
}

func isAppExtension(_ path: String) -> Bool {
path.hasSuffix(".appex")
}

func codesign(
identity: String,
path: String,
options: String = "--timestamp --force --preserve-metadata=entitlements --verbose=4 --options runtime"
) throws {
print("Code-signing \(path)...")
let command = "codesign -s \"\(identity)\" \(options) \(path)"
guard shell(command) == 0 else {
throw CodeSigningError.failedToCodeSign("Failed to code-sign \(path).")
}
}

func recursivelyCodesign(path: String, identity: String) throws {
let fm = FileManager.default
guard let pathEnumerator = fm.enumerator(atPath: path) else {
throw AppBundleSigningError.couldNotEnumerate(
"Failed to enumerate directory at \(path)."
)
}

for case let enumeratedItem as String in pathEnumerator {
guard isLibrary(enumeratedItem) || isAppExtension(enumeratedItem) else { continue }
try codesign(identity: identity, path: "\(path)/\(enumeratedItem)")
}
}

func codesignClientAppBundle(
at clientAppDir: String, withCodeSignIdentity codeSignIdentity: String
) throws {
print("Code-signing Nextcloud Desktop Client libraries, frameworks and plugins...")

let clientContentsDir = "\(clientAppDir)/Contents"

try recursivelyCodesign(path: "\(clientContentsDir)/Frameworks", identity: codeSignIdentity)
try recursivelyCodesign(path: "\(clientContentsDir)/PlugIns", identity: codeSignIdentity)
try recursivelyCodesign(path: "\(clientContentsDir)/Resources", identity: codeSignIdentity)

print("Code-signing Nextcloud Desktop Client app bundle...")
try codesign(identity: codeSignIdentity, path: clientAppDir)
}
35 changes: 35 additions & 0 deletions admin/osx/mac-crafter/Sources/Utils/Install.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2024 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

import Foundation

enum InstallError: Error {
case failedToInstall(String)
}

func installIfMissing(
_ command: String,
_ installCommand: String,
installCommandEnv: [String: String]? = nil
) throws {
if commandExists(command) {
print("\(command) is installed.")
} else {
print("\(command) is missing. Installing...")
guard shell(installCommand, env: installCommandEnv) == 0 else {
throw InstallError.failedToInstall("Failed to install \(command).")
}
print("\(command) installed.")
}
}
60 changes: 60 additions & 0 deletions admin/osx/mac-crafter/Sources/Utils/Shell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2024 by Claudio Cambra <claudio.cambra@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

import Foundation

@discardableResult
func run(
_ launchPath: String,
_ args: [String],
env: [String: String]? = nil,
quiet: Bool = false
) -> Int32 {
let task = Process()
task.launchPath = launchPath
task.arguments = args

if let env,
let combinedEnv = task.environment?.merging(env, uniquingKeysWith: { (_, new) in new })
{
task.environment = combinedEnv
}

if quiet {
task.standardOutput = nil
task.standardError = nil
}

task.launch()
task.waitUntilExit()
return task.terminationStatus
}

func run(
_ launchPath: String,
_ args: String...,
env: [String: String]? = nil,
quiet: Bool = false
) -> Int32 {
return run(launchPath, args, env: env, quiet: quiet)
}

@discardableResult
func shell(_ commands: String..., env: [String: String]? = nil, quiet: Bool = false) -> Int32 {
return run("/bin/zsh", ["-c"] + commands, env: env, quiet: quiet)
}

func commandExists(_ command: String) -> Bool {
return run("/usr/bin/type", command, quiet: true) == 0
}
Loading
Loading