This guide explains how to correctly clone, configure, and run the Telegram iOS app using Bazel + Xcode, avoiding all common pitfalls.
It is based on real errors and obstacles encountered during setup:
- Xcode version mismatch
- Missing configuration files
- Provisioning / signing errors
- Extensions breaking the build
- Confusion between Terminal and Xcode
- Bazel / rules_xcodeproj misleading errors
If you follow this guide step by step, the app will run in the iOS Simulator and allow login.
- Bazel is the real build system
- Xcode does NOT build Telegram directly
- Xcode is used only for:
- editing code
- indexing
- debugging
- launching the app (via Bazel scripts)
The script build-system/Make/Make.py:
- validates environment
- generates the Xcode project
- configures Bazel flags
If this is not understood, most errors will be repeated.
- macOS
- Python 3.10+
- Xcode installed
xcode-select -p
Expected output:
/Applications/Xcode.app/Contents/Developer
Check version:
xcodebuild -version
❌ Cloning without submodules will cause obscure build failures.
git clone <TELEGRAM_IOS_REPOSITORY_URL>
cd Telegram-iOS
git submodule update --init --recursive
These files do NOT exist (even if mentioned elsewhere):
- development_configuration.json
- local-dev.json (by default)
ls build-system/*.json
Typical output:
appcenter-configuration.json
appstore-configuration.json
template_minimal_development_configuration.json
👉 For local development + simulator, always start from:
template_minimal_development_configuration.json
❌ Real mistake: referencing a config file that does not exist.
cp build-system/template_minimal_development_configuration.json build-system/local-dev.json
📍 The file must be inside build-system/. Edit build-system/local-dev.json only if required by the template. Do not invent keys.
- Xcode version mismatch
- Missing codesigning arguments
- Provisioning profile errors (even for simulator)
- Extensions breaking the build
Run in macOS Terminal (not Xcode):
python3 build-system/Make/Make.py \
--cacheDir="$HOME/telegram-bazel-cache" \
--overrideXcodeVersion \
generateProject \
--configurationPath build-system/local-dev.json \
--xcodeManagedCodesigning \
--disableProvisioningProfiles \
--disableExtensions
-
--overrideXcodeVersion Prevents failure if your Xcode version is newer than required
-
--xcodeManagedCodesigning Required by the script
-
--disableProvisioningProfiles Prevents Bazel from searching for .mobileprovision files
-
--disableExtensions Skips extension targets that require extra signing If this command fails, do not continue.
Open exactly:
Telegram/Telegram.xcodeproj
❌ Do NOT open:
- the repo folder
- any .xcworkspace
- a newly created project
- Scheme: Telegram
- Device: iPhone Simulator (iOS 18.x)
- Bundle Identifier
- Development Team
- Automatic Signing
- Provisioning Profiles
If Xcode fails on the BazelDependencies target:
- Select target BazelDependencies
- Go to Build Settings → Signing
- Set:
Code Signing Identity → Sign to Run Locally
📌 This helps Xcode run auxiliary targets without requiring real signing.
Press:
Cmd + R
What actually happens:
- Xcode runs scripts
- Scripts call Bazel
- Bazel builds the app
- App installs in the simulator
- Debugger attaches
👉 Xcode does not build Telegram traditionally. If successful:
- App launches
- Login works
- UI is functional
No. Run generateProject only when:
- switching branches
- BUILD files change
- large git pull
For daily development:
- Just Cmd + R in Xcode
This is normal:
- Xcode indexing
- Bazel resolving dependencies
- rules_xcodeproj scripts running It is not an error.
No.
- Make.py runs in Terminal
- Xcode indexing is independent
Telegram uses a custom UI framework. Not all system visual styles are adopted automatically. This is expected behavior.
Because:
- Bazel controls the build
- Xcode is only a frontend
- Manual signing changes break consistency