This file provides guidelines for AI coding agents working on the BuildShared repository.
BuildShared is a Swift Package that provides shared build infrastructure for compiling C/C++ libraries into XCFrameworks for multiple Apple platforms (iOS, macOS, tvOS, visionOS).
Since this is a library package consumed by other projects, there are no direct build/test commands in this repo. Testing is done by:
# Build the package (validation only)
swift build
# Generate Xcode project for inspection
swift package generate-xcodeprojSources/BuildShared/
├── BuildShared.swift # Module entry with global exports
├── Protocols/
│ └── BuildLibrary.swift # BuildLibrary protocol definition
├── Models/
│ ├── PlatformType.swift # Platform enums (iOS, macOS, etc.)
│ ├── ArchType.swift # Architecture enums (arm64, x86_64, arm64e)
│ └── PackageTarget.swift # Binary target definition
├── Options/
│ ├── ArgumentOptions.swift # Public options class (API compatible)
│ └── BuildOptions.swift # Internal options struct
├── Builders/
│ ├── BaseBuild.swift # Main build orchestration (~730 lines)
│ ├── CombineBaseBuild.swift # Combines multiple static libraries
│ └── ZipBaseBuild.swift # Works with pre-built zip archives
├── Errors/
│ └── BuildError.swift # Swift error types with NSError compatibility
└── Utilities/
├── Utility.swift # Shell execution and process management
└── URL+Extensions.swift # URL path manipulation helpers
- Version: Swift 5.8+
- Platforms: macOS 11.0+, iOS 14.0+, tvOS 14.0+
- Use 4 spaces for indentation
- Opening braces on the same line:
func foo() { - Max line length: ~120 characters
- No trailing whitespace
- Always use
import Foundationat the top - No unused imports
- Group imports: Foundation first, then others
- Types: PascalCase (
BaseBuild,PlatformType,ArgumentOptions) - Functions/Methods: camelCase (
buildALL(),beforeBuild()) - Variables/Properties: camelCase (
directoryURL,enableDebug) - Constants: camelCase for instance, PascalCase for enum cases
- Enum cases: camelCase (e.g.,
case arm64, x86_64, arm64e) - Protocols: PascalCase with descriptive names (
BuildLibrary)
- Use explicit types for public APIs
- Prefer
anyfor existential types (e.g.,any BuildLibrary) - Use
RawRepresentableenums for string-backed types - Use
CaseIterablefor enums that need iteration
- Use
openfor classes intended to be subclassed (BaseBuild,CombineBaseBuild) - Use
publicfor general APIs - Mark override methods with
overridekeyword - Include explicit access modifiers on all declarations
- New code uses
BuildErrorenum with proper error descriptions - Legacy compatibility:
BuildError.nsErrorprovides NSError conversion - Original code uses
try!in many places for simplicity - Use
throwsfor methods that can fail and need to propagate errors
- Use
//for single-line comments - Include Chinese comments where they add clarity (follow existing patterns)
- Comment complex build logic and platform-specific workarounds
Build Classes Hierarchy:
BaseBuild (open class, ~730 lines)
├── CombineBaseBuild (open class) - Merges static libraries into one
└── ZipBaseBuild (open class) - Downloads pre-built libraries
Key Protocols:
BuildLibrary: Defines library metadata (url, version, targets)
Key Enums:
PlatformType: iOS, macOS, tvOS, visionOS variants (with simulators)ArchType: arm64, x86_64, arm64e
let options = try BuildRunner.performCommand()
let builder = MyBuild(library: library, options: options)
try builder.buildALL()- Use
Utility.launch()for command execution - Use
Utility.shell()for simple command execution - Always pass environment variables explicitly
- Use
currentDirectoryURLfor working directory context - Check for tool availability with
Utility.shell("which <tool>")
- Platform logic lives in
PlatformTypeenum methods - Architecture logic lives in
ArchTypeenum - Use conditional compilation sparingly (
#if arch(x86_64)) - Document workarounds with comments explaining the issue
- Use triple quotes
"""for multi-line strings - Use string interpolation:
\(variable) - Use raw values for enum string representations
- This is a library used by other projects
- Changes should be backward compatible
- No tests in this repo - tested by consuming projects
Adding a new platform:
- Add case to
PlatformTypeenum in Models/PlatformType.swift - Implement
minVersion,name,frameworkName,architectures - Add
mesonSubSystem,cmakeSystemName,host()implementations - Update
sdkproperty - Add platform-specific flags in
cFlags()/ldFlags()if needed
Modifying build behavior:
- Extend
BaseBuildclass for new build systems - Override methods in subclasses to customize behavior
- Key override points:
beforeBuild(): Setup (clone, patches)build(platform:arch:): Actual compilationconfigure(buildURL:environ:platform:arch:): Build system configurationarguments(platform:arch:): Additional build argumentsflagsDependencelibrarys(): Dependency libraries
Adding error types:
- Add case to
BuildErrorenum in Errors/BuildError.swift - Implement
errorDescriptionfor user-friendly messages - Add corresponding code in
nsErrorproperty for NSError compatibility
- Requires Homebrew tools: autoconf, automake, libtool, pkg-config, wget, cmake, meson, ninja
- Uses system tools: git, xcodebuild, lipo, zip, clang
- This package is designed for macOS build hosts only
- Requires Xcode with SDKs for target platforms
- Build output goes to
./dist/directory in consuming projects - Original single-file design (base.swift) has been refactored into modular structure
- All public APIs remain compatible with previous versions
- 2025-02-10: Migrated from single 1485-line base.swift to modular structure
- Split into 14 separate files organized by concern
- Maintained 100% API backward compatibility
- Added BuildError enum for better error handling (internally)
- Added BuildOptions struct for type-safe options (internally)
- No breaking changes to public interface