Git Product home page Git Product logo

guise's Introduction

Build Status

Guise - Generate Public API for Swift Frameworks/Libraries

This command line tool will generate the public interface for a swift framework or library using sourcekitten. The tool will infer the environment variables set by xcode build and generate the public API. This tool was built so that it is possible to review the public interface during code review.

note: By default guise will output to stdout and you will need to redirect the output to a file in order to save it.

screenshot

Usage

This command line tool is meant to be used in an Xcode Run Script Phase.

screenshot

guise generate > $PROJECT_DIR/API.swift

Download a pre-built release

  1. Head over to Releases
  2. Download guise from one of the versions

Install from source

make release

The binary will be output at the top level of the directory.

Development

make project
open Guise.xcodeproj

Motivation & Discovery

I was at a stage where me and my team were creating modules for an iOS app, this helped us seperate concerns - but we rarely did an API review of those modules because it wasn't easy. And being able to review the API is something we deemed quite important as a team moving forward. By reviewing the API we can question the interface and care less about what's behind it, because that can be refactored at a later date.

One of the team members noticed if you โŒ˜ + Click on the module name (import FeatureA), you see a generated interface! Bingo! This looked like the information what we needed to get.

I knew a tool called sourcekitten existed, which allows you to interact with SourceKit, and specifically remember reading how to log exactly what it's doing using a little trick shown here.

export SOURCEKIT_LOGGING=3 && /Applications/Xcode.app/Contents/MacOS/Xcode

Using this we were able to track down that when you open the interface, it makes the following request: source.request.editor.open.interface

{
  key.request: source.request.editor.open.interface,
  key.name: "9662B804-A91C-4AB4-ACEF-ABF02A9D0192",
  key.compilerargs: [
    "-target",
    "arm64-apple-ios11.3",
    "-module-name",
    "FuturesTests",
    "-sdk",
    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk",
    "-I",
    "-Xcc",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/swift-overrides.hmap",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-own-target-headers.hmap",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-all-target-headers.hmap",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos/include",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/DerivedSources/arm64",
    "-I",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/DerivedSources",
    "-I",
    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/usr/local/include",
    "-F",
    "-Xcc",
    "-F",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos",
    "-F",
    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks",
    "-F",
    "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/PrivateFrameworks",
    "-D",
    "DEBUG",
    "-D",
    "DEBUG=1",
    "-Xcc",
    "-iquote",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-generated-files.hmap /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-project-headers.hmap",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/swift-overrides.hmap",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-own-target-headers.hmap",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/FuturesTests-all-target-headers.hmap",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos/include",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/DerivedSources/arm64",
    "-Xcc",
    "-I",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Intermediates.noindex/Futures.build/Debug-iphoneos/FuturesTests.build/DerivedSources",
    "-Xcc",
    "-F",
    "-Xcc",
    "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos",
    "-Xcc",
    "-D",
    "-Xcc",
    "DEBUG=1",
    "-Xcc",
    "-working-directory",
    "-Xcc",
    "/Users/oliveratkinson/Programming/iOS/Futures",
    ""
  ],
  key.modulename: "Futures",
  key.toolchains: [
    "com.apple.dt.toolchain.XcodeDefault"
  ],
  key.synthesizedextensions: 1
}

We noticed a lot of the arguments above were not actually required to get the information we needed, so we deleted the excess ones and ended up with a much smaller snippet:

key.request: source.request.editor.open.interface
key.name: "9662B804-A91C-4AB4-ACEF-ABF02A9D0192"
key.compilerargs:
    - "-target"
    - "arm64-apple-ios11.3"
    - "-sdk"
    - "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk"
    - "-I"
    - "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos"
    - "-F"
    - "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos"
    - "-I"
    - "/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Futures-gieuezrbbfehmphisgvebirbwkml/Build/Products/Debug-iphoneos/include"
key.modulename: "Futures"
key.toolchains: [ "com.apple.dt.toolchain.XcodeDefault" ]
key.synthesizedextensions: 1

Then by inspecting the values inside and the values passed using the environment variables in xcodebuild I was able to build a template:

key.request: source.request.editor.open.interface
key.name: "9662B804-A91C-4AB4-ACEF-ABF02A9D0192"
key.compilerargs:
    - "-target"
    - "{{CURRENT_ARCH}}-apple-{{SWIFT_PLATFORM_TARGET_PREFIX}}{{IPHONEOS_DEPLOYMENT_TARGET or MACOSX_DEPLOYMENT_TARGET}}"
    - "-sdk"
    - "{{SDK_DIR}}"
    - "-I"
    - "{{CONFIGURATION_BUILD_DIR}}"
    - "-F"
    - "{{CONFIGURATION_BUILD_DIR}}"
    - "-I"
    - "{{CONFIGURATION_BUILD_DIR}}/include"
key.modulename: "{{PRODUCT_MODULE_NAME}}"
key.toolchains:
    - "{{TOOLCHAIN_IDENTIFIER}}"
key.synthesizedextensions: 1

I initially created a bash script for this https://gist.github.com/ollieatkinson/b8b84a1de3e06946abb76eeeada73574, which worked fine but I wanted to play around with a swift command line tool.

So... after all of that, we can now use the tool guise to generate API.swift and track the changes to a public interface of a module during code review.

Cheers ๐Ÿป

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.