Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
# https://github.com/mxcl/xcodebuild
- uses: mxcl/xcodebuild@v1
- uses: actions/checkout@v4
with:
platform: macOS
working-directory: MacDependency
action: build # default = `test`
submodules: true

- name: Build MacDependency
run: |
cd MacDependency
xcodebuild -project MacDependency.xcodeproj \
-scheme MacDependency \
-configuration Release \
CODE_SIGN_IDENTITY="-" \
AD_HOC_CODE_SIGNING_ALLOWED=YES \
ONLY_ACTIVE_ARCH=YES \
build
28 changes: 28 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,34 @@ xcuserdata/

# End of https://www.toptal.com/developers/gitignore/api/xcode

# Build artifacts
build/
build.xcresult/
DerivedData/
*.app
*.dmg
*.dSYM

# macOS
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
13 changes: 13 additions & 0 deletions MacDependency/AppDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// AppDelegate.h
// MacDependency
//
// Application delegate to handle auto-opening MacDependency binary
// and command-line argument processing.
//

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>

@end
78 changes: 78 additions & 0 deletions MacDependency/AppDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// AppDelegate.m
// MacDependency
//
// Application delegate to handle auto-opening MacDependency binary
// and command-line argument processing.
//

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
// Get command line arguments from NSProcessInfo
NSArray<NSString *> *arguments = [[NSProcessInfo processInfo] arguments];

// arguments[0] is the executable path, so check if there are additional args
if (arguments.count > 1) {
// User provided file path(s) as arguments
[self openFilesFromCommandLine:arguments];
} else {
// No arguments - auto-open MacDependency binary itself
[self openDefaultFile];
}
}

- (void)openFilesFromCommandLine:(NSArray<NSString *> *)arguments {
// Skip first argument (executable path)
for (NSInteger i = 1; i < arguments.count; i++) {
NSString *filePath = arguments[i];

// Convert to absolute path if needed
if (![filePath isAbsolutePath]) {
NSString *currentDir = [[NSFileManager defaultManager] currentDirectoryPath];
filePath = [currentDir stringByAppendingPathComponent:filePath];
}

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

// Use NSDocumentController to open the document
[[NSDocumentController sharedDocumentController]
openDocumentWithContentsOfURL:fileURL
display:YES
completionHandler:^(NSDocument *document, BOOL wasAlreadyOpen, NSError *error) {
if (error) {
NSLog(@"Error opening file %@: %@", filePath, error.localizedDescription);
// Show error dialog to user
[[NSAlert alertWithError:error] runModal];
}
}];
}
}

- (void)openDefaultFile {
// Get path to the MacDependency executable inside Contents/MacOS/
NSString *executablePath = [[NSBundle mainBundle] executablePath];

NSURL *fileURL = [NSURL fileURLWithPath:executablePath];

// Open the executable using NSDocumentController
[[NSDocumentController sharedDocumentController]
openDocumentWithContentsOfURL:fileURL
display:YES
completionHandler:^(NSDocument *document, BOOL wasAlreadyOpen, NSError *error) {
if (error) {
NSLog(@"Error opening default file: %@", error.localizedDescription);
// Don't show error dialog here - user didn't explicitly request this
}
}];
}

// Don't interfere with normal document opening via Finder
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
// Return NO to let NSDocumentController handle it normally
return NO;
}

@end
7 changes: 6 additions & 1 deletion MacDependency/Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="9F0" id="9F1"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29" userLabel="MainMenu">
Expand Down Expand Up @@ -145,5 +149,6 @@
</items>
</menu>
<customObject id="419" customClass="NSFontManager"/>
<customObject id="9F0" customClass="AppDelegate"/>
</objects>
</document>
4 changes: 4 additions & 0 deletions MacDependency/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,9 @@
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSAppleEventsUsageDescription</key>
<string>MacDependency needs to access system files to analyze Mach-O binaries and their dependencies.</string>
<key>NSSystemAdministrationUsageDescription</key>
<string>MacDependency requires access to system libraries and frameworks to display dependency information.</string>
</dict>
</plist>
16 changes: 16 additions & 0 deletions MacDependency/MacDependency.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?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>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
10 changes: 10 additions & 0 deletions MacDependency/MacDependency.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
8ED4567B10516D6200FAC99F /* MyDocumentWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ED4567A10516D6200FAC99F /* MyDocumentWindow.m */; };
8EFDEF7A101007B300E4D54D /* ConversionStdString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8EFDEF79101007B300E4D54D /* ConversionStdString.mm */; };
8EFDEF9310100F1700E4D54D /* VersionFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EFDEF9210100F1700E4D54D /* VersionFormatter.m */; };
9F00000320241201DEADBEEF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F00000220241201DEADBEEF /* AppDelegate.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -101,6 +102,9 @@
8EFDEF79101007B300E4D54D /* ConversionStdString.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ConversionStdString.mm; sourceTree = "<group>"; wrapsLines = 0; };
8EFDEF9110100F1700E4D54D /* VersionFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionFormatter.h; sourceTree = "<group>"; wrapsLines = 0; };
8EFDEF9210100F1700E4D54D /* VersionFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionFormatter.m; sourceTree = "<group>"; wrapsLines = 0; };
9F00000120241201DEADBEEF /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
9F00000220241201DEADBEEF /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9F00000420241202DEADBEEF /* MacDependency.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MacDependency.entitlements; sourceTree = "<group>"; };
ADCDF191276D87BD002476ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
ADCDF192276D87BD002476ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MyDocument.xib; sourceTree = "<group>"; };
ADCDF194276D87BF002476ED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
Expand Down Expand Up @@ -163,6 +167,8 @@
2A37F4ABFDCFA73011CA2CEA /* Classes */ = {
isa = PBXGroup;
children = (
9F00000120241201DEADBEEF /* AppDelegate.h */,
9F00000220241201DEADBEEF /* AppDelegate.m */,
8ECFE3441061192D00685EDF /* PrioritySplitViewDelegate.h */,
8ECFE3451061192D00685EDF /* PrioritySplitViewDelegate.m */,
8EC4F15E10400F02001F9FB8 /* ArchitecturesController.h */,
Expand Down Expand Up @@ -212,6 +218,7 @@
8E131503100F7C3C00367510 /* MainMenu.xib */,
8E131505100F7C3C00367510 /* MyDocument.xib */,
8E1314FD100F7C1D00367510 /* Info.plist */,
9F00000420241202DEADBEEF /* MacDependency.entitlements */,
8E1315C3100F8F1400367510 /* Localizable.strings */,
);
name = Resources;
Expand Down Expand Up @@ -327,6 +334,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9F00000320241201DEADBEEF /* AppDelegate.m in Sources */,
8ED32F48100B68FF00EBF623 /* MachOModel.mm in Sources */,
8ED330CE100BD19800EBF623 /* SymbolTableEntryModel.mm in Sources */,
8E1314FA100F7BFC00367510 /* MyDocument.mm in Sources */,
Expand Down Expand Up @@ -403,6 +411,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = MacDependency.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
Expand All @@ -426,6 +435,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = MacDependency.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEAD_CODE_STRIPPING = YES;
Expand Down
79 changes: 79 additions & 0 deletions MacDependency/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,82 @@ MacDependency shows all dependent libraries and frameworks of a given executable
More information available in the [Wiki](../../wiki).

![Screenshot](images/macdependency.png)

## Features

- **Auto-open Example**: When launched without arguments, MacDependency automatically opens and displays its own binary as a working example
- **Command-Line Support**: Open files directly from the command line
- **Multiple Architectures**: View dependencies for different CPU architectures (x86_64, ARM64, etc.)
- **Symbol Table Viewer**: Browse symbol tables and exported functions
- **Dependency Tree**: Hierarchical view of all library dependencies

## Usage

### GUI Usage

Simply double-click `MacDependency.app` or drag a file onto the application icon to analyze it.

When launched without any file, MacDependency will automatically open itself as an example, showing you how the application works.

### Command-Line Usage

You can also launch MacDependency from the command line to analyze specific files:

```bash
# Open a single application
MacDependency.app/Contents/MacOS/MacDependency /Applications/Safari.app

# Open a binary directly
MacDependency.app/Contents/MacOS/MacDependency /bin/ls

# Open multiple files (each opens in a separate window)
MacDependency.app/Contents/MacOS/MacDependency /bin/ls /bin/cat /usr/bin/tar

# Use relative paths
cd /Applications
MacDependency.app/Contents/MacOS/MacDependency Safari.app
```

## Building

### Requirements
- macOS with Xcode installed
- Command line tools for Xcode

### Build Instructions

To build MacDependency from source:

```bash
cd MacDependency
xcodebuild -project MacDependency.xcodeproj -scheme MacDependency -configuration Release \
CODE_SIGN_IDENTITY="-" AD_HOC_CODE_SIGNING_ALLOWED=YES clean build
```

The built application will be located at:
```
~/Library/Developer/Xcode/DerivedData/MacDependency-*/Build/Products/Release/MacDependency.app
```

**Note**: The build command includes ad-hoc code signing which is required for the app to run on modern macOS versions. After building, you may need to sign the embedded framework:

```bash
codesign -f -s - ~/Library/Developer/Xcode/DerivedData/MacDependency-*/Build/Products/Release/MacDependency.app/Contents/Frameworks/MachO.framework
codesign -f -s - ~/Library/Developer/Xcode/DerivedData/MacDependency-*/Build/Products/Release/MacDependency.app
```

### Alternative Build Method

You can also open the project in Xcode and build from the IDE:

1. Open `MacDependency/MacDependency.xcodeproj` in Xcode
2. Select the MacDependency scheme
3. Choose Product > Build (⌘B)

### Creating a DMG

After building, you can create a DMG installer using the included script:

```bash
./create_dmg_for_app.sh
```
Loading