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

Prevent embedding static frameworks #490

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/

### Fixed
- Transitively link static dependency's dynamic dependencies correctly https://github.com/tuist/tuist/pull/484 by @adamkhazi
- Prevent embedding static frameworks https://github.com/tuist/tuist/pull/490 by @kwridan

## 0.17.0

Expand Down
15 changes: 2 additions & 13 deletions Sources/TuistGenerator/Graph/Graph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,6 @@ class Graph: Graphing {

references.append(contentsOf: otherTargetFrameworks)

/// Pre-built frameworks
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 299 takes care of embedding pre-compiled nodes (which include FrameworkNode) while checking their linkage (dynamic vs static)

let transitiveFrameworks = findAll(targetNode: targetNode)
.lazy
.filter(FrameworkNode.self)
.map(\.path)
.map(DependencyReference.absolute)

references.append(contentsOf: transitiveFrameworks)

return Set(references).sorted()
}

Expand Down Expand Up @@ -424,10 +415,8 @@ extension Graph {

visited.insert(node)

// swiftlint:disable:next force_cast
if node != targetNode, node is T, test(node as! T) {
// swiftlint:disable:next force_cast
references.insert(node as! T)
if node != targetNode, let matchingNode = node as? T, test(matchingNode) {
references.insert(matchingNode)
}

if node != targetNode, let node = node as? T, skip(node) {
Expand Down
29 changes: 29 additions & 0 deletions Tests/TuistGeneratorTests/Graph/GraphTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,35 @@ final class GraphTests: XCTestCase {
])
}

func test_embeddableFrameworks_when_precompiledStaticFramework() throws {
// Given
let target = Target.test(name: "Main")
let project = Project.test(targets: [target])

let frameworkNode = FrameworkNode(path: "/test/StaticFramework.framework")
let targetNode = TargetNode(
project: project,
target: target,
dependencies: [frameworkNode]
)
let cache = GraphLoaderCache()
cache.add(targetNode: targetNode)
let graph = Graph.test(cache: cache)

system.succeedCommand("/usr/bin/file", "/test/StaticFramework.framework/StaticFramework",
output: "current ar archive random library")

// When
let result = try graph.embeddableFrameworks(
path: project.path,
name: target.name,
system: system
)

// Then
XCTAssertTrue(result.isEmpty)
}

func test_embeddableFrameworks_ordered() throws {
// Given
let dependencyNames = (0 ..< 10).shuffled().map { "Dependency\($0)" }
Expand Down
33 changes: 22 additions & 11 deletions fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,27 +160,38 @@ Workspace:
- App:
- MainApp (iOS app)
- MainAppTests (iOS unit tests)
- A:
- A (static framework iOS)
- ATests (iOS unit tests)
- B:
- B (static framework iOS)
- BTests (iOS unit tests)
- C:
- C (static framework iOS)
- CTests (iOS unit tests)
- D:
- D (dynamic framework iOS)
- Modules
- A:
- A (static framework iOS)
- ATests (iOS unit tests)
- B:
- B (static framework iOS)
- BTests (iOS unit tests)
- C:
- C (static framework iOS)
- CTests (iOS unit tests)
- D:
- D (dynamic framework iOS)
```

A standalone `Prebuilt` project is used to generate a prebuilt static framework:

```
- Prebuilt
- PrebuiltStaticFramework (static framework iOS)
```

Dependencies:

- App -> A
- App -> C
- App -> PrebuiltStaticFramework
- A -> B
- A -> C
- C -> D

Note: to re-create `PrebuiltStaticFramework.framework` run `fixtures/ios_app_with_static_frameworks/Prebuilt//build.sh`

## ios_app_with_tests

Simple app with tests.
Expand Down
24 changes: 24 additions & 0 deletions fixtures/ios_app_with_static_frameworks/Prebuilt/Config/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright TuistΒ©. All rights reserved.</string>
</dict>
</plist>
14 changes: 14 additions & 0 deletions fixtures/ios_app_with_static_frameworks/Prebuilt/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ProjectDescription

let project = Project(
name: "Prebuilt",
targets: [
Target(name: "PrebuiltStaticFramework",
platform: .iOS,
product: .staticFramework,
bundleId: "io.tuist.PrebuiltStaticFramework",
infoPlist: "Config/Info.plist",
sources: "Sources/**",
dependencies: [])
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

public class StaticFrameworkClass {
public init() {}

public func hello() -> String {
return "StaticFrameworkClass.hello()"
}
}
41 changes: 41 additions & 0 deletions fixtures/ios_app_with_static_frameworks/Prebuilt/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh

tuist generate

WORKSPACE_NAME="Prebuilt"
FRAMEWORK_NAME="PrebuiltStaticFramework"
TEMP_DIR="/tmp/tuist-$FRAMEWORK_NAME-fixture"
IPHONE_SIM_DIR="$TEMP_DIR/Build/Products/Debug-iphoneos"
IPHONE_OS_DIR="$TEMP_DIR/Build/Products/Debug-iphonesimulator"

mkdir -p $TEMP_DIR

xcrun xcodebuild build -scheme "$FRAMEWORK_NAME" -workspace "$WORKSPACE_NAME.xcworkspace" -sdk iphoneos -destination "generic/platform=iOS" -derivedDataPath $TEMP_DIR
xcrun xcodebuild build -scheme "$FRAMEWORK_NAME" -workspace "$WORKSPACE_NAME.xcworkspace" -sdk iphonesimulator -derivedDataPath $TEMP_DIR

mkdir -p "prebuilt/$FRAMEWORK_NAME.framework"

lipo -create \
"$IPHONE_OS_DIR/$FRAMEWORK_NAME.framework/$FRAMEWORK_NAME" \
"$IPHONE_SIM_DIR/$FRAMEWORK_NAME.framework/$FRAMEWORK_NAME" \
-output "$(pwd)/prebuilt/$FRAMEWORK_NAME.framework/$FRAMEWORK_NAME"

cp \
"$IPHONE_OS_DIR/$FRAMEWORK_NAME.framework/Info.plist" \
"$(pwd)/prebuilt/$FRAMEWORK_NAME.framework/Info.plist"

mkdir -p "prebuilt/$FRAMEWORK_NAME.framework/Headers"
cp -r \
"$IPHONE_OS_DIR/$FRAMEWORK_NAME.framework/Headers/"* \
"$(pwd)/prebuilt/$FRAMEWORK_NAME.framework/Headers/"

mkdir -p "prebuilt/$FRAMEWORK_NAME.framework/Modules"
cp \
"$IPHONE_OS_DIR/$FRAMEWORK_NAME.framework/Modules/module.modulemap" \
"$(pwd)/prebuilt/$FRAMEWORK_NAME.framework/Modules/module.modulemap"

mkdir -p "prebuilt/$FRAMEWORK_NAME.framework/Modules/$FRAMEWORK_NAME.swiftmodule"
cp -r \
"$IPHONE_OS_DIR/$FRAMEWORK_NAME.framework/Modules/$FRAMEWORK_NAME.swiftmodule/"* \
"$IPHONE_SIM_DIR/$FRAMEWORK_NAME.framework/Modules/$FRAMEWORK_NAME.swiftmodule/"* \
"$(pwd)/prebuilt/$FRAMEWORK_NAME.framework/Modules/$FRAMEWORK_NAME.swiftmodule/"