คุณผสานรวม WebAssembly เข้ากับการตั้งค่านี้ได้อย่างไร ในบทความนี้ เราจะใช้ C/C++ และ Emscripten เป็นตัวอย่าง
WebAssembly (WASM) มักถูกมองว่าเป็นพื้นฐานด้านประสิทธิภาพหรือวิธีเรียกใช้ฐานโค้ด C++ ที่มีอยู่บนเว็บ squoosh.app สร้างขึ้นเพื่อแสดงให้เห็นว่า WASM มีมุมมองอย่างน้อย 3 มุมมอง ได้แก่ การใช้ระบบนิเวศขนาดใหญ่ของภาษาโปรแกรมอื่นๆ Emscripten ให้คุณใช้โค้ด C/C++ ได้ Rust มี WASM ในตัว และทีม Go ก็กำลังพัฒนาด้วย และเรามั่นใจว่าจะมีภาษาอื่นๆ ตามมาอีกมากมาย
ในกรณีเหล่านี้ wasm ไม่ใช่หัวใจหลักของแอป แต่เป็นชิ้นส่วนของปริศนาอีกชิ้นหนึ่ง แอปของคุณมี JavaScript, CSS, ชิ้นงานรูปภาพ, ระบบบิลด์ที่เน้นเว็บ และอาจรวมถึงเฟรมเวิร์กอย่าง React อยู่แล้ว คุณผสานรวม WebAssembly เข้ากับการตั้งค่านี้ได้อย่างไร ในบทความนี้ เราจะอธิบายเรื่องนี้โดยใช้ C/C++ และ Emscripten เป็นตัวอย่าง
Docker
เราพบว่า Docker มีประโยชน์อย่างยิ่งเมื่อทำงานกับ Emscripten ไลบรารี C/C++ มักเขียนขึ้นให้ทำงานร่วมกับระบบปฏิบัติการที่ใช้สร้าง การมีสภาพแวดล้อมที่สอดคล้องกันมีประโยชน์อย่างยิ่ง เมื่อใช้ Docker คุณจะได้รับระบบ Linux แบบเสมือนจริงที่ตั้งค่าให้ทำงานร่วมกับ Emscripten ไว้แล้ว รวมถึงมีเครื่องมือและไลบรารีที่ต้องพึ่งพาทั้งหมดติดตั้งไว้แล้ว หากมีบางอย่างขาดหายไป คุณก็แค่ติดตั้งได้โดยไม่ต้องกังวลว่าจะส่งผลต่อเครื่องหรือโปรเจ็กต์อื่นๆ ของคุณอย่างไร หากเกิดข้อผิดพลาด ให้ทิ้งคอนเทนเนอร์และเริ่มใหม่ หากใช้งานได้ 1 ครั้ง คุณจะมั่นใจได้ว่าระบบจะยังคงทำงานต่อไปและได้ผลลัพธ์เหมือนกัน
Docker Registry มีภาพ Emscripten โดย trzeci ที่เราใช้อยู่
การผสานรวมกับ npm
ในกรณีส่วนใหญ่ จุดแรกเข้าของโปรเจ็กต์เว็บคือ npm's
package.json
ตามธรรมเนียมแล้ว โปรเจ็กต์ส่วนใหญ่จะสร้างด้วย npm install &&
npm run build
ได้
โดยทั่วไปแล้ว คุณควรถือว่าอาร์ติแฟกต์การสร้างที่ Emscripten สร้างขึ้น (ไฟล์ .js
และ .wasm
) เป็นโมดูล JavaScript และชิ้นงานอีกชิ้นหนึ่ง ไฟล์ JavaScript สามารถจัดการโดยเครื่องมือรวมไฟล์ เช่น webpack หรือ rollup และไฟล์ 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
ใส่เชลล์ไว้ในโหมด "Fail Fast" หากคําสั่งใดในสคริปต์แสดงข้อผิดพลาด ระบบจะยกเลิกสคริปต์ทั้งรายการทันที ซึ่งมีประโยชน์อย่างยิ่งเนื่องจากเอาต์พุตสุดท้ายของสคริปต์จะเป็นข้อความ "สำเร็จ" หรือข้อผิดพลาดที่ทำให้บิลด์ไม่สำเร็จเสมอ
คำสั่ง export
ช่วยให้คุณกําหนดค่าตัวแปรสภาพแวดล้อม 2 รายการ ซึ่งช่วยให้คุณส่งพารามิเตอร์บรรทัดคำสั่งเพิ่มเติมไปยังคอมไพเลอร์ C (CFLAGS
), คอมไพเลอร์ C++ (CXXFLAGS
) และโปรแกรมลิงก์ (LDFLAGS
) ได้ โดยทั้ง 3 รายการจะได้รับการตั้งค่าเครื่องมือเพิ่มประสิทธิภาพผ่าน OPTIMIZE
เพื่อให้แน่ใจว่าทุกอย่างได้รับการเพิ่มประสิทธิภาพในลักษณะเดียวกัน ค่าที่เป็นไปได้สำหรับตัวแปร OPTIMIZE
มี 2 ค่า ดังนี้
-O0
: ไม่เพิ่มประสิทธิภาพ ไม่มีการกำจัดโค้ดที่ตาย และ Emscripten จะไม่ลดขนาดโค้ด JavaScript ที่สร้างขึ้นด้วย เหมาะสำหรับการแก้ไขข้อบกพร่อง-O3
: เพิ่มประสิทธิภาพอย่างจริงจัง-Os
: เพิ่มประสิทธิภาพอย่างเต็มรูปแบบโดยให้ขนาดเป็นเกณฑ์รอง-Oz
: เพิ่มประสิทธิภาพเพื่อลดขนาดโดยเสียประสิทธิภาพหากจำเป็น
สําหรับเว็บ เราขอแนะนํา -Os
ส่วนใหญ่
คำสั่ง emcc
มีตัวเลือกมากมายในตัวเอง โปรดทราบว่า emcc ควรเป็น "เครื่องมือเปลี่ยนทดแทนคอมไพเลอร์อย่าง GCC หรือ clang" ดังนั้น Flag ทั้งหมดที่คุณอาจรู้จักจาก GCC ก็มีแนวโน้มที่ emcc จะใช้ด้วยเช่นกัน Flag -s
มีลักษณะพิเศษตรงที่ช่วยให้เราสามารถกําหนดค่า Emscripten ได้โดยเฉพาะ ตัวเลือกทั้งหมดที่ใช้ได้อยู่ใน settings.js
ของ Emscripten แต่ไฟล์นั้นอาจดูน่าสับสน ต่อไปนี้คือรายการ Flag ของ Emscripten ที่ฉันคิดว่าสำคัญที่สุดสำหรับนักพัฒนาเว็บ
--bind
enables embind-s STRICT=1
หยุดรองรับตัวเลือกการสร้างที่เลิกใช้งานทั้งหมด วิธีนี้ช่วยให้มั่นใจว่าโค้ดจะคอมไพล์ในลักษณะที่ใช้งานร่วมกันได้ในอนาคต-s ALLOW_MEMORY_GROWTH=1
อนุญาตให้เพิ่มหน่วยความจำโดยอัตโนมัติหากจําเป็น ณ เวลาที่เขียน Emscripten จะจัดสรรหน่วยความจำ 16 MB ในขั้นต้น เมื่อโค้ดของคุณจัดสรรพื้นที่หน่วยความจำ ตัวเลือกนี้จะกำหนดว่าการดำเนินการเหล่านี้จะทำให้โมดูล WASM ทั้งหมดทำงานไม่สำเร็จเมื่อหน่วยความจำหมดลง หรืออนุญาตให้โค้ดกาวขยายหน่วยความจำทั้งหมดเพื่อรองรับการจัดสรรหรือไม่-s MALLOC=...
เลือกการใช้งานmalloc()
ที่จะใช้emmalloc
เป็นmalloc()
ขนาดเล็กและรวดเร็วที่ติดตั้งใช้งานสำหรับ Emscripten โดยเฉพาะ อีกทางเลือกหนึ่งคือdlmalloc
ซึ่งเป็นการติดตั้งใช้งานmalloc()
อย่างเต็มรูปแบบ คุณจำเป็นต้องเปลี่ยนไปใช้dlmalloc
เฉพาะในกรณีที่คุณจัดสรรออบเจ็กต์ขนาดเล็กจำนวนมากเป็นประจำหรือต้องการใช้การแยกชุดข้อความ-s EXPORT_ES6=1
จะเปลี่ยนโค้ด JavaScript เป็นโมดูล ES6 ที่มีการส่งออกเริ่มต้นที่ทำงานร่วมกับเครื่องมือรวมโค้ดได้ และต้องตั้งค่า-s MODULARIZE=1
ด้วย
Flag ต่อไปนี้ไม่จําเป็นเสมอไปหรือมีประโยชน์สําหรับวัตถุประสงค์ในการแก้ไขข้อบกพร่องเท่านั้น
-s FILESYSTEM=0
เป็น Flag ที่เกี่ยวข้องกับ Emscripten และความสามารถในการจำลองระบบไฟล์ให้คุณเมื่อโค้ด C/C++ ใช้การดำเนินการของระบบไฟล์ โดยจะทำการวิเคราะห์บางอย่างในโค้ดที่คอมไพล์เพื่อตัดสินใจว่าจะรวมการจําลองไฟล์ระบบไว้ในโค้ดกาวหรือไม่ อย่างไรก็ตาม บางครั้งการวิเคราะห์นี้อาจผิดพลาดและคุณอาจต้องจ่ายเงินเพิ่ม 70 KB สำหรับโค้ดการเชื่อมโยงเพิ่มเติมเพื่อจำลองระบบไฟล์ที่คุณอาจไม่ต้องการ-s FILESYSTEM=0
ช่วยให้คุณสามารถบังคับให้ Emscripten ยกเว้นโค้ดนี้-g4
จะทำให้ Emscripten รวมข้อมูลการแก้ไขข้อบกพร่องไว้ใน.wasm
และยังสร้างไฟล์ Source Map สำหรับโมดูล 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>
(นี่คือ gist ที่มีไฟล์ทั้งหมด)
หากต้องการสร้างทุกอย่าง ให้เรียกใช้
$ npm install
$ npm run build
$ npm run serve
ไปที่ localhost:8080 แล้วคุณจะเห็นเอาต์พุตต่อไปนี้ในคอนโซล DevTools
การเพิ่มโค้ด C/C++ เป็นส่วนที่ต้องพึ่งพา
หากต้องการสร้างไลบรารี C/C++ สําหรับเว็บแอป คุณต้องใส่โค้ดของไลบรารีนั้นไว้ในโปรเจ็กต์ คุณสามารถเพิ่มโค้ดลงในที่เก็บข้อมูลของโปรเจ็กต์ด้วยตนเอง หรือจะใช้ npm เพื่อจัดการการพึ่งพาประเภทเหล่านี้ก็ได้เช่นกัน สมมติว่าฉันต้องการใช้ libvpx ในเว็บแอป ไลบรารี libvpx เป็นไลบรารี C++ ที่ใช้เข้ารหัสรูปภาพด้วย VP8 ซึ่งเป็นตัวแปลงรหัสที่ใช้ในไฟล์ .webm
อย่างไรก็ตาม libvpx ไม่ได้อยู่ใน npm และไม่มี package.json
เราจึงติดตั้งโดยใช้ npm โดยตรงไม่ได้
ทางออกของปัญหานี้ก็คือ napa ซึ่งช่วยให้คุณติดตั้ง URL ของที่เก็บ Git ใดก็ได้เป็นข้อกำหนดไว้ในโฟลเดอร์ node_modules
ติดตั้ง Napa เป็นการอ้างอิง
$ npm install --save napa
และตรวจสอบว่าได้เรียกใช้ napa
เป็นสคริปต์การติดตั้ง
{
// ...
"scripts": {
"install": "napa",
// ...
},
"napa": {
"libvpx": "git+https://github.com/webmproject/libvpx"
}
// ...
}
เมื่อคุณเรียกใช้ npm install
แล้ว Napa จะดูแลการโคลนที่เก็บ GitHub ของ libvpx ไปยัง node_modules
ของคุณโดยใช้ชื่อ libvpx
ตอนนี้คุณขยายสคริปต์การสร้างเพื่อสร้าง libvpx ได้แล้ว libvpx ใช้ configure
และ make
ในการสร้าง แต่โชคดีที่ Emscripten ช่วยตรวจสอบได้ว่า configure
และ make
ใช้คอมไพเลอร์ของ Emscripten คำสั่ง Wrapper 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++ แบ่งออกเป็น 2 ส่วน ได้แก่ ส่วนหัว (เดิมคือไฟล์ .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
นั่นคือเหตุผลที่ต้องมี Flag -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 ...
(นี่คือ gist ที่มีไฟล์ทั้งหมด)
คำสั่ง eval
ช่วยให้เราสามารถตั้งค่าตัวแปรสภาพแวดล้อมโดยการส่งพารามิเตอร์ไปยังสคริปต์บิลด์ คำสั่ง test
จะข้ามการสร้าง libvpx หากมีการตั้งค่า $SKIP_LIBVPX
(เป็นค่าใดก็ได้)
ตอนนี้คุณสามารถคอมไพล์โมดูลได้โดยไม่ต้องสร้าง libvpx ขึ้นมาใหม่ โดยทำดังนี้
$ npm run build:emscripten -- SKIP_LIBVPX=1
การปรับแต่งสภาพแวดล้อมการสร้าง
บางครั้งไลบรารีอาจต้องใช้เครื่องมือเพิ่มเติมในการสร้าง หากไม่มีทรัพยากรเหล่านี้ในสภาพแวดล้อมการสร้างที่อิมเมจ Docker มีให้ คุณจะต้องเพิ่มทรัพยากรเหล่านั้นด้วยตนเอง ตัวอย่างเช่น สมมติว่าคุณต้องการสร้างเอกสารประกอบของ libvpx โดยใช้ doxygen ด้วย 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 คุณต้องปรับ package.json
เล็กน้อยเพื่อให้แน่ใจว่าระบบได้สร้างและทำให้รูปภาพ Docker พร้อมใช้งานแล้วก่อนเรียกใช้ build.sh
โดยทำดังนี้
{
// ...
"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",
// ...
},
// ...
}
(นี่คือ gist ที่มีไฟล์ทั้งหมด)
ซึ่งจะสร้างอิมเมจ Docker ในกรณีที่ยังไม่ได้สร้างเท่านั้น จากนั้นทุกอย่างจะทำงานเหมือนเดิม แต่ตอนนี้สภาพแวดล้อมการสร้างมีคำสั่ง doxygen
ที่ใช้ได้แล้ว ซึ่งจะทำให้มีการรวบรวมเอกสารประกอบของ libvpx ด้วย
บทสรุป
ไม่น่าแปลกใจเลยที่โค้ด C/C++ และ npm จะไม่เข้ากันได้ดีนัก แต่คุณสามารถทำให้ระบบทำงานได้อย่างสะดวกสบายด้วยเครื่องมือเพิ่มเติมและการจัดแยกที่ Docker มีให้ การตั้งค่านี้อาจใช้ไม่ได้กับทุกโปรเจ็กต์ แต่ถือเป็นจุดเริ่มต้นที่ดีที่คุณสามารถปรับให้เหมาะกับความต้องการของคุณได้ หากมีคำแนะนำในการปรับปรุง โปรดแชร์
ภาคผนวก: การใช้เลเยอร์อิมเมจ Docker
อีกวิธีหนึ่งคือรวมปัญหาเหล่านี้ไว้กับ Docker และแนวทางการแคชที่ชาญฉลาดของ Docker Docker จะเรียกใช้ไฟล์ Docker แบบทีละขั้นตอนและกำหนดผลลัพธ์ของแต่ละขั้นตอนเป็นอิมเมจของตนเอง รูปภาพขั้นกลางเหล่านี้มักเรียกว่า "เลเยอร์" หากคำสั่งใน Dockerfile ไม่มีการเปลี่ยนแปลง Docker จะไม่เรียกใช้ขั้นตอนนั้นอีกครั้งเมื่อคุณสร้าง Dockerfile อีกครั้ง แต่จะใช้เลเยอร์จากครั้งที่สร้างรูปภาพครั้งล่าสุดแทน
ก่อนหน้านี้ คุณต้องใช้ความพยายามบางอย่างเพื่อไม่ให้ต้องสร้าง libvpx ใหม่ทุกครั้งที่สร้างแอป แต่ตอนนี้คุณสามารถย้ายวิธีการสร้าง libvpx จาก build.sh
ไปยัง Dockerfile
เพื่อใช้ประโยชน์จากกลไกการแคชของ Docker แทน
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
(นี่คือ gist ที่มีไฟล์ทั้งหมด)
โปรดทราบว่าคุณต้องติดตั้ง git และโคลน libvpx ด้วยตนเองเนื่องจากคุณไม่มีการมาสก์การเชื่อมโยงเมื่อเรียกใช้ docker build
ผลข้างเคียงคือคุณไม่จำเป็นต้องใช้
napa อีกต่อไป