Conditional Compilation कंपाइलर को बिल्ड समय पर ज्ञात शर्तों के आधार पर स्रोत कोड के कुछ हिस्सों को शामिल या छोड़ने की अनुमति देता है। The Swift Programming Language (2026) के अनुसार, #if निर्देश मशीन कोड उत्पादन से पहले AST विश्लेषण के दौरान संसाधित होता है। Conditional Compilation डेवलपर्स को बिना दोहराव के कई प्लेटफ़ॉर्म और कॉन्फ़िगरेशन के लिए एकल कोडबेस बनाए रखने की क्षमता देता है।
मुख्य बिंदु
Conditional Compilation एक तंत्र है जिसमें कंपाइलर सशर्त संकलन निर्देशों का विश्लेषण करता है और आउटपुट बाइनरी में केवल उन कोड ब्लॉक्स को शामिल करता है जिनकी शर्तें पूरी होती हैं। यह एक एकल कोडबेस रखने की अनुमति देता है जो विभिन्न लक्ष्य प्लेटफ़ॉर्म और कॉन्फ़िगरेशन के अनुकूल होता है।
यह अवधारणा C/C++ से प्रीप्रोसेसर निर्देशों #ifdef, #ifndef, #endif के साथ आई है। आधुनिक भाषाओं (Swift, Rust, Go) में, तंत्र बिना किसी अलग प्रीप्रोसेसर के कंपाइलर स्तर पर काम करता है, जो सुरक्षा बढ़ाता है: सशर्त ब्लॉक्स वाक्य-रचना की दृष्टि से सही होने चाहिए भले ही वे संकलित न हों।
Apple WWDC सत्र “Embrace Swift” (2025) के अनुसार, लगभग 40% Swift प्रोजेक्ट एक ही लक्ष्य में iOS और macOS का समर्थन करने के लिए सशर्त संकलन का उपयोग करते हैं। UIKit और SwiftUI वाले प्रोजेक्ट्स के लिए, UI कोड अक्सर #if os(iOS) और #if os(macOS) निर्देशों से विभाजित होता है, जिससे व्यावसायिक तर्क का पुन: उपयोग संभव होता है।
मुख्य लाभ संकलन-समय सुरक्षा है। अनुपयुक्त प्लेटफ़ॉर्म का कोड न केवल निष्पादित नहीं होता, बल्कि संकलित भी नहीं होता। इसका मतलब है कि iOS-विशिष्ट कोड में त्रुटियाँ macOS के लिए बनाते समय प्रकट नहीं होंगी, और इसके विपरीत। रनटाइम जाँचें ऐसी गारंटी नहीं देतीं।
Swift चार मुख्य निर्देश प्रदान करता है: #if, #elseif, #else, #endif. C प्रीप्रोसेसर के विपरीत, Swift सभी शाखाओं में कोड की वाक्य-रचना की शुद्धता की आवश्यकता रखता है — कंपाइलर सभी कोड को पार्स करता है लेकिन केवल सक्रिय शाखाओं के लिए मशीन कोड उत्पन्न करता है।
Swift अंतर्निहित जाँच फ़ंक्शन का समर्थन करता है: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows)। ये फ़ंक्शन उस लक्ष्य प्लेटफ़ॉर्म की जाँच करते हैं जिसके लिए एप्लिकेशन बनाया जा रहा है। && और || के साथ संयोजन जटिल शर्तें बनाने की अनुमति देता है।
// iOS, macOS और tvOS के लिए एकीकृत कोड
import Foundation
class PlatformService {
func getSystemVersion() -> String {
#if os(iOS) || os(tvOS)
return UIDevice.current.systemVersion
#elseif os(macOS)
let vers = ProcessInfo.processInfo.operatingSystemVersion
return "\(vers.majorVersion).\(vers.minorVersion)"
#else
return "unknown"
#endif
}
}
Swift कंपाइलर संस्करण जाँच का समर्थन करता है: #if swift(>=5.9)। यह उन लाइब्रेरीज़ और फ्रेमवर्क के लिए उपयोगी है जो कई Swift संस्करणों का समर्थन करते हैं। नई भाषा सुविधाएँ (जैसे Swift 5.9 में मैक्रोज़) ऐसी जाँच द्वारा संरक्षित की जा सकती हैं।
// पिछड़ी संगतता
#if swift(>=5.9)
@MainActor
struct ModernView: View {
var body: some View {
Text("Modern SwiftUI")
}
}
#else
struct ModernView: View {
var body: some View {
Text("Legacy SwiftUI")
}
}
#endif
canImport(ModuleName) फ़ंक्शन जाँचता है कि निर्दिष्ट मॉड्यूल वर्तमान बिल्ड वातावरण में उपलब्ध है या नहीं। यह सबसे लचीला तंत्र है: यह किसी विशिष्ट प्लेटफ़ॉर्म से बंधा नहीं है। उदाहरण के लिए, CoreHaptics का उपयोग करने वाला कोड केवल उन उपकरणों पर संकलित होगा जहाँ यह फ्रेमवर्क उपलब्ध है।
#if canImport(CoreHaptics)
import CoreHaptics
class HapticManager {
private var engine: CHHapticEngine?
func playTapFeedback() {
guard let engine else { return }
// स्पर्श प्रतिक्रिया कार्यान्वयन
}
}
#endif
Kotlin भाषा में प्रीप्रोसेसर निर्देश नहीं हैं। इसके बजाय, Android पारिस्थितिकी तंत्र तीन विकल्प प्रदान करता है: BuildConfig फ़ील्ड (रनटाइम जाँच), sourceSets (पूरी फ़ाइलों को बदलना), और expect/actual (Kotlin Multiplatform में)।
Gradle sourceSets विभिन्न फ्लेवर या बिल्ड प्रकारों के लिए अलग-अलग क्लास कार्यान्वयन की अनुमति देते हैं। src/debug/ निर्देशिका में डीबग कार्यान्वयन है, src/release/ में — रिलीज़ कार्यान्वयन। बिल्ड के दौरान, Gradle उपयुक्त sourceSet का चयन करता है और केवल उसकी फ़ाइलों को संकलित करता है।
// src/debug/kotlin/com/example/Logger.kt
object Logger {
fun log(tag: String, message: String) {
Log.d(tag, message)
}
}
// src/release/kotlin/com/example/Logger.kt
object Logger {
fun log(tag: String, message: String) {
// रिलीज़ में No-op
}
}
KMP expect तंत्र (सामान्य कोड में घोषणा) और actual (विशिष्ट प्लेटफ़ॉर्म के लिए कार्यान्वयन) प्रदान करता है। यह एक संकलन-समय तंत्र है: iOS के लिए iOS sourceSet से actual कार्यान्वयन संकलित होता है, Android के लिए — Android sourceSet से। गैर-लक्ष्य कार्यान्वयन संकलित नहीं होते।
// commonMain — expect घोषणा
expect fun getPlatformName(): String
// androidMain — Android के लिए actual
actual fun getPlatformName(): String =
"Android \${Build.VERSION.SDK_INT}"
// iosMain — iOS के लिए actual
actual fun getPlatformName(): String =
UIDevice.current.systemName() + " " + UIDevice.current.systemVersion
Android NDK के माध्यम से मूल लाइब्रेरी विकसित करते समय, #ifdef, #ifndef, #define निर्देशों के साथ क्लासिक C/C++ प्रीप्रोसेसर का उपयोग किया जाता है। Swift के विपरीत, C प्रीप्रोसेसर टेक्स्ट स्तर पर काम करता है — निष्क्रिय शाखाओं में कोड वाक्य-रचना की दृष्टि से गलत हो सकता है।
NDK प्रत्येक प्लेटफ़ॉर्म के लिए मैक्रो परिभाषित करता है: __ANDROID__ (Android), __APPLE__ (iOS/macOS), __linux__ (Linux)। आर्किटेक्चर के लिए: __arm__, __aarch64__, __x86_64__। ये मैक्रो कंपाइलर द्वारा लक्ष्य प्लेटफ़ॉर्म के लिए बनाते समय स्वचालित रूप से सेट किए जाते हैं।
// Android और iOS के लिए मूल कोड
#include <cstdint>
#ifdef __ANDROID__
int32_t getJniEnv(JNIEnv* env) {
return env->GetVersion();
}
#elif defined(__APPLE__)
#include <TargetConditionals.h>
int32_t getOsVersion() {
#if TARGET_OS_IOS
return "iOS";
#elif TARGET_OS_OSX
return "macOS";
#endif
}
#endif
NDK के साथ काम करते समय, यह याद रखना महत्वपूर्ण है कि C/C++ प्रीप्रोसेसर एक टेक्स्ट प्रतिस्थापन है। यदि निष्क्रिय शाखा में वाक्य-रचना त्रुटि है, तो कंपाइलर इसे नहीं देखेगा, लेकिन यदि गलत #define एक सक्रिय शाखा को तोड़ता है — त्रुटि प्रकट होगी। #define श्रृंखलाओं को कम करने और constexpr स्थिरांक का उपयोग करने की अनुशंसा की जाती है।
Rust के लिए, जो UniFFI और Mozilla Application Services के माध्यम से मोबाइल विकास में भी उपयोग किया जाता है, इसका अपना तंत्र है — Cargo.toml में फ़ीचर फ़्लैग। Rust में #[cfg(target_os = “android”)] जैसे फ़्लैग Swift निर्देशों के समान काम करते हैं: जाँच कंपाइलर स्तर पर की जाती है, प्रीप्रोसेसर पर नहीं। यह Rust को उन मूल लाइब्रेरीज़ के लिए एक आकर्षक विकल्प बनाता है जिन्हें एक कोडबेस से Android और iOS के लिए संकलित होना चाहिए।
Conditional Compilation सख्ती से परिभाषित परिदृश्यों में प्रभावी है। गलत उपयोग करने पर, यह कोड स्मेल बनाता है जिसका परीक्षण और रखरखाव करना मुश्किल होता है। आइए सही परिदृश्यों और सामान्य गलतियों पर विचार करें।
पहला परिदृश्य — प्लेटफ़ॉर्म एब्स्ट्रैक्शन: एक एकल फ़ेसाड जिसके अंदर Conditional Compilation प्लेटफ़ॉर्म कार्यान्वयन का चयन करता है। दूसरा — डीबगिंग और प्रोफ़ाइलिंग: डेवलपर उपकरण जो रिलीज़ में नहीं जाने चाहिए। तीसरा — पिछड़ी संगतता: पुराने OS संस्करणों के लिए समर्थन जब तक न्यूनतम संस्करण अपडेट न हो।
| परिदृश्य | भाषा | शर्त |
|---|---|---|
| प्लेटफ़ॉर्म एब्स्ट्रैक्शन | Swift | #if os(iOS) |
| डीबगिंग | Swift/ObjC | #if DEBUG |
| पिछड़ी संगतता | Swift | #if swift(>=5.7) |
| मूल लाइब्रेरी | C/C++ | #ifdef __ANDROID__ |
| A/B परीक्षण | Java/Kotlin | BuildConfig.FLAVOR |
सबसे खतरनाक एंटीपैटर्न — पूरे कोड में निर्देशों का प्रसार। यदि हर दूसरी फ़ाइल में #if है, तो यह संकेत है कि आर्किटेक्चर को रीफ़ैक्टरिंग की आवश्यकता है। सही समाधान — प्लेटफ़ॉर्म कोड को प्रोटोकॉल/इंटरफ़ेस के पीछे निकालना और डिपेंडेंसी इंजेक्शन का उपयोग करना।
अक्सर पूछे जाने वाले प्रश्न
Conditional Compilation संकलन समय पर काम करता है: निष्क्रिय कोड बाइनरी में नहीं जाता। रनटाइम जाँच (if / switch) हमेशा संकलित होती हैं, शर्त निष्पादन के दौरान जाँची जाती है। पहला अधिक सुरक्षित और कुशल है, दूसरा अधिक लचीला (बिना पुनर्निर्माण के बदला जा सकता है)।
हाँ, Swift फ़ंक्शन के अंदर #if, लूप और यहाँ तक कि एक्सप्रेशन के अंदर भी निर्देशों की अनुमति देता है। यह उन सुविधाओं में से एक है जो Swift के शुरुआती संस्करणों में गायब थी। उदाहरण के लिए: let x = #if DEBUG 1 #else 0 #endif — मान्य कोड।
Kotlin डेवलपर्स ने जानबूझकर प्रीप्रोसेसर को अस्वीकार कर दिया, इसे नाज़ुक कोड का स्रोत मानते हुए। इसके बजाय, वे expect/actual (संकलन-समय सुरक्षा) और Gradle sourceSets (फ़ाइल स्तर पर अलगाव) प्रदान करते हैं। दोनों दृष्टिकोण टेक्स्ट प्रतिस्थापन से अधिक विश्वसनीय हैं।
CI में विभिन्न फ़्लैग संयोजनों के साथ एप्लिकेशन बनाएँ। Swift के लिए: विभिन्न Active Compilation Conditions के साथ अलग Xcode स्कीम कॉन्फ़िगर करें। Android के लिए: अलग Build Variants कॉन्फ़िगर करें और प्रत्येक के लिए परीक्षण चलाएँ। स्वचालन अनिवार्य है।
Swift में, #if शर्त एक कंपाइलर निर्देश है। यदि शर्त स्वयं वाक्य-रचना की दृष्टि से गलत है (जैसे, os() नाम में टाइपो), तो कंपाइलर संकलन त्रुटि जारी करेगा। C/C++ में, प्रीप्रोसेसर बस मैक्रो नहीं ढूँढेगा और शर्त झूठी हो जाएगी।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें