├── .dockerignore ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .rubocop.yml ├── CHANGELOG.md ├── Dockerfile ├── Gemfile ├── LICENSE ├── Makefile ├── Makefile.docker ├── README.md ├── Rakefile ├── Vagrantfile ├── ext └── libv8-node │ ├── builder.rb │ ├── extconf.rb │ ├── location.rb │ └── paths.rb ├── lib ├── libv8-node.rb └── libv8 │ ├── node.rb │ └── node │ └── version.rb ├── libexec ├── build-libv8 ├── build-monolith ├── download-node ├── extract-node ├── inject-libv8 ├── metadata └── platform ├── libv8-node.gemspec ├── patch ├── gyp-libv8_monolith.patch ├── py2-genv8constants.patch ├── py2-icutrim.patch ├── py3-genv8constants.patch ├── v8-disable-madv-dontfork.patch ├── v8-disable-pkey.patch └── v8-no-assert-trivially-copyable.patch ├── sums ├── v16.10.0.sum ├── v16.11.1.sum ├── v16.3.0.sum ├── v16.4.2.sum ├── v16.5.0.sum ├── v16.6.2.sum ├── v16.7.0.sum ├── v16.8.0.sum ├── v16.9.1.sum ├── v17.3.1.sum ├── v17.9.1.sum ├── v18.13.0.sum ├── v18.8.0.sum ├── v19.9.0.sum ├── v20.12.1.sum ├── v20.2.0.sum ├── v21.7.2.sum ├── v22.5.1.sum ├── v22.6.0.sum └── v22.7.0.sum ├── test └── gtest │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Framework.h │ ├── c_v8_tests.cc │ └── check_glibc.c └── vagrant └── provision-smartos.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /src 3 | /vendor 4 | /Gemfile.lock 5 | *.gem 6 | Makefile 7 | *.so 8 | *.bundle 9 | /ext/libv8-node/.location.yml 10 | /test/mini_racer 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | - pull_request 4 | - push 5 | 6 | jobs: 7 | rubocop: 8 | name: Lint (Rubocop) 9 | runs-on: ubuntu-20.04 10 | container: ruby:3.1 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - name: Bundle 15 | run: bundle install 16 | - name: Rubocop 17 | run: bundle exec rubocop -f simple 18 | shellcheck: 19 | name: Lint (Shellcheck) 20 | runs-on: ubuntu-20.04 21 | container: debian:10 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v2 25 | - name: Install shellcheck 26 | run: apt-get update && apt-get install -y shellcheck 27 | - name: Shellcheck 28 | run: shellcheck libexec/* 29 | build-ruby: 30 | name: Build (ruby) 31 | outputs: 32 | GEM_VERSION: ${{ steps.set-metadata.outputs.GEM_VERSION }} 33 | runs-on: ubuntu-20.04 34 | container: ruby:3.1 35 | steps: 36 | - name: Update Rubygems and Bundler 37 | run: | 38 | gem update --system 3.3.26 39 | gem install bundler -v '~> 2.3.26' 40 | - name: Checkout 41 | uses: actions/checkout@v2 42 | - name: Bundle 43 | run: bundle install 44 | - name: Set metadata 45 | id: set-metadata 46 | run: | 47 | ./libexec/metadata ruby_platform | tee ruby_platform 48 | echo "::set-output name=RUBY_PLATFORM::$(cat ruby_platform)" 49 | ./libexec/metadata gem_platform | tee gem_platform 50 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 51 | ./libexec/metadata gem_version | tee gem_version 52 | echo "::set-output name=GEM_VERSION::$(cat gem_version)" 53 | ./libexec/metadata node_version | tee node_version 54 | echo "::set-output name=NODE_VERSION::$(cat node_version)" 55 | ./libexec/metadata libv8_version | tee libv8_version 56 | echo "::set-output name=LIBV8_VERSION::$(cat libv8_version)" 57 | - name: Download Node.js 58 | run: | 59 | ./libexec/download-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 60 | - name: Extract Node.js 61 | run: | 62 | ./libexec/extract-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 63 | - name: Validate V8 version 64 | run: | 65 | ./libexec/metadata libv8_version_h | tee libv8_version_h 66 | diff libv8_version_h libv8_version 67 | - name: Build gem 68 | run: | 69 | bundle exec rake build 70 | - name: Upload gem 71 | uses: actions/upload-artifact@v1 72 | with: 73 | name: gem-${{ steps.set-metadata.outputs.GEM_VERSION }}-ruby 74 | path: pkg 75 | build-darwin: 76 | strategy: 77 | fail-fast: false 78 | matrix: 79 | platform: 80 | - x86_64 81 | - arm64 82 | name: Build (darwin) 83 | outputs: 84 | GEM_VERSION: ${{ steps.set-metadata.outputs.GEM_VERSION }} 85 | runs-on: macos-12 86 | env: 87 | TARGET_PLATFORM: ${{ matrix.platform }}-darwin 88 | RUBY_TARGET_PLATFORM: ${{ matrix.platform }}-darwin 89 | steps: 90 | - name: Checkout 91 | uses: actions/checkout@v2 92 | - name: Bundle 93 | run: bundle install 94 | - name: Set metadata 95 | id: set-metadata 96 | run: | 97 | ./libexec/metadata ruby_platform | tee ruby_platform 98 | echo "::set-output name=RUBY_PLATFORM::$(cat ruby_platform)" 99 | ./libexec/metadata gem_platform | tee gem_platform 100 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 101 | ./libexec/metadata gem_version | tee gem_version 102 | echo "::set-output name=GEM_VERSION::$(cat gem_version)" 103 | ./libexec/metadata node_version | tee node_version 104 | echo "::set-output name=NODE_VERSION::$(cat node_version)" 105 | ./libexec/metadata libv8_version | tee libv8_version 106 | echo "::set-output name=LIBV8_VERSION::$(cat libv8_version)" 107 | - name: Download Node.js 108 | run: | 109 | ./libexec/download-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 110 | - name: Extract Node.js 111 | run: | 112 | ./libexec/extract-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 113 | - name: Validate V8 version 114 | run: | 115 | ./libexec/metadata libv8_version_h | tee libv8_version_h 116 | diff libv8_version_h libv8_version 117 | - name: Build V8 118 | run: | 119 | ./libexec/build-libv8 ${{ steps.set-metadata.outputs.NODE_VERSION }} 120 | - name: Build Monolith 121 | run: | 122 | ./libexec/build-monolith ${{ steps.set-metadata.outputs.NODE_VERSION }} 123 | - name: Inject V8 124 | run: | 125 | ./libexec/inject-libv8 ${{ steps.set-metadata.outputs.NODE_VERSION }} 126 | - name: Test V8 in C++ 127 | if: matrix.platform != 'arm64' 128 | run: | 129 | cd test/gtest 130 | cmake -S . -B build 131 | cd build 132 | cmake --build . 133 | ./c_v8_tests 134 | - name: Build binary gem 135 | run: | 136 | bundle exec rake binary 137 | - name: Upload V8 138 | uses: actions/upload-artifact@v1 139 | with: 140 | name: v8-${{ steps.set-metadata.outputs.LIBV8_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }} 141 | path: vendor 142 | - name: Upload gem 143 | uses: actions/upload-artifact@v1 144 | with: 145 | name: gem-${{ steps.set-metadata.outputs.GEM_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }} 146 | path: pkg 147 | build-linux: 148 | strategy: 149 | fail-fast: false 150 | matrix: 151 | platform: 152 | - amd64 153 | - arm64 154 | # arm 155 | # ppc64le 156 | # s390x 157 | libc: 158 | - gnu 159 | include: 160 | - platform: amd64 161 | libc: musl 162 | name: Build (linux) 163 | outputs: 164 | GEM_VERSION: ${{ steps.set-metadata.outputs.GEM_VERSION }} 165 | runs-on: ubuntu-20.04 166 | steps: 167 | - name: Set cross-compilation platform 168 | id: platform 169 | run: | 170 | case ${{ matrix.platform }} in 171 | amd64) 172 | case ${{ matrix.libc }} in 173 | gnu) 174 | echo 'x86_64-linux-gnu' 175 | ;; 176 | musl) 177 | echo 'x86_64-alpine-linux-musl' 178 | ;; 179 | esac 180 | ;; 181 | arm64) 182 | echo 'aarch64-linux-gnu' 183 | ;; 184 | esac | tee target_platform 185 | case ${{ matrix.platform }} in 186 | amd64) 187 | case ${{ matrix.libc }} in 188 | gnu) 189 | echo 'x86_64-linux' 190 | ;; 191 | musl) 192 | echo 'x86_64-linux-musl' 193 | ;; 194 | esac 195 | ;; 196 | arm64) 197 | echo 'aarch64-linux' 198 | ;; 199 | esac | tee ruby_target_platform 200 | echo "::set-output name=target_platform::$(cat target_platform)" 201 | echo "::set-output name=ruby_target_platform::$(cat ruby_target_platform)" 202 | - name: Start container 203 | id: container 204 | run: | 205 | case ${{ matrix.libc }} in 206 | gnu) 207 | echo 'ruby:2.7' 208 | ;; 209 | musl) 210 | echo 'ruby:2.7-alpine' 211 | ;; 212 | esac | tee container_image 213 | echo "::set-output name=image::$(cat container_image)" 214 | docker run --rm -d -v "${PWD}":"${PWD}" -w "${PWD}" --platform linux/amd64 -e RUBY_TARGET_PLATFORM=${{ steps.platform.outputs.ruby_target_platform }} -e TARGET_PLATFORM=${{ steps.platform.outputs.target_platform }} $(cat container_image) /bin/sleep 64d | tee container_id 215 | docker exec -w "${PWD}" $(cat container_id) uname -a 216 | echo "::set-output name=id::$(cat container_id)" 217 | - name: Install Alpine system dependencies 218 | if: ${{ matrix.libc == 'musl' }} 219 | run: docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apk add --no-cache build-base linux-headers bash python3 git curl tar cmake clang ccache 220 | - name: Install Debian system dependencies 221 | if: ${{ matrix.libc == 'gnu' }} 222 | run: | 223 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apt-get update 224 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apt-get install -y cmake clang ccache 225 | - name: Install Debian cross-compiler 226 | if: ${{ matrix.libc == 'gnu' && matrix.platform != 'amd64' }} 227 | run: | 228 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apt-get install -y binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 229 | - name: Update Rubygems and Bundler 230 | run: | 231 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} gem update --system 3.3.26 232 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} gem install bundler -v '~> 2.3.26' 233 | - name: Checkout 234 | uses: actions/checkout@v2 235 | - name: Bundle 236 | run: docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bundle install 237 | - name: Set metadata 238 | id: set-metadata 239 | run: | 240 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata ruby_platform | tee ruby_platform 241 | echo "::set-output name=RUBY_PLATFORM::$(cat ruby_platform)" 242 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata gem_platform | tee gem_platform 243 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 244 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata gem_version | tee gem_version 245 | echo "::set-output name=GEM_VERSION::$(cat gem_version)" 246 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata node_version | tee node_version 247 | echo "::set-output name=NODE_VERSION::$(cat node_version)" 248 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata libv8_version | tee libv8_version 249 | echo "::set-output name=LIBV8_VERSION::$(cat libv8_version)" 250 | - name: Download Node.js 251 | run: | 252 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/download-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 253 | - name: Extract Node.js 254 | run: | 255 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/extract-node ${{ steps.set-metadata.outputs.NODE_VERSION }} 256 | - name: Validate V8 version 257 | run: | 258 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/metadata libv8_version_h | tee libv8_version_h 259 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} diff libv8_version_h libv8_version 260 | - name: Build V8 261 | run: | 262 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/build-libv8 ${{ steps.set-metadata.outputs.NODE_VERSION }} 263 | - name: Build Monolith 264 | run: | 265 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/build-monolith ${{ steps.set-metadata.outputs.NODE_VERSION }} 266 | - name: Inject V8 267 | run: | 268 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ./libexec/inject-libv8 ${{ steps.set-metadata.outputs.NODE_VERSION }} 269 | - name: Test V8 in C++ 270 | if: matrix.platform != 'arm64' 271 | run: | 272 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bash -c "cd test/gtest && cmake -S . -B build && cd build && cmake --build . && ctest" 273 | - name: Build binary gem 274 | run: | 275 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bundle exec rake binary[${{ steps.platform.outputs.ruby_target_platform }}] 276 | - name: Upload V8 277 | uses: actions/upload-artifact@v1 278 | with: 279 | name: v8-${{ steps.set-metadata.outputs.LIBV8_VERSION }}-${{ steps.platform.outputs.ruby_target_platform }} 280 | path: vendor 281 | - name: Upload gem 282 | uses: actions/upload-artifact@v1 283 | with: 284 | name: gem-${{ steps.set-metadata.outputs.GEM_VERSION }}-${{ steps.platform.outputs.ruby_target_platform }} 285 | path: pkg 286 | test-ruby: 287 | strategy: 288 | fail-fast: false 289 | matrix: 290 | platform: 291 | - amd64 292 | # other platforms would need emulation, which is way too slow 293 | container: 294 | - image: ruby:3.1 295 | version: '3.1' 296 | libc: gnu 297 | - image: ruby:3.1-alpine 298 | version: '3.1' 299 | libc: musl 300 | - image: ruby:3.2 301 | version: '3.2' 302 | libc: gnu 303 | - image: ruby:3.2-alpine 304 | version: '3.2' 305 | libc: musl 306 | - image: ruby:3.3 307 | version: '3.3' 308 | libc: gnu 309 | - image: ruby:3.3-alpine 310 | version: '3.3' 311 | libc: musl 312 | name: Test (ruby) (${{ matrix.container.version }}, ${{ matrix.platform }}, ${{ matrix.container.libc }}) 313 | needs: build-ruby 314 | runs-on: ubuntu-20.04 315 | container: ${{ matrix.container.image }} 316 | steps: 317 | - name: Install Alpine system dependencies 318 | if: ${{ matrix.container.libc == 'musl' }} 319 | run: apk add --no-cache build-base linux-headers bash python3 git curl tar 320 | - name: Update Rubygems and Bundler 321 | run: | 322 | gem update --system 3.3.26 323 | gem install bundler -v '~> 2.3.26' 324 | - name: Set metadata 325 | id: set-metadata 326 | run: | 327 | ruby -e 'puts Gem.platforms.last.to_s' | tee gem_platform 328 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 329 | - name: Download a single artifact 330 | uses: actions/download-artifact@v2 331 | with: 332 | name: gem-${{ needs.build-ruby.outputs.GEM_VERSION }}-ruby 333 | path: pkg 334 | - name: Install gem 335 | run: gem install --verbose pkg/libv8-node-${{ needs.build-ruby.outputs.GEM_VERSION }}.gem 336 | - name: Test with mini_racer 337 | run: | 338 | export BUNDLE_FORCE_RUBY_PLATFORM=y 339 | git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 340 | cd test/mini_racer 341 | git fetch origin refs/pull/299/head 342 | git checkout FETCH_HEAD 343 | git reset --hard 344 | git clean -f -d -x 345 | ruby -i -ne '$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"${{ needs.build-ruby.outputs.GEM_VERSION }}\"\n") : print' lib/mini_racer/version.rb 346 | ruby -i -ne '$_ =~ /spec.required_ruby_version/ ? "" : print' mini_racer.gemspec 347 | bundle install 348 | bundle exec rake compile 349 | bundle exec rake test 350 | test-darwin: 351 | strategy: 352 | fail-fast: false 353 | matrix: 354 | platform: 355 | - x86_64 356 | # arm64 357 | name: Test (darwin) 358 | needs: build-darwin 359 | runs-on: macos-12 360 | steps: 361 | - name: Set metadata 362 | id: set-metadata 363 | run: | 364 | ruby -e 'puts Gem.platforms.last.to_s.gsub(/-darwin-?\d+/, "-darwin")' | tee gem_platform 365 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 366 | - name: Download a single artifact 367 | uses: actions/download-artifact@v2 368 | with: 369 | name: gem-${{ needs.build-darwin.outputs.GEM_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }} 370 | path: pkg 371 | - name: Install gem 372 | run: gem install pkg/libv8-node-${{ needs.build-darwin.outputs.GEM_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }}.gem 373 | - name: Test with mini_racer 374 | run: | 375 | git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 376 | cd test/mini_racer 377 | git fetch origin refs/pull/299/head 378 | git checkout FETCH_HEAD 379 | git reset --hard 380 | git clean -f -d -x 381 | ruby -i -ne '$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"${{ needs.build-darwin.outputs.GEM_VERSION }}\"\n") : print' lib/mini_racer/version.rb 382 | ruby -i -ne '$_ =~ /spec.required_ruby_version/ ? "" : print' mini_racer.gemspec 383 | bundle install 384 | bundle exec rake compile 385 | bundle exec rake test 386 | test-linux: 387 | strategy: 388 | fail-fast: false 389 | matrix: 390 | version: 391 | - '3.1' 392 | - '3.2' 393 | - '3.3' 394 | platform: 395 | - amd64 396 | # arm64 397 | # arm 398 | # ppc64le 399 | # s390x 400 | libc: 401 | - gnu 402 | - musl 403 | include: 404 | - version: '3.1' 405 | platform: 'arm64' 406 | libc: 'gnu' 407 | - version: '3.2' 408 | platform: 'arm64' 409 | libc: 'gnu' 410 | - version: '3.3' 411 | platform: 'arm64' 412 | libc: 'gnu' 413 | name: Test (linux) 414 | needs: build-linux 415 | runs-on: ubuntu-20.04 416 | steps: 417 | - name: Enable ${{ matrix.platform }} platform 418 | id: qemu 419 | if: ${{ matrix.platform != 'amd64' }} 420 | run: | 421 | docker run --privileged --rm tonistiigi/binfmt:latest --install ${{ matrix.platform }} | tee platforms.json 422 | echo "::set-output name=platforms::$(cat platforms.json)" 423 | - name: Start container 424 | id: container 425 | run: | 426 | case ${{ matrix.libc }} in 427 | gnu) 428 | echo 'ruby:${{ matrix.version }}' 429 | ;; 430 | musl) 431 | echo 'ruby:${{ matrix.version }}-alpine' 432 | ;; 433 | esac | tee container_image 434 | echo "::set-output name=image::$(cat container_image)" 435 | docker run --rm -d -v "${PWD}":"${PWD}" -w "${PWD}" --platform linux/${{ matrix.platform }} $(cat container_image) /bin/sleep 64d | tee container_id 436 | docker exec -w "${PWD}" $(cat container_id) uname -a 437 | echo "::set-output name=id::$(cat container_id)" 438 | - name: Install Alpine system dependencies 439 | if: ${{ matrix.libc == 'musl' }} 440 | run: docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apk add --no-cache build-base git libstdc++ 441 | - name: Update Rubygems and Bundler 442 | run: | 443 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} gem update --system 3.3.26 444 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} gem install bundler -v '~> 2.3.26' 445 | - name: Set metadata 446 | id: set-metadata 447 | run: | 448 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} ruby -e 'puts Gem::Platform.local.tap { |p| RUBY_PLATFORM =~ /musl/ && p.version.nil? and p.instance_eval { @version = "musl" } }.to_s' | tee gem_platform 449 | echo "::set-output name=GEM_PLATFORM::$(cat gem_platform)" 450 | - name: Download a single artifact 451 | uses: actions/download-artifact@v2 452 | with: 453 | name: gem-${{ needs.build-linux.outputs.GEM_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }} 454 | path: pkg 455 | - name: Install gem 456 | run: docker exec -w "${PWD}" ${{ steps.container.outputs.id }} gem install pkg/libv8-node-${{ needs.build-linux.outputs.GEM_VERSION }}-${{ steps.set-metadata.outputs.GEM_PLATFORM }}.gem 457 | - name: Test with mini_racer 458 | run: | 459 | git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 460 | cd test/mini_racer 461 | git fetch origin refs/pull/299/head 462 | git checkout FETCH_HEAD 463 | git reset --hard 464 | git clean -f -d -x 465 | ruby -i -ne '$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"${{ needs.build-linux.outputs.GEM_VERSION }}\"\n") : print' lib/mini_racer/version.rb 466 | ruby -i -ne '$_ =~ /spec.required_ruby_version/ ? "" : print' mini_racer.gemspec 467 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bundle install 468 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bundle exec rake compile 469 | docker exec -w "${PWD}" ${{ steps.container.outputs.id }} bundle exec rake test 470 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /src 3 | /vendor 4 | /Gemfile.lock 5 | *.gem 6 | Makefile 7 | /ext/libv8-node/.location.yml 8 | /test/mini_racer 9 | /test/bundle 10 | *.nix 11 | *.vim 12 | .envrc 13 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | SuggestExtensions: false 3 | NewCops: disable 4 | TargetRubyVersion: 2.0 5 | Exclude: 6 | - src/**/* 7 | - pkg/**/* 8 | - vendor/**/* 9 | - test/**/* 10 | 11 | Naming/FileName: 12 | Exclude: 13 | - lib/libv8-node.rb 14 | 15 | Style/Documentation: 16 | Enabled: false 17 | 18 | Style/ClassAndModuleChildren: 19 | Enabled: false 20 | 21 | Style/NumericPredicate: 22 | Enabled: false 23 | 24 | Metrics/LineLength: 25 | Enabled: false 26 | 27 | Style/WordArray: 28 | Enabled: false 29 | 30 | Style/PerlBackrefs: 31 | Enabled: false 32 | 33 | Gemspec/RequiredRubyVersion: 34 | Enabled: false 35 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyjs/libv8-node/8900cf67862f6d65e578ea1ef8cd5d48555753f8/CHANGELOG.md -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG RUBY_VERSION=2.7 2 | FROM ruby:${RUBY_VERSION} 3 | 4 | RUN test ! -f /etc/alpine-release || apk add --no-cache build-base bash python3 git curl tar ccache clang 5 | RUN test -f /etc/alpine-release || (apt-get update && apt-get install -y ccache) 6 | ENV CCACHE_DIR=/ccache 7 | 8 | RUN gem update --system 3.3.26 && gem install bundler -v '~> 2.3.26' 9 | 10 | RUN mkdir -p /code 11 | WORKDIR /code 12 | 13 | ARG NODE_VERSION=18.13.0 14 | 15 | COPY sums/v${NODE_VERSION}.sum /code/sums/ 16 | COPY libexec/download-node /code/libexec/ 17 | RUN ./libexec/download-node ${NODE_VERSION} 18 | COPY libexec/extract-node /code/libexec/ 19 | COPY patch/* /code/patch/ 20 | RUN ./libexec/extract-node ${NODE_VERSION} 21 | COPY libexec/platform /code/libexec/ 22 | COPY libexec/build-libv8 /code/libexec/ 23 | RUN --mount=type=cache,id=ccache,target=/ccache/ ./libexec/build-libv8 ${NODE_VERSION} 24 | COPY libexec/build-monolith /code/libexec/ 25 | RUN ./libexec/build-monolith ${NODE_VERSION} 26 | COPY libexec/inject-libv8 /code/libexec/ 27 | RUN ./libexec/inject-libv8 ${NODE_VERSION} 28 | 29 | COPY Gemfile libv8-node.gemspec /code/ 30 | COPY lib/libv8/node/version.rb /code/lib/libv8/node/version.rb 31 | RUN bundle install 32 | 33 | COPY . /code/ 34 | RUN bundle exec rake binary 35 | 36 | CMD /bin/bash 37 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009,2010 Charles Lowell 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PWD := $(shell pwd) 2 | OS := $(shell uname -s | tr '[A-Z]' '[a-z]') 3 | CPU := $(shell uname -m) 4 | VERSION := $(shell ./libexec/metadata version) 5 | NODE_VERSION := $(shell ./libexec/metadata node_version) 6 | RUBY_VERSION = $(shell ruby -e 'puts RUBY_VERSION.gsub(/\d+$$/, "0")') 7 | 8 | .PHONY: vars 9 | vars: 10 | @echo $(PWD) 11 | @echo $(OS) $(CPU) 12 | @echo $(VERSION) $(NODE_VERSION) 13 | @echo $(RUBY_VERSION) 14 | 15 | .PHONY: all 16 | all: gem test 17 | 18 | .PHONY: build 19 | build: src/node-v$(NODE_VERSION)/out/Release/node 20 | 21 | .PHONY: lib 22 | lib: src/node-v$(NODE_VERSION)/out/Release/libv8_monolith.a 23 | 24 | .PHONY: gem 25 | gem: pkg/libv8-node-$(VERSION)-$(CPU)-$(OS).gem 26 | 27 | .PHONY: test 28 | test: test/$(CPU)-$(OS) 29 | 30 | .PHONY: ctest 31 | ctest: vendor/v8 32 | cd test/gtest && cmake -S . -B build && cd build && cmake --build . && ctest 33 | 34 | src/node-v$(NODE_VERSION).tar.gz: 35 | ./libexec/download-node $(NODE_VERSION) 36 | 37 | src/node-v$(NODE_VERSION): src/node-v$(NODE_VERSION).tar.gz 38 | ./libexec/extract-node $(NODE_VERSION) 39 | 40 | src/node-v$(NODE_VERSION)/out/Release/node: src/node-v$(NODE_VERSION) 41 | ./libexec/build-libv8 $(NODE_VERSION) 42 | 43 | src/node-v$(NODE_VERSION)/out/Release/libv8_monolith.a: src/node-v$(NODE_VERSION)/out/Release/node 44 | ./libexec/build-monolith $(NODE_VERSION) 45 | 46 | .PHONY: vendor/v8 47 | vendor/v8: src/node-v$(NODE_VERSION)/out/Release/libv8_monolith.a 48 | ./libexec/inject-libv8 $(NODE_VERSION) 49 | 50 | pkg/libv8-node-$(VERSION)-$(CPU)-$(OS).gem: vendor/v8 51 | bundle exec rake binary 52 | 53 | .PHONY: test/$(CPU)-$(OS) 54 | test/$(CPU)-$(OS): pkg/libv8-node-$(VERSION)-$(CPU)-$(OS).gem 55 | test -d test/mini_racer || git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 56 | cd test/mini_racer && git fetch origin refs/pull/299/head && git checkout FETCH_HEAD && git reset --hard && git clean -f -d -x 57 | ruby -i -ne '$$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"$(VERSION)\"\n") : print' test/mini_racer/lib/mini_racer/version.rb 58 | ruby -i -ne '$$_ =~ /spec.required_ruby_version/ ? "" : print' test/mini_racer/mini_racer.gemspec 59 | cd test/mini_racer && env TOP="$(PWD)" GEM_HOME="$(PWD)/test/bundle/ruby/$(RUBY_VERSION)" BUNDLE_PATH="$(PWD)/test/bundle" sh -c 'rm -rf "$${GEM_HOME}" && gem install $${TOP}/$< && bundle install && bundle exec rake compile && bundle exec rake test' 60 | -------------------------------------------------------------------------------- /Makefile.docker: -------------------------------------------------------------------------------- 1 | PWD := $(shell pwd) 2 | OS := $(shell uname -s | tr '[A-Z]' '[a-z]') 3 | CPU := $(shell uname -m) 4 | VERSION := $(shell ./libexec/metadata version) 5 | NODE_VERSION := $(shell ./libexec/metadata node_version) 6 | RUBY_VERSION = $(shell ruby -e 'puts RUBY_VERSION.gsub(/\d+$$/, "0")') 7 | 8 | vars: 9 | @echo $(PWD) 10 | @echo $(OS) $(CPU) 11 | @echo $(VERSION) $(NODE_VERSION) 12 | @echo $(RUBY_VERSION) 13 | 14 | all: gem test 15 | 16 | gem: pkg/libv8-node-$(VERSION)-$(CPU)-$(OS).gem 17 | 18 | test: test/$(CPU)-$(OS) 19 | 20 | test/linux: test/$(subst arm64,aarch64,$(CPU))-linux 21 | test/linux-musl: test/$(subst arm64,aarch64,$(CPU))-linux-musl 22 | 23 | pkg/libv8-node-$(VERSION)-x86_64-linux.gem: 24 | docker buildx build --platform linux/amd64 --build-arg RUBY_VERSION=2.7 --build-arg NODE_VERSION=$(NODE_VERSION) --progress plain -t libv8-node:$(VERSION)-gnu . 25 | docker run --platform linux/amd64 --rm -it -v "$(PWD)/pkg":/pkg libv8-node:$(VERSION)-gnu cp $@ /pkg/ 26 | 27 | pkg/libv8-node-$(VERSION)-x86_64-linux-musl.gem: 28 | docker buildx build --platform linux/amd64 --build-arg RUBY_VERSION=2.7-alpine --build-arg NODE_VERSION=$(NODE_VERSION) --progress plain -t libv8-node:$(VERSION)-musl . 29 | docker run --platform linux/amd64 --rm -it -v "$(PWD)/pkg":/pkg libv8-node:$(VERSION)-musl cp $@ /pkg/ 30 | 31 | pkg/libv8-node-$(VERSION)-aarch64-linux.gem: 32 | docker buildx build --platform linux/arm64 --build-arg RUBY_VERSION=2.7 --build-arg NODE_VERSION=$(NODE_VERSION) --progress plain -t libv8-node:$(VERSION)-gnu . 33 | docker run --platform linux/arm64 --rm -it -v "$(PWD)/pkg":/pkg libv8-node:$(VERSION)-gnu cp $@ /pkg/ 34 | 35 | pkg/libv8-node-$(VERSION)-aarch64-linux-musl.gem: 36 | docker buildx build --platform linux/arm64 --build-arg RUBY_VERSION=2.7-alpine --build-arg NODE_VERSION=$(NODE_VERSION) --progress plain -t libv8-node:$(VERSION)-musl . 37 | docker run --platform linux/arm64 --rm -it -v "$(PWD)/pkg":/pkg libv8-node:$(VERSION)-musl cp $@ /pkg/ 38 | 39 | test/x86_64-linux: pkg/libv8-node-$(VERSION)-x86_64-linux.gem 40 | test -d test/mini_racer || git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 41 | cd test/mini_racer 42 | ruby -i -ne '$$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"$(VERSION)\"\n") : print' test/mini_racer/lib/mini_racer/version.rb 43 | ruby -i -ne '$$_ =~ /spec.required_ruby_version/ ? "" : print' test/mini_racer/mini_racer.gemspec 44 | docker run --platform linux/amd64 --rm -it -v "$(PWD)/test:/code/test" -w "/code/test/mini_racer" libv8-node:$(VERSION)-gnu sh -c 'gem install ../../$< && bundle install && bundle exec rake compile && bundle exec rake test' 45 | 46 | test/x86_64-linux-musl: pkg/libv8-node-$(VERSION)-x86_64-linux-musl.gem 47 | test -d test/mini_racer || git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 48 | cd test/mini_racer 49 | ruby -i -ne '$$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"$(VERSION)\"\n") : print' test/mini_racer/lib/mini_racer/version.rb 50 | ruby -i -ne '$$_ =~ /spec.required_ruby_version/ ? "" : print' test/mini_racer/mini_racer.gemspec 51 | docker run --platform linux/amd64 --rm -it -v "$(PWD)/test:/code/test" -w "/code/test/mini_racer" libv8-node:$(VERSION)-musl sh -c 'gem install ../../$< && bundle install && bundle exec rake compile && bundle exec rake test' 52 | 53 | test/aarch64-linux: pkg/libv8-node-$(VERSION)-aarch64-linux.gem 54 | test -d test/mini_racer || git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 55 | cd test/mini_racer 56 | ruby -i -ne '$$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"$(VERSION)\"\n") : print' test/mini_racer/lib/mini_racer/version.rb 57 | ruby -i -ne '$$_ =~ /spec.required_ruby_version/ ? "" : print' test/mini_racer/mini_racer.gemspec 58 | docker run --platform linux/arm64 --rm -it -v "$(PWD)/test:/code/test" -w "/code/test/mini_racer" libv8-node:$(VERSION)-gnu sh -c 'gem install ../../$< && bundle install && bundle exec rake compile && bundle exec rake test' 59 | 60 | test/aarch64-linux-musl: pkg/libv8-node-$(VERSION)-aarch64-linux-musl.gem 61 | test -d test/mini_racer || git clone https://github.com/rubyjs/mini_racer.git test/mini_racer --depth 1 62 | cd test/mini_racer 63 | ruby -i -ne '$$_ =~ /^\s+LIBV8_NODE_VERSION/ ? print(" LIBV8_NODE_VERSION = \"$(VERSION)\"\n") : print' test/mini_racer/lib/mini_racer/version.rb 64 | ruby -i -ne '$$_ =~ /spec.required_ruby_version/ ? "" : print' test/mini_racer/mini_racer.gemspec 65 | docker run --platform linux/arm64 --rm -it -v "$(PWD)/test:/code/test" -w "/code/test/mini_racer" libv8-node:$(VERSION)-musl sh -c 'gem install ../../$< && bundle install && bundle exec rake compile && bundle exec rake test' 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libv8-node 2 | 3 | A project for distributing the v8 runtime libraries and headers in both source and binary form, packaged as a language-independent zip and as a Ruby gem. 4 | 5 | ## Why? 6 | 7 | The goal of libv8-node is three-fold: 8 | 9 | - provide a build environment reliably producing a set of (non-Ruby) pre-compiled v8 libraries for as many platforms as possible 10 | - package the pre-compiled v8 libraries as a binary gem leveraging rubygems platform matching 11 | - provide a gem performing an automated compilation for all other platforms 12 | 13 | Not only does this drastically reduce gem install times, but it also reduces dependencies on the local machine receiving the gem, as well as unifying the configurable variants that v8 supports. 14 | 15 | ## How? (also why Node?) 16 | 17 | Upstream V8 is dependent on a set of complicated Google-provided tools that fetch source *and* a set of upstream-built compiler toolchains. These are only supported to the extent that they enable the current Chrome versions to build, and only for Chrome-supported platforms. This means that these tools operate on a rolling release basis purely for Google's needs and rely on source control for fetching, thus in practice are only provided as convenience, only allow a frozen-in-time overall relationship and receive no backports, frequently breaking in the context of stable releases, and don't easily support many platforms. 18 | 19 | Conversely, the Node.js team vendors v8 in their source code, integrate it in their build system, maintain that across many platforms with public tiered support, backport stability and security fixes under a public timeline, all packaged as a simple tarball. 20 | 21 | Therefore we fetch a Node tarball, extract it, build it, save the v8 headers and built libraries, vendor the result, and build a gem from it. 22 | 23 | See the Node [platform list](https://github.com/nodejs/node/blob/master/BUILDING.md#platform-list) and [support schedule](https://nodejs.org/en/about/releases/). 24 | 25 | ## Do I get a binary? 26 | 27 | It depends on what the Node version supports, how much of the platforms we can have in CI, and which hardware we have access to. 28 | 29 | Check the CI artifacts on the repo's GitHub Actions and [libv8-node on rubygems.org](https://rubygems.org/gems/libv8-node) to be sure. 30 | 31 | Here's an informal list of platforms we push so far, with equally informal tiers: 32 | 33 | Tier 0 (CI built and tested): 34 | 35 | - x86_64-darwin (17 to 20) 36 | - x86_64-linux 37 | - x86_64-linux-musl 38 | 39 | Tier 1 (manual build and test): 40 | 41 | - arm64-darwin (20) 42 | 43 | Tier 2 (manual build and test, has known stability issues): 44 | 45 | - aarch64-linux 46 | - aarch64-linux-musl 47 | 48 | As a fallback, the source gem (`ruby` gem platform) should compile on all Node supported platforms (including e.g. ppc64le or solaris), but we may not have tested it. Help is welcome! 49 | 50 | If a published binary does not work for you, bundler allows to force using the `ruby` platform via `force_ruby_platform`, which will compile from source. 51 | 52 | ### Note on OS X macOS binaries 53 | 54 | If you're installing libv8 on a macOS system that is present in the list above, and despite that, RubyGems insists on downloading a source version and compiling it, check the output of ruby -e 'puts Gem::Platform.local'. If it does not reflect the current version of your OS, recompile Ruby. 55 | 56 | The platform gets hardcoded in Ruby during compilation and if you've updated your OS since you've compiled Ruby, it does not represent correctly your current platform which leads to RubyGems trying to download a platform-specific gem for the older version of your OS. 57 | 58 | ### Note on Alpine/musl 59 | 60 | There is an outstanding issue with rubygems and bundler, where it may misselect the incorrect platform (e.g picking linux instead of linux-musl) 61 | 62 | ## Versioning 63 | 64 | The gem versioning is Node-based, e.g node 15.14.0 gives the gem 15.14.0.0. The last number is an increment for libv8-node fixes. We try as mucha s possible not to include too much changes in such gem fixes, so you can consider these like "patch" in semver. 65 | 66 | Compared to the `libv8` gem, there is no odd/even scheme, thanks to the intriduction in bundler of the `force_ruby_platform` flag. 67 | 68 | ## Requirements 69 | 70 | ### Building 71 | 72 | Building from source has a number of requirements, which mostly depend on the Node version. You can find these in the corresponding Node tree. 73 | 74 | - https://github.com/nodejs/node/blob/master/BUILDING.md#supported-toolchains 75 | - https://github.com/nodejs/node/blob/master/BUILDING.md#building-nodejs-on-supported-platforms 76 | 77 | Be sure to check the one for the Node version in use. 78 | 79 | ### Linking 80 | 81 | Linking against the produced binaries e.g when installing a `ruby`-platform `mini_racer`) also has similar requirements. Notably, please make sure to have similarly recent compiler and libc++ installed. 82 | 83 | ## Building from the repo 84 | 85 | See `BUILDING.md`. Also make sure to read `CONTRIBUTING.md` if you plan to help. 86 | 87 | ## About 88 | 89 | This project spun off of [libv8](http://github.com/rubyjs/libv8), which itself spun off of [therubyracer](http://github.com/rubyjs/therubyracer) which depends on having a specific version of V8 to compile and run against. However, actually delivering that version reliably to all the different platforms proved to be a challenge to say the least. 90 | 91 | ## License 92 | 93 | (The MIT License) 94 | 95 | Copyright (c) 2009,2010 Charles Lowell 96 | 97 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 98 | 99 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 100 | 101 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 102 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | 3 | Bundler::GemHelper.install_tasks 4 | 5 | module Helpers 6 | module_function 7 | 8 | def binary_gemspec(platform: Gem::Platform.local, str: RUBY_PLATFORM) 9 | # TODO: old rubygems and cross compile 10 | platform.instance_eval { @version = 'musl' } if str =~ /-musl/ && platform.version.nil? 11 | 12 | gemspec = eval(File.read('libv8-node.gemspec')) # rubocop:disable Security/Eval 13 | gemspec.platform = platform 14 | gemspec 15 | end 16 | 17 | def binary_gem_name(platform = Gem::Platform.local) 18 | File.basename(binary_gemspec(platform).cache_file) 19 | end 20 | end 21 | 22 | task :compile, [:platform] => [] do |_, args| 23 | local_platform = Gem::Platform.local 24 | target_platform = Gem::Platform.new(ENV['RUBY_TARGET_PLATFORM'] || args.to_h[:platform] || Gem::Platform.local) 25 | 26 | target_platform.instance_eval { @version = nil } if target_platform.os == 'darwin' 27 | 28 | puts "local platform: #{local_platform}" 29 | puts "target platform: #{target_platform}" 30 | 31 | ENV['RUBY_TARGET_PLATFORM'] = target_platform.to_s 32 | 33 | if (libs = Dir["vendor/v8/#{target_platform}/**/*.a"]).any? 34 | puts "found: #{libs.inspect}" 35 | next 36 | end 37 | 38 | Dir.chdir('ext/libv8-node') do # gem install behaves like that 39 | sh 'ruby extconf.rb' 40 | end 41 | end 42 | 43 | task :binary, [:platform] => [:compile] do |_, args| 44 | local_platform = Gem::Platform.local.dup 45 | target_platform = Gem::Platform.new(ENV['RUBY_TARGET_PLATFORM'] || args.to_h[:platform] || Gem::Platform.local) 46 | 47 | target_platform.instance_eval { @version = nil } if target_platform.os == 'darwin' 48 | 49 | puts "local platform: #{local_platform}" 50 | puts "target platform: #{target_platform}" 51 | gemspec = Helpers.binary_gemspec(platform: target_platform) 52 | gemspec.extensions.clear 53 | 54 | # We don't need most things for the binary 55 | gemspec.files = [] 56 | gemspec.files += ['lib/libv8-node.rb', 'lib/libv8/node.rb', 'lib/libv8/node/version.rb'] 57 | gemspec.files += ['ext/libv8-node/location.rb', 'ext/libv8-node/paths.rb'] 58 | gemspec.files += ['ext/libv8-node/.location.yml'] 59 | 60 | # V8 61 | gemspec.files += Dir['vendor/v8/include/**/*.h'] 62 | gemspec.files += Dir["vendor/v8/#{target_platform}/**/*.a"] 63 | 64 | FileUtils.chmod(0o0644, gemspec.files) 65 | FileUtils.mkdir_p('pkg') 66 | 67 | package = if Gem::VERSION < '2.0.0' 68 | Gem::Builder.new(gemspec).build 69 | else 70 | require 'rubygems/package' 71 | Gem::Package.build(gemspec) 72 | end 73 | 74 | FileUtils.mv(package, 'pkg') 75 | end 76 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure('2') do |config| 2 | config.vm.box = 'secretescapes/smartos-base64' 3 | config.vm.box_version = '1.0.0' 4 | config.vm.synced_folder './vagrant', '/usbkey/user_home/vagrant/vagrant', 5 | type: 'rsync', 6 | owner: 'vagrant', group: 'vagrant', 7 | disabled: false 8 | config.vm.synced_folder '.', '/usbkey/user_home/vagrant/ruby-libv8-node', 9 | type: 'rsync', 10 | rsync__exclude: ['.vagrant/', 'vagrant/', 'src/', 'pkg/', 'vendor/', 'Gemfile.lock', '*.so', '*.bundle', 'tmp/'], 11 | owner: 'vagrant', group: 'vagrant', 12 | disabled: false 13 | config.ssh.insert_key = false 14 | config.ssh.sudo_command = '/usr/bin/pfexec %c' 15 | config.solaris11.suexec_cmd = '/usr/bin/pfexec' 16 | config.solaris.suexec_cmd = '/usr/bin/pfexec' 17 | config.vm.provider 'virtualbox' do |v| 18 | v.customize ['modifyvm', :id, '--memory', 4096] 19 | v.customize ['modifyvm', :id, '--cpus', 2] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /ext/libv8-node/builder.rb: -------------------------------------------------------------------------------- 1 | unless $LOAD_PATH.include?(File.expand_path('../../lib', __dir__)) # rubocop:disable Style/IfUnlessModifier 2 | $LOAD_PATH.unshift(File.expand_path('../../lib', __dir__)) 3 | end 4 | require 'libv8/node/version' 5 | 6 | module Libv8::Node 7 | class BuilderError < StandardError; end 8 | 9 | class Builder 10 | def build_libv8! 11 | version = Libv8::Node::NODE_VERSION 12 | download_node(version) || raise(BuilderError, "failed to download node #{NODE_VERSION}") 13 | extract_node(version) || raise(BuilderError, "failed to extract node #{NODE_VERSION}") 14 | build_libv8(version) || raise(BuilderError, "failed to build libv8 #{NODE_VERSION}") 15 | build_monolith(version) || raise(BuilderError, "failed to build monolith #{NODE_VERSION}") 16 | inject_libv8(version) || raise(BuilderError, "failed to inject libv8 #{NODE_VERSION}") 17 | 18 | 0 19 | end 20 | 21 | def remove_intermediates! 22 | FileUtils.rm_rf(File.expand_path('../../src', __dir__)) 23 | end 24 | 25 | private 26 | 27 | def download_node(version) 28 | system(script('download-node'), version) 29 | end 30 | 31 | def extract_node(version) 32 | system(script('extract-node'), version) 33 | end 34 | 35 | def build_libv8(version) 36 | system(script('build-libv8'), version) 37 | end 38 | 39 | def build_monolith(version) 40 | system(script('build-monolith'), version) 41 | end 42 | 43 | def inject_libv8(version) 44 | system(script('inject-libv8'), version) 45 | end 46 | 47 | def script(name) 48 | File.expand_path("../../libexec/#{name}", __dir__).tap do |v| 49 | puts "==== in #{Dir.pwd}" 50 | puts "==== running #{v}" 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /ext/libv8-node/extconf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'mkmf' 4 | 5 | if RUBY_ENGINE == 'truffleruby' 6 | File.write('Makefile', dummy_makefile($srcdir).join('')) # rubocop:disable Style/GlobalVars 7 | return 8 | end 9 | 10 | create_makefile('libv8-node') 11 | 12 | require File.expand_path('location', __dir__) 13 | location = Libv8::Node::Location::Vendor.new 14 | 15 | exit location.install! 16 | -------------------------------------------------------------------------------- /ext/libv8-node/location.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yaml' 4 | require 'pathname' 5 | require File.expand_path('paths', __dir__) 6 | 7 | module Libv8; end 8 | 9 | module Libv8::Node 10 | class Location 11 | def install! 12 | File.open(Pathname(__FILE__).dirname.join('.location.yml'), 'w') do |f| 13 | f.write(to_yaml) 14 | end 15 | 16 | 0 17 | end 18 | 19 | def self.load! 20 | File.open(Pathname(__FILE__).dirname.join('.location.yml')) do |f| 21 | YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(f) : YAML.load(f) # rubocop:disable Security/YAMLLoad 22 | end 23 | end 24 | 25 | class Vendor < Location 26 | def install! 27 | require File.expand_path('builder', __dir__) 28 | 29 | builder = Libv8::Node::Builder.new 30 | exit_status = builder.build_libv8! 31 | builder.remove_intermediates! 32 | 33 | super if exit_status == 0 34 | 35 | verify_installation! 36 | 37 | exit_status 38 | end 39 | 40 | def configure(context = MkmfContext.new) 41 | context.incflags.insert(0, Libv8::Node::Paths.include_paths.map { |p| "-I#{p}" }.join(' ') << ' ') 42 | context.ldflags.insert(0, Libv8::Node::Paths.object_paths.join(' ') << ' ') 43 | end 44 | 45 | def verify_installation! 46 | include_paths = Libv8::Node::Paths.include_paths 47 | 48 | unless include_paths.detect { |p| Pathname(p).join('v8.h').exist? } # rubocop:disable Style/IfUnlessModifier 49 | raise(HeaderNotFound, "Unable to locate 'v8.h' in the libv8 header paths: #{include_paths.inspect}") 50 | end 51 | 52 | Libv8::Node::Paths.object_paths.each do |p| 53 | raise(ArchiveNotFound, p) unless File.exist?(p) 54 | end 55 | end 56 | 57 | class HeaderNotFound < StandardError; end 58 | 59 | class ArchiveNotFound < StandardError 60 | def initialize(filename) 61 | super "libv8 did not install properly, expected binary v8 archive '#{filename}'to exist, but it was not found" 62 | end 63 | end 64 | end 65 | 66 | class MkmfContext 67 | def incflags 68 | $INCFLAGS # rubocop:disable Style/GlobalVars 69 | end 70 | 71 | def ldflags 72 | $LDFLAGS # rubocop:disable Style/GlobalVars 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /ext/libv8-node/paths.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | require 'shellwords' 3 | 4 | module Libv8; end 5 | 6 | module Libv8::Node 7 | module Paths 8 | module_function 9 | 10 | def include_paths 11 | [Shellwords.escape(File.join(vendored_source_path, 'include'))] 12 | end 13 | 14 | def object_paths 15 | [Shellwords.escape(File.join(vendored_source_path, 16 | platform, 17 | 'libv8', 18 | 'obj', 19 | "libv8_monolith.#{config['LIBEXT']}"))] 20 | end 21 | 22 | def platform 23 | Gem::Platform.local.tap { |p| RUBY_PLATFORM =~ /musl/ && p.version.nil? && p.instance_eval { @version = 'musl' } }.to_s.gsub(/-darwin-?\d+/, '-darwin') 24 | end 25 | 26 | def config 27 | RbConfig::MAKEFILE_CONFIG 28 | end 29 | 30 | def vendored_source_path 31 | File.expand_path('../../vendor/v8', __dir__) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/libv8-node.rb: -------------------------------------------------------------------------------- 1 | require 'libv8/node' 2 | -------------------------------------------------------------------------------- /lib/libv8/node.rb: -------------------------------------------------------------------------------- 1 | require 'libv8/node/version' 2 | require 'libv8-node/location' 3 | 4 | module Libv8; end 5 | 6 | module Libv8::Node 7 | def self.configure_makefile 8 | location = Location.load! 9 | location.configure 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/libv8/node/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Libv8 4 | end 5 | 6 | module Libv8::Node 7 | VERSION = '22.7.0.1' 8 | NODE_VERSION = '22.7.0' 9 | LIBV8_VERSION = '12.4.254.21' # from src/node-.../deps/v8/include/v8-version.h 10 | end 11 | -------------------------------------------------------------------------------- /libexec/build-libv8: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | libexec="$(cd "$(dirname "$0")"; pwd)" 7 | top="${libexec}/.." 8 | src="${2:-"${top}/src"}" 9 | version="${1:-$("${libexec}/metadata" node_version)}" 10 | 11 | NJOBS="${NJOBS:-$(getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || true)}" 12 | NJOBS="${NJOBS:-1}" 13 | 14 | echo "parallel job count: ${NJOBS}" 15 | 16 | BUILDTYPE="${BUILDTYPE:-Release}" 17 | 18 | cd "${src}/node-v${version}" 19 | 20 | configure_flags='--openssl-no-asm --without-npm --shared --with-intl=full-icu' 21 | eval "$("${libexec}/platform")" 22 | 23 | echo "configure: ${configure_flags}" 24 | echo "compilers: CC='${CC}' CXX='${CXX}' CC_host='${CC_host:-}' CXX_host='${CXX_host:-}'" 25 | 26 | ${CC} -v 27 | ${CXX} -v 28 | 29 | # shellcheck disable=SC2086 30 | ./configure ${configure_flags} 31 | 32 | make BUILDTYPE="${BUILDTYPE}" config.gypi 33 | make BUILDTYPE="${BUILDTYPE}" "out/Makefile" 34 | 35 | # workaround for node specifying `-msign-return-address=all` in ALL `CFLAGS` for aarch64 builds 36 | # (if the host isn't also aarch64, this flag causes a compiler error) 37 | 38 | # shellcheck disable=SC2154 # these variables are defined by `eval`ing the output of the platform script above 39 | if [ "$host_platform" != "$target_platform" ] && [ "${target_platform%%-*}" = "aarch64" ]; then 40 | find . -iname "*.host.mk" -exec sed -i '/-msign-return-address/d' {} ';' 41 | fi 42 | 43 | export PATH="${PWD}/out/tools/bin:${PATH}" 44 | make -j"${NJOBS}" -C out BUILDTYPE="${BUILDTYPE}" V=0 45 | -------------------------------------------------------------------------------- /libexec/build-monolith: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | libexec="$(cd "$(dirname "$0")"; pwd)" 7 | top="${libexec}/.." 8 | src="${2:-"${top}/src"}" 9 | version="${1:-$("${libexec}/metadata" node_version)}" 10 | 11 | cd "${src}/node-v${version}" 12 | 13 | BASEDIR="${PWD}" 14 | BUILDTYPE="${BUILDTYPE:-Release}" 15 | LIBV8_MONOLITH="libv8_monolith.a" 16 | 17 | cd "out/${BUILDTYPE}/obj.target" 18 | 19 | platform=$(uname) 20 | 21 | rm -f "${LIBV8_MONOLITH}" 22 | case "${platform}" in 23 | "SunOS") 24 | /usr/xpg4/bin/find . '(' '!' -path './icutools/deps/icu-small/source/stubdata/stubdata.o' ')' -path "./torque_*/**/*.o" -or -path "./v8*/**/*.o" -or -path "./icu*/**/*.o" | sort | uniq | xargs ar cq "${LIBV8_MONOLITH}" 25 | ;; 26 | "Darwin") 27 | /usr/bin/find . '(' '!' -path './icutools/deps/icu-small/source/stubdata/stubdata.o' ')' -path "./torque_*/**/*.o" -or -path "./v8*/**/*.o" -or -path "./icu*/**/*.o" | sort | uniq | xargs /usr/bin/ar -cq "${LIBV8_MONOLITH}" 28 | ;; 29 | "Linux") 30 | find . '(' '!' -path './icutools/deps/icu-small/source/stubdata/stubdata.o' ')' -and '(' -path "./torque_*/**/*.o" -or -path "./v8*/**/*.o" -or -path "./icu*/**/*.o" ')' | sort | uniq | xargs ar -cqSP "${LIBV8_MONOLITH}" 31 | ar -sP "${LIBV8_MONOLITH}" 32 | ;; 33 | *) 34 | echo "Unsupported platform: ${platform}" 35 | exit 1 36 | ;; 37 | esac 38 | 39 | mv -f "${LIBV8_MONOLITH}" "${BASEDIR}/out/${BUILDTYPE}/${LIBV8_MONOLITH}" 40 | -------------------------------------------------------------------------------- /libexec/download-node: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | libexec="$(cd "$(dirname "$0")"; pwd)" 7 | top="${libexec}/.." 8 | src="${2:-"${top}/src"}" 9 | version="${1:-$("${libexec}/metadata" node_version)}" 10 | 11 | check_sum() { 12 | filename="${1}" 13 | expected="${2}" 14 | if command -v shasum >/dev/null; then 15 | echo "${expected} ${filename}" | shasum -c 16 | elif command -v gsha256sum >/dev/null; then 17 | echo "${expected} ${filename}" | gsha256sum -c 18 | else 19 | echo "${expected} ${filename}" | sha256sum -c 20 | fi 21 | } 22 | 23 | download() { 24 | file="${1}" 25 | url="${2}" 26 | 27 | platform="$(uname)" 28 | 29 | case "${platform}" in 30 | SunOS) 31 | CURLOPTS="${CURLOPTS:--k}" 32 | ;; 33 | *) 34 | CURLOPTS="${CURLOPTS:-}" 35 | ;; 36 | esac 37 | 38 | if command -v curl >/dev/null 2>&1; then 39 | # shellcheck disable=SC2086 40 | curl ${CURLOPTS} -L -o "${file}" "${url}" 41 | else 42 | wget -O "${file}" "${url}" 43 | fi 44 | } 45 | 46 | if [ -f "${top}/sums/v${version}.sum" ]; then 47 | sha256sum="$(cat "${top}/sums/v${version}.sum")" 48 | else 49 | sha256sum='0000000000000000000000000000000000000000000000000000000000000000' 50 | fi 51 | 52 | if [ -f "${src}/node-v${version}.tar.gz" ]; then 53 | if check_sum "${src}/node-v${version}.tar.gz" "${sha256sum}"; then 54 | exit 0 55 | fi 56 | fi 57 | 58 | mkdir -p "${src}" 59 | download "${src}/node-v${version}.tar.gz" "https://nodejs.org/dist/v${version}/node-v${version}.tar.gz" 60 | check_sum "${src}/node-v${version}.tar.gz" "${sha256sum}" && exit 0 61 | -------------------------------------------------------------------------------- /libexec/extract-node: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | libexec="$(cd "$(dirname "$0")"; pwd)" 7 | top="${libexec}/.." 8 | src="${2:-"${top}/src"}" 9 | version="${1:-$("${libexec}/metadata" node_version)}" 10 | 11 | extract() { 12 | dir="${1}" 13 | file="${2}" 14 | 15 | platform=$(uname) 16 | case "${platform}" in 17 | SunOS) 18 | TAR="${TAR:-gtar}" 19 | ;; 20 | *) 21 | TAR="${TAR:-tar}" 22 | ;; 23 | esac 24 | 25 | "${TAR}" -C "${dir}" -xz -f "${file}" 26 | } 27 | 28 | extract "${src}" "${src}/node-v${version}.tar.gz" 29 | 30 | cd "${src}/node-v${version}" 31 | 32 | #patch -p1 < "${top}"/patch/gyp-libv8_monolith.patch 33 | #patch -p1 < "${top}"/patch/py2-icutrim.patch 34 | #patch -p1 < "${top}"/patch/py2-genv8constants.patch 35 | patch -p1 < "${top}"/patch/v8-no-assert-trivially-copyable.patch 36 | patch -p1 < "${top}"/patch/v8-disable-madv-dontfork.patch 37 | patch -p1 < "${top}"/patch/v8-disable-pkey.patch 38 | 39 | # TODO: the following still fails on py3 so the above one forcing py2 is needed 40 | # patch -p1 < ../../py3-genv8constants.patch 41 | # 42 | # This is the error: 43 | # 44 | # Traceback (most recent call last): 45 | # File "tools/genv8constants.py", line 99, in 46 | # curr_val += int('0x%s' % octetstr, 16) << (curr_octet * 8) 47 | # ValueError: invalid literal for int() with base 16: "0xb'04 '" 48 | # node_dtrace_ustack.target.mk:13: recipe for target '/usbkey/user_home/vagrant/ruby-libv8-node/src/node-14.14.0/out/Release/obj/gen/v8constants.h' failed 49 | -------------------------------------------------------------------------------- /libexec/inject-libv8: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | libexec="$(cd "$(dirname "$0")"; pwd)" 7 | top="${libexec}/.." 8 | src="${2:-"${top}/src"}" 9 | version="${1:-$("${libexec}/metadata" node_version)}" 10 | 11 | cd "${src}/node-v${version}" 12 | 13 | BASEDIR="${PWD}" 14 | BUILDTYPE="${BUILDTYPE:-Release}" 15 | 16 | eval "$("${libexec}/platform")" 17 | 18 | cd "${BASEDIR}/deps/v8/include" 19 | 20 | rm -rf "${top}/vendor/v8/include" 21 | find . -name '*.h' | while read -r header; do 22 | dir="${top}/vendor/v8/include/$(dirname "${header}")" 23 | mkdir -p "${dir}" 24 | cp "${header}" "${dir}" 25 | done 26 | 27 | cd "${BASEDIR}/out/${BUILDTYPE}" 28 | 29 | case "${RUBY_TARGET_PLATFORM}" in 30 | *-darwin*) 31 | RUBY_TARGET_PLATFORM="$(echo "${RUBY_TARGET_PLATFORM}" | sed -e 's/-darwin[0-9]*/-darwin/')" 32 | ;; 33 | esac 34 | 35 | rm -rf "${top}/vendor/v8/${RUBY_TARGET_PLATFORM}" 36 | # shellcheck disable=SC2043 37 | for lib in libv8_monolith.a; do 38 | dir="${top}/vendor/v8/${RUBY_TARGET_PLATFORM}/libv8/obj/$(dirname "${lib}")" 39 | mkdir -p "${dir}" 40 | rm -f "${dir}/${lib}" 41 | 42 | if [ "$STRIP_NEEDS_EXTRACT" = "y" ]; then 43 | # manual extract/strip objects/build archive sequence 44 | # because `strip` can't deal with these 45 | # (presumably due to that folder issue mentioned below) 46 | ( 47 | tmpdir="$(mktemp -d)" 48 | trap 'rm -r "$tmpdir"' EXIT 49 | mkdir "$tmpdir/stage" 50 | cd "$tmpdir/stage" 51 | 52 | # create folders named in `ar` archive (`ar -x` fails to create these) 53 | "$AR" "$ARLISTFLAGS" "$BASEDIR/out/$BUILDTYPE/$lib" | while read -r path; do 54 | dirname "$path" 55 | done | uniq | xargs mkdir -p 56 | "$AR" "$AREXTRACTFLAGS" "$BASEDIR/out/${BUILDTYPE}/$lib" 57 | 58 | # strip all objects 59 | "$FIND" -type f -exec "$STRIP" -Sx {} + 60 | 61 | # rebuild the archive 62 | "$FIND" -type f -exec "$AR" "$ARCOLLECTFLAGS" "../$lib" {} + 63 | $ARBUILDSYMBOLS "../$lib" 64 | mv "../$lib" "$dir/$lib" 65 | ) 66 | echo "${BASEDIR}/out/${BUILDTYPE}/${lib} -> ${dir}/${lib}" 67 | else 68 | echo "${BASEDIR}/out/${BUILDTYPE}/${lib} -> ${dir}/${lib}" 69 | "${STRIP}" -S -x -o "${dir}/${lib}" "${lib}" 70 | fi 71 | done 72 | 73 | mkdir -p "${top}/ext/libv8-node" 74 | echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' > "${top}/ext/libv8-node/.location.yml" 75 | -------------------------------------------------------------------------------- /libexec/metadata: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case "$1" in 4 | ruby_platform) 5 | ruby -e 'puts RUBY_PLATFORM' 6 | ;; 7 | gem_platform) 8 | ruby -e 'puts Gem::Platform.local.tap { |p| RUBY_PLATFORM =~ /musl/ && p.version.nil? and p.instance_eval { @version = "musl" } }.to_s.gsub(/-darwin-?\d+/, "-darwin")' 9 | ;; 10 | gem_version|version) 11 | ruby -I'lib' -r'libv8/node/version' -e 'puts Libv8::Node::VERSION' 12 | ;; 13 | node_version) 14 | ruby -I'lib' -r'libv8/node/version' -e 'puts Libv8::Node::NODE_VERSION' 15 | ;; 16 | libv8_version) 17 | ruby -I'lib' -r'libv8/node/version' -e 'puts Libv8::Node::LIBV8_VERSION' 18 | ;; 19 | libv8_version_h) 20 | # shellcheck disable=SC2016 21 | ruby -e 'h = File.read("src/node-v'"$("$0" node_version)"'/deps/v8/include/v8-version.h"); eval h.each_line.with_object([]) { |l, e| l =~ /#define (V8_[A-Z_]+)\s(\d+)/ && e << "#{$1} = #{$2}" }.join(";"); puts "#{V8_MAJOR_VERSION}.#{V8_MINOR_VERSION}.#{V8_BUILD_NUMBER}.#{V8_PATCH_LEVEL}"' 22 | ;; 23 | *) 24 | exit 64 25 | ;; 26 | esac 27 | -------------------------------------------------------------------------------- /libexec/platform: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -u 5 | 6 | if command -v clang >/dev/null 2>&1; then 7 | CC="${CC:-clang}" 8 | CXX="${CXX:-clang++}" 9 | elif command -v gcc >/dev/null 2>&1; then 10 | CC="${CC:-gcc}" 11 | CXX="${CXX:-g++}" 12 | elif command -v cc >/dev/null 2>&1; then 13 | CC="${CC:-cc}" 14 | CXX="${CXX:-c++}" 15 | fi 16 | 17 | STRIP="${STRIP:-strip}" 18 | AR="${AR:-ar}" 19 | AREXTRACTFLAGS="${AREXTRACTFLAGS:--x}" 20 | ARLISTFLAGS="${ARLISTFLAGS:--t}" 21 | ARCOLLECTFLAGS="${ARCOLLECTFLAGS:-cqS}" 22 | # this is the command to build the symbol table in an ar archive. 23 | ARBUILDSYMBOLS="${ARBUILDSYMBOLS:-ranlib}" 24 | FIND="${FIND:-find}" 25 | STRIP_NEEDS_EXTRACT="${STRIP_NEEDS_EXTRACT:-n}" 26 | 27 | triple=$(${CC} -dumpmachine) 28 | host_platform="${triple}" 29 | target_platform="${TARGET_PLATFORM:-${1:-}}" 30 | target_platform="${target_platform:-${host_platform}}" 31 | 32 | case "${target_platform}" in 33 | x86_64*-linux-musl) 34 | RUBY_TARGET_PLATFORM='x86_64-linux-musl' 35 | ;; 36 | x86_64*-linux-*) 37 | RUBY_TARGET_PLATFORM='x86_64-linux' 38 | ;; 39 | aarch64*-linux-musl) 40 | RUBY_TARGET_PLATFORM='aarch64-linux-musl' 41 | ;; 42 | aarch64*-linux-*) 43 | RUBY_TARGET_PLATFORM='aarch64-linux' 44 | ;; 45 | arm*-linux-musl) 46 | RUBY_TARGET_PLATFORM='arm-linux-musl' 47 | ;; 48 | arm*-linux-*) 49 | RUBY_TARGET_PLATFORM='arm-linux' 50 | ;; 51 | x86_64*-darwin*) 52 | # not for cross compilation 53 | RUBY_TARGET_PLATFORM='x86_64-darwin' 54 | ;; 55 | arm64*-darwin*) 56 | # not for cross compilation 57 | RUBY_TARGET_PLATFORM='arm64-darwin' 58 | ;; 59 | *) 60 | if [ "${host_platform}" != "${target_platform}" ]; then 61 | echo 'cross compilation not supported' 62 | exit 1 63 | fi 64 | RUBY_TARGET_PLATFORM="$(ruby -e 'puts Gem::Platform.local.to_s')" 65 | ;; 66 | esac 67 | 68 | case "${host_platform}" in 69 | *solaris*) 70 | CC="${CC:-/opt/local/gcc7/bin/gcc}" 71 | CXX="${CXX:-/opt/local/gcc7/bin/g++}" 72 | STRIP="gstrip" 73 | ;; 74 | *linux*) 75 | STRIP_NEEDS_EXTRACT="y" 76 | ARCOLLECTFLAGS="-cqSP" 77 | ARBUILDSYMBOLS="${AR} -sP" 78 | ;; 79 | esac 80 | 81 | if [ "${host_platform}" != "${target_platform}" ]; then 82 | echo "# cross compiling host: ${host_platform} target: ${target_platform}" 83 | case "${target_platform}" in 84 | aarch64-*linux*) 85 | CC='aarch64-linux-gnu-gcc' 86 | CXX='aarch64-linux-gnu-g++' 87 | CC_host='gcc' 88 | CXX_host='g++' 89 | STRIP='aarch64-linux-gnu-strip' 90 | configure_flags='--dest-cpu=arm64 --cross-compiling --dest-os=linux --with-arm-float-abi=hard --with-arm-fpu=neon' 91 | ;; 92 | arm*-*linux*) 93 | CC='arm-linux-gnueabihf-gcc' 94 | CXX='arm-linux-gnueabihf-g++' 95 | CC_host='gcc -m32' 96 | CXX_host='g++ -m32' 97 | STRIP='arm-linux-gnueabihf-strip' 98 | configure_flags='--dest-cpu=arm --cross-compiling --dest-os=linux --with-arm-float-abi=hard --with-arm-fpu=neon' 99 | ;; 100 | x86_64-*linux*) 101 | CC='x86_64-linux-gnu-gcc' 102 | CXX='x86_64-linux-gnu-g++' 103 | CC_host='gcc' 104 | CXX_host='g++' 105 | STRIP='x86_64-linux-gnu-strip' 106 | configure_flags='--dest-cpu=x86_64 --cross-compiling --dest-os=linux' 107 | ;; 108 | x86_64*-darwin*) 109 | CC='clang -arch x86_64' 110 | CXX='clang++ -arch x86_64' 111 | CC_host='clang' 112 | CXX_host='clang++' 113 | STRIP='strip' 114 | configure_flags='--dest-cpu=x86_64 --cross-compiling --dest-os=mac' 115 | ;; 116 | arm64*-darwin*) 117 | CC='clang -arch arm64' 118 | CXX='clang++ -arch arm64' 119 | CC_host='clang' 120 | CXX_host='clang++' 121 | STRIP='strip' 122 | configure_flags='--dest-cpu=arm64 --cross-compiling --dest-os=mac' 123 | ;; 124 | *) 125 | configure_flags='' 126 | ;; 127 | esac 128 | else 129 | configure_flags='' 130 | fi 131 | 132 | # TODO: building with pointer compression is broken 133 | # case "${target_platform}" in 134 | # arm64-*) 135 | # configure_flags="${configure_flags} --experimental-enable-pointer-compression" 136 | # ;; 137 | # arm*-*linux*) 138 | # : 139 | # ;; 140 | # *) 141 | # configure_flags="${configure_flags} --experimental-enable-pointer-compression" 142 | # ;; 143 | # esac 144 | 145 | if command -v ccache >/dev/null 2>&1; then 146 | if [ -n "${CC:-}" ] && [ "${CC}" = "${CC#ccache}" ]; then 147 | CC="ccache ${CC}" 148 | CXX="ccache ${CXX}" 149 | fi 150 | 151 | if [ -n "${CC_host:-}" ] && [ "${CC_host}" = "${CC_host#ccache}" ]; then 152 | CC_host="ccache ${CC_host}" 153 | CXX_host="ccache ${CXX_host}" 154 | fi 155 | fi 156 | 157 | cat < 12' 26 | s.add_development_dependency 'rubocop', '~> 1.44.0' 27 | end 28 | -------------------------------------------------------------------------------- /patch/gyp-libv8_monolith.patch: -------------------------------------------------------------------------------- 1 | --- a/node.gyp 2020-11-04 15:55:48.000000000 +0100 2 | +++ b/node.gyp 2020-11-04 15:55:51.000000000 +0100 3 | @@ -1467,6 +1467,16 @@ 4 | }], 5 | ], 6 | }, # node_mksnapshot 7 | + { 8 | + 'target_name': 'libv8_monolith', 9 | + 'type': 'none', 10 | + 'includes': [ 11 | + 'node.gypi' 12 | + ], 13 | + #'dependencies': [ 14 | + # 'tools/v8_gypfiles/v8.gyp:v8_monolith', 15 | + #], 16 | + }, 17 | ], # end targets 18 | 19 | 'conditions': [ 20 | --- a/tools/v8_gypfiles/v8.gyp 2020-11-04 16:34:06.000000000 +0100 21 | +++ b/tools/v8_gypfiles/v8.gyp 2020-11-04 16:34:10.000000000 +0100 22 | @@ -1726,5 +1726,21 @@ 23 | '<(V8_ROOT)/third_party/zlib/google/compression_utils_portable.h', 24 | ], 25 | }, # v8_zlib 26 | + { 27 | + 'target_name': 'v8_monolith', 28 | + 'type': 'static_library', 29 | + 'sources': [ 30 | + ':')) 8 | -v8dbg = re.compile(bytes('^v8dbg.*$')) 9 | -numpattern = re.compile(bytes('^[0-9a-fA-F]{2} $')) 10 | +if str == bytes: 11 | + pattern = re.compile(bytes('([0-9a-fA-F]{8}|[0-9a-fA-F]{16}) <(.*)>:')) 12 | + v8dbg = re.compile(bytes('^v8dbg.*$')) 13 | + numpattern = re.compile(bytes('^[0-9a-fA-F]{2} $')) 14 | +else: 15 | + pattern = re.compile(bytes('([0-9a-fA-F]{8}|[0-9a-fA-F]{16}) <(.*)>:', 'utf-8')) 16 | + v8dbg = re.compile(bytes('^v8dbg.*$', 'utf-8')) 17 | + numpattern = re.compile(bytes('^[0-9a-fA-F]{2} $', 'utf-8')) 18 | octets = 4 19 | 20 | outfile.write(""" 21 | -------------------------------------------------------------------------------- /patch/v8-disable-madv-dontfork.patch: -------------------------------------------------------------------------------- 1 | diff --git a/tools/v8_gypfiles/features.gypi b/tools/v8_gypfiles/features.gypi 2 | index 6e21dac6d7..bcf022fb28 100644 3 | --- a/tools/v8_gypfiles/features.gypi 4 | +++ b/tools/v8_gypfiles/features.gypi 5 | @@ -73,7 +73,10 @@ 6 | }, { 7 | 'v8_enable_etw_stack_walking': 0, 8 | }], 9 | - ['OS=="linux"', { 10 | + # Disable madvise(MADV_DONTFORK), it's a great optimization for programs 11 | + # that fork & exec but not for programs that fork and keep running. 12 | + # It makes mini_racer's test/test_forking.rb test segfault. 13 | + ['False and OS=="linux"', { 14 | # Sets -dV8_ENABLE_PRIVATE_MAPPING_FORK_OPTIMIZATION. 15 | # 16 | # This flag speeds up the performance of fork/execve on Linux systems for 17 | -------------------------------------------------------------------------------- /patch/v8-disable-pkey.patch: -------------------------------------------------------------------------------- 1 | diff --git a/deps/v8/src/base/build_config.h b/deps/v8/src/base/build_config.h 2 | index 9ed4c8f102..dfca698506 100644 3 | --- a/deps/v8/src/base/build_config.h 4 | +++ b/deps/v8/src/base/build_config.h 5 | @@ -35,11 +35,8 @@ 6 | #define V8_HAS_PTHREAD_JIT_WRITE_PROTECT 0 7 | #endif 8 | 9 | -#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) 10 | -#define V8_HAS_PKU_JIT_WRITE_PROTECT 1 11 | -#else 12 | +// disabled, see https://issues.chromium.org/issues/360909072 13 | #define V8_HAS_PKU_JIT_WRITE_PROTECT 0 14 | -#endif 15 | 16 | #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) 17 | #define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK true 18 | -------------------------------------------------------------------------------- /patch/v8-no-assert-trivially-copyable.patch: -------------------------------------------------------------------------------- 1 | diff --git a/deps/v8/src/base/small-vector.h b/deps/v8/src/base/small-vector.h 2 | index edaab3a7a6..533a536178 100644 3 | --- a/deps/v8/src/base/small-vector.h 4 | +++ b/deps/v8/src/base/small-vector.h 5 | @@ -20,9 +20,6 @@ namespace base { 6 | // dynamic storage when it overflows. 7 | template > 8 | class SmallVector { 9 | - // Currently only support trivially copyable and trivially destructible data 10 | - // types, as it uses memcpy to copy elements and never calls destructors. 11 | - ASSERT_TRIVIALLY_COPYABLE(T); 12 | static_assert(std::is_trivially_destructible::value); 13 | 14 | public: 15 | -------------------------------------------------------------------------------- /sums/v16.10.0.sum: -------------------------------------------------------------------------------- 1 | 69b09bb0c4cd9add7eb501b1625a405b15d6ce53596e98b863c8d066e0b6b202 2 | -------------------------------------------------------------------------------- /sums/v16.11.1.sum: -------------------------------------------------------------------------------- 1 | 8b5a54b284e524984772d34dc2efc68a10fc2f91db11390c6035ef2a9509ef2c 2 | -------------------------------------------------------------------------------- /sums/v16.3.0.sum: -------------------------------------------------------------------------------- 1 | 11d00034a9864660eadf9835d09de2bed97b245093626705d8917897d8f36704 2 | -------------------------------------------------------------------------------- /sums/v16.4.2.sum: -------------------------------------------------------------------------------- 1 | 46d907a06fe020ee8d7e6753357b82edd16f3871f8caaa188841d29d265de7bd 2 | -------------------------------------------------------------------------------- /sums/v16.5.0.sum: -------------------------------------------------------------------------------- 1 | a0d233cde072822af7fd3043b866e526a1739df32c3ace6210ae289f3266ccb7 2 | -------------------------------------------------------------------------------- /sums/v16.6.2.sum: -------------------------------------------------------------------------------- 1 | e8df4a0084c379a37c11b315b7d068760a38598119d7ca9262977adcbbb58933 2 | -------------------------------------------------------------------------------- /sums/v16.7.0.sum: -------------------------------------------------------------------------------- 1 | 0c4a82acc5ae67744d56f2c97db54b859f2b3ef8e78deacfb8aed0ed4c7cb690 2 | -------------------------------------------------------------------------------- /sums/v16.8.0.sum: -------------------------------------------------------------------------------- 1 | 0cc13572bc7c5a9bf7a2c5cb2800ff045780e43d0fa6e3eb0f1be46b4bf9a1c6 2 | -------------------------------------------------------------------------------- /sums/v16.9.1.sum: -------------------------------------------------------------------------------- 1 | 2cfab037d84550556999af6328e9b657842d9b183e6be2a4995c87d2c49e9d03 2 | -------------------------------------------------------------------------------- /sums/v17.3.1.sum: -------------------------------------------------------------------------------- 1 | 34ed7eeb1fd088c59e2719c229dc9587c9f106b45329798ca3945c386ac824ed -------------------------------------------------------------------------------- /sums/v17.9.1.sum: -------------------------------------------------------------------------------- 1 | 1102f5e0aafaab8014d19c6c57142caf2ba3ef69d88d7a7f0f82798051796027 2 | -------------------------------------------------------------------------------- /sums/v18.13.0.sum: -------------------------------------------------------------------------------- 1 | 61ae68446438c2479e466d551b6e8c898097d56722957b1a8466ec8476a590d2 2 | 3 | -------------------------------------------------------------------------------- /sums/v18.8.0.sum: -------------------------------------------------------------------------------- 1 | 676a3ca9bdbe7381e49652f2f78705f83175f3844a7450893d562faa35537ba2 2 | -------------------------------------------------------------------------------- /sums/v19.9.0.sum: -------------------------------------------------------------------------------- 1 | c9293eb40dff8e5f55ef8da7cf1b9fd71b4a6a513620d02bbd158936e85216f2 2 | -------------------------------------------------------------------------------- /sums/v20.12.1.sum: -------------------------------------------------------------------------------- 1 | b9bef0314e12773ef004368ee56a2db509a948d4170b9efb07441bac1f1407a0 2 | -------------------------------------------------------------------------------- /sums/v20.2.0.sum: -------------------------------------------------------------------------------- 1 | cd1b0eb67fffe83112034fbdc64b363287e017f835251702f041982633e4b6aa 2 | -------------------------------------------------------------------------------- /sums/v21.7.2.sum: -------------------------------------------------------------------------------- 1 | dc1b18771e7ed3da051fc2242806bfde5ae02b63fe7205e80156e92de8f8fa3d 2 | -------------------------------------------------------------------------------- /sums/v22.5.1.sum: -------------------------------------------------------------------------------- 1 | 4a1b383f6036def4bb183f18e71a10b58784db269f9953618418bbaf47692972 2 | -------------------------------------------------------------------------------- /sums/v22.6.0.sum: -------------------------------------------------------------------------------- 1 | af4a8747651385515163db5da0d2e217da15cf7c832672b234128ed5118f086d 2 | -------------------------------------------------------------------------------- /sums/v22.7.0.sum: -------------------------------------------------------------------------------- 1 | 7a7c99282d59866d971b2da12c99596cb15782b9c3efe2e2146390c14f4d490e 2 | -------------------------------------------------------------------------------- /test/gtest/.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt.user 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | _deps 12 | build 13 | lib 14 | bin 15 | -------------------------------------------------------------------------------- /test/gtest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(gtest) 3 | 4 | # V8 requires at least C++17 5 | set(CMAKE_CXX_STANDARD 17) 6 | 7 | include(FetchContent) 8 | FetchContent_Declare( 9 | googletest 10 | URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip 11 | ) 12 | # For Windows: Prevent overriding the parent project's compiler/linker settings 13 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 14 | FetchContent_MakeAvailable(googletest) 15 | 16 | enable_testing() 17 | 18 | include_directories(${CMAKE_SOURCE_DIR}/../../vendor/v8/include/) 19 | 20 | add_executable( 21 | c_v8_tests 22 | c_v8_tests.cc 23 | ) 24 | target_link_libraries( 25 | c_v8_tests 26 | GTest::gtest_main 27 | ) 28 | 29 | string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) 30 | string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} system_arch) 31 | 32 | set(vendor_arch "${system_arch}-${system_name}") 33 | 34 | if(${system_name} STREQUAL "linux") 35 | try_compile(is_glibc ${CMAKE_BINARY_DIR}/check_glibc ${CMAKE_SOURCE_DIR}/check_glibc.c) 36 | if(NOT is_glibc) 37 | # assume non-glibc is musl-libc 38 | string(APPEND vendor_arch "-musl") 39 | endif() 40 | endif() 41 | 42 | message(STATUS "Detected vendor architecture directory: ${vendor_arch}") 43 | 44 | # TODO?: Detect and support ruby-arch builds? 45 | target_link_libraries(c_v8_tests ${CMAKE_SOURCE_DIR}/../../vendor/v8/${vendor_arch}/libv8/obj/libv8_monolith.a) 46 | 47 | # This has to be after the v8 monolith for some build setups. 48 | target_link_libraries(c_v8_tests dl) 49 | 50 | include(GoogleTest) 51 | gtest_discover_tests(c_v8_tests) 52 | -------------------------------------------------------------------------------- /test/gtest/Framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct Framework { 8 | typedef std::function basic_main; 9 | typedef std::function iso_main; 10 | typedef std::function&)> ctx_main; 11 | 12 | inline static void run(basic_main main) { 13 | std::shared_ptr platform = v8::platform::NewDefaultPlatform(); 14 | v8::V8::InitializePlatform(platform.get()); 15 | v8::V8::Initialize(); 16 | main(); 17 | 18 | v8::V8::Dispose(); 19 | v8::V8::DisposePlatform(); 20 | } 21 | 22 | inline static void runWithIsolateRaw(iso_main main) { 23 | Framework::run([main]() -> void { 24 | v8::Isolate::CreateParams p; 25 | p.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); 26 | v8::Isolate* iso = v8::Isolate::New(p); 27 | 28 | main(iso); 29 | 30 | iso->Dispose(); 31 | delete p.array_buffer_allocator; 32 | }); 33 | } 34 | 35 | inline static void runWithIsolate(iso_main main) { 36 | Framework::runWithIsolateRaw([main](v8::Isolate* iso) -> void { 37 | v8::Locker lock { iso }; 38 | v8::Isolate::Scope iScope { iso }; 39 | v8::HandleScope hScope { iso }; 40 | 41 | main(iso); 42 | }); 43 | } 44 | 45 | inline static void runWithContext(ctx_main main) { 46 | Framework::runWithIsolate([main](v8::Isolate* iso) -> void { 47 | v8::Local ctx = v8::Context::New(iso); 48 | v8::Context::Scope cScope { ctx }; 49 | 50 | main(ctx); 51 | }); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /test/gtest/c_v8_tests.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "Framework.h" 7 | 8 | // Demonstrate some basic assertions. 9 | TEST(FRLocaleTest, LocaleTests) { 10 | Framework::runWithContext([](v8::Local& ctx) -> void { 11 | v8::Local script = v8::Script::Compile(ctx, v8::String::NewFromUtf8Literal(ctx->GetIsolate(), "new Date('April 28 2021').toLocaleDateString('fr-FR');")).ToLocalChecked(); 12 | v8::Local result = script->Run(ctx).ToLocalChecked(); 13 | v8::Local resultStr = result->ToString(ctx).ToLocalChecked(); 14 | v8::String::Utf8Value resultUTF8(ctx->GetIsolate(), resultStr); 15 | 16 | EXPECT_STREQ(*resultUTF8, "28/04/2021"); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/gtest/check_glibc.c: -------------------------------------------------------------------------------- 1 | #warning "This is not a source file -- it exists purely to allow CMake to distinguish between glibc and musl-libc. If you see this message, you are likely doing something incorrectly." 2 | 3 | #include 4 | 5 | #ifndef __GLIBC__ 6 | #error "__GLIBC__ is undef -- not glibc!" 7 | #endif 8 | 9 | int main() { } 10 | 11 | -------------------------------------------------------------------------------- /vagrant/provision-smartos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pfexec pkgin update 4 | pfexec pkgin -yV in clang gcc49 gcc7 git gmake patch ruby24 5 | pfexec gem install bundler -v '~> 2.1.4' 6 | 7 | --------------------------------------------------------------------------------