এমস্ক্রিপ্টেন এবং এনপিএম

আপনি কিভাবে এই সেটআপে WebAssembly একত্রিত করবেন? এই নিবন্ধে আমরা উদাহরণ হিসেবে C/C++ এবং Emscripten-এর সাথে এটি কাজ করতে যাচ্ছি।

WebAssembly (wasm) প্রায়ই হয় একটি পারফরম্যান্স আদিম বা ওয়েবে আপনার বিদ্যমান C++ কোডবেস চালানোর উপায় হিসাবে তৈরি করা হয়। squoosh.app এর মাধ্যমে, আমরা দেখাতে চেয়েছিলাম যে wasm-এর জন্য অন্তত একটি তৃতীয় দৃষ্টিকোণ রয়েছে: অন্যান্য প্রোগ্রামিং ভাষার বিশাল ইকোসিস্টেম ব্যবহার করা। Emscripten-এর সাথে, আপনি C/C++ কোড ব্যবহার করতে পারেন, মরিচা বিল্ট ইন রয়েছে , এবং Go টিমও এতে কাজ করছে । আমি নিশ্চিত যে অন্যান্য অনেক ভাষা অনুসরণ করবে।

এই পরিস্থিতিতে, wasm আপনার অ্যাপের কেন্দ্রবিন্দু নয়, বরং একটি ধাঁধার অংশ: অন্য একটি মডিউল। আপনার অ্যাপে ইতিমধ্যেই জাভাস্ক্রিপ্ট, সিএসএস, ইমেজ অ্যাসেট, একটি ওয়েব-কেন্দ্রিক বিল্ড সিস্টেম এবং এমনকি প্রতিক্রিয়ার মতো ফ্রেমওয়ার্কও রয়েছে। আপনি কিভাবে এই সেটআপে WebAssembly একত্রিত করবেন? এই নিবন্ধে আমরা উদাহরণ হিসেবে C/C++ এবং Emscripten-এর সাথে এটি কাজ করতে যাচ্ছি।

ডকার

এমস্ক্রিপ্টেনের সাথে কাজ করার সময় আমি ডকারকে অমূল্য বলে খুঁজে পেয়েছি। C/C++ লাইব্রেরিগুলি প্রায়ই যে অপারেটিং সিস্টেমে তৈরি করা হয় তার সাথে কাজ করার জন্য লেখা হয়। একটি সামঞ্জস্যপূর্ণ পরিবেশ থাকা অবিশ্বাস্যভাবে সহায়ক। ডকারের সাথে আপনি একটি ভার্চুয়ালাইজড লিনাক্স সিস্টেম পাবেন যা ইতিমধ্যেই এমস্ক্রিপ্টেনের সাথে কাজ করার জন্য সেট আপ করা হয়েছে এবং সমস্ত সরঞ্জাম এবং নির্ভরতা ইনস্টল করা আছে। যদি কিছু অনুপস্থিত থাকে তবে এটি আপনার নিজের মেশিন বা আপনার অন্যান্য প্রকল্পগুলিকে কীভাবে প্রভাবিত করে সে সম্পর্কে চিন্তা না করেই আপনি এটি ইনস্টল করতে পারেন। কিছু ভুল হলে, পাত্রটি ফেলে দিন এবং আবার শুরু করুন। যদি এটি একবার কাজ করে, আপনি নিশ্চিত হতে পারেন যে এটি কাজ চালিয়ে যাবে এবং অভিন্ন ফলাফল দেবে।

ডকার রেজিস্ট্রিতে trzeci দ্বারা একটি Emscripten চিত্র রয়েছে যা আমি ব্যাপকভাবে ব্যবহার করছি।

npm এর সাথে ইন্টিগ্রেশন

বেশিরভাগ ক্ষেত্রে, একটি ওয়েব প্রজেক্টের এন্ট্রি পয়েন্ট হল npm-এর package.json । নিয়মানুযায়ী, অধিকাংশ প্রকল্প npm install && npm run build দিয়ে তৈরি করা যেতে পারে।

সাধারণভাবে, Emscripten (a .js এবং একটি .wasm ফাইল) দ্বারা উত্পাদিত বিল্ড আর্টিফ্যাক্টগুলিকে অন্য জাভাস্ক্রিপ্ট মডিউল এবং অন্য একটি সম্পদ হিসাবে বিবেচনা করা উচিত। JavaScript ফাইলটি ওয়েবপ্যাক বা রোলআপের মতো একটি বান্ডলার দ্বারা পরিচালনা করা যেতে পারে এবং wasm ফাইলটিকে চিত্রের মতো অন্য যেকোন বড় বাইনারি সম্পদের মতো বিবেচনা করা উচিত।

যেমন, আপনার "স্বাভাবিক" বিল্ড প্রক্রিয়া শুরু হওয়ার আগে Emscripten বিল্ড আর্টিফ্যাক্টগুলি তৈরি করা দরকার:

{
   
"name": "my-worldchanging-project",
   
"scripts": {
   
"build:emscripten": "docker run --rm -v $(pwd):/src trzeci/emscripten
./build.sh",
   
"build:app": "<the old build command>",
   
"build": "npm run build:emscripten && npm run build:app",
   
// ...
   
},
   
// ...
}

নতুন build:emscripten টাস্কটি সরাসরি এমস্ক্রিপ্টেনকে আমন্ত্রণ জানাতে পারে, তবে আগেই উল্লেখ করা হয়েছে, বিল্ড পরিবেশটি সামঞ্জস্যপূর্ণ কিনা তা নিশ্চিত করতে আমি ডকার ব্যবহার করার পরামর্শ দিই।

docker run ... trzeci/emscripten ./build.sh ডকারকে trzeci/emscripten ইমেজ ব্যবহার করে একটি নতুন কন্টেইনার স্পিন করতে এবং ./build.sh কমান্ড চালাতে বলে। build.sh একটি শেল স্ক্রিপ্ট যা আপনি পরবর্তী লিখতে যাচ্ছেন! --rm ডকারকে কন্টেইনারটি চালানোর পরে মুছে ফেলতে বলে। এইভাবে, আপনি সময়ের সাথে সাথে বাসি মেশিনের চিত্রগুলির একটি সংগ্রহ তৈরি করবেন না। -v $(pwd):/src অর্থ হল আপনি ডকারকে কন্টেইনারের ভিতরে /src এ বর্তমান ডিরেক্টরি ( $(pwd) ) কে "মিরর" করতে চান। কন্টেইনারের ভিতরে /src ডিরেক্টরির ফাইলগুলিতে আপনি যে কোনও পরিবর্তন করেন তা আপনার প্রকৃত প্রকল্পে মিরর করা হবে। এই মিরর করা ডিরেক্টরিগুলিকে "বাইন্ড মাউন্ট" বলা হয়।

আসুন build.sh এ একবার দেখে নেওয়া যাক:

#!/bin/bash

set -e

export OPTIMIZE="-Os"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CXXFLAGS="${OPTIMIZE}"

echo
"============================================="
echo
"Compiling wasm bindings"
echo
"============================================="
(
   
# Compile C/C++ code
    emcc
\
    $
{OPTIMIZE} \
   
--bind \
   
-s STRICT=1 \
   
-s ALLOW_MEMORY_GROWTH=1 \
   
-s MALLOC=emmalloc \
   
-s MODULARIZE=1 \
   
-s EXPORT_ES6=1 \
   
-o ./my-module.js \
    src
/my-module.cpp

   
# Create output folder
    mkdir
-p dist
   
# Move artifacts
    mv
my-module.{js,wasm} dist
)
echo
"============================================="
echo
"Compiling wasm bindings done"
echo
"============================================="

এখানে ব্যবচ্ছেদ করার অনেক কিছু আছে!

set -e শেলটিকে "fail fast" মোডে রাখে। যদি স্ক্রিপ্টের কোনো কমান্ড একটি ত্রুটি ফিরিয়ে দেয়, সমগ্র স্ক্রিপ্ট অবিলম্বে বাতিল হয়ে যায়। এটি অবিশ্বাস্যভাবে সহায়ক হতে পারে কারণ স্ক্রিপ্টের শেষ আউটপুট সর্বদা একটি সাফল্যের বার্তা বা ত্রুটি যা বিল্ডটিকে ব্যর্থ করে দেয়।

export বিবৃতি দিয়ে, আপনি কয়েকটি পরিবেশের ভেরিয়েবলের মান নির্ধারণ করেন। তারা আপনাকে C কম্পাইলার ( CFLAGS ), C++ কম্পাইলার ( CXXFLAGS ), এবং লিঙ্কার ( LDFLAGS ) এ অতিরিক্ত কমান্ড-লাইন পরামিতি পাস করার অনুমতি দেয়। তারা সবাই OPTIMIZE মাধ্যমে অপ্টিমাইজার সেটিংস গ্রহণ করে যাতে সবকিছু একইভাবে অপ্টিমাইজ করা হয় তা নিশ্চিত করতে। OPTIMIZE ভেরিয়েবলের জন্য কয়েকটি সম্ভাব্য মান রয়েছে:

  • -O0 : কোন অপটিমাইজেশন করবেন না। কোন ডেড কোড বাদ দেওয়া হয় না, এবং Emscripten জাভাস্ক্রিপ্ট কোডটি নির্গত করে না। ডিবাগ করার জন্য ভাল।
  • -O3 : পারফরম্যান্সের জন্য আক্রমনাত্মকভাবে অপ্টিমাইজ করুন।
  • -Os : একটি গৌণ মানদণ্ড হিসাবে কর্মক্ষমতা এবং আকারের জন্য আক্রমনাত্মকভাবে অপ্টিমাইজ করুন৷
  • -Oz : আকারের জন্য আক্রমনাত্মকভাবে অপ্টিমাইজ করুন, প্রয়োজনে কর্মক্ষমতা ত্যাগ করুন।

ওয়েবের জন্য, আমি বেশিরভাগই সুপারিশ করি -Os

emcc কমান্ডের নিজস্ব অগণিত বিকল্প রয়েছে। মনে রাখবেন যে emcc একটি "GCC বা clang এর মত কম্পাইলারদের জন্য ড্রপ-ইন প্রতিস্থাপন" বলে মনে করা হয়। তাই আপনি GCC থেকে জানেন এমন সমস্ত পতাকা সম্ভবত emcc দ্বারা প্রয়োগ করা হবে। -s পতাকা বিশেষ যে এটি আমাদেরকে বিশেষভাবে Emscripten কনফিগার করতে দেয়। Emscripten-এর settings.js এ সমস্ত উপলব্ধ বিকল্প পাওয়া যাবে, কিন্তু সেই ফাইলটি বেশ অপ্রতিরোধ্য হতে পারে। এখানে Emscripten পতাকাগুলির একটি তালিকা রয়েছে যা আমি মনে করি ওয়েব বিকাশকারীদের জন্য সবচেয়ে গুরুত্বপূর্ণ:

  • --bind এম্বিন্ড সক্ষম করে।
  • -s STRICT=1 ড্রপ সমর্থন সমস্ত অবচয়িত বিল্ড বিকল্পের জন্য। এটি নিশ্চিত করে যে আপনার কোড একটি ফরোয়ার্ড সামঞ্জস্যপূর্ণ পদ্ধতিতে তৈরি হয়।
  • -s ALLOW_MEMORY_GROWTH=1 প্রয়োজনে মেমরি স্বয়ংক্রিয়ভাবে বৃদ্ধি পেতে দেয়। লেখার সময়, Emscripten প্রাথমিকভাবে 16MB মেমরি বরাদ্দ করবে। যেহেতু আপনার কোড মেমরির অংশগুলি বরাদ্দ করে, এই বিকল্পটি সিদ্ধান্ত নেয় যে এই ক্রিয়াকলাপগুলি মেমরি নিঃশেষ হয়ে গেলে সমগ্র wasm মডিউলটিকে ব্যর্থ করে দেবে, বা যদি আঠালো কোডটি বরাদ্দের জন্য মোট মেমরি প্রসারিত করার অনুমতি দেয়।
  • -s MALLOC=... কোন malloc() বাস্তবায়ন ব্যবহার করতে হবে তা বেছে নেয়। emmalloc একটি ছোট এবং দ্রুত malloc() বাস্তবায়ন বিশেষভাবে Emscripten এর জন্য। বিকল্পটি হল dlmalloc , একটি সম্পূর্ণরূপে উন্নত malloc() বাস্তবায়ন। আপনি যদি ঘন ঘন অনেকগুলি ছোট বস্তু বরাদ্দ করেন বা আপনি যদি থ্রেডিং ব্যবহার করতে চান তবে আপনাকে শুধুমাত্র dlmalloc এ স্যুইচ করতে হবে।
  • -s EXPORT_ES6=1 জাভাস্ক্রিপ্ট কোডটিকে একটি ডিফল্ট এক্সপোর্ট সহ একটি ES6 মডিউলে পরিণত করবে যা যেকোনো বান্ডলারের সাথে কাজ করে। এছাড়াও -s MODULARIZE=1 সেট করা প্রয়োজন।

নিম্নলিখিত পতাকাগুলি সর্বদা প্রয়োজনীয় নয় বা শুধুমাত্র ডিবাগিং উদ্দেশ্যে সহায়ক:

  • -s FILESYSTEM=0 হল একটি পতাকা যা Emscripten এর সাথে সম্পর্কিত এবং এটি আপনার জন্য একটি ফাইল সিস্টেম অনুকরণ করার ক্ষমতা রাখে যখন আপনার C/C++ কোড ফাইল সিস্টেম অপারেশন ব্যবহার করে। এটি আঠালো কোডে ফাইলসিস্টেম এমুলেশন অন্তর্ভুক্ত করবে কি না তা সিদ্ধান্ত নিতে কম্পাইল করা কোডের উপর কিছু বিশ্লেষণ করে। কখনও কখনও, যাইহোক, এই বিশ্লেষণটি ভুল হতে পারে এবং আপনি একটি ফাইল সিস্টেম ইমুলেশনের জন্য অতিরিক্ত আঠালো কোডে একটি বরং মোটা 70kB প্রদান করেন যা আপনার প্রয়োজন নাও হতে পারে। -s FILESYSTEM=0 দিয়ে আপনি Emscripten কে এই কোডটি অন্তর্ভুক্ত না করতে বাধ্য করতে পারেন।
  • -g4 এমস্ক্রিপ্টেনকে .wasm এ ডিবাগিং তথ্য অন্তর্ভুক্ত করবে এবং wasm মডিউলের জন্য একটি সোর্স ম্যাপ ফাইল নির্গত করবে। আপনি তাদের ডিবাগিং বিভাগে Emscripten দিয়ে ডিবাগিং সম্পর্কে আরও পড়তে পারেন।

এবং সেখানে আপনি যান! এই সেটআপটি পরীক্ষা করার জন্য, আসুন একটি ছোট my-module.cpp চাবুক তৈরি করি:

    #include <emscripten/bind.h>

   
using namespace emscripten;

   
int say_hello() {
      printf
("Hello from your wasm module\n");
     
return 0;
   
}

    EMSCRIPTEN_BINDINGS
(my_module) {
      function
("sayHello", &say_hello);
   
}

এবং একটি index.html :

    <!doctype html>
   
<title>Emscripten + npm example</title>
    Open the console to see the output from the wasm module.
   
<script type="module">
   
import wasmModule from "./my-module.js";

   
const instance = wasmModule({
      onRuntimeInitialized
() {
        instance
.sayHello();
     
}
   
});
   
</script>

(এখানে সমস্ত ফাইল ধারণকারী একটি সারাংশ আছে।)

সবকিছু তৈরি করতে, চালান

$ npm install
$ npm run build
$ npm run serve

লোকালহোস্টে নেভিগেট করা:8080 আপনাকে DevTools কনসোলে নিম্নলিখিত আউটপুট দেখাবে:

DevTools C++ এবং Emscripten এর মাধ্যমে মুদ্রিত একটি বার্তা দেখাচ্ছে।

নির্ভরতা হিসাবে C/C++ কোড যোগ করা হচ্ছে

আপনি যদি আপনার ওয়েব অ্যাপের জন্য একটি C/C++ লাইব্রেরি তৈরি করতে চান, তাহলে আপনার প্রোজেক্টের অংশ হতে এর কোড প্রয়োজন। আপনি ম্যানুয়ালি আপনার প্রোজেক্টের রিপোজিটরিতে কোড যোগ করতে পারেন অথবা আপনি এই ধরনের নির্ভরতাগুলি পরিচালনা করতে npm ব্যবহার করতে পারেন। ধরা যাক আমি আমার ওয়েবঅ্যাপে libvpx ব্যবহার করতে চাই। libvpx হল একটি C++ লাইব্রেরি যা .webm ফাইলে ব্যবহৃত কোডেক VP8 দিয়ে ছবি এনকোড করার জন্য। যাইহোক, libvpx npm-এ নেই এবং একটি package.json নেই, তাই আমি সরাসরি npm ব্যবহার করে এটি ইনস্টল করতে পারছি না।

এই ধাঁধা থেকে বেরিয়ে আসার জন্য ন্যাপা আছে। napa আপনাকে আপনার node_modules ফোল্ডারে নির্ভরতা হিসাবে যেকোন গিট রিপোজিটরি URL ইনস্টল করার অনুমতি দেয়।

একটি নির্ভরতা হিসাবে napa ইনস্টল করুন:

$ npm install --save napa

এবং একটি ইনস্টল স্ক্রিপ্ট হিসাবে napa চালানো নিশ্চিত করুন:

{
// ...
"scripts": {
   
"install": "napa",
   
// ...
},
"napa": {
   
"libvpx": "git+https://github.com/webmproject/libvpx"
}
// ...
}

আপনি যখন npm install চালান, তখন napa libvpx GitHub সংগ্রহস্থলকে libvpx নামে আপনার node_modules এ ক্লোন করার যত্ন নেয়।

আপনি এখন libvpx তৈরি করতে আপনার বিল্ড স্ক্রিপ্ট প্রসারিত করতে পারেন। libvpx configure এবং make ব্যবহার করে। সৌভাগ্যবশত, Emscripten configure এবং Emscripten এর কম্পাইলার ব্যবহার নিশ্চিত make সাহায্য করতে পারে। এই উদ্দেশ্যে র‍্যাপার কমান্ড রয়েছে emconfigure এবং emmake :

# ... above is unchanged ...
echo
"============================================="
echo
"Compiling libvpx"
echo
"============================================="
(
    rm
-rf build-vpx || true
    mkdir build
-vpx
    cd build
-vpx
    emconfigure
../node_modules/libvpx/configure \
   
--target=generic-gnu
    emmake make
)
echo
"============================================="
echo
"Compiling libvpx done"
echo
"============================================="

echo
"============================================="
echo
"Compiling wasm bindings"
echo
"============================================="
# ... below is unchanged ...

AC/C++ লাইব্রেরি দুটি ভাগে বিভক্ত: শিরোনাম (ঐতিহ্যগতভাবে .h বা .hpp ফাইল) যা ডেটা স্ট্রাকচার, ক্লাস, কনস্ট্যান্ট ইত্যাদি সংজ্ঞায়িত করে যা একটি লাইব্রেরি প্রকাশ করে এবং প্রকৃত লাইব্রেরি (ঐতিহ্যগতভাবে .so বা .a ফাইল)। আপনার কোডে লাইব্রেরির VPX_CODEC_ABI_VERSION ধ্রুবক ব্যবহার করতে, আপনাকে #include স্টেটমেন্ট ব্যবহার করে লাইব্রেরির হেডার ফাইলগুলি অন্তর্ভুক্ত করতে হবে:

#include "vpxenc.h"
#include <emscripten/bind.h>

int say_hello() {
    printf
("Hello from your wasm module with libvpx %d\n", VPX_CODEC_ABI_VERSION);
   
return 0;
}

সমস্যা হল যে কম্পাইলার জানে না কোথায় vpxenc.h খুঁজতে হবে। এই -I পতাকা জন্য কি. এটি কম্পাইলারকে বলে যে হেডার ফাইলগুলির জন্য কোন ডিরেক্টরিগুলি পরীক্ষা করতে হবে। উপরন্তু, আপনাকে কম্পাইলারকে প্রকৃত লাইব্রেরি ফাইল দিতে হবে:

# ... above is unchanged ...
echo
"============================================="
echo
"Compiling wasm bindings"
echo
"============================================="
(
   
# Compile C/C++ code
    emcc
\
    $
{OPTIMIZE} \
   
--bind \
   
-s STRICT=1 \
   
-s ALLOW_MEMORY_GROWTH=1 \
   
-s ASSERTIONS=0 \
   
-s MALLOC=emmalloc \
   
-s MODULARIZE=1 \
   
-s EXPORT_ES6=1 \
   
-o ./my-module.js \
   
-I ./node_modules/libvpx \
    src
/my-module.cpp \
    build
-vpx/libvpx.a

# ... below is unchanged ...

যদি আপনি এখন npm run build চালান, আপনি দেখতে পাবেন যে প্রক্রিয়াটি একটি নতুন .js এবং একটি নতুন .wasm ফাইল তৈরি করে এবং ডেমো পৃষ্ঠাটি প্রকৃতপক্ষে ধ্রুবকটি আউটপুট করবে:

DevTools emscripten এর মাধ্যমে মুদ্রিত libvpx এর ABI সংস্করণ দেখানো হচ্ছে।

আপনি আরও লক্ষ্য করবেন যে বিল্ড প্রক্রিয়াটি দীর্ঘ সময় নেয়। দীর্ঘ নির্মাণ সময়ের কারণ পরিবর্তিত হতে পারে. libvpx এর ক্ষেত্রে, এটি একটি দীর্ঘ সময় নেয় কারণ এটি প্রতিবার আপনার বিল্ড কমান্ড চালানোর সময় VP8 এবং VP9 উভয়ের জন্য একটি এনকোডার এবং একটি ডিকোডার কম্পাইল করে, যদিও সোর্স ফাইলগুলি পরিবর্তিত হয়নি। এমনকি আপনার my-module.cpp এ একটি ছোট পরিবর্তন তৈরি হতে অনেক সময় লাগবে। libvpx-এর বিল্ড আর্টিফ্যাক্টগুলি প্রথমবার তৈরি হয়ে গেলে কাছাকাছি রাখা খুবই উপকারী হবে।

এটি অর্জন করার একটি উপায় হল পরিবেশ ভেরিয়েবল ব্যবহার করা।

# ... above is unchanged ...
eval $@

echo
"============================================="
echo
"Compiling libvpx"
echo
"============================================="
test
-n "$SKIP_LIBVPX" || (
    rm
-rf build-vpx || true
    mkdir build
-vpx
    cd build
-vpx
    emconfigure
../node_modules/libvpx/configure \
   
--target=generic-gnu
    emmake make
)
echo
"============================================="
echo
"Compiling libvpx done"
echo
"============================================="
# ... below is unchanged ...

(এখানে সমস্ত ফাইল ধারণকারী একটি সারাংশ আছে.)

eval কমান্ড আমাদের বিল্ড স্ক্রিপ্টে প্যারামিটার পাস করে পরিবেশ ভেরিয়েবল সেট করতে দেয়। যদি $SKIP_LIBVPX সেট করা থাকে (যেকোনো মানের জন্য) test কমান্ডটি libvpx নির্মাণ এড়িয়ে যাবে।

এখন আপনি আপনার মডিউল কম্পাইল করতে পারেন কিন্তু libvpx পুনর্নির্মাণ এড়িয়ে যান:

$ npm run build:emscripten -- SKIP_LIBVPX=1

বিল্ড পরিবেশ কাস্টমাইজ করা

কখনও কখনও লাইব্রেরি নির্মাণের জন্য অতিরিক্ত সরঞ্জামের উপর নির্ভর করে। যদি এই নির্ভরতাগুলি ডকার ইমেজ দ্বারা প্রদত্ত বিল্ড পরিবেশে অনুপস্থিত থাকে তবে আপনাকে সেগুলি নিজেই যুক্ত করতে হবে। একটি উদাহরণ হিসাবে, ধরা যাক আপনি ডক্সিজেন ব্যবহার করে libvpx এর ডকুমেন্টেশন তৈরি করতে চান। আপনার ডকার কন্টেইনারের ভিতরে ডক্সিজেন উপলব্ধ নয়, তবে আপনি apt ব্যবহার করে এটি ইনস্টল করতে পারেন।

আপনি যদি আপনার build.sh এ এটি করতে চান, আপনি যখনই আপনার লাইব্রেরি তৈরি করতে চান তখন আপনি ডক্সিজেন পুনরায় ডাউনলোড এবং পুনরায় ইনস্টল করবেন। এটি শুধুমাত্র অপব্যয় হবে না, তবে এটি অফলাইনে থাকাকালীন আপনার প্রকল্পে কাজ করা থেকেও বিরত থাকবে।

এখানে আপনার নিজস্ব ডকার ইমেজ তৈরি করা অর্থপূর্ণ। ডকার চিত্রগুলি একটি Dockerfile লিখে তৈরি করা হয় যা বিল্ডের পদক্ষেপগুলি বর্ণনা করে। ডকারফাইলগুলি বেশ শক্তিশালী এবং অনেকগুলি কমান্ড রয়েছে, তবে বেশিরভাগ সময় আপনি কেবল FROM , RUN এবং ADD ব্যবহার করে দূরে যেতে পারেন। এই ক্ষেত্রে:

FROM trzeci/emscripten

RUN apt
-get update && \
    apt
-get install -qqy doxygen

FROM এর সাথে, আপনি ঘোষণা করতে পারেন যে আপনি কোন ডকার ইমেজটি একটি প্রারম্ভিক পয়েন্ট হিসাবে ব্যবহার করতে চান। আমি একটি ভিত্তি হিসাবে trzeci/emscripten বেছে নিয়েছি — যে ছবিটি আপনি সব সময় ব্যবহার করছেন। RUN দিয়ে, আপনি ডকারকে কন্টেইনারের ভিতরে শেল কমান্ড চালানোর নির্দেশ দেন। এই কমান্ডগুলি কন্টেইনারে যাই হোক না কেন তা এখন ডকার চিত্রের অংশ। আপনি build.sh চালানোর আগে আপনার ডকার ইমেজ তৈরি করা হয়েছে এবং উপলব্ধ রয়েছে তা নিশ্চিত করতে, আপনাকে আপনার package.json কিছুটা সামঞ্জস্য করতে হবে:

{
   
// ...
   
"scripts": {
   
"build:dockerimage": "docker image inspect -f '.' mydockerimage || docker build -t mydockerimage .",
   
"build:emscripten": "docker run --rm -v $(pwd):/src mydockerimage ./build.sh",
   
"build": "npm run build:dockerimage && npm run build:emscripten && npm run build:app",
   
// ...
   
},
   
// ...
}

(এখানে সমস্ত ফাইল ধারণকারী একটি সারাংশ আছে.)

এটি আপনার ডকার ইমেজ তৈরি করবে, কিন্তু শুধুমাত্র যদি এটি এখনও নির্মিত না হয়। তারপর সবকিছু আগের মতোই চলে, কিন্তু এখন বিল্ড এনভায়রনমেন্টে doxygen কমান্ড উপলব্ধ রয়েছে, যার ফলে libvpx-এর ডকুমেন্টেশনও তৈরি হবে।

উপসংহার

এটি আশ্চর্যজনক নয় যে C/C++ কোড এবং npm একটি প্রাকৃতিক উপযুক্ত নয়, তবে আপনি কিছু অতিরিক্ত টুলিং এবং ডকার যে বিচ্ছিন্নতা প্রদান করে তা দিয়ে আপনি এটি বেশ স্বাচ্ছন্দ্যে কাজ করতে পারেন। এই সেটআপটি প্রতিটি প্রকল্পের জন্য কাজ করবে না, তবে এটি একটি শালীন সূচনা পয়েন্ট যা আপনি আপনার প্রয়োজনের জন্য সামঞ্জস্য করতে পারেন। যদি আপনার উন্নতি হয়, শেয়ার করুন.

পরিশিষ্ট: ডকার ইমেজ স্তর ব্যবহার করা

একটি বিকল্প সমাধান হ'ল ডকার এবং ক্যাশিংয়ের জন্য ডকারের স্মার্ট পদ্ধতির সাথে এই সমস্যাগুলির আরও এনক্যাপসুলেট করা। ডকার ধাপে ধাপে ডকারফাইলস চালায় এবং প্রতিটি ধাপের ফলাফলকে তার নিজস্ব একটি ছবি বরাদ্দ করে। এই মধ্যবর্তী চিত্রগুলিকে প্রায়ই "স্তর" বলা হয়। যদি একটি ডকারফাইলের একটি কমান্ড পরিবর্তিত না হয়, আপনি ডকারফাইলটি পুনরায় তৈরি করার সময় ডকার আসলে সেই পদক্ষেপটি পুনরায় চালাবে না। পরিবর্তে এটি শেষবার ইমেজ তৈরি করার সময় থেকে স্তরটি পুনরায় ব্যবহার করে।

পূর্বে, আপনি প্রতিবার আপনার অ্যাপ তৈরি করার সময় libvpx পুনর্নির্মাণ না করার জন্য আপনাকে কিছু প্রচেষ্টার মধ্য দিয়ে যেতে হয়েছিল। পরিবর্তে আপনি Docker এর ক্যাশিং প্রক্রিয়া ব্যবহার করার জন্য আপনার build.sh থেকে Dockerfile এ libvpx-এর জন্য বিল্ডিং নির্দেশাবলী সরাতে পারেন:

FROM trzeci/emscripten

RUN apt
-get update && \
    apt
-get install -qqy doxygen git && \
    mkdir
-p /opt/libvpx/build && \
    git clone https
://github.com/webmproject/libvpx /opt/libvpx/src
RUN cd
/opt/libvpx/build && \
    emconfigure
../src/configure --target=generic-gnu && \
    emmake make

(এখানে সমস্ত ফাইল ধারণকারী একটি সারাংশ আছে.)

মনে রাখবেন যে আপনাকে ম্যানুয়ালি git এবং ক্লোন libvpx ইনস্টল করতে হবে কারণ docker build চালানোর সময় আপনার বাইন্ড মাউন্ট নেই। একটি পার্শ্ব প্রতিক্রিয়া হিসাবে, নাপা আর প্রয়োজন নেই।