ادغام سیستم‌های ساخت سفارشی C/C++‎ بااستفاده از Ninja (آزمایشی)

If you don't use CMake or ndk-build but want full integration of the Android Gradle plugin (AGP) C/C++ build and Android Studio, you can create a custom C/C++ build system by making a shell script that writes build information in the Ninja build file format.

پشتیبانی آزمایشی از سیستم‌های ساخت سفارشی C/C++‎ به Android Studio و AGP اضافه شده است. این ویژگی از Android Studio Dolphin | 2021.3.1 Canary 4 دردسترس است.

نمای کلی

الگوی رایج برای پروژه‌های C/C++‎، به‌ویژه آن‌هایی که چندین پلاتفرم را هدف قرار می‌دهند، تولید پروژه‌هایی برای هریک از آن پلاتفرم‌ها ازطریق برخی‌از نمایش‌های اساسی است. نمونه برجسته‌ای از این الگو CMake است. ‫CMake می‌تواند پروژه‌هایی برای Android،‏ iOS، و دیگر پلاتفرم‌ها از یک نمایش زیربنایی واحد تولید کند که در فایل CMakeLists.txt ذخیره شده است.

درحالی‌که CMake مستقیماً توسط AGP پشتیبانی می‌شود، تولیدکننده‌های پروژه دیگری نیز وجود دارند که مستقیماً پشتیبانی نمی‌شوند:

این نوع تولیدکننده‌های پروژه یا از Ninja به‌عنوان نمایش پس‌بک ساخت C/C++‎ پشتیبانی می‌کنند یا می‌توانند برای تولید Ninja به‌عنوان نمایش پس‌بک سازگار شوند.

وقتی پروژه AGP با تولیدکننده سیستم پروژه C/C++‎ ادغام‌شده به‌درستی پیکربندی شود، کاربران می‌توانند:

  • ساختن از خط فرمان و «استودیو Android».

  • منابع را با پشتیبانی کامل از سرویس زبان (برای مثال، رفتن به تعریف) در Android Studio ویرایش کنید.

  • استفاده کردن از اشکال‌زداهای «استودیو Android» برای اشکال‌زدایی فرایندهای ترکیبی و بومی.

نحوه اصلاح ساخت برای استفاده از دستورگان پیکربندی ساخت C/C++ سفارشی

این بخش مراحل استفاده از اسکریپت پیکربندی ساخت سفارشی C/C++‎ از AGP را شرح می‌دهد.

مرحله ۱: فایل build.gradle در سطح ماژول را برای ارجاع به اسکریپت پیکربندی اصلاح کنید

برای فعال کردن پشتیبانی Ninja در AGP،‏ experimentalProperties را در فایل build.gradle در سطح ماژول پیکربندی کنید:

android {
  defaultConfig {
    externalNativeBuild {
      experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
      experimentalProperties["ninja.path"] = "source-file-list.txt"
      experimentalProperties["ninja.configure"] = "configure-ninja"
      experimentalProperties["ninja.arguments"] = [
            "\${ndk.moduleMakeFile}",
            "--variant=\${ndk.variantName}",
            "--abi=Android-\${ndk.abi}",
            "--configuration-dir=\${ndk.configurationDir}",
            "--ndk-version=\${ndk.moduleNdkVersion}",
            "--min-sdk-version=\${ndk.minSdkVersion}"
       ]
     }
   }

این ویژگی‌ها توسط AGP به‌صورت زیر تفسیر می‌شوند:

  • ‫ninja.abiFilters فهرستی از رابط‌های دودویی نرم‌افزار برای ساخت است. مقادیر معتبر عبارتند از: x86، x86-64، armeabi-v7a، و arm64-v8a.

  • ninja.path مسیری به فایل پروژه C/C++‎ است. قالب این فایل می‌تواند هر چیزی که می‌خواهید باشد. تغییرات در این فایل باعث ایجاد پیام‌واره‌ای برای همگام‌سازی Gradle در Android Studio می‌شود.

  • ninja.configure مسیری به فایل اسکریپت است که توسط Gradle اجرا خواهد شد وقتی که پیکربندی پروژه C/C++‎ لازم باشد. پروژه در اولین ساخت، درطول همگام‌سازی Gradle در Android Studio، یا زمانی که یکی از ورودی‌های اسکریپت پیکربندی تغییر می‌کند، پیکربندی می‌شود.

  • ninja.arguments فهرستی از متغیرهای مستقل است که به اسکریپت تعریف‌شده توسط ninja.configure ارسال خواهد شد. عناصر موجود در این فهرست می‌توانند به مجموعه‌ای از ماکروها ارجاع دهند که مقادیر آن‌ها به بافت پیکربندی فعلی در AGP بستگی دارد:

    • ${ndk.moduleMakeFile} مسیر کامل فایل ninja.configure است. بنابراین در این مثال، C:\path\to\configure-ninja.bat خواهد بود.

    • ${ndk.variantName} نام نسخه AGP فعلی است که درحال ساخت است. برای مثال، اشکال‌زدایی یا انتشار.

    • ${ndk.abi} نام AGP ABI فعلی است که درحال ساخت است. برای مثال، x86 یا arm64-v8a.

    • ${ndk.buildRoot} نام پوشه‌ای است که توسط AGP تولید شده است و نوشتار خروجی خود را در آن می‌نویسد. جزئیات این موضوع در مرحله ۲: ایجاد دستورگان پیکربندی توضیح داده خواهد شد.

    • ${ndk.ndkVersion} نسخه NDK است که باید استفاده شود. این معمولاً مقداری است که به android.ndkVersion در فایل build.gradle ارسال می‌شود یا مقدار پیش‌فرض است اگر هیچ مقداری وجود نداشته باشد.

    • ${ndk.minPlatform} حداقل پلاتفرم Android هدف است که AGP درخواست کرده است.

  • ninja.targets فهرستی از اهداف Ninja خاص است که باید ساخته شود.

مرحله ۲: ساختن اسکریپت پیکربندی

حداقل مسئولیت اسکریپت پیکربندی (configure-ninja.bat در مثال قبلی) تولید فایل build.ninja است که وقتی با Ninja ساخته می‌شود، همه بروندادهای بومی پروژه را کامپایل و پیوند خواهد کرد. معمولاً این فایل‌ها از نوع .o (شیء)، .a (بایگانی)، و .so (شیء مشترک) هستند.

اسکریپت پیکربندی می‌تواند فایل build.ninja را در دو مکان مختلف بنویسد که به نیازهای شما بستگی دارد.

  • اگر AGP بتواند مکان را انتخاب کند، اسکریپت پیکربندی build.ninja را در مکان تنظیم‌شده در ماکرو ${ndk.buildRoot} می‌نویسد.

  • اگر اسکریپت پیکربندی باید مکان فایل build.ninja را انتخاب کند، فایلی با نام build.ninja.txt را نیز در مکان تنظیم‌شده در ماکرو ${ndk.buildRoot} می‌نویسد. این فایل حاوی مسیر کامل به فایل build.ninja است که اسکریپت پیکربندی نوشته است.

ساختار فایل build.ninja

به‌طورکلی، اکثر ساختارهایی که به‌درستی ساخت Android C/C++‎ را نشان می‌دهند، کار خواهند کرد. عناصر کلیدی موردنیاز AGP و «استودیو Android» عبارت‌اند از:

  • فهرست فایل‌های منبع C/C++‎ به‌همراه پرچم‌های موردنیاز Clang برای کامپایل کردن آن‌ها.

  • فهرست کتابخانه‌های برونداد. این فایل‌ها معمولاً .so (شیء هم‌رسانی‌شده) هستند اما می‌توانند .a (بایگانی) یا اجرایی (بدون پسوند) نیز باشند.

اگر به نمونه‌هایی از نحوه تولید فایل build.ninja نیاز دارید، می‌توانید به خروجی CMake هنگام استفاده از تولیدکننده build.ninja نگاه کنید.

در اینجا نمونه‌ای از الگوی build.ninja حداقلی آورده شده است.

rule COMPILE
   command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

build source.o : COMPILE source.cpp
build lib.so : LINK source.o

توصیه‌ها

علاوه‌بر الزامات (فهرست فایل‌های منبع و کتابخانه‌های خروجی)، در اینجا چند توصیه ارائه شده است.

اعلام خروجی‌های نام‌گذاری‌شده با قوانین phony

درصورت امکان، توصیه می‌شود که ساختار build.ninja از قوانین phony استفاده کند تا به خروجی‌های ساخت نام‌های قابل‌خواندن برای انسان بدهد. بنابراین، برای مثال، اگر خروجی‌ای به‌نام c:/path/to/lib.so دارید، می‌توانید نامی قابل‌خواندن برای انسان به‌صورت زیر به آن بدهید.

build curl: phony /path/to/lib.so

مزیت انجام این کار این است که می‌توانید این نام را به‌عنوان هدف ساخت در فایل build.gradle مشخص کنید. برای مثال:

android {
  defaultConfig {
    externalNativeBuild {
      ...
      experimentalProperties["ninja.targets"] = [ "curl" ]

مشخص کردن هدف «همه»

وقتی هدف all را مشخص می‌کنید، این مجموعه پیش‌فرض کتابخانه‌های ساخته‌شده توسط AGP خواهد بود وقتی هیچ هدفی به‌طور صریح در فایل build.gradle مشخص نشده باشد.

rule COMPILE
   command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so

روش ساخت جایگزین را مشخص کنید (اختیاری)

یک مورد استفاده پیشرفته‌تر، پیچیدن یک سیستم ساخت موجود است که Ninja نیست مبتنی بر. در این حالت، همچنان باید همه منابع را با پرچم‌هایشان به‌همراه کتابخانه‌های خروجی نشان دهید تا «استودیو Android» بتواند ویژگی‌های مناسب سرویس زبان مانند تکمیل خودکار و رفتن به تعریف را ارائه دهد. اما می‌خواهید AGP درطول ساخت واقعی به سیستم ساخت زیربنایی واگذار کند.

برای انجام این کار، می‌توانید از خروجی ساخت Ninja با افزونه خاصی .passthrough استفاده کنید.

به‌عنوان مثالی ملموس‌تر، برای پیچیدن MSBuild، اسکریپت پیکربندی شما build.ninja را طبق معمول تولید می‌کند، اما یک هدف عبوری نیز اضافه می‌کند که نحوه فراخوانی MSBuild توسط AGP را تعریف می‌کند.

rule COMPILE
   command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
   command = /path/to/ndk/clang $in -o $out {other flags}

rule MBSUILD_CURL
  command = /path/to/msbuild {flags to build curl with MSBuild}

build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL

ارائه بازخورد

این ویژگی آزمایشی است، بنابراین از بازخورد شما بسیار سپاس‌گزاریم. می‌توانید ازطریق کانال‌های زیر بازخورد ارائه دهید:

  • برای بازخورد کلی، نظری به اشکال مربوطه اضافه کنید.

  • برای گزارش کردن اشکال، Android Studio را باز کنید و روی راهنما > ارسال بازخورد کلیک کنید. حتماً به «سیستم‌های ساخت سفارشی C/C++» ارجاع دهید تا به هدایت اشکال کمک کنید.

  • برای گزارش کردن اشکال درصورت نصب نبودن «استودیو Android»، بااستفاده از الگوی اشکال اشکال را ثبت کنید.