GithubHelp home page GithubHelp logo

felixherrmann / swift-package-list Goto Github PK

View Code? Open in Web Editor NEW
106.0 2.0 15.0 416 KB

A command-line tool to get all used SPM-dependencies of an Xcode project or workspace.

License: MIT License

Swift 99.73% Makefile 0.27%
swift swift-package-manager license json shell xcode plist objective-c macos settings-bundle

swift-package-list's Introduction

SwiftPackageList

Xcode Build SwiftLint

A command-line tool to get all used Swift Package dependencies.

The output includes all the Package.resolved informations and the license from the checkouts. You can also generate a JSON, PLIST, Settings.bundle or PDF file.

Additionally there is a Swift Package to read the generated package-list file from the application's bundle or to use pre-build UI for SwiftUI and UIKit.

Command-Line Tool

Installation

Using Homebrew

brew tap FelixHerrmann/tap
brew install swift-package-list

Using Mint:

mint install FelixHerrmann/swift-package-list

Installing from source:

Clone or download this repository and run make install, make update or make uninstall.

Usage

Open the terminal and run swift-package-list <project-path> with the path to the project file you want to generate the list from. Currently supported are:

  • *.xcodeproj for Xcode projects
  • *.xcworkspace for Xcode workspaces
  • Package.swift for Swift packages
  • Project.swift for Tuist projects
  • Dependencies.swift for Tuist projects with external dependencies

In addition to that you can specify the following options:

Option Description
--custom-derived-data-path <custom-derived-data-path> A custom path to your DerivedData-folder.
--custom-source-packages-path <custom-source-packages-path> A custom path to the SourcePackages-folder.
--output-type <output-type> The type of output for the package-list. (values: stdout, json, plist, settings-bundle, pdf; default: stdout)
--output-path <output-path> The path where the package-list file will be stored. (Not required for stdout output-type)
--custom-file-name <custom-file-name> A custom filename to be used instead of the default ones.
--requires-license Will skip the packages without a license-file.
--version Show the version.
-h, --help Show help information.

Build Tool Plugin

The easiest way to add this tool to your project is using the provided build-tool plugin, available for both Xcode projects and Swift packages.

For Xcode projects simply add it under the Run Build Tool Plug-ins section in the Target's Build Phases tab after you have added this package to the project's Package Dependencies; for Swift packages configure it in the Package.swift manifest, as described here.

By default this will use the JSON output with --requires-license but you can create a swift-package-list-config.json in your project's root to configure that behavior, both project and target specific (target configs have precedence over the project one). Everything in the configuration is optional and has the following format:

{
    "projectPath" : "Project.xcworkspace",
    "project" : {
        "outputType" : "plist",
        "requiresLicense" : false
    },
    "targets" : {
        "Target 1" : {
            "outputType" : "settings-bundle",
            "requiresLicense" : true
        },
        "Target 2" : {
            "outputType" : "json",
            "requiresLicense" : true
        }
    }
}

Once added and configured the file(s) will get generated during every build process and are available in the App's bundle. You can then open them manually or use the various options in the included Swift Package.

Note

When using Xcode Cloud add defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES to ci_post_clone.sh which disables the plugin validation.

Run Script Phase

You can easily set up a Run Script Phase in your target of your Xcode project to keep the package-list file up to date automatically:

  1. open the corresponding target and click on the plus under the Build Phases section
  2. select New Run Script Phase and add the following script into the code box:
if command -v swift-package-list &> /dev/null; then
    OUTPUT_PATH=$SOURCE_ROOT/$TARGETNAME
    swift-package-list "$PROJECT_FILE_PATH" --output-type json --output-path "$OUTPUT_PATH" --requires-license
else
    echo "warning: swift-package-list not installed"
fi
  1. move the Phase above the Copy Bundle Resources-phase
  2. optionally you can rename the Phase by double-clicking on the title
  3. build your project (cmd + b)
  4. right-click on the targets-folder in the sidebar and select Add Files to "<project-name>"
  5. select package-list.json in the Finder-window

The package-list file will be updated now on every build and can be opened from the bundle in your app. You can do that manually or use the Swift Package for that.

Xcode Workspace (CocoaPods)

If you have an Xcode workspace instead of a standard Xcode project everything works exactly the same, you just need a slightly modified script for the Run Script Phase:

if command -v swift-package-list &> /dev/null; then
    OUTPUT_PATH=$SOURCE_ROOT/$TARGETNAME
    WORKSPACE_FILE_PATH=${PROJECT_FILE_PATH%.xcodeproj}.xcworkspace
    swift-package-list "$WORKSPACE_FILE_PATH" --output-type json --output-path "$OUTPUT_PATH" --requires-license
else
    echo "warning: swift-package-list not installed"
fi

Homebrew Troubleshooting on Apple Silicon

If you used Homebrew to install the Command-Line Tool on an Apple Silicon Mac, Xcode will not recognize the swift-package-list command. This is because Homebrew uses it's own /bin directory and Xcode's PATH environment variable is not aware of that. There are 2 easy ways to fix this issue:

  • add export PATH="$PATH:/opt/homebrew/bin" as the first line to your build script
  • execute ln -s /opt/homebrew/bin/swift-package-list /usr/local/bin/swift-package-list in your Terminal

Mint Troubleshooting

If you used Mint to install the Command-Line Tool, Xcode will not recognize the swift-package-list command. This is because Mint uses it's own /bin directory and Xcode's PATH environment variable is not aware of that. There are 2 easy ways to fix this issue:

  • add export PATH="$PATH:$HOME/.mint/bin/" as the first line to your build script
  • execute ln -s $HOME/.mint/bin/swift-package-list /usr/local/bin/swift-package-list in your Terminal

Settings Bundle

You can also generate a Settings.bundle file to show the acknowledgements in the Settings app. This works slightly different than the other file types, because a Settings Bundle is a collection of several files and might already exist in your app. Just specify --output-type settings-bundle on the command execution.

Important: The Root.plist and Root.strings files will (unlike the other files) only be created if they not already exists, otherwise it would remove existing configurations. Make sure you set up the Acknowledgements.plist correctly as a Child Pane as shown below:

<dict>
    <key>Type</key>
    <string>PSChildPaneSpecifier</string>
    <key>Title</key>
    <string>Acknowledgements</string>
    <key>File</key>
    <string>Acknowledgements</string>
</dict>

For more information on how to set up and use a Settings Bundle, take a look at Apple's documentation.

PDF

On macOS it is more common to show a Acknowledgments.pdf file. Therefore you have the option to generate a PDF with all licenses. Just specify --output-type pdf on the command execution.

It uses the project's file name (without extension) as the product name and, if present, the organization-name from the project file. You can set that in your project's file inspector as shown here.

Once created and added to the project, it can be easily accessed from the application's bundle like the following:

import SwiftPackageList

let url = Bundle.main.acknowledgementsURL

You can then use QuickLook, NSWorkspace.open(_:) or any other method to display the PDF.

Swift Package

Load the generated package-list file from the bundle or use some pre-build UI components.

Requirements

  • macOS 10.15
  • iOS 13.0
  • tvOS 13.0
  • watchOS 6.0
  • visionOS 1.0

Usage

Add the package to your project as shown here.

It contains 2 libraries; SwiftPackageList for loading the Data and SwiftPackageListUI to get an iOS Settings-like user interface.

SwiftPackageList

import SwiftPackageList

let packageProvider = JSONPackageProvider()
do {
    let packages = try packageProvider.packages()
    // use packages
} catch {
    print(error)
}

SwiftPackageListUI

import SwiftPackageListUI

let acknowledgmentsViewController = SPLAcknowledgmentsTableViewController()
acknowledgmentsViewController.canOpenRepositoryLink = true
navigationController.pushViewController(acknowledgmentsViewController, animated: true)
import SwiftPackageListUI

var body: some View {
    NavigationStack {
        AcknowledgmentsList()
    }
}

Localization

The Settings Bundle and the UI-components are currently localized in the following languages:

Name Code
Arabic ar
Chinese, Simplified zh-Hans
Chinese, Traditional zh-Hant
English en
French fr
German de
Hindi hi
Italian it
Polish pl
Portuguese pt
Russian ru
Spanish es
Turkish tr
Ukrainian uk

If a language has mistakes or is missing, feel free to create an issue or open a pull request.

License

SwiftPackageList is available under the MIT license. See the LICENSE file for more info.

swift-package-list's People

Contributors

dependabot[bot] avatar felixherrmann avatar m4p avatar makcakir avatar mmllr avatar tunous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

swift-package-list's Issues

Feature Request: Output into stdout

Thanks for the very useful tool!

I would like to suggest that outputting into stdout might be a very useful addition to using this tool in various pipelines :-)

Currently I was able to capture the output by using mkfifo and juggling around with it, but if something goes wrong (e.g. Package.resolved is not in a current state so the tool crashes with a "file not found" error), the other end of the pipeline reading from the fifo gets stuck and has to time out...

Project Revision

The Core target has some limitations. The following things would be helpful for future development:

  • Project type protocol-based
  • some of the internal file/directory logic could be represented by a type
  • scan subcommand can be represented by a new output type of the generate subcommand
  • this eliminates the need for a subcommand for the main functionality

Improve error handling

Currently we print the error message and then return in the run method. This can easily be replaced with throwing an error with description.

Support for Swift Package Projects

Currently there is no support for SPM projects. We have everything we need to accomplish that (underlying Xcode workspace, derived-data directory etc.).

Issue Generating Package List with Tuist 4 Project Structure

Hi @FelixHerrmann,

First off, thanks for developing such an incredible package. It's been a game-changer for my projects. Currently, I'm working on integrating it into a new project, structured as follows, with dependencies managed via Package.swift that is consumed by Tuist 4.

.
├── App
   ├── App.xcodeproj
   ├── Project.swift
   ├── Tests
   └── iOS
├── Frameworks
   ├── AppFeature
   ├── Core
   ├── DesignSystem
   └── HomeFeature
├── Package.resolved
├── Package.swift
├── Qualifly-PPL-H.xcworkspace
├── Tuist
   ├── Config.swift
   └── ProjectDescriptionHelpers
└── Workspace.swift

However, I've encountered an issue when executing swift-package-list with the error message:

> swift-package-list Package.swift                                    
Error: No build directory found in /Developer/Xcode/DerivedData for project Developer/ProjectName/Package.swift

Could anyone provide insights or suggestions on how to resolve this error?

Add customFileName Option

Hi,

I'd like to be able to specify the output file name.

Can't see that in the options, just the path?

Thanks,

Jules.

Feature Request: Resolving Package name instead of repository name

Hi, thank you for maintaining this great tool!

Looking at the output it seems like that the dependency name from Package.resolved is always the repository name but not the Package name as in the name as defined in the Package.swift file.

As an example see the following output:

{
    "license" : "Copyright 2015 Catamorphic, Co.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http:\/\/www.apache.org\/licenses\/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
    "name" : "ios-client-sdk",
    "repositoryURL" : "https:\/\/github.com\/launchdarkly\/ios-client-sdk",
    "revision" : "89d87b2b492624dab41dc407fd11b18ebb3e90cf",
    "version" : "8.3.1"
  },

name is defined as ios-client-sdk here.

When looking at the Package.swift file in the dependencies repo however we see that the Package name is in fact LaunchDarkly.
I think it would be beneficial if this script could fetch the 'user facing' dependency name resolved from the Package file.

Support for Tuist Projects

Hello. Thanks for your great tool.

I have a suggestion to add some improvements to your tool.
For now, we can define the path to xcodeproj/xcworkspace because we need the Package.resolved file.
But for now, in iOS community, teams are using Tuist to configure their project. With using Tuist you don't have Package.resolved file like other standard projects. Instead, you have a .package.resolved file that creates by Tuist when you setup the project.

What do you think about it?

SPLPackageList returning nil

The validation checks on the Serialization classes are wrong, they only check in the opposite direction, we can simply get rid of them.

Error: The version of the Package.resolved is not supported

I'm using Xcode 15.3 and the build phase for swift-package-list creates this error

Error: The version of the Package.resolved is not supported

I have the following

.package(url: "https://github.com/FelixHerrmann/swift-package-list.git", from: "4.1.0"),
.product(name: "SwiftPackageListUI", package: "swift-package-list"),

Earlier I had the old version 3.0.10, which had the same issue, upgrading didn't help.

Any suggestions please ?

Thanks,

Jules

Question re. swift-package-list

I have updated SwiftPackageList to 1.4.0. This caused a package called swift-argument-parser v1.0.3 to get added to the SPM. Is this OK?

Following the new instructions, I downloaded project and ran make update and received the following error:

sh uninstall.sh
sh: uninstall.sh: No such file or directory
make: *** [update] Error 127

Thought I would try uninstall and install:

make uninstall returns rm -f "/usr/local/bin/swift-package-list"

make install returns the following:

swift build --configuration release
Fetching https://github.com/apple/swift-argument-parser from cache
Fetched https://github.com/apple/swift-argument-parser (0.57s)
Computing version for https://github.com/apple/swift-argument-parser
Computed https://github.com/apple/swift-argument-parser at 1.0.3 (0.62s)
Creating working copy for https://github.com/apple/swift-argument-parser
Working copy of https://github.com/apple/swift-argument-parser resolved at 1.0.3
[13/13] Build complete!
cp -f ".build/release/SwiftPackageListCommand" "/usr/local/bin/swift-package-list"
cp: .build/release/SwiftPackageListCommand: No such file or directory
make: *** [install] Error 1

Am I doing something wrong?

Build Package.resolved version system

Xcode 13.3 introduced a new Package.resolved version (2). The entire object structure has changed (as shown in #19) and we need a system to support version 1, 2 and any upcoming versions. Version 2 gets also rid of the package name... we have to switch to the last path component of the repository URL (which is not ideal but better than the new identity parameter).

AppKit not being found

Hi,

Thanks a lot for this Swift package first of all!

I just integreated in my iOS app, and unfortunately I'm unable to make it work, as I'm getting an error in PDFGenerator complaining with No such module AppKit.

I following the steps in the README installing it via Homebrew, then generating the package-list.json, adding it to the Xcode project and adding the build phase.

Have I done something incorrectly? I've currently imported all three packages (the binary too) when adding your package dependency to my project.

Thanks!

Feature Request: add `LicenseName` field to the output

I want to start with saying: I love this software! Thanks for creating it!

I was wondering if there is an easy way to add the license name as a field to the output? The output files right now have a license file with the raw text of the license, but I was wondering if you would be open to add the licenseName, in the form of an SPDX license identifier to the output as well?

Background: In our software attributions list, we list all the included components, their name, version and license identifier. Then, when one clicks on a license, the full text appears, but we first want to start by showing just the license identifier.

In our use case we are using the json output of the package list.

Build script phase not working

First of all, thank you for making this! It works beautifully when I run it from the terminal!

Unfortunately, I have not been able to get it to work as a build script phase. I installed swift-package-list on my machine beforehand, but it still doesn't work. I also tried adding it as a package dependency to my project, but that also didn't work. Either way it gives the warning "swift-package-list not installed". I am just using an xcodeproj, not xcworkspace. I'm happy to give any additional details that might be helpful. Thank you!

4.0 Migration Guide

4.0 has a lot of API, it's a good opportunity to start writing migration guides.

Build phase - Build input files cannot be found

Hi,

I added the SPM, added the executable and the ui...

I assumed I didn't have to install (Aka using mint) as I used the SPM ?

Added the build phase and I'm getting this error...

error: Build input files cannot be found: '/Users/jm/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/ArgumentParser.o', '/Users/jm/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/ArgumentParserToolInfo.o' (in target 'swift-package-list' from project 'SwiftPackageList')

Any ideas ?

Thanks,

Jules.

Feature request: Support for -clonedSourcePackagesDirPath

First of all, love this software :)

If I run xcodebuild -resolvePackageDependencies with an additional argument of -clonedSourcePackagesDirPath ~/Packages swift-package-list cannot find the workspace-state.json.

Enhancement

In addition to --derived-data-path can you also provide an alternative --source-packages-data-path to override this?

Rationale

  • Some CI scenarios benefit from clearing derived data, so xcodebuild provides the ability to resolve packages to a different location.

Is this a feature you could add, please?

Repositories with file-extensions in name not working

For example, integrating SQLite with https://github.com/stephencelis/SQLite.swift results in a runtime error: The file "SQLite" couldn't be opened because there is no such file; adding the optional git extension like https://github.com/stephencelis/SQLite.swift.git works.

Full DocC documentations

Currently there is only the basic documentation and a big README describing everything. This can be improved by configuring a proper and interactive DocC documentation.

Dependency Tree is missing

The Swift Package Manager can show you a Dependency-Tree. But that works only on packages directly, not on projects. So you can never see a Dependency-Tree for your project.

If this tool could build a Depdency-Tree for your project, that would be fantastic.

I build a script for that, but having it in your tool would be better, especially since I don't have your experience and am not 100% sure if that's 100% resistent against edge-cases:

if [[ $1 == "" ]]; then
  echo "Missing build dir as 1st parameter"
  exit 1
fi

if [[ $2 == "" ]]; then
  echo "Missing project dir as 2nd parameter"
  exit 1
fi

BUILD_DIR=$1
PROJECT_DIR=$2

echo "Build dependencies tree"
cd "$BUILD_DIR/../../SourcePackages/checkouts"
exportFile="$PROJECT_DIR/dependencies-tree.md"
echo "# Dependencies trees for each Swift-Package" > "$exportFile"
echo "" >> "$exportFile"
echo "Build date: $(date '+%Y-%d-%m %a %H:%M:%S %Z')" >> "$exportFile"
echo "" >> "$exportFile"
for directory in */; do
  echo "Tree for $directory"
  echo "" >> "$exportFile"
  echo "## Tree for $directory" >> "$exportFile"
  pushd $directory
  swift package show-dependencies >> "$exportFile"
  echo "" >> "$exportFile"
  echo "" >> "$exportFile"
  popd
done

No such module 'AppKit'

Hi,

I have an iOS project and am using the AcknowledgmentsList from SwiftPackageListUI.

I've selected the ..

SwiftPackageListUI
Swift-Package-List

.. spm packages...

However, I'm getting an error from the PDFBuilder

image

As the error mentions, think it needs and if statement etc...

Jules.

Support for Xcode Workspaces

I keep getting the following error message: No checkouts-path found in your DerivedData-folder

Xcode 13.2.1, macOS Monterey 12.2

Support for visionOS

The project is already building on visionOS, just need to add it as a supported platform.

Support for Tuist 4

Once Tuist 4 is released CI will fail because the test examples have the old project format and tuist dump can no longer compile it.

Package List Revision

Currently there is one top-level function that handles the entire package-list reading from a bundle; this is not very flexible, especially in the UI target.

Error: The file “swift-package-list” couldn’t be opened because there is no such file

Would love to try out your tool, but regardless of the installation method I get the same error (see below). You got any idea? I double checked the $PATH already but this seems fine.

Version: 4.0.1

Mint

mint run swift-package-list Test.xcodeproj
Error: The file “swift-package-list” couldn’t be opened because there is no such file.

Homebrew

swift-package-list Test.xcodeproj
Error: The file “swift-package-list” couldn’t be opened because there is no such file

Xcode Build Plugin

Run script build phase 'SwiftPackageListPlugin' will be run during every build because the option to run the script phase "Based on dependency analysis" is unchecked.

PhaseScriptExecution SwiftPackageListPlugin <HIDDEN>

Error: The file “swift-package-list” couldn’t be opened because there is no such file.
LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
Command PhaseScriptExecution failed with a nonzero exit code

Error: The file “swift-package-list” couldn’t be opened because there is no such file.

LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted

Command PhaseScriptExecution failed with a nonzero exit code

Support Tuist 4.x.x

New Tuist version no longer uses Tuist/Dependencies.swift but rather Tuist/Package.swift. In the current state running the command produces:

No build directory found in /Users/anurag.ajwani/Library/Developer/Xcode/DerivedData for ...

Command:

swift-package-list Tuist/Package.swift \
    --output-type settings-bundle \
    --output-path App/Resources

Swift Package Plugin Configuration

Currently there is a plugin for each output-type; this causes multiple problems:

  1. Multiple plugins cannot share code with each other. This results in a lot of duplication and things could be overseen when the CLI tool changes.
  2. There is no way to configure the plugin and users have to rely on the decided defaults.
  3. Because of 2. projects inside workspaces cannot tell the plugin to use the workspace file, instead they will keep using the project file and therefore will no longer use the correct Package.resolved data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.