diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6b99987..30466ef2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,27 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + pod-lint: + name: Pod Lint + runs-on: macos-15 + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3.5' + bundler-cache: true + - name: Select Xcode Version + run: sudo xcode-select --switch /Applications/Xcode_16.app/Contents/Developer + - name: Download visionOS + run: | + sudo xcodebuild -runFirstLaunch + sudo xcrun simctl list + sudo xcodebuild -downloadPlatform visionOS + sudo xcodebuild -runFirstLaunch + - name: Lint Podspec + run: bundle exec pod lib lint --verbose --fail-fast --swift-version=6.0 --allow-warnings # We can stop allowing warnings once ZippyJSON creates a release that contains https://github.com/michaeleisel/ZippyJSON/pull/67 + linux: name: Build and Test on Linux runs-on: ubuntu-latest diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..0163af7e --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.3.5 \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..dac62b05 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +ruby '3.3.5' + +source 'https://rubygems.org' + +gem 'cocoapods', '~> 1.16.0' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..4429690c --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,115 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + activesupport (7.2.2.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + atomos (0.1.3) + base64 (0.2.0) + benchmark (0.4.0) + bigdecimal (3.1.9) + claide (1.1.0) + cocoapods (1.16.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.16.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.27.0, < 2.0) + cocoapods-core (1.16.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored2 (3.1.2) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) + drb (2.2.1) + escape (0.0.4) + ethon (0.16.0) + ffi (>= 1.15.0) + ffi (1.17.1) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + httpclient (2.8.3) + i18n (1.14.6) + concurrent-ruby (~> 1.0) + json (2.9.1) + logger (1.6.4) + minitest (5.25.4) + molinillo (0.8.0) + nanaimo (0.4.0) + nap (1.1.0) + netrc (0.11.0) + nkf (0.2.0) + public_suffix (4.0.7) + rexml (3.4.0) + ruby-macho (2.5.1) + securerandom (0.4.1) + typhoeus (1.4.1) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + xcodeproj (1.27.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 1.16.0) + +RUBY VERSION + ruby 3.3.5p100 + +BUNDLED WITH + 2.5.16 diff --git a/Package.swift b/Package.swift index 0157ddf7..4d48a75f 100644 --- a/Package.swift +++ b/Package.swift @@ -29,7 +29,14 @@ let package = Package( name: "InstallSafeDITool", targets: ["InstallSafeDITool"] ), - ], + ] + ( + Context.environment["SAFEDI_COCOAPODS_PROTOCOL_PLUGIN"] != nil ? [ + .executable( + name: "SafeDIMacros", + targets: ["SafeDIMacros"] + ) + ] : [] + ), dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0"), .package(url: "https://github.com/apple/swift-collections.git", from: "1.0.0"), @@ -56,20 +63,38 @@ let package = Package( .swiftLanguageMode(.v6), ] ), - .macro( - name: "SafeDIMacros", - dependencies: [ - "SafeDICore", - .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), - .product(name: "SwiftDiagnostics", package: "swift-syntax"), - .product(name: "SwiftSyntax", package: "swift-syntax"), - .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), - .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), - ], - swiftSettings: [ - .swiftLanguageMode(.v6), - ] - ), + Context.environment["SAFEDI_COCOAPODS_PROTOCOL_PLUGIN"] != nil + ? + .executableTarget( + name: "SafeDIMacros", + dependencies: [ + "SafeDICore", + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + .product(name: "SwiftDiagnostics", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + ], + swiftSettings: [ + .swiftLanguageMode(.v6), + ] + ) + : + .macro( + name: "SafeDIMacros", + dependencies: [ + "SafeDICore", + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + .product(name: "SwiftDiagnostics", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + ], + swiftSettings: [ + .swiftLanguageMode(.v6), + ] + ), + .testTarget( name: "SafeDIMacrosTests", dependencies: [ diff --git a/README.md b/README.md index f791b3aa..e1c66904 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ You can see sample integrations in the [Examples folder](Examples/). If you are ### Adding SafeDI as a Dependency +#### Swift package manager + To add the SafeDI framework as a dependency to a package utilizing [Swift Package Manager](https://github.com/apple/swift-package-manager), add the following lines to your `Package.swift` file: ```swift @@ -82,6 +84,14 @@ dependencies: [ To install the SafeDI framework into an Xcode project with Swift Package Manager, follow [Appleā€™s instructions](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) to add `https://github.com/dfed/SafeDI.git` as a dependency. +#### Cocoapods + +To add the SafeDI framework as a dependency to a package utilizing [CocoaPods](http://cocoapods.org), add the following to your `Podfile`: + +```ruby +pod 'SafeDI', '~> 1.0.0' +``` + ### Generating your dependency tree SafeDI provides a code generation plugin named `SafeDIGenerator`. This plugin works out of the box on a limited number of project configurations. If your project does not fall into these well-supported configurations, you can configure your build to utilize the `SafeDITool` command-line executable directly. diff --git a/SafeDI.podspec b/SafeDI.podspec new file mode 100644 index 00000000..efe2494c --- /dev/null +++ b/SafeDI.podspec @@ -0,0 +1,44 @@ +Pod::Spec.new do |s| + s.name = 'SafeDI' + s.version = '1.0.0' + s.summary = 'Compile-time-safe dependency injection' + s.homepage = 'https://github.com/dfed/SafeDI' + s.license = 'MIT' + s.authors = 'Dan Federman' + s.source = { :git => 'https://github.com/dfed/SafeDI.git', :tag => s.version } + + s.ios.deployment_target = '13.0' + s.tvos.deployment_target = '13.0' + s.watchos.deployment_target = '6.0' + s.macos.deployment_target = '10.15' + s.visionos.deployment_target = '1.0' + + s.source_files = 'Sources/SafeDI/**/*.{swift}' + s.preserve_paths = 'Package.swift', 'Sources/SafeDIMacros' + + # The below scripts and flags were inspired by https://soumyamahunt.medium.com/support-swift-macros-with-cocoapods-3911f9317042 + script = <<-SCRIPT.squish + env -i PATH="$PATH" "$SHELL" -l -c + "swift build -c release --product SafeDIMacros + --sdk \\"`xcrun --show-sdk-path`\\" + --package-path \\"$PODS_TARGET_SRCROOT\\" + --scratch-path \\"${PODS_BUILD_DIR}/Macros/SafeDIMacros\\"" + SCRIPT + + s.script_phase = { + :name => 'Build SafeDIMacros macro plugin', + :script => script, + :input_files => Dir.glob("{Package.swift,Sources/SafeDIMacros/**/*,Sources/SafeDICore/**/*").map { + |path| "$(PODS_TARGET_SRCROOT)/#{path}" + }, + :output_files => ['$(PODS_BUILD_DIR)/Macros/SafeDIMacros/release/SafeDIMacros-tool'], + :execution_position => :before_compile + } + + xcconfig = { + 'OTHER_SWIFT_FLAGS' => "-Xfrontend -load-plugin-executable -Xfrontend ${PODS_BUILD_DIR}/Macros/SafeDIMacros/release/SafeDIMacros-tool#SafeDIMacros", + 'SAFEDI_PLUGIN_BUILD_ENVIRONMENT' => 'SAFEDI_BEING_USED_FROM_COCOAPODS=true' + } + s.user_target_xcconfig = xcconfig + s.pod_target_xcconfig = xcconfig +end diff --git a/Sources/SafeDICore/Models/Instantiable.swift b/Sources/SafeDICore/Models/InstantiableStruct.swift similarity index 100% rename from Sources/SafeDICore/Models/Instantiable.swift rename to Sources/SafeDICore/Models/InstantiableStruct.swift