Setting up a new development machine for a .NET MAUI project sounds simple.
Install .NET.
Install Xcode.
Install Android Studio.
Clone the repository.
Run the application.
At least, that's how it looks on paper.
When you're setting up a Mac for an existing production .NET MAUI project, there are several more pieces involved. The .NET SDK, MAUI workload, Xcode, iOS tooling, Android SDK, JDK, device configuration, signing, and project-specific requirements all need to work together.
I recently went through this process while setting up a Mac for an existing .NET MAUI application. Along the way, I encountered several issues that were not obvious from the initial setup.
That experience led me to a simple conclusion:
A development environment isn't ready when the tools are installed. It's ready when the application can build, run, and be debugged.
This is Part 1 of a two-part series.
- Part 1: Setting up a reliable .NET MAUI development environment on macOS
- Part 2: Troubleshooting .NET MAUI setup issues on macOS
Table of Contents
- What We Are Trying to Achieve
- 1. Start With the Repository
- 2. Install and Verify the .NET SDK
- 3. Install the .NET MAUI Workload
- 4. Configure Xcode for iOS Development
- 5. Pay Attention to Xcode and MAUI Compatibility
- 6. Verify the iOS Simulator
- 7. Configure Android
- 8. Verify the JDK
- 9. Configure the Android SDK
- 10. Emulator or Physical Device?
- 11. Connect a Physical Android Device
- 12. Restore the Actual Project
- 13. Don't Ignore Warnings
- 14. Validate Debugging, Not Just Deployment
- 15. My Setup Checklist
- What I Learned
- Conclusion
What We Are Trying to Achieve
The goal isn't just to install the required tools.
We want to reach this state:
Project requirements
↓
.NET SDK
↓
.NET MAUI workload
↓
Xcode + iOS tooling
↓
Android SDK + JDK
↓
Simulator / Emulator
↓
Physical device
↓
Project restore
↓
Build
↓
Run
↓
Debug
If any layer is missing or incompatible, the setup may appear complete while the actual application still doesn't work.
1. Start With the Repository
Before installing anything, look at the project.
This is probably the most important step in the entire setup.
Don't start by installing the latest versions of every tool.
Instead, first determine what the application actually expects.
For a .NET MAUI repository, look for files such as:
global.json
Directory.Build.props
*.csproj
NuGet.config
README.md
docs/
Things worth checking include:
- .NET SDK version
- MAUI version
- MAUI workload version
- Target frameworks
- Android API level
- iOS minimum version
- Required NuGet feeds
- Development tooling
- Signing requirements
For example, a repository may contain a global.json similar to:
{
"sdk": {
"version": "10.0.203",
"rollForward": "disable"
},
"tools": {
"dotnet-workload-version": "10.0.203"
}
}
And a central MSBuild file may define the MAUI version:
<PropertyGroup>
<MauiVersion>10.0.60</MauiVersion>
</PropertyGroup>
This immediately tells us something important:
The repository is part of the setup documentation.
The project itself often contains more accurate requirements than a generic installation guide.
2. Install and Verify the .NET SDK
Once the required version is known, install the corresponding .NET SDK.
After installation, don't assume it worked.
Verify it:
dotnet --version
Then inspect the complete environment:
dotnet --info
The second command is particularly useful because it shows:
- SDK version
- Runtime version
- OS
- Architecture
- Workload information
- SDK installation path
-
global.jsoninformation
For example:
.NET SDK:
Version: 10.0.203
Runtime Environment:
OS: Mac OS X
Architecture: arm64
If the project has a global.json, make sure the SDK being used matches it.
Why not simply use the latest SDK?
Because an existing application may have been tested against a specific SDK and workload combination.
A newer SDK isn't automatically a better SDK for an existing project.
For project setup, compatibility is more important than recency.
3. Install the .NET MAUI Workload
Installing the .NET SDK doesn't automatically mean the MAUI development environment is ready.
Check the installed workloads:
dotnet workload list
If MAUI isn't installed, install it:
dotnet workload install maui
Then verify again:
dotnet workload list
For repositories that pin the workload version, follow the repository's configuration rather than manually selecting an unrelated workload version.
This distinction matters because the MAUI workload is closely tied to the .NET SDK and platform tooling.
4. Configure Xcode for iOS Development
For iOS development, Xcode is not optional.
After installing Xcode, verify which developer directory macOS is using:
xcode-select -p
Then check the Xcode version:
xcodebuild -version
A common setup issue is having Apple's Command Line Tools installed while Xcode itself is not the active developer directory.
For example:
/Library/Developer/CommandLineTools
may be returned by:
xcode-select -p
while commands such as xcodebuild or simctl still require the full Xcode installation.
If necessary, select Xcode explicitly:
sudo xcode-select --switch /Applications/Xcode.app
Then verify again:
xcodebuild -version
The important lesson is:
Installed doesn't necessarily mean configured.
5. Pay Attention to Xcode and MAUI Compatibility
This is an area where mobile development differs from many typical .NET applications.
Your application depends on multiple layers:
.NET SDK
↓
.NET MAUI workload
↓
.NET iOS workload
↓
Xcode
↓
Apple SDK
Changing one of these can affect the others.
For example, upgrading Xcode may require using a compatible .NET workload version.
So when troubleshooting an iOS build, capture the versions together:
dotnet --info
dotnet workload list
xcodebuild -version
Don't troubleshoot them independently.
Think of them as a toolchain, not separate applications.
6. Verify the iOS Simulator
Once Xcode is configured, launch the Simulator.
You can open it with:
open -a Simulator
You can also inspect available runtimes:
xcrun simctl list runtimes
And devices:
xcrun simctl list devices
At this point, the objective is simple:
Can the Mac see an iOS simulator that the MAUI project can target?
If yes, move on to the actual application.
7. Configure Android
Android has another dependency chain:
.NET SDK
↓
.NET MAUI
↓
Android SDK
↓
JDK
↓
Android Build Tools
↓
ADB
↓
Emulator / Physical Device
The JDK is particularly important.
A .NET MAUI Android build isn't only dependent on .NET. The Android toolchain also needs a compatible Java Development Kit.
8. Verify the JDK
First check whether Java is available:
java -version
Also check:
/usr/libexec/java_home -V
The important thing isn't simply having Java installed.
The build system needs to be able to find the correct JDK.
This distinction becomes especially important when multiple Java installations exist on a development machine.
A JDK can exist on disk while the .NET Android build still reports that it cannot find a Java SDK.
We'll look at this scenario in detail in Part 2.
9. Configure the Android SDK
The Android SDK needs several components depending on the project's requirements.
Typical components include:
platform-tools
platforms;android-XX
build-tools;XX.X.X
cmdline-tools
emulator
system-images
Check the SDK location and installed components.
For example:
echo $ANDROID_HOME
And:
ls "$ANDROID_HOME"
ADB should also be available:
adb version
If adb isn't found but the Android SDK's platform-tools directory exists, the SDK may be installed correctly but not configured on your shell's PATH.
For example:
export ANDROID_HOME="$HOME/Library/Developer/Android/sdk"
export PATH="$ANDROID_HOME/platform-tools:$PATH"
Then:
adb devices
10. Emulator or Physical Device?
For Android development, there are two common deployment targets:
- Android Emulator
- Physical Android device
Both are useful.
The emulator is convenient for everyday development and testing different configurations.
A physical device is particularly useful for validating:
- Real hardware behavior
- Device-specific issues
- OS-specific behavior
- Performance
- Lifecycle behavior
- Native platform behavior
For production mobile applications, I prefer having access to both.
11. Connect a Physical Android Device
To debug on a physical Android device:
- Enable Developer Options.
- Enable USB debugging.
- Connect the device to the Mac.
- Authorize the computer on the device.
- Verify the connection.
Run:
adb devices
A successfully connected device should appear as:
List of devices attached
<device-id> device
Once ADB sees the device, the next question is whether the MAUI project can actually build and deploy to it.
That distinction is important.
ADB sees device
≠
MAUI can deploy application
Both need to be verified.
12. Restore the Actual Project
Now we get to the most important part.
Stop testing the environment with individual commands.
Test the actual application.
From the repository root:
dotnet restore
Or, if the repository provides a solution file:
dotnet restore ALPAMobile.sln
Then build the required platform.
iOS
dotnet build ALPAMobile/ALPAMobile.csproj \
-f net10.0-ios \
-c Debug
Android
dotnet build ALPAMobile/ALPAMobile.csproj \
-f net10.0-android \
-c Debug
The exact project and target framework will obviously vary by repository.
13. Don't Ignore Warnings
A successful build can still produce useful warnings.
For example, dependency security warnings may appear during restore or build.
These should not automatically be treated as setup failures.
Separate the output into categories:
Build errors
Warnings
Dependency warnings
Environment warnings
Runtime issues
This makes troubleshooting much easier.
The objective during initial setup is to determine:
Can the application successfully restore, compile, deploy, and run?
Not:
Does the terminal output contain zero warnings?
Those are different goals.
14. Validate Debugging, Not Just Deployment
The final step is to verify the actual development workflow.
For example:
Open project
↓
Start Debug
↓
Application builds
↓
Application deploys
↓
Application launches
↓
Debugger attaches
↓
Breakpoint hits
This is a much stronger validation than simply seeing an application icon appear on a simulator or device.
A developer environment should support the workflow you actually need every day.
15. My Setup Checklist
After going through the setup process, I found it useful to think of the environment as a checklist rather than a collection of installed applications.
Project
- [ ] Repository cloned
- [ ]
global.jsonchecked - [ ] MAUI version checked
- [ ] Target frameworks checked
- [ ] Project-specific documentation reviewed
.NET
- [ ] Required SDK installed
- [ ] Correct SDK selected
- [ ] MAUI workload installed
- [ ] Workload version verified
iOS
- [ ] Xcode installed
- [ ] Xcode selected with
xcode-select - [ ] Xcode version verified
- [ ] iOS runtime installed
- [ ] Simulator launches
- [ ] Application builds for iOS
Android
- [ ] JDK installed
- [ ] JDK discoverable by the build
- [ ] Android SDK installed
- [ ] Required platform installed
- [ ] Build tools installed
- [ ] Platform tools installed
- [ ] ADB available
- [ ] Emulator configured
- [ ] Physical device detected
Application
- [ ] Dependencies restored
- [ ] iOS Debug build succeeds
- [ ] Android Debug build succeeds
- [ ] iOS Simulator launches application
- [ ] Android Emulator launches application
- [ ] Physical Android device launches application
- [ ] Debugger attaches successfully
What I Learned
The biggest lesson from setting up a new Mac for an existing MAUI project was that environment setup is really dependency management.
The tools don't exist independently.
A simplified view looks like this:
Project
│
▼
.NET SDK version
│
▼
MAUI workload
/ \
/ \
▼ ▼
Xcode Android SDK
│ │
iOS SDK JDK
│ │
Simulator ADB/device
If one layer is incompatible or incorrectly configured, the failure may appear somewhere else.
For example, an Android build error may look like a project problem when the actual issue is simply that the build process cannot locate the JDK.
Likewise, an iOS build problem may initially look like a MAUI problem when the underlying issue is the selected Xcode installation or an incompatible toolchain combination.
This is why I now approach a new development environment with three questions:
1. What does the project require?
Don't guess.
Read the repository configuration.
2. What is actually installed?
Use commands such as:
dotnet --info
dotnet workload list
xcodebuild -version
java -version
adb version
3. Does the actual application work?
Ultimately:
Restore → Build → Deploy → Run → Debug
is the real test.
Conclusion
Setting up .NET MAUI on macOS isn't difficult because any single component is particularly complicated.
It's challenging because several components have to work together.
The most reliable approach I've found is:
Inspect → Install → Configure → Verify → Build → Run → Debug
And most importantly:
Don't consider the machine ready just because the installation completed. Consider it ready when the actual application can be developed on it.
In Part 2, I'll go through the troubleshooting side of this setup - including what happens when Xcode is installed but isn't being used, Android SDK installation partially succeeds, the JDK exists but the build can't find it, and how to systematically diagnose these problems instead of repeatedly reinstalling tools.
Coming next: Part 2-Troubleshooting .NET MAUI on macOS: From Build Errors to Device Debugging
Top comments (0)