इस सेटअप में WebAssembly को कैसे इंटिग्रेट किया जाता है? इस लेख में, हम उदाहरण के तौर पर C/C++ और Emscripten का इस्तेमाल करके, इस प्रोसेस को पूरा करेंगे.
WebAssembly (wasm) को अक्सर परफ़ॉर्मेंस प्रिमिटिव या वेब पर अपने मौजूदा C++ कोडबेस को चलाने के तरीके के तौर पर फ़्रेम किया जाता है. squoosh.app की मदद से, हम यह दिखाना चाहते थे कि WASM के लिए कम से कम एक और तरीका है: अन्य प्रोग्रामिंग भाषाओं के बड़े नेटवर्क का इस्तेमाल करना. Emscripten की मदद से, C/C++ कोड का इस्तेमाल किया जा सकता है. साथ ही, Rust में पहले से ही wasm की सुविधा मौजूद है. Go टीम भी इस पर काम कर रही है. मुझे भरोसा है कि आने वाले समय में कई और भाषाओं में भी यह सुविधा उपलब्ध होगी.
इन स्थितियों में, wasm आपके ऐप्लिकेशन का मुख्य हिस्सा नहीं है, बल्कि यह एक पहेली का एक टुकड़ा है: एक और मॉड्यूल. आपके ऐप्लिकेशन में पहले से ही JavaScript, CSS, इमेज ऐसेट, वेब-केंद्रित बिल्ड सिस्टम, और शायद React जैसा फ़्रेमवर्क भी मौजूद है. इस सेटअप में WebAssembly को कैसे इंटिग्रेट किया जाता है? इस लेख में, हम उदाहरण के तौर पर C/C++ और Emscripten के साथ काम करेंगे.
Docker
मुझे Emscripten के साथ काम करते समय, Docker का इस्तेमाल बहुत मददगार लगा. C/C++ लाइब्रेरी को अक्सर उस ऑपरेटिंग सिस्टम के साथ काम करने के लिए लिखा जाता है जिस पर इन्हें बनाया गया है. एक जैसा एनवायरमेंट बनाए रखना बहुत मददगार होता है. Docker की मदद से, आपको वर्चुअलाइज़ किया गया Linux सिस्टम मिलता है. यह सिस्टम, Emscripten के साथ काम करने के लिए पहले से सेट अप होता है. साथ ही, इसमें सभी टूल और डिपेंडेंसी पहले से इंस्टॉल होती हैं. अगर कुछ मौजूद नहीं है, तो उसे आसानी से इंस्टॉल किया जा सकता है. इसके लिए, आपको यह चिंता करने की ज़रूरत नहीं है कि इससे आपकी मशीन या अन्य प्रोजेक्ट पर क्या असर पड़ेगा. अगर कोई गड़बड़ी होती है, तो कंटेनर को फेंक दें और फिर से शुरू करें. अगर यह एक बार काम करता है, तो आप भरोसा रखें कि यह काम करता रहेगा और एक जैसे नतीजे देगा.
Docker Registry में, trzeci की Emscripten इमेज है. इसका इस्तेमाल मैं काफ़ी समय से कर रहा हूं.
npm के साथ इंटिग्रेशन
ज़्यादातर मामलों में, किसी वेब प्रोजेक्ट का एंट्री पॉइंट npm का
package.json
होता है. आम तौर पर, ज़्यादातर प्रोजेक्ट npm install &&
npm run build
के साथ बनाए जा सकते हैं.
आम तौर पर, Emscripten से जनरेट किए गए बिल्ड आर्टफ़ैक्ट (.js
और .wasm
फ़ाइल) को किसी दूसरे JavaScript मॉड्यूल और किसी दूसरी एसेट के तौर पर ही माना जाना चाहिए. 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
टास्क, Emscripten को सीधे तौर पर शुरू कर सकता है. हालांकि, जैसा कि पहले बताया गया है, हमारा सुझाव है कि Docker का इस्तेमाल करें, ताकि यह पक्का किया जा सके कि बिल्ड एनवायरमेंट एक जैसा हो.
docker run ... trzeci/emscripten ./build.sh
, Docker को trzeci/emscripten
इमेज का इस्तेमाल करके नया कंटेनर बनाने और ./build.sh
कमांड चलाने के लिए कहता है.
build.sh
एक शेल स्क्रिप्ट है, जिसे आपको अगले चरण में लिखना है! --rm
, Docker को कंटेनर के बंद होने के बाद उसे मिटाने के लिए कहता है. इस तरह, समय के साथ मशीन इमेज का पुराना कलेक्शन नहीं बनता. -v $(pwd):/src
का मतलब है कि आपको Docker को कंटेनर में मौजूद मौजूदा डायरेक्ट्री ($(pwd)
) को /src
में "मिरर" करना है. कंटेनर में मौजूद /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
, शेल को "फ़ेल फ़ास्ट" मोड में डालता है. अगर स्क्रिप्ट में कोई निर्देश गड़बड़ी का मैसेज दिखाता है, तो पूरी स्क्रिप्ट तुरंत बंद हो जाती है. यह काफ़ी मददगार हो सकता है, क्योंकि स्क्रिप्ट का आखिरी आउटपुट हमेशा सफलता का मैसेज या वह गड़बड़ी होगी जिसकी वजह से बिल्ड पूरा नहीं हो पाया.
export
स्टेटमेंट की मदद से, कुछ एनवायरमेंट वैरिएबल की वैल्यू तय की जाती हैं. इनकी मदद से, C कंपाइलर (CFLAGS
), C++ कंपाइलर (CXXFLAGS
), और लिंकर (LDFLAGS
) को अन्य कमांड-लाइन पैरामीटर पास किए जा सकते हैं. इन सभी को OPTIMIZE
के ज़रिए ऑप्टिमाइज़र सेटिंग मिलती हैं, ताकि यह पक्का किया जा सके कि सभी चीज़ें एक ही तरह से ऑप्टिमाइज़ की जाएं. OPTIMIZE
वैरिएबल के लिए, ये वैल्यू हो सकती हैं:
-O0
: कोई ऑप्टिमाइज़ेशन न करें. इसमें कोई भी डेड कोड नहीं हटाया जाता. साथ ही, Emscripten, उत्सर्जित किए गए JavaScript कोड को छोटा भी नहीं करता. डीबग करने के लिए अच्छा है.-O3
: परफ़ॉर्मेंस को बेहतर बनाने के लिए, कैंपेन को ज़्यादा से ज़्यादा ऑप्टिमाइज़ करें.-Os
: परफ़ॉर्मेंस और साइज़ को दूसरे आधार के तौर पर ज़्यादा से ज़्यादा ऑप्टिमाइज़ करें.-Oz
: साइज़ को ज़्यादा से ज़्यादा ऑप्टिमाइज़ करें. इसके लिए, ज़रूरत पड़ने पर परफ़ॉर्मेंस को कम करें.
वेब के लिए, मेरा सुझाव है कि ज़्यादातर -Os
का इस्तेमाल करें.
emcc
कमांड के कई विकल्प होते हैं. ध्यान दें कि emcc को "GCC या clang जैसे कंपाइलर के लिए ड्रॉप-इन रिप्लेसमेंट" माना जाता है. इसलिए, GCC से आपको जो भी फ़्लैग पता हैं, वे सभी emcc में भी लागू किए जाएंगे. -s
फ़्लैग खास इसलिए है, क्योंकि इससे हमें Emscripten को खास तौर पर कॉन्फ़िगर करने की अनुमति मिलती है. Emscripten के settings.js
में सभी उपलब्ध विकल्प देखे जा सकते हैं. हालांकि, यह फ़ाइल बहुत बड़ी हो सकती है. यहां Emscripten के उन फ़्लैग की सूची दी गई है जो मुझे लगता है कि वेब डेवलपर के लिए सबसे ज़्यादा ज़रूरी हैं:
--bind
embind करने की सुविधा चालू करता है.-s STRICT=1
, अब उन सभी बिल्ड विकल्पों के साथ काम नहीं करता जो अब काम नहीं करते. इससे यह पक्का होता है कि आपका कोड, आने वाले समय में भी काम करता रहेगा.-s ALLOW_MEMORY_GROWTH=1
की मदद से, ज़रूरत पड़ने पर मेमोरी अपने-आप बढ़ जाती है. Emscripten, कोड लिखने के समय शुरुआत में 16 एमबी मेमोरी को ऐलोकेट करेगा. आपका कोड, मेमोरी के हिस्से को असाइन करता है. इस विकल्प से यह तय होता है कि मेमोरी खत्म होने पर, इन ऑपरेशन की वजह से क्या पूरा wasm मॉड्यूल काम करना बंद कर देगा या ग्लू कोड को असाइनमेंट के हिसाब से कुल मेमोरी बढ़ाने की अनुमति होगी.-s MALLOC=...
यह चुनता है किmalloc()
को किस तरह लागू करना है.emmalloc
, Emscripten के लिए खास तौर पर बनाया गया एक छोटा और तेज़malloc()
वर्शन है. इसके लिए,dlmalloc
का इस्तेमाल किया जा सकता है. यहmalloc()
को पूरी तरह से लागू करने का तरीका है. आपकोdlmalloc
पर सिर्फ़ तब स्विच करना होगा, जब आपको बार-बार बहुत सारे छोटे ऑब्जेक्ट असाइन करने हों या आपको थ्रेडिंग का इस्तेमाल करना हो.-s EXPORT_ES6=1
, JavaScript कोड को ES6 मॉड्यूल में बदल देगा. इसमें डिफ़ॉल्ट एक्सपोर्ट होगा, जो किसी भी बंडलर के साथ काम करता है. इसके लिए,-s MODULARIZE=1
को भी सेट करना ज़रूरी है.
नीचे दिए गए फ़्लैग हमेशा ज़रूरी नहीं होते या सिर्फ़ डीबग करने के लिए मददगार होते हैं:
-s FILESYSTEM=0
एक फ़्लैग है, जो Emscripten और फ़ाइल सिस्टम को एमुलेट करने की इसकी क्षमता से जुड़ा है. ऐसा तब होता है, जब आपका C/C++ कोड फ़ाइल सिस्टम के ऑपरेशन का इस्तेमाल करता है. यह उस कोड का कुछ विश्लेषण करता है जिसे यह कंपाइल करता है. इससे यह तय किया जाता है कि ग्लू कोड में फ़ाइल सिस्टम इम्यूलेशन को शामिल करना है या नहीं. हालांकि, कभी-कभी इस विश्लेषण में गड़बड़ी हो सकती है. ऐसे में, आपको फ़ाइल सिस्टम के ऐसे इम्यूलेशन के लिए 70 केबी का ज़्यादा ग्लू कोड देना पड़ सकता है जिसकी शायद आपको ज़रूरत न हो.-s FILESYSTEM=0
का इस्तेमाल करके, Emscripten को इस कोड को शामिल न करने के लिए मजबूर किया जा सकता है.-g4
से Emscripten,.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
localhost:8080 पर जाने पर, आपको DevTools कंसोल में यह आउटपुट दिखेगा:
C/C++ कोड को डिपेंडेंसी के तौर पर जोड़ना
अगर आपको अपने वेब ऐप्लिकेशन के लिए C/C++ लाइब्रेरी बनानी है, तो आपको उसका कोड अपने प्रोजेक्ट का हिस्सा बनाना होगा. अपने प्रोजेक्ट की रिपॉज़िटरी में कोड को मैन्युअल तरीके से जोड़ा जा सकता है. इसके अलावा, इस तरह की डिपेंडेंसी को मैनेज करने के लिए, npm का भी इस्तेमाल किया जा सकता है. मान लें कि मुझे अपने वेबऐप्लिकेशन में libvpx का इस्तेमाल करना है. libvpx, C++ लाइब्रेरी है, जो VP8 की मदद से इमेज को कोड में बदलती है. VP8, .webm
फ़ाइलों में इस्तेमाल किया जाने वाला कोडेक है.
हालांकि, libvpx npm पर मौजूद नहीं है और इसमें package.json
नहीं है. इसलिए, इसे सीधे npm का इस्तेमाल करके इंस्टॉल नहीं किया जा सकता.
इस समस्या से बचने के लिए, napa टूल का इस्तेमाल करें. इसकी मदद से, किसी भी git रिपॉज़िटरी यूआरएल को अपने node_modules
फ़ोल्डर में डिपेंडेंसी के तौर पर इंस्टॉल किया जा सकता है.
डिपेंडेंसी के तौर पर 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
और
make
, Emscripten के कंपाइलर का इस्तेमाल करें. इस काम के लिए, रैपर कमांड 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 ...
C/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
फ़ाइल बनती है. साथ ही, डेमो पेज पर कॉन्स्टेंट दिखेगा:
आपको यह भी पता चलेगा कि बिल्ड करने की प्रोसेस में काफ़ी समय लगता है. बिल्ड में लगने वाले समय की वजह अलग-अलग हो सकती है. 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
बिल्ड एनवायरमेंट को पसंद के मुताबिक बनाना
कभी-कभी लाइब्रेरी बनाने के लिए, अन्य टूल की ज़रूरत पड़ती है. अगर Docker इमेज से मिले बिल्ड एनवायरमेंट में ये डिपेंडेंसी मौजूद नहीं हैं, तो आपको उन्हें खुद जोड़ना होगा. उदाहरण के लिए, मान लें कि आपको doxygen का इस्तेमाल करके, libvpx का दस्तावेज़ भी बनाना है. Doxygen, आपके Docker कंटेनर में उपलब्ध नहीं है. हालांकि, इसे apt
का इस्तेमाल करके इंस्टॉल किया जा सकता है.
अगर आपको build.sh
में ऐसा करना है, तो लाइब्रेरी बनाने के लिए, आपको हर बार doxygen को फिर से डाउनलोड और इंस्टॉल करना होगा. ऐसा करना न सिर्फ़ बेकार होगा, बल्कि इससे ऑफ़लाइन होने पर भी प्रोजेक्ट पर काम नहीं किया जा सकेगा.
ऐसे में, अपनी Docker इमेज बनाना सही रहता है. Docker इमेज बनाने के लिए, Dockerfile
लिखा जाता है. इसमें इमेज बनाने के चरणों के बारे में बताया जाता है. Dockerfile काफ़ी बेहतरीन होते हैं और इनमें कई निर्देश होते हैं. हालांकि, ज़्यादातर मामलों में सिर्फ़ FROM
, RUN
, और ADD
का इस्तेमाल करके काम किया जा सकता है. इस मामले में:
FROM trzeci/emscripten
RUN apt-get update && \
apt-get install -qqy doxygen
FROM
का इस्तेमाल करके, यह तय किया जा सकता है कि शुरुआती बिंदु के तौर पर आपको किस Docker इमेज का इस्तेमाल करना है. मैंने trzeci/emscripten
को आधार के तौर पर चुना है — वह इमेज जिसका इस्तेमाल अब तक किया जा रहा है. RUN
का इस्तेमाल करके, Docker को कंटेनर में शेल कमांड चलाने का निर्देश दिया जाता है. इन निर्देशों से कंटेनर में जो भी बदलाव होते हैं वे अब Docker इमेज का हिस्सा बन जाते हैं. build.sh
को चलाने से पहले, यह पक्का करने के लिए कि आपकी Docker इमेज बन गई है और वह उपलब्ध है, आपको अपने 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",
// ...
},
// ...
}
(यहां सभी फ़ाइलों का खास ब्यौरा दिया गया है.)
इससे आपकी Docker इमेज बन जाएगी, लेकिन सिर्फ़ तब जब वह अब तक न बनी हो. इसके बाद, सब कुछ पहले की तरह ही चलता है. हालांकि, अब बिल्ड एनवायरमेंट में doxygen
कमांड उपलब्ध है. इसकी वजह से, libvpx का दस्तावेज़ भी बन जाएगा.
नतीजा
यह कोई आश्चर्य की बात नहीं है कि C/C++ कोड और npm एक साथ काम नहीं करते. हालांकि, Docker के कुछ अतिरिक्त टूल और अलग-अलग कंटेनर में काम करने की सुविधा का इस्तेमाल करके, इन दोनों को आसानी से साथ में काम कराया जा सकता है. यह सेटअप हर प्रोजेक्ट के लिए काम नहीं करेगा. हालांकि, यह एक अच्छा शुरुआती बिंदु है, जिसे अपनी ज़रूरतों के हिसाब से अडजस्ट किया जा सकता है. अगर आपको इसमें कोई सुधार करना है, तो कृपया शेयर करें.
परिशिष्ट: Docker इमेज लेयर का इस्तेमाल करना
इन समस्याओं को हल करने का एक और तरीका है, Docker और कैश मेमोरी के लिए Docker के स्मार्ट तरीके का इस्तेमाल करना. Docker, Dockerfiles को सिलसिलेवार तरीके से लागू करता है और हर चरण के नतीजे को अपनी इमेज असाइन करता है. इन इंटरमीडिएट इमेज को अक्सर "लेयर" कहा जाता है. अगर Dockerfile में कोई कमांड नहीं बदला है, तो Dockerfile को फिर से बनाते समय, Docker उस चरण को फिर से नहीं चलाएगा. इसके बजाय, वह पिछली बार इमेज बनाने के दौरान इस्तेमाल की गई लेयर का फिर से इस्तेमाल करता है.
पहले, ऐप्लिकेशन बनाने के दौरान हर बार libvpx को फिर से बनाने की ज़रूरत पड़ती थी. हालांकि, अब Docker के कैश मेमोरी से जुड़े तरीके का इस्तेमाल करने के लिए, libvpx को बनाने के निर्देशों को build.sh
से Dockerfile
में ले जाया जा सकता है:
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
को चलाते समय आपके पास
बाइंड माउंट नहीं होते. इस वजह से, अब आपको एनएपीए की ज़रूरत नहीं है.