Skip to content

Commit d0fa608

Browse files
cjihrigShogunPanda
andcommitted
lib,src,test,doc: add node:ffi module
PR-URL: #62072 Co-authored-by: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Bryan English <bryan@bryanenglish.com>
1 parent d080801 commit d0fa608

File tree

262 files changed

+79237
-25
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

262 files changed

+79237
-25
lines changed

.github/workflows/test-shared.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ jobs:
196196
--arg ccache "${NIX_SCCACHE:-null}" \
197197
--arg devTools '[]' \
198198
--arg benchmarkTools '[]' \
199-
${{ endsWith(matrix.system, '-darwin') && '--arg withAmaro false --arg withLief false --arg withSQLite false --arg extraConfigFlags ''["--without-inspector" "--without-node-options"]'' \' || '\' }}
199+
${{ endsWith(matrix.system, '-darwin') && '--arg withAmaro false --arg withLief false --arg withSQLite false --arg withFFI false --arg extraConfigFlags ''["--without-inspector" "--without-node-options"]'' \' || '\' }}
200200
--run '
201201
make -C "$TAR_DIR" run-ci -j4 V=1 TEST_CI_ARGS="-p actions --measure-flakiness 9 --skip-tests=$CI_SKIP_TESTS"
202202
' "$TAR_DIR/shell.nix"

.github/workflows/tools.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ on:
2626
- histogram
2727
- icu
2828
- inspector_protocol
29+
- libffi
2930
- libuv
3031
- llhttp
3132
- minimatch
@@ -161,6 +162,14 @@ jobs:
161162
cat temp-output
162163
tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true
163164
rm temp-output
165+
- id: libffi
166+
subsystem: deps
167+
label: dependencies, ffi
168+
run: |
169+
./tools/dep_updaters/update-libffi.sh > temp-output
170+
cat temp-output
171+
tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true
172+
rm temp-output
164173
- id: libuv
165174
subsystem: deps
166175
label: dependencies

Makefile

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ v8: ## Build deps/v8.
318318
tools/make-v8.sh $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS)
319319

320320
.PHONY: jstest
321-
jstest: build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests ## Run addon tests and JS tests.
321+
jstest: build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests build-ffi-tests ## Run addon tests and JS tests.
322322
$(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \
323323
$(TEST_CI_ARGS) \
324324
--skip-tests=$(CI_SKIP_TESTS) \
@@ -344,6 +344,7 @@ test: all ## Run default tests and build docs.
344344
$(MAKE) -s build-js-native-api-tests
345345
$(MAKE) -s build-node-api-tests
346346
$(MAKE) -s build-sqlite-tests
347+
$(MAKE) -s build-ffi-tests
347348
$(MAKE) -s cctest
348349
$(MAKE) -s jstest
349350

@@ -353,6 +354,7 @@ test-only: all ## Run default tests without building the docs.
353354
$(MAKE) build-js-native-api-tests
354355
$(MAKE) build-node-api-tests
355356
$(MAKE) build-sqlite-tests
357+
$(MAKE) build-ffi-tests
356358
$(MAKE) cctest
357359
$(MAKE) jstest
358360
$(MAKE) tooltest
@@ -364,6 +366,7 @@ test-cov: all ## Run coverage tests.
364366
$(MAKE) build-js-native-api-tests
365367
$(MAKE) build-node-api-tests
366368
$(MAKE) build-sqlite-tests
369+
$(MAKE) build-ffi-tests
367370
$(MAKE) cctest
368371
CI_SKIP_TESTS=$(COV_SKIP_TESTS) $(MAKE) jstest
369372

@@ -542,6 +545,29 @@ else
542545
build-sqlite-tests:
543546
endif
544547

548+
FFI_BINDING_GYPS := $(wildcard test/ffi/*/binding.gyp)
549+
550+
FFI_BINDING_SOURCES := \
551+
$(wildcard test/ffi/*/*.c) \
552+
$(wildcard test/ffi/*/*.def)
553+
554+
ifndef NOFFI
555+
# Depends on $(NODE_EXE) as order-only to avoid ETXTBSY on AIX when make
556+
# tries to execute node while it is still being linked in parallel.
557+
test/ffi/.buildstamp: $(ADDONS_PREREQS) \
558+
$(FFI_BINDING_GYPS) $(FFI_BINDING_SOURCES) | $(NODE_EXE)
559+
@$(call run_build_addons,"$$PWD/test/ffi",$@)
560+
else
561+
test/ffi/.buildstamp:
562+
endif
563+
564+
.PHONY: build-ffi-tests
565+
ifndef NOFFI
566+
build-ffi-tests: | test/ffi/.buildstamp ## Build FFI tests.
567+
else
568+
build-ffi-tests:
569+
endif
570+
545571
.PHONY: clear-stalled
546572
clear-stalled: ## Clear any stalled processes.
547573
$(info Clean up any leftover processes but don't error if found.)
@@ -552,7 +578,7 @@ clear-stalled: ## Clear any stalled processes.
552578
fi
553579

554580
.PHONY: test-build
555-
test-build: | all build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests ## Build all tests.
581+
test-build: | all build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests build-ffi-tests ## Build all tests.
556582

557583
.PHONY: test-build-js-native-api
558584
test-build-js-native-api: all build-js-native-api-tests ## Build JS Native-API tests.
@@ -563,6 +589,8 @@ test-build-node-api: all build-node-api-tests ## Build Node-API tests.
563589
.PHONY: test-build-sqlite
564590
test-build-sqlite: all build-sqlite-tests ## Build SQLite tests.
565591

592+
.PHONY: test-build-ffi
593+
test-build-ffi: all build-ffi-tests ## Build FFI tests.
566594

567595
.PHONY: test-all
568596
test-all: test-build ## Run default tests with both Debug and Release builds.
@@ -591,7 +619,7 @@ endif
591619

592620
# Related CI job: node-test-commit-arm-fanned
593621
test-ci-native: LOGLEVEL := info ## Build and test addons without building anything else.
594-
test-ci-native: | benchmark/napi/.buildstamp test/addons/.buildstamp test/js-native-api/.buildstamp test/node-api/.buildstamp test/sqlite/.buildstamp
622+
test-ci-native: | benchmark/napi/.buildstamp test/addons/.buildstamp test/js-native-api/.buildstamp test/node-api/.buildstamp test/sqlite/.buildstamp test/ffi/.buildstamp
595623
$(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \
596624
--mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \
597625
$(TEST_CI_ARGS) $(CI_NATIVE_SUITES)
@@ -614,7 +642,7 @@ test-ci-js: | clear-stalled ## Build and test JavaScript with building anything
614642
.PHONY: test-ci
615643
# Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned
616644
test-ci: LOGLEVEL := info ## Build and test everything (CI).
617-
test-ci: | clear-stalled bench-addons-build build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests doc-only
645+
test-ci: | clear-stalled bench-addons-build build-addons build-js-native-api-tests build-node-api-tests build-sqlite-tests build-ffi-tests doc-only
618646
out/Release/cctest --gtest_output=xml:out/junit/cctest.xml
619647
$(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \
620648
--mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \
@@ -632,6 +660,7 @@ test-ci: | clear-stalled bench-addons-build build-addons build-js-native-api-tes
632660
build-ci: ## Build everything (CI).
633661
$(PYTHON) ./configure --verbose $(CONFIG_FLAGS)
634662
$(MAKE)
663+
$(MAKE) build-ffi-tests
635664

636665
.PHONY: run-ci
637666
# Run by CI tests, exceptions:
@@ -734,6 +763,16 @@ test-sqlite-clean: ## Remove SQLite testing artifacts.
734763
$(RM) -r test/sqlite/*/build
735764
$(RM) test/sqlite/.buildstamp
736765

766+
.PHONY: test-ffi
767+
test-ffi: test-build-ffi ## Run FFI tests.
768+
$(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) ffi
769+
770+
.PHONY: test-ffi-clean
771+
.NOTPARALLEL: test-ffi-clean
772+
test-ffi-clean: ## Remove FFI testing artifacts.
773+
$(RM) -r test/ffi/*/build
774+
$(RM) test/ffi/.buildstamp
775+
737776
.PHONY: test-addons
738777
test-addons: test-build test-js-native-api test-node-api ## Run addon tests.
739778
$(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) addons
@@ -1228,6 +1267,7 @@ ifeq ($(SKIP_SHARED_DEPS), 1)
12281267
$(RM) -r $(TARNAME)/deps/icu-small
12291268
$(RM) -r $(TARNAME)/deps/icu-tmp
12301269
$(RM) -r $(TARNAME)/deps/LIEF
1270+
$(RM) -r $(TARNAME)/deps/libffi
12311271
$(RM) -r $(TARNAME)/deps/llhttp
12321272
$(RM) -r $(TARNAME)/deps/merve
12331273
$(RM) -r $(TARNAME)/deps/nbytes
@@ -1502,6 +1542,7 @@ LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \
15021542
test/embedding/*.cc \
15031543
test/embedding/*.h \
15041544
test/sqlite/*/*.c \
1545+
test/ffi/*/*.c \
15051546
test/fixtures/*.c \
15061547
test/js-native-api/*/*.cc \
15071548
test/node-api/*/*.cc \
@@ -1526,6 +1567,7 @@ FORMAT_CPP_FILES += $(wildcard \
15261567
test/node-api/*/*.c \
15271568
test/node-api/*/*.h \
15281569
test/sqlite/*/*.c \
1570+
test/ffi/*/*.c \
15291571
)
15301572

15311573
# Code blocks don't have newline at the end,

configure.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,28 @@
686686
dest='shared_sqlite_libpath',
687687
help='a directory to search for the shared sqlite DLL')
688688

689+
shared_optgroup.add_argument('--shared-ffi',
690+
action='store_true',
691+
dest='shared_ffi',
692+
default=None,
693+
help='link to a shared libffi DLL instead of static linking')
694+
695+
shared_optgroup.add_argument('--shared-ffi-includes',
696+
action='store',
697+
dest='shared_ffi_includes',
698+
help='directory containing libffi header files')
699+
700+
shared_optgroup.add_argument('--shared-ffi-libname',
701+
action='store',
702+
dest='shared_ffi_libname',
703+
default='ffi',
704+
help='alternative libffi name to link to [default: %(default)s]')
705+
706+
shared_optgroup.add_argument('--shared-ffi-libpath',
707+
action='store',
708+
dest='shared_ffi_libpath',
709+
help='a directory to search for the shared libffi DLL')
710+
689711
shared_optgroup.add_argument('--shared-temporal_capi',
690712
action='store_true',
691713
dest='shared_temporal_capi',
@@ -1017,6 +1039,12 @@
10171039
default=None,
10181040
help='build without SQLite (disables SQLite and Web Storage API)')
10191041

1042+
parser.add_argument('--without-ffi',
1043+
action='store_true',
1044+
dest='without_ffi',
1045+
default=None,
1046+
help='build without FFI (Foreign Function Interface) support')
1047+
10201048
parser.add_argument('--experimental-quic',
10211049
action='store_true',
10221050
dest='experimental_quic',
@@ -2233,6 +2261,43 @@ def without_sqlite_error(option):
22332261

22342262
configure_library('sqlite', o, pkgname='sqlite3')
22352263

2264+
def bundled_ffi_supported(os_name, target_arch):
2265+
supported = {
2266+
'freebsd': {'arm', 'arm64', 'x64'},
2267+
'linux': {'arm', 'arm64', 'x64'},
2268+
'mac': {'arm64', 'x64'},
2269+
'win': {'arm64', 'x64'},
2270+
}
2271+
2272+
if target_arch == 'x86':
2273+
target_arch = 'ia32'
2274+
2275+
return target_arch in supported.get(os_name, set())
2276+
2277+
def configure_ffi(o):
2278+
use_ffi = not options.without_ffi
2279+
2280+
if use_ffi and not options.shared_ffi:
2281+
target_arch = o['variables']['target_arch']
2282+
if not bundled_ffi_supported(flavor, target_arch):
2283+
warn(f'FFI is disabled for {flavor}/{target_arch}: the bundled libffi '
2284+
'integration is not available on this platform. Use --shared-ffi '
2285+
'to provide a system libffi or --without-ffi to silence this '
2286+
'warning.')
2287+
use_ffi = False
2288+
2289+
o['variables']['node_use_ffi'] = b(use_ffi)
2290+
2291+
if options.without_ffi:
2292+
if options.shared_ffi:
2293+
error('--without-ffi is incompatible with --shared-ffi')
2294+
return
2295+
2296+
if not use_ffi:
2297+
return
2298+
2299+
configure_library('ffi', o, pkgname='libffi')
2300+
22362301
def configure_quic(o):
22372302
o['variables']['node_use_quic'] = b(options.experimental_quic and
22382303
not options.without_ssl)
@@ -2686,6 +2751,7 @@ def make_bin_override():
26862751
configure_library('ngtcp2', output, pkgname='libngtcp2')
26872752
configure_lief(output);
26882753
configure_sqlite(output);
2754+
configure_ffi(output);
26892755
configure_library('temporal_capi', output)
26902756
configure_library('uvwasi', output)
26912757
configure_library('zstd', output, pkgname='libzstd')

0 commit comments

Comments
 (0)