How to create a framework that uses C with Xcode

Step 1:  Create a Cocoa Touch Framework

File -> New -> Project -> Cocoa Touch Framework

Xcode new project dialog highlighting Cocoa Touch Framework template

Name it SwiftCFramework

Step 2: Create xcconfig file:

Finder save dialog creating a new xcconfig file

Xcode build configuration files, more commonly known by their [xcconfig](https://nshipster.com/xcconfig/) file extension, allow build settings for your app to be declared and managed without Xcode.

Step 3: Add xcconfig to the Configurations section of the Project Info

Xcode project info showing custom xcconfig configuration selection

Step 4: Add swiftcframework.mapmodule and public.mapmodule files to the project

Xcode file navigator with module map files added to the framework

Module map file contents displayed in Xcode editor

Step 5: Add C header files and make sure their Target Membership is set to Private

Project navigator showing C header files with private target membership

Step 6: Add a run script to remove private headers and create a public modulemap file

Name the script “Make C Header Files Private”

Run script build phase removing private headers and copying module map

# Delete PrivateHeaders folder
rm -rf ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/PrivateHeaders

# Remove module.modulemap file
rm ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

# Copy public.modulemap file and rename it to module.modulemap
cp ${SRCROOT}/Supporting/public.modulemap ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

# Append the Swift module so you can access you Swift code in Objective-C via @import MyFramework.Swift
echo "module ${PRODUCT_NAME}.Swift { header \"${PRODUCT_NAME}-Swift.h\" }" >> ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

Step 7: Add the framework to a test application

Test application target linked with the custom framework in Xcode

The code is available on the SwiftCFramework GitHub repository.

FAQ

How do I create a Swift framework that wraps C code in Xcode?
Create a Cocoa Touch Framework target, configure an xcconfig file for build settings, add C headers and module map files to describe your C APIs, and then link the framework into a sample app so Swift code can import and call the C functions.
How can I keep C headers private while still exposing them through a module map?
Mark C headers as Private in the framework target and add a run script build phase that removes the PrivateHeaders folder, replaces the default module.modulemap with a curated public.modulemap, and appends a Swift submodule entry so Objective-C can import the generated Swift header.

Welcome to The infinite monkey theorem

Somewhere a monkey just typed Shakespeare in TypeScript. Be the first to read the masterpieces (and the hilarious misfires) landing on the blog.

Subscribe to The infinite monkey theorem

We fling fresh posts—no banana peels attached—straight to your inbox.