<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tools on kenji.blog</title><link>http://kenji.blog/ar/categories/tools/</link><description>Recent content in Tools on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/tools/index.xml" rel="self" type="application/rss+xml"/><item><title>دليل إعداد بيئة بناء C++ متعددة المنصات باستخدام CMake</title><link>http://kenji.blog/ar/p/cmake-cross-platform-build-environment-guide/</link><pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/cmake-cross-platform-build-environment-guide/</guid><description>&lt;img src="http://kenji.blog/p/cmake-cross-platform-build-environment-guide/img/eyecatch.jpg" alt="Featured image of post دليل إعداد بيئة بناء C++ متعددة المنصات باستخدام CMake" />&lt;p>في تطوير برمجيات C++، كان اختيار &amp;ldquo;نظام البناء&amp;rdquo; وإعداده مشكلة تزعج العديد من المطورين لسنوات طويلة. نظرًا لعدم وجود مدير حزم قياسي رسمي أو نظام بناء للغة C++، كان من الضروري استخدام مترجمات وأدوات بناء مختلفة (مثل MSVC، GCC، Clang، Make، Ninja) وفقًا لكل منصة (Windows، Linux، macOS).&lt;/p>
&lt;p>ومع ذلك، أصبح &lt;strong>CMake&lt;/strong> الآن المعيار الفعلي في الصناعة، ومن خلال استخدام CMake بشكل صحيح، يمكنك بناء بيئة بناء متعددة المنصات بأناقة من ملف &lt;code>CMakeLists.txt&lt;/code> واحد.&lt;/p>
&lt;p>في هذا المقال، سنشرح بشكل شامل ومفصل خطوات إعداد بيئة بناء C++ متعددة المنصات باستخدام أحدث أساليب CMake (Modern CMake)، بدءًا من الأساسيات وحتى التقنيات المتقدمة.&lt;/p>
&lt;h2 id="1-ما-هو-cmake-مفهوم-نظام-البناء-الوصفي-meta-build-system">1. ما هو CMake؟ (مفهوم نظام البناء الوصفي Meta-Build System)
&lt;/h2>&lt;p>أداة CMake في حد ذاتها ليست أداة لترجمة كود المصدر مباشرة. إنما هي &amp;ldquo;نظام لتوليد أنظمة البناء&amp;rdquo;، أي أنها &lt;strong>نظام بناء وصفي (Meta-Build System)&lt;/strong>.&lt;/p>
&lt;p>يتمثل الدور الرئيسي لـ CMake في قراءة ملفات إعدادات مجردة لا تعتمد على المنصة أو المترجم (&lt;code>CMakeLists.txt&lt;/code>)، وتوليد نصوص البناء الأصلية تلقائيًا (Native Build Scripts) والمناسبة لكل بيئة (مثل: &lt;code>Makefile&lt;/code> لنظام Linux، أو ملفات مشروع &lt;code>.sln&lt;/code> لـ Visual Studio في Windows، أو &lt;code>build.ninja&lt;/code> السريع).&lt;/p>
&lt;p>يوضح الشكل التالي عملية التوليد في CMake.&lt;/p>
&lt;div class="mermaid">graph TD
A["CMakeLists.txt (إعدادات بناء مجردة)"] --> B["CMake (تكوين وتوليد)"]
B --> C["ملفات Make في Unix"]
B --> D["ملفات بناء Ninja"]
B --> E["حلول Visual Studio"]
B --> F["مشاريع Xcode"]
C --> G["أداة البناء الأصلية (make, ninja, MSBuild, xcodebuild)"]
D --> G
E --> G
F --> G
G --> H["ملف تنفيذي / مكتبة مشتركة / مكتبة ثابتة"]&lt;/div>
&lt;p>وبهذه الطريقة، من خلال وضع CMake في المنتصف، يمكن للمطورين إدارة مشاريع C++ دون القلق بشأن الاختلافات الدقيقة في الأوامر بين أنظمة التشغيل المختلفة.&lt;/p>
&lt;h2 id="2-أساسيات-modern-cmake-من-المتغيرات-إلى-الأهداف-targets">2. أساسيات Modern CMake: من المتغيرات إلى الأهداف (Targets)
&lt;/h2>&lt;p>يُطلق على الصياغة المستخدمة في CMake الإصدار 3.0 وما بعده اسم &amp;ldquo;Modern CMake&amp;rdquo;، وتختلف فلسفة تصميمها جذريًا عن الإصدارات السابقة (Legacy CMake). في الإصدارات القديمة، كان النهج السائد هو إعادة كتابة المتغيرات العامة على مستوى الدليل (مثل استخدام &lt;code>include_directories()&lt;/code> أو &lt;code>link_libraries()&lt;/code>)، ولكن هذا غالبًا ما كان يتسبب في آثار جانبية خطيرة حيث تنتقل الإعدادات عن غير قصد إلى وحدات أخرى.&lt;/p>
&lt;p>أما في Modern CMake، يتم التعامل مع كل شيء على أنه &lt;strong>أهداف (Targets)&lt;/strong> و&lt;strong>خصائص (Properties)&lt;/strong>. وهو يشبه العلاقة بين الفئات (Classes) والمتغيرات العضوة في البرمجة كائنية التوجه.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>الأهداف (Targets)&lt;/strong>: الملفات التنفيذية (Executables) والمكتبات (Libraries).&lt;/li>
&lt;li>&lt;strong>الخصائص (Properties)&lt;/strong>: ملفات المصدر، وأدلة التضمين، وخيارات الترجمة، والمكتبات الأخرى المرتبطة اللازمة لبناء هذا الهدف.&lt;/li>
&lt;/ul>
&lt;p>من خلال تغليف الإعدادات وتخصيصها لهدف معين فقط، يصبح من الممكن إنشاء تعريفات بناء آمنة لا تنهار حتى في المشاريع الكبيرة.&lt;/p>
&lt;h3 id="ملف-cmakeliststxt-بالأدنى-المطلوب">ملف &lt;code>CMakeLists.txt&lt;/code> بالأدنى المطلوب
&lt;/h3>&lt;p>أولاً، دعنا نلقي نظرة على ملف &lt;code>CMakeLists.txt&lt;/code> الأساسي.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># تحديد الحد الأدنى المطلوب لإصدار CMake
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تحديد اسم المشروع واللغة المستخدمة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">VERSION&lt;/span> &lt;span class="s">1.0.0&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># طلب معيار C++ القياسي (C++20)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_EXTENSIONS&lt;/span> &lt;span class="s">OFF&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c"># تعطيل الامتدادات الخاصة بالمترجم
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تعريف هدف الملف التنفيذي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في بضعة أسطر فقط، يكتمل إعداد البناء لملف تنفيذي محمول يطلب C++20 ويعطل امتدادات المترجم.&lt;/p>
&lt;h2 id="3-التبعيات-والنطاق-public--private--interface">3. التبعيات والنطاق: PUBLIC / PRIVATE / INTERFACE
&lt;/h2>&lt;p>لإتقان Modern CMake، فإن المفهوم الأهم والأكثر تعقيدًا هو معدّلات الوصول الثلاثة (النطاقات) &lt;strong>&lt;code>PUBLIC&lt;/code> و &lt;code>PRIVATE&lt;/code> و &lt;code>INTERFACE&lt;/code>&lt;/strong> المستخدمة في وظائف مثل &lt;code>target_include_directories&lt;/code> و &lt;code>target_link_libraries&lt;/code>.&lt;/p>
&lt;p>تُستخدم هذه المعدّلات للتحكم في خصائص الهدف (مثل مسارات التضمين والمكتبات التابعة) من حيث ما إذا كانت &amp;ldquo;مطلوبة لبناء الهدف نفسه؟&amp;rdquo; و &amp;ldquo;هل يجب تمريرها إلى الأهداف الأخرى التي تعتمد عليه؟&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>PRIVATE&lt;/code>&lt;/strong>: مطلوب فقط لبناء الهدف نفسه. &lt;strong>لا&lt;/strong> ينتقل إلى الأهداف التابعة.&lt;/li>
&lt;li>&lt;strong>&lt;code>INTERFACE&lt;/code>&lt;/strong>: غير مطلوب لبناء الهدف نفسه، لكنه &lt;strong>ينتقل&lt;/strong> إلى بناء الأهداف التابعة (يُستخدم في المكتبات التي تتكون من ملفات ترويسة فقط).&lt;/li>
&lt;li>&lt;strong>&lt;code>PUBLIC&lt;/code>&lt;/strong>: مطلوب لبناء الهدف نفسه، و&lt;strong>ينتقل&lt;/strong> أيضًا إلى الأهداف التابعة (&lt;code>PRIVATE&lt;/code> + &lt;code>INTERFACE&lt;/code>).&lt;/li>
&lt;/ol>
&lt;p>دعنا نتصور نقل التبعيات (انتقال متطلبات الاستخدام Usage Requirements) في الشكل التالي.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Libraries"
MathLib["MathLib (مكتبة ثابتة)"]
NetworkLib["NetworkLib (مكتبة مشتركة)"]
HeaderLib["HeaderLib (ترويسة فقط)"]
end
subgraph "Application"
App["التطبيق الرئيسي"]
end
App -- "target_link_libraries(App PRIVATE MathLib)" --> MathLib
App -- "target_link_libraries(App PUBLIC NetworkLib)" --> NetworkLib
NetworkLib -- "target_link_libraries(NetworkLib INTERFACE HeaderLib)" --> HeaderLib
note1["يعتمد App على تنفيذ MathLib، لكنه لا يعرضه للخارج"]
note2["تكشف NetworkLib عن واجهة HeaderLib"]&lt;/div>
&lt;h3 id="أمثلة-محددة-على-استخدام-النطاقات">أمثلة محددة على استخدام النطاقات
&lt;/h3>&lt;p>لنفترض أن مكتبة &lt;code>MyLib&lt;/code> تستخدم &lt;code>nlohmann/json&lt;/code> كجزء من تنفيذها الداخلي، ولكنها لا تضمن &lt;code>nlohmann/json&lt;/code> في ملف الترويسة العام &lt;code>MyLib.hpp&lt;/code>. في هذه الحالة، لا يحتاج مستخدم &lt;code>MyLib&lt;/code> (التطبيق) إلى معرفة وجود مكتبة JSON.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># تعريف المكتبة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">src/MyLib.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تحديد أدلة التضمين لمشروعنا
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># دليل include مطلوب لمن يستخدم MyLib، لذا يتم تعيينه كـ PUBLIC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># دليل src يُستخدم فقط في تنفيذ MyLib، لذا يتم تعيينه كـ PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_include_directories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PUBLIC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">INSTALL_INTERFACE:include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">${&lt;/span>&lt;span class="nv">CMAKE_CURRENT_SOURCE_DIR&lt;/span>&lt;span class="o">}&lt;/span>&lt;span class="s">/src&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تُستخدم مكتبة json في التنفيذ الداخلي فقط، لذا يتم ربطها كـ PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">nlohmann_json::nlohmann_json&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>على العكس، إذا كان ملف &lt;code>MyLib.hpp&lt;/code> يحتوي على &lt;code>#include &amp;lt;nlohmann/json.hpp&amp;gt;&lt;/code>، فإن المستخدم الذي يستدعي &lt;code>MyLib&lt;/code> سيحتاج إلى معرفة مسار ترويسة JSON وإلا سيحدث خطأ في الترجمة، لذا يجب ربطها كـ &lt;code>PUBLIC&lt;/code>. من خلال تعيين هذا النطاق بشكل صحيح، يمكنك تقليل وقت البناء ومنع تسرب التبعيات غير الضرورية.&lt;/p>
&lt;h2 id="4-البناء-خارج-المصدر-out-of-source-build">4. البناء خارج المصدر (Out-of-source Build)
&lt;/h2>&lt;p>أحد أفضل الممارسات التي يجب اتباعها دائمًا عند استخدام CMake هو &lt;strong>البناء خارج المصدر&lt;/strong>.
هذا يعني عدم إخراج أي نتائج بناء (مثل ملفات الكائنات أو الملفات التنفيذية) في الدليل الذي توجد به التعليمات البرمجية المصدرية (شجرة المصدر)، ولكن يتم البناء في دليل مخصص منفصل (عادةً &lt;code>build/&lt;/code>).&lt;/p>
&lt;div class="mermaid">graph TD
Root["جذر المشروع (مستودع Git)"]
Root --> Src["src/"]
Root --> Inc["include/"]
Root --> CMake["CMakeLists.txt"]
Root -. "إنشاء دليل البناء" .-> Build["build/ (خارج المصدر)"]
Build --> Obj["CMakeFiles/ (ملفات الكائنات والذاكرة المخبئية)"]
Build --> Bin["الملفات الثنائية (MyApp.exe)"]
Build --> Gen["Makefile مُولد / build.ninja"]&lt;/div>
&lt;p>باستخدام هذا الهيكل، إذا كنت ترغب في إعادة ضبط بيئة البناء، فما عليك سوى حذف دليل &lt;code>build&lt;/code> بالكامل. ونظرًا لعدم تلويث شجرة المصدر، تصبح إدارتها في Git أسهل (تحتاج فقط إلى إضافة &lt;code>build/&lt;/code> إلى &lt;code>.gitignore&lt;/code>).&lt;/p>
&lt;h3 id="خطوات-تنفيذ-البناء">خطوات تنفيذ البناء
&lt;/h3>&lt;p>في Modern CMake، يمكنك تنفيذ البناء باستخدام أوامر مشتركة لا تعتمد على نظام التشغيل أو أدوات البناء.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. التكوين والتوليد (إنشاء دليل البناء مع تعيين الإعدادات)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake -S . -B build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. البناء الفعلي (الترجمة والربط)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (اختياري) استخدم الخيار -j للبناء متعدد مؤشرات الترابط (Multithreaded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>هنا يعني الأمر &lt;code>cmake -S . -B build&lt;/code> &amp;ldquo;استخدم الدليل الحالي (&lt;code>.&lt;/code>) كدليل مصدر، واجعل الدليل &lt;code>build&lt;/code> هو دليل البناء&amp;rdquo;.&lt;/p>
&lt;h2 id="5-كيفية-إدراج-مكتبات-الطرف-الثالث">5. كيفية إدراج مكتبات الطرف الثالث
&lt;/h2>&lt;p>في تطوير C++، لطالما كان إدراج مكتبات خارجية (مكتبات الطرف الثالث) يشكل تحديًا. ومع ذلك، هناك الآن ثلاثة أساليب رئيسية تعتبر قياسية:&lt;/p>
&lt;h3 id="51-find_package-البحث-عن-المكتبات-المثبتة-في-النظام">5.1. find_package (البحث عن المكتبات المثبتة في النظام)
&lt;/h3>&lt;p>هذه هي الطريقة الأكثر تقليدية، حيث يتم البحث عن المكتبات المثبتة بالفعل في النظام (مثل OpenSSL أو Zlib) وربطها.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB_FOUND&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">ZLIB::ZLIB&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-fetchcontent-التحميل-من-المصدر-والدمج">5.2. FetchContent (التحميل من المصدر والدمج)
&lt;/h3>&lt;p>تم تقديم هذه الوحدة في CMake 3.11، وأصبحت أقوى منذ 3.14. تقوم هذه الوحدة بتنزيل التعليمات البرمجية المصدرية مباشرة من مستودع Git أو رابط URL خارجي أثناء وقت البناء، وتقوم ببنائها مع المشروع كجزء منه. وبما أنه يمكن إدارة التبعيات مركزيًا، فإنه يوفر مستوى عاليًا جدًا من قابلية إعادة الإنتاج عبر المنصات المختلفة.&lt;/p>
&lt;p>فيما يلي مثال على إدراج GoogleTest باستخدام FetchContent:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">FetchContent&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">FetchContent_Declare&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">googletest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_REPOSITORY&lt;/span> &lt;span class="s">https://github.com/google/googletest.git&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_TAG&lt;/span> &lt;span class="s">v1.14.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># توفير المكتبة للمشروع
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">FetchContent_MakeAvailable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">googletest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># إنشاء ملف تنفيذي للاختبار وربطه
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">test/main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-التكامل-مع-vcpkg">5.3. التكامل مع vcpkg
&lt;/h3>&lt;p>باستخدام &lt;strong>vcpkg&lt;/strong>، وهو مدير حزم لـ C++ تديره Microsoft، يمكنك بسهولة إدراج الآلاف من المكتبات. تم تصميم vcpkg ليتكامل بسلاسة مع CMake.&lt;/p>
&lt;p>عند تشغيل CMake، ما عليك سوى تحديد ملف أداة السلسلة (Toolchain) الخاص بـ vcpkg، وسيؤدي ذلك إلى جعل &lt;code>find_package&lt;/code> يبحث تلقائيًا عن المكتبات داخل vcpkg.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE&lt;span class="o">=&lt;/span>/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>علاوة على ذلك، من خلال وضع &lt;code>vcpkg.json&lt;/code> (وضع البيان Manifest Mode) في جذر المشروع، يمكنك أتمتة إدارة إصدارات المكتبات المطلوبة بالكامل.&lt;/p>
&lt;h2 id="6-علامات-المترجم-للتعامل-مع-الأنظمة-المتعددة-المنصات-cross-platform-compiler-flags">6. علامات المترجم للتعامل مع الأنظمة المتعددة المنصات (Cross-Platform Compiler Flags)
&lt;/h2>&lt;p>لتجاوز البناء في بيئات مثل Windows (MSVC) و Linux (GCC/Clang) و macOS (Apple Clang)، من الضروري تعيين العلامات الخاصة بالمترجم بشكل صحيح.&lt;/p>
&lt;p>باستخدام &lt;strong>تعبيرات المولد (Generator Expressions)&lt;/strong> الخاصة بـ CMake، يمكنك كتابة تفريعات شرطية بشكل تصريحي، مثل &amp;ldquo;إذا كان المترجم هو MSVC، استخدم هذه العلامة، وإلا استخدم تلك&amp;rdquo;. تستخدم تعبيرات المولد صيغة &lt;code>$&amp;lt;...&amp;gt;&lt;/code> ويتم تقييمها في مرحلة توليد نظام البناء (مرحلة Generate).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># مثال على تمكين أعلى مستوى من التحذيرات على جميع المنصات
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># في حالة MSVC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;CXX_COMPILER_ID:MSVC&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">:/W4&lt;/span> &lt;span class="s">/WX&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># في حالة GCC أو Clang
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;OR:$&amp;lt;CXX_COMPILER_ID:GNU&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:Clang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:AppleClang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;gt;:-Wall&lt;/span> &lt;span class="s">-Wextra&lt;/span> &lt;span class="s">-Wpedantic&lt;/span> &lt;span class="s">-Werror&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>باستخدام هذه الطريقة، تتجنب الإفراط في استخدام التفريعات الشرطية مثل &lt;code>if(MSVC)&lt;/code> التي تجعل &lt;code>CMakeLists.txt&lt;/code> صعب القراءة، وتتيح إعدادات مرنة لكل هدف على حدة.&lt;/p>
&lt;h2 id="7-إعداد-بيئة-الاختبار-ctest">7. إعداد بيئة الاختبار (CTest)
&lt;/h2>&lt;p>يعد إدخال الاختبارات الآلية أمرًا ضروريًا لضمان الجودة في البيئات متعددة المنصات. يأتي CMake مزودًا بمشغل اختبارات يُدعى &lt;strong>CTest&lt;/strong> بشكل افتراضي.&lt;/p>
&lt;p>إليك خطوات دمج GoogleTest، الذي تم إدراجه مسبقًا عبر &lt;code>FetchContent&lt;/code>، مع CTest:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># تفعيل ميزة الاختبار (يُكتب مرة واحدة في ملف CMakeLists.txt الجذري)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">test/math_test.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span> &lt;span class="s">MyLib&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تسجيل كاختبار في CTest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">GoogleTest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">gtest_discover_tests&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بعد البناء، ما عليك سوى تنفيذ الأمر &lt;code>ctest&lt;/code> داخل دليل البناء، وسيتم تشغيل جميع الاختبارات والإبلاغ عن النتائج.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ctest --output-on-failure -C Release
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-النظرية-والنماذج-الرياضية-لأنظمة-البناء">8. النظرية والنماذج الرياضية لأنظمة البناء
&lt;/h2>&lt;p>دعونا نغير المنظور قليلًا وندرس نظام البناء وكفاءة الترجمة المتوازية في المشاريع الكبيرة باستخدام نماذج رياضية.&lt;/p>
&lt;p>تقليل وقت البناء (وقت الترجمة) هو التحدي الأبدي في تطوير C++. يمكن تقليل وقت البناء من خلال تقسيم التعليمات البرمجية المصدرية والترجمة المتوازية. يتم نمذجة هذا التسريع (Speedup) الناتج عن التوازي باستخدام &lt;strong>قانون أمدال (Amdahl&amp;rsquo;s Law)&lt;/strong>.&lt;/p>
&lt;p>إذا افترضنا أن نسبة الجزء القابل للتوازي من البرنامج هي $P$، ونسبة الجزء الذي يجب تنفيذه تسلسليًا (غير القابل للتوازي) هي $1-P$، وأن عدد المعالجات المستخدمة هو $N$، فإن الحد الأقصى النظري لنسبة التسريع الإجمالية $S(N)$ يُعبر عنه بالمعادلة التالية:&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>في عملية بناء C++، تكون عملية &amp;ldquo;ترجمة كل ملف &lt;code>.cpp&lt;/code> إلى &lt;code>.o&lt;/code> أو &lt;code>.obj&lt;/code>&amp;rdquo; مستقلة وقابلة للتوازي (وهي تمثل الجزء $P$)، بينما &amp;ldquo;عملية الدمج النهائية بواسطة الرابط (Linker)&amp;rdquo; تتم بشكل تسلسلي أساسي (وهي تمثل الجزء $1-P$).&lt;/p>
&lt;p>لذلك، مهما زاد عدد نوى وحدة المعالجة المركزية (CPU) المُجهزة ($N \to \infty$)، طالما أن عنق الزجاجة المتمثل في وقت الربط موجود، فإن الحد الأقصى لنسبة التسريع سيقترب من المعادلة التالية:&lt;/p>
$$ \lim_{N \to \infty} S(N) = \frac{1}{1 - P} $$
&lt;p>ما تشير إليه هذه المعادلة هو أن &amp;ldquo;هناك حدود لتقليل وقت البناء بمجرد زيادة نوى وحدة المعالجة المركزية&amp;rdquo;. إن الاستخدام السليم لـ &lt;code>PRIVATE&lt;/code> و &lt;code>INTERFACE&lt;/code> في Modern CMake لتقليل تبعيات ملفات الترويسة إلى الحد الأدنى (مثل استخدام التصريحات الأمامية Forward Declarations)، وبالتالي زيادة نسبة $P$ وتقليل الأجزاء التي تحتاج إلى إعادة الترجمة أثناء البناء التزايدي (Incremental Build)، هو استراتيجية تسريع البناء الأكثر فعالية عمليًا.&lt;/p>
&lt;p>بالإضافة إلى ذلك، لتقليل وقت الربط، من المهم التبديل من المكتبات الثابتة (Static Libraries) إلى المكتبات المشتركة / DLL (Shared Libraries)، أو استخدام روابط سريعة مثل LLD / Mold.&lt;/p>
&lt;p>في CMake، يمكنك تحديد الرابط بسهولة كما يلي:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># إعداد لاستخدام رابط lld في بيئة Clang/GCC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">UNIX&lt;/span> &lt;span class="s">AND&lt;/span> &lt;span class="s">NOT&lt;/span> &lt;span class="s">APPLE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s2">&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-مثال-عملي-على-هياكل-الأدلة-المعقدة">9. مثال عملي على هياكل الأدلة المعقدة
&lt;/h2>&lt;p>في تطوير التطبيقات الفعلية، يكون هيكل الدليل مزيجًا من العديد من الوحدات (Modules). أخيرًا، سنعرض الهيكل المثالي لدليل مشروع متوسط الحجم والعلاقة بين ملفات &lt;code>CMakeLists.txt&lt;/code> للأب والابن.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ProjectRoot/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── CMakeLists.txt (الجذر: تعريف المشروع بالكامل)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── vcpkg.json (تعريف المكتبات التابعة)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── external/ (الوحدات الخارجية)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── include/ (الترويسات العامة)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── myapp/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── src/ (التعليمات البرمجية المصدرية وتعريفات البناء الداخلية)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── main.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── math/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── Vector3.hpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── Vector3.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── network/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── NetworkManager.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── tests/ (أكواد الاختبار)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── math_test.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ملف &lt;code>CMakeLists.txt&lt;/code> في الجذر يقوم فقط بإعداد البيئة وتعريف الخيارات العامة، ويضيف الأدلة الفرعية باستخدام &lt;code>add_subdirectory()&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Root &lt;code>CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># الإعدادات العامة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># تفعيل الاختبارات
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># إضافة الأدلة الفرعية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">src&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">tests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>&lt;code>src/CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># إضافة كل وحدة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">network&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># الملف التنفيذي النهائي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ربط الوحدات
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">MathLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">NetworkLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>من خلال تقسيم &lt;code>CMakeLists.txt&lt;/code> لكل دليل بهذه الطريقة وتحديدها كتابعيات بين الأهداف، تزداد قابلية إعادة الاستخدام للوحدات وتتحسن وتيرة التوازي في البناء. هذا هو الجوهر الحقيقي &amp;ldquo;لبيئة البناء القائمة على الوحدات&amp;rdquo; التي يدعو إليها Modern CMake.&lt;/p>
&lt;h2 id="10-الخلاصة">10. الخلاصة
&lt;/h2>&lt;p>لقد شرحنا خطوات إعداد بيئة بناء C++ متعددة المنصات باستخدام CMake.
دعونا نراجع النقاط الرئيسية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>فهم نظام البناء الوصفي (Meta-Build System)&lt;/strong>: أداة CMake هي أداة لتوليد نصوص البناء.&lt;/li>
&lt;li>&lt;strong>التزام نهج Modern CMake&lt;/strong>: عدم استخدام المتغيرات، بل تغليف الإعدادات بنهج &lt;strong>موجه نحو الهدف (Target-Oriented)&lt;/strong> باستخدام وظائف مثل &lt;code>add_executable&lt;/code> و &lt;code>target_link_libraries&lt;/code> و &lt;code>target_include_directories&lt;/code>.&lt;/li>
&lt;li>&lt;strong>التعيين السليم للنطاق (Scope)&lt;/strong>: الاستخدام الصحيح لـ &lt;code>PUBLIC&lt;/code> و &lt;code>PRIVATE&lt;/code> و &lt;code>INTERFACE&lt;/code> للتحكم في امتداد التبعيات.&lt;/li>
&lt;li>&lt;strong>التزام البناء خارج المصدر (Out-of-source Build)&lt;/strong>: إجراء البناء داخل دليل &lt;code>build/&lt;/code> وعدم تلويث شجرة المصدر.&lt;/li>
&lt;li>&lt;strong>تكامل الطرف الثالث&lt;/strong>: أتمتة حل المكتبات التابعة باستخدام &lt;code>FetchContent&lt;/code> و &lt;code>vcpkg&lt;/code>.&lt;/li>
&lt;li>&lt;strong>الاستفادة من تعبيرات المولد (Generator Expressions)&lt;/strong>: استيعاب الفروق الذكية في علامات كل مترجم.&lt;/li>
&lt;li>&lt;strong>النهج الرياضي&lt;/strong>: الوعي بقانون أمدال لتقليل التبعيات وزيادة كفاءة الترجمة المتوازية.&lt;/li>
&lt;/ol>
&lt;p>قد يبدو CMake معقدًا في البداية، ولكن بمجرد أن تفهم مفهوم الأهداف والخصائص، يمكنك الحفاظ على بيئة بناء منظمة مهما كان مشروع C++ معقدًا أو ضخمًا. نأمل أن تستخدم هذا المقال كمرجع لإعداد بيئة تطوير C++ باستخدام أحدث صياغات Modern CMake.&lt;/p></description></item></channel></rss>