Emscripten และ npm

คุณจะผสานรวม WebAssembly ในการตั้งค่านี้ได้อย่างไร ในบทความนี้เราจะใช้ C/C++ และ Emscripten เป็นตัวอย่าง

WebAssembly (เดิมคือ) มักใช้กับ อยู่ในกรอบของประสิทธิภาพพื้นฐานหรือวิธีการเรียกใช้ C++ ที่มีอยู่ ของโค้ดเบสบนเว็บ สำหรับ squoosh.app เราต้องการแสดง อย่างน้อยก็มีมุมมองที่ 3 สำหรับ Wasm นั่นคือการใช้ประโยชน์จาก ระบบนิเวศของภาษาโปรแกรมอื่นๆ ด้วย Emscripten คุณสามารถใช้โค้ด C/C++ Rust มีการสนับสนุน Wasm ในตัว และฟังก์ชัน Go ทีมกำลังดำเนินการอยู่ด้วย ฉัน ภาษาอื่นๆ ที่จะตามมาในอนาคต

ในสถานการณ์เหล่านี้ Wasm ไม่ใช่ส่วนสำคัญของแอป แต่เป็นปริศนา ชิ้นส่วน: เป็นอีกโมดูลหนึ่ง แอปของคุณมี JavaScript, CSS, ชิ้นงานรูปภาพ, ระบบบิลด์ที่เน้นเว็บเป็นหลัก และแม้แต่กรอบการทำงานอย่าง React เธอเป็นยังไง ผสานรวม WebAssembly ลงในการตั้งค่านี้ไหม ในบทความนี้เราจะพูดถึงเรื่องนี้ โดยใช้ C/C++ และ Emscripten เป็นตัวอย่าง

Docker

ฉันพบว่า Docker มีประโยชน์อย่างมากเมื่อทำงานกับ Emscripten C/C++ ห้องสมุดมักเขียนขึ้นให้ทำงานกับระบบปฏิบัติการที่สร้างขึ้นมา การมีสภาพแวดล้อมที่สอดคล้องกันนั้นเป็นประโยชน์อย่างมาก เมื่อใช้ Docker คุณจะได้รับ ระบบ Linux เสมือนที่ตั้งค่าไว้แล้วให้ทำงานกับ Emscripten และมี ติดตั้งเครื่องมือและทรัพยากร Dependency ทั้งหมดแล้ว หากมีข้อมูลขาดหายไป คุณสามารถ คุณสามารถติดตั้งแอปพลิเคชันได้โดยไม่ต้องกังวลว่า จะส่งผลกระทบต่อเครื่องของคุณเองหรือ โปรเจ็กต์อื่นๆ หากเกิดข้อผิดพลาด ให้ทิ้งที่ใส่ของแล้วเปิดใหม่ ใหม่ หากได้ผลเพียงครั้งเดียว คุณก็มั่นใจได้ว่าโฆษณาจะยังคงใช้งานได้ต่อไปและ ให้ผลลัพธ์ที่เหมือนกัน

Docker Registry มี Emscripten รูปภาพโดย trzeci ที่ฉันใช้งานมาอย่างยาวนาน

การผสานรวมกับ npm

ในกรณีส่วนใหญ่ จุดแรกเข้าของโปรเจ็กต์เว็บคือ npm package.json โดยปกติจะสร้างโปรเจ็กต์ส่วนใหญ่ได้ด้วย npm install && npm run build

โดยทั่วไปแล้ว อาร์ติแฟกต์ของบิลด์ที่ Emscripten สร้างขึ้น (.js และ .wasm ) ควรถือเป็นเพียงโมดูล JavaScript อื่นและ เนื้อหา ไฟล์ JavaScript สามารถจัดการโดย Bundler เช่น 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 ภายใน ระบบจะมิเรอร์คอนเทนเนอร์ไปยังโปรเจ็กต์จริงของคุณ ไดเรกทอรีที่มิเรอร์เหล่านี้ เรียกว่า "bind mounts"

มาลองดูกันที่ 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 ให้คุณกำหนดค่าของสภาพแวดล้อม 2 รายการ ตัวแปร ซึ่งช่วยให้คุณส่งผ่านพารามิเตอร์บรรทัดคำสั่งเพิ่มเติมไปยัง C คอมไพเลอร์ (CFLAGS), คอมไพเลอร์ C++ (CXXFLAGS) และ Linker (LDFLAGS) ทุกคนจะได้รับการตั้งค่าเครื่องมือเพิ่มประสิทธิภาพผ่าน OPTIMIZE เพื่อให้มั่นใจว่า ทุกอย่างจะได้รับการเพิ่มประสิทธิภาพในลักษณะเดียวกัน ค่าที่เป็นไปได้มี 2 ค่า สำหรับตัวแปร OPTIMIZE:

  • -O0: ห้ามเพิ่มประสิทธิภาพใดๆ ไม่มีการลบโค้ดที่ใช้งานไม่ได้ และ Emscripten ไม่ลดขนาดโค้ด JavaScript ที่เครื่องมือส่งออกมาเช่นกัน เหมาะสำหรับการแก้ไขข้อบกพร่อง
  • -O3: เพิ่มประสิทธิภาพในเชิงรุก
  • -Os: เพิ่มประสิทธิภาพในเชิงรุกเพื่อเพิ่มประสิทธิภาพและขนาดในฐานะรอง เกณฑ์
  • -Oz: เพิ่มประสิทธิภาพในเชิงรุกเรื่องขนาด โดยลดประสิทธิภาพหากจำเป็น

สำหรับเว็บ เราแนะนำให้ใช้ -Os เป็นส่วนใหญ่

คำสั่ง emcc มีตัวเลือกมากมายในตัว โปรดทราบว่า emcc คือ ควรจะเป็น "การแทนที่แบบดร็อปอินสำหรับคอมไพเลอร์ เช่น GCC หรือคำแลง" เอาละ สถานะต่างๆ ที่คุณอาจทราบจาก GCC มักจะดำเนินการโดย emcc เช่น Flag -s มีความพิเศษตรงที่ช่วยให้เรากำหนดค่า Emscripten ได้ โดยเฉพาะอย่างยิ่ง ตัวเลือกที่มีทั้งหมดสามารถดูได้ใน Emscripten settings.js แต่ไฟล์นี้ก็มีมากเกินไป นี่คือรายการแฟล็ก Emscripten ที่ฉันคิดว่าสำคัญที่สุดสำหรับนักพัฒนาเว็บ

  • --bind เปิดใช้ embind
  • -s STRICT=1 ลดการรองรับตัวเลือกบิลด์ทั้งหมดที่เลิกใช้งานแล้ว วิธีนี้ช่วยให้มั่นใจว่า ที่โค้ดของคุณสร้างในลักษณะที่เข้ากันได้แบบส่งต่อ
  • -s ALLOW_MEMORY_GROWTH=1 อนุญาตให้เพิ่มหน่วยความจำโดยอัตโนมัติหาก ตามความจำเป็น ขณะที่เขียน Emscripten จะจัดสรรหน่วยความจำ 16 MB ในตอนแรก เมื่อโค้ดจัดสรรหน่วยความจำเป็นส่วนๆ ตัวเลือกนี้จะกำหนดว่า การดำเนินการเหล่านี้จะทําให้โมดูล Wasm ทั้งหมดล้มเหลวเมื่อหน่วยความจํา หมดแล้ว หรือหาก Glue Code ได้รับอนุญาตให้ขยายหน่วยความจำทั้งหมดเป็น รองรับการจัดสรร
  • -s MALLOC=... จะเลือกการใช้งาน malloc() ที่จะใช้ emmalloc คือ การใช้งาน malloc() ขนาดเล็กและรวดเร็วสำหรับ Emscripten โดยเฉพาะ อีกตัวเลือกหนึ่งคือ dlmalloc ซึ่งเป็นการใช้งาน malloc() อย่างเต็มรูปแบบ คุณเท่านั้น ต้องเปลี่ยนเป็น dlmalloc หากคุณจัดสรรวัตถุขนาดเล็กจำนวนมาก บ่อยครั้งหรือหากคุณต้องการใช้การแยกชุดข้อความ
  • -s EXPORT_ES6=1 จะเปลี่ยนโค้ด JavaScript เป็นโมดูล ES6 ที่มี การส่งออกเริ่มต้นที่ใช้งานได้กับ Bundler ใดก็ได้ ยังต้อง-s MODULARIZE=1เพื่อ ตั้งค่าได้

แฟล็กต่อไปนี้ไม่จำเป็นเสมอไปหรือมีประโยชน์ในการแก้ไขข้อบกพร่องเท่านั้น วัตถุประสงค์:

  • -s FILESYSTEM=0 เป็น Flag ที่เกี่ยวข้องกับ Emscripten และความสามารถในการ จำลองระบบไฟล์ให้คุณเมื่อโค้ด C/C++ ใช้การดำเนินการของระบบไฟล์ โดยจะทำการวิเคราะห์โค้ดที่คอมไพล์เพื่อตัดสินใจว่าจะรวม ใน Glue Code ได้หรือไม่ แต่ในบางครั้ง การวิเคราะห์อาจผิดพลาดได้ และคุณต้องจ่ายค่าบริการค่อนข้างมาก 70kB สำหรับกาวเพิ่มเติม สำหรับการจำลองระบบไฟล์ที่คุณอาจไม่จำเป็นต้องใช้ คุณจะบังคับให้ Emscripten ไม่รวมรหัสนี้ได้ด้วย -s FILESYSTEM=0
  • -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 ควรแสดงเอาต์พุตต่อไปนี้ใน คอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ:

เครื่องมือสำหรับนักพัฒนาเว็บแสดงข้อความที่พิมพ์ผ่าน C++ และ Emscripten

เพิ่มโค้ด C/C++ เป็นทรัพยากร Dependency

หากต้องการสร้างไลบรารี C/C++ สำหรับเว็บแอป คุณต้องใช้โค้ดของ ของโปรเจ็กต์ของคุณ คุณเพิ่มโค้ดลงในที่เก็บของโปรเจ็กต์ด้วยตนเองได้ หรือจะใช้ npm เพื่อจัดการทรัพยากร Dependency เหล่านี้ได้ด้วย สมมติว่าฉัน ต้องการใช้ libvpx ในเว็บแอปของฉัน libvpx เป็นไลบรารี C++ เพื่อเข้ารหัสรูปภาพด้วย VP8 ซึ่งเป็นตัวแปลงรหัสที่ใช้ใน .webm ไฟล์ แต่ libvpx ไม่ได้อยู่ใน npm และไม่มี package.json ก็เลย ให้ติดตั้งโดยใช้ npm โดยตรง

เพื่อก้าวออกจากปริศนานี้ napa napa ช่วยให้คุณติดตั้ง git ได้ URL ที่เก็บเป็นทรัพยากร Dependency ในโฟลเดอร์ node_modules

ติดตั้ง Napa เป็นทรัพยากร Dependency

$ npm install --save napa

และเรียกใช้ napa เป็นสคริปต์การติดตั้ง

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

เมื่อเรียกใช้ npm install Napa จะเป็นผู้ดูแลการโคลน libvpx GitHub ลงใน 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 ธงมีไว้สําหรับ -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
แสดงเวอร์ชัน ABI ของ libvpx ที่พิมพ์ผ่าน emscripten

นอกจากนี้ คุณจะเห็นว่ากระบวนการสร้างใช้เวลานาน เหตุผลที่ เวลาในการสร้างนานๆ อาจแตกต่างกันไป ในกรณีของ 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 ช่วยให้เราตั้งค่าตัวแปรสภาพแวดล้อมโดยการส่งพารามิเตอร์ ลงในสคริปต์บิลด์ คำสั่ง test จะข้ามการสร้าง libvpx หาก มีการตั้งค่า $SKIP_LIBVPX (เป็นค่าใดก็ได้)

ตอนนี้คุณสามารถคอมไพล์โมดูล แต่ข้ามการสร้าง libvpx ใหม่ได้ดังนี้

$ npm run build:emscripten -- SKIP_LIBVPX=1

การปรับแต่งสภาพแวดล้อมของบิลด์

บางครั้งไลบรารีอาจขึ้นอยู่กับเครื่องมือเพิ่มเติมในการสร้าง หากทรัพยากร Dependency เหล่านี้ หายไปในสภาพแวดล้อมของบิลด์จากอิมเมจ Docker คุณต้อง ให้เพิ่มด้วยตนเอง ตัวอย่างเช่น สมมติว่าคุณต้องการสร้าง ของ 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 เรียกใช้คำสั่ง Shell ภายใน คอนเทนเนอร์ การเปลี่ยนแปลงคำสั่งเหล่านี้กับคอนเทนเนอร์เป็นส่วนหนึ่งของ อิมเมจ Docker เพื่อให้แน่ใจว่าได้มีการสร้างอิมเมจ Docker ของคุณ พร้อมใช้งานก่อนที่จะเรียกใช้ 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",
    // ...
    },
    // ...
}

(นี่คือสรุป ที่มีไฟล์ทั้งหมดอยู่)

การดำเนินการนี้จะสร้างอิมเมจ Docker ของคุณต่อเมื่อคุณยังไม่ได้สร้างเท่านั้น จากนั้น ทุกอย่างทำงานเหมือนเดิม แต่ตอนนี้สภาพแวดล้อมของบิลด์มี doxygen พร้อมใช้งาน ซึ่งจะทำให้เอกสารประกอบของ libvpx สร้างขึ้นเป็น

บทสรุป

จึงไม่น่าแปลกใจที่โค้ด C/C++ และ npm จะไม่เหมาะกับคุณ แต่คุณสามารถ ทำให้โมเดลใช้งานได้ค่อนข้างสะดวกสบายด้วยเครื่องมือเพิ่มเติมและการแยก ที่ Docker มีให้ การตั้งค่านี้ใช้ได้กับบางโปรเจ็กต์เท่านั้น แต่เป็น จุดเริ่มต้นที่ดีที่คุณสามารถปรับให้เข้ากับความต้องการของคุณ หากคุณมี โปรดแชร์

ภาคผนวก: การใช้เลเยอร์รูปภาพ Docker

อีกโซลูชันหนึ่งคือการสรุปปัญหาเหล่านี้ให้มากขึ้นด้วย Docker และ วิธีการแคชที่ชาญฉลาดของ Docker Docker เรียกใช้ Dockerfiles ทีละขั้นตอนและ กำหนดผลลัพธ์ของแต่ละขั้นตอนซึ่งจะแสดงรูปภาพของขั้นตอนนั้นเอง รูปภาพระดับกลางเหล่านี้ มักเรียกว่า "เลเยอร์" หากคำสั่งใน 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

(นี่คือสรุป ที่มีไฟล์ทั้งหมดอยู่)

โปรดทราบว่าคุณต้องติดตั้ง git และ clone libvpx ด้วยตนเอง เนื่องจากคุณไม่มี เชื่อมโยงตัวยึดเมื่อเรียกใช้ docker build คุณไม่จำเป็นต้อง Napa อีกต่อไป