Skip to content

Commit 6e102d0

Browse files
committed
Add scaffolding for Node.js module in VS Code extension
I want the VS Code extension to use our change_detecting_configuration_filesystem classes. These classes need access to OS-specific APIs, thus we need to use FFI or a Node.js extension. Create a super basic Node.js extension called quick-lint-js-node-fs. The extension doesn't do anything interesting. This commit only sets up the build process. Also, adjust collect-copyright script to work with header-only libraries (with manual intervention). Otherwise, node and node-addon-api get no credit.
1 parent 9ecd2dd commit 6e102d0

File tree

15 files changed

+397
-20
lines changed

15 files changed

+397
-20
lines changed

.github/workflows/build-and-test-plugin-vscode.yml

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,51 @@ on:
88
types: [opened, synchronize]
99

1010
jobs:
11-
build:
12-
name: extension
11+
build-node-addon:
12+
name: Node.js addon for ${{ matrix.os.name }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os:
17+
- {runs_on: macos-10.15, name: "macOS", archive_name: "macos", CC: /usr/local/opt/llvm/bin/clang, CXX: /usr/local/opt/llvm/bin/clang++, CFLAGS: "-isystem /usr/local/opt/llvm/include -isystem /usr/local/opt/llvm/include/c++/v1 -mmacosx-version-min=10.9 -D_LIBCPP_DISABLE_AVAILABILITY", LDFLAGS: "-L/usr/local/opt/llvm/lib -mlinker-version=278 -nostdlib++ /usr/local/opt/llvm/lib/libc++.a /usr/local/opt/llvm/lib/libc++abi.a"}
18+
- {runs_on: ubuntu-latest, name: "Linux", archive_name: "linux", CC: gcc-8, CXX: g++-8, LDFLAGS: "-static-libgcc -static-libstdc++"}
19+
- {runs_on: windows-latest, name: "Windows", archive_name: "windows", CMAKE_FLAGS: "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded"}
20+
runs-on: ${{ matrix.os.runs_on }}
21+
container: ${{ fromJSON('["", "ghcr.io/quick-lint/quick-lint-js-github-builder:v1"]')[matrix.os.runs_on == 'ubuntu-latest'] }}
22+
env:
23+
CMAKE_CXX_COMPILER: ${{ matrix.os.CXX }}
24+
CMAKE_CXX_FLAGS: ${{ matrix.os.CFLAGS }}
25+
CMAKE_C_COMPILER: ${{ matrix.os.CC }}
26+
CMAKE_C_FLAGS: ${{ matrix.os.CFLAGS }}
27+
CMAKE_EXE_LINKER_FLAGS: ${{ matrix.os.LDFLAGS }}
28+
CMAKE_EXTRA_FLAGS: ${{ matrix.os.CMAKE_FLAGS }}
29+
CMAKE_SHARED_LINKER_FLAGS: ${{ matrix.os.LDFLAGS }}
30+
QLJS_COLLECT_COPYRIGHT_NO_WARNINGS: 1
31+
32+
steps:
33+
- name: checkout
34+
uses: actions/checkout@v2
35+
36+
- name: configure
37+
run: |
38+
env | grep '^CMAKE\|^QUICK_LINT_JS' | sort
39+
cmake ${CMAKE_C_COMPILER+-DCMAKE_C_COMPILER="${CMAKE_C_COMPILER}"} ${CMAKE_CXX_COMPILER+-DCMAKE_CXX_COMPILER="${CMAKE_CXX_COMPILER}"} -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=NO -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}" -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}" -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}" -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" -DQUICK_LINT_JS_ENABLE_VSCODE=YES ${CMAKE_EXTRA_FLAGS} -S . -B build
40+
shell: bash
41+
- name: build
42+
run: cmake --build build --config Release --target quick-lint-js-node-fs quick-lint-js-node-fs-licenses
43+
- name: install
44+
run: cmake --install build --component vscode --prefix wasm
45+
46+
- name: upload build to workflow
47+
uses: actions/upload-artifact@v2
48+
with:
49+
if-no-files-found: error
50+
name: quick-lint-js-node-${{ matrix.os.archive_name }}
51+
path: wasm/dist/
52+
53+
build-extension:
54+
name: VS Code extension
55+
needs: build-node-addon
1356
runs-on: ubuntu-latest
1457
# TODO(strager): Use ghcr.io/quick-lint/quick-lint-js-github-builder.
1558
env:
@@ -27,6 +70,19 @@ jobs:
2770
sudo apt-get update
2871
sudo apt-get install -y ninja-build
2972
73+
- uses: actions/download-artifact@v2
74+
with:
75+
name: quick-lint-js-node-linux
76+
path: ./wasm/dist/
77+
- uses: actions/download-artifact@v2
78+
with:
79+
name: quick-lint-js-node-macos
80+
path: ./wasm/dist/
81+
- uses: actions/download-artifact@v2
82+
with:
83+
name: quick-lint-js-node-windows
84+
path: ./wasm/dist/
85+
3086
- name: C++ configure
3187
run: emcmake cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS='-O3 -flto' -DCMAKE_CXX_FLAGS='-O3 -fno-rtti -fno-exceptions -flto'
3288
- name: C++ build

.github/workflows/build-wasm.yml

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,16 @@ on:
99

1010
jobs:
1111
build:
12-
name: wasm
13-
runs-on: ubuntu-latest
14-
container: ghcr.io/quick-lint/quick-lint-js-github-builder:v3
12+
name: ${{ matrix.os.name }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os:
17+
- {runs_on: macos-10.15, name: "macOS", CMAKE_FLAGS: "-G Ninja"}
18+
- {runs_on: ubuntu-latest, name: "Ubuntu 16.04", CMAKE_FLAGS: "-G Ninja"}
19+
- {runs_on: windows-latest, name: "Windows"}
20+
runs-on: ${{ matrix.os.runs_on }}
21+
container: ${{ fromJSON('["", "ghcr.io/quick-lint/quick-lint-js-github-builder:v3"]')[matrix.os.runs_on == 'ubuntu-latest'] }}
1522
env:
1623
QLJS_COLLECT_COPYRIGHT_NO_WARNINGS: 1
1724
steps:
@@ -21,12 +28,23 @@ jobs:
2128
- name: checkout
2229
uses: actions/checkout@v2
2330

24-
- name: C++ configure
25-
run: emcmake cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
26-
- name: C++ build
27-
run: emmake cmake --build build --target quick-lint-js-vscode quick-lint-js-vscode-licenses
28-
- name: C++ install
29-
run: emmake cmake --install build --component vscode --prefix wasm
31+
- name: install build dependencies
32+
if: ${{ matrix.os.runs_on == "macos-10.15" }}
33+
run: brew install ninja
34+
35+
- name: C++ Node.js configure
36+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DQUICK_LINT_JS_ENABLE_VSCODE=YES ${{ matrix.os.CMAKE_FLAGS }}
37+
- name: C++ Node.js build
38+
run: cmake --build build --config Debug --target quick-lint-js-node-fs quick-lint-js-node-fs-licenses
39+
- name: C++ Node.js install
40+
run: cmake --install build --component vscode --prefix wasm
41+
42+
- name: C++ wasm configure
43+
run: emcmake cmake -S . -B build-emscripten -DCMAKE_BUILD_TYPE=Debug ${{ matrix.os.CMAKE_FLAGS }}
44+
- name: C++ wasm build
45+
run: emmake cmake --build build-emscripten --target quick-lint-js-vscode quick-lint-js-vscode-licenses
46+
- name: C++ wasm install
47+
run: emmake cmake --install build-emscripten --component vscode --prefix wasm
3048

3149
- name: JS configure
3250
run: cd wasm && yarn install

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ project(quick-lint-js)
1010
include(GNUInstallDirs)
1111

1212
option(QUICK_LINT_JS_ENABLE_BENCHMARKS "Build microbenchmark programs" OFF)
13+
option(QUICK_LINT_JS_ENABLE_VSCODE "Build VS Code extension bits" OFF)
14+
1315
set(
1416
QUICK_LINT_JS_INSTALL_LICENSES_DIR
1517
"${CMAKE_INSTALL_DOCDIR}"

cmake/QuickLintJSCopyright.cmake

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
set(QUICK_LINT_JS_COLLECT_COPYRIGHT "${CMAKE_CURRENT_LIST_DIR}/../tools/collect-copyright")
55

66
function (quick_lint_js_collect_copyright NAME)
7-
cmake_parse_arguments("" "" "OUTPUT_FILE;TARGET" "" ${ARGN})
7+
cmake_parse_arguments(
8+
""
9+
""
10+
"OUTPUT_FILE;TARGET"
11+
"EXTRA_VENDOR_PROJECTS"
12+
${ARGN}
13+
)
814
set(LINKMAP_FILE "${CMAKE_CURRENT_BINARY_DIR}/${_TARGET}.trace")
915

1016
set(ERROR_MESSAGE_SEVERITY WARNING)
@@ -69,6 +75,15 @@ function (quick_lint_js_collect_copyright NAME)
6975
)
7076
endif ()
7177

78+
if (_EXTRA_VENDOR_PROJECTS)
79+
list(
80+
APPEND
81+
COLLECT_COPYRIGHT_OPTIONS
82+
--extra-vendor-projects
83+
${_EXTRA_VENDOR_PROJECTS}
84+
)
85+
endif ()
86+
7287
add_custom_command(
7388
OUTPUT "${_OUTPUT_FILE}"
7489
COMMAND

plugin/vscode/.vscodeignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
!node_modules/
77
!node_modules/quick-lint-js-wasm/
88
!node_modules/quick-lint-js-wasm/dist/
9-
!node_modules/quick-lint-js-wasm/dist/copyright.txt
10-
!node_modules/quick-lint-js-wasm/dist/quick-lint-js-vscode.wasm
9+
!node_modules/quick-lint-js-wasm/dist/*
1110
!node_modules/quick-lint-js-wasm/quick-lint-js.js
1211
!package.json

tools/collect-copyright

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ archive_to_vendor_project = {
2828
"libboost.a": "boost",
2929
"libquick-lint-js-lib.a": None,
3030
"libsimdjson.a": "simdjson",
31+
"node-napi.lib": None, # Dynamically linked.
3132
"quick-lint-js-lib.lib": None,
3233
"simdjson.lib": "simdjson",
3334
# HACK(strager): Ignore these libraries for now.
@@ -66,6 +67,12 @@ def main() -> None:
6667
default=False,
6768
help="Don't assume system package manager manages the standard library",
6869
)
70+
parser.add_argument(
71+
"--extra-vendor-projects",
72+
default=[],
73+
help="Include license information for these projects from --vendor-readme",
74+
nargs="+",
75+
)
6976
parser.add_argument(
7077
"--vendor-readme",
7178
required=False,
@@ -103,6 +110,7 @@ Parts of quick-lint-js might be distributed under different licenses:
103110
vendor_projects=vendor_projects,
104111
vendor_directory=vendor_readme_file.parent,
105112
is_cross_compiling_emscripten=args.cross_compiling_emscripten,
113+
extra_vendor_projects=args.extra_vendor_projects,
106114
)
107115

108116

@@ -111,6 +119,7 @@ def dump_from_linkmap(
111119
vendor_projects: typing.List["VendorReadmeProject"],
112120
vendor_directory: pathlib.Path,
113121
is_cross_compiling_emscripten: bool,
122+
extra_vendor_projects: typing.List[str],
114123
) -> None:
115124
link_map = parse_link_map(link_map_file.read_text())
116125
linked_system_archives = [
@@ -123,6 +132,7 @@ def dump_from_linkmap(
123132
]
124133
dump_from_vendor(
125134
linked_vendored_archives,
135+
project_names=extra_vendor_projects,
126136
vendor_projects=vendor_projects,
127137
vendor_directory=vendor_directory,
128138
)
@@ -134,9 +144,11 @@ def dump_from_linkmap(
134144

135145
def dump_from_vendor(
136146
archives: typing.List[str],
147+
project_names: typing.List[str],
137148
vendor_projects: typing.List["VendorReadmeProject"],
138149
vendor_directory: pathlib.Path,
139150
) -> None:
151+
all_project_names = project_names
140152
for archive in sorted(archives):
141153
try:
142154
vendor_project_name = archive_to_vendor_project[pathlib.Path(archive).name]
@@ -145,13 +157,16 @@ def dump_from_vendor(
145157
if vendor_project_name is None:
146158
# Archive is quick-lint-js itself. Its license is handled elsewhere.
147159
continue
160+
all_project_names.append(vendor_project_name)
148161

162+
all_project_names = sorted(set(all_project_names))
163+
for vendor_project_name in all_project_names:
149164
matching_vendor_projects = [
150165
p for p in vendor_projects if p.project_name == vendor_project_name
151166
]
152167
if len(matching_vendor_projects) != 1:
153168
raise Exception(
154-
f"could not find vendor project for archive: {archive} (project name: {vendor_project_name}"
169+
f"could not find vendor project for project name: {vendor_project_name}"
155170
) from None
156171
vendor_project = matching_vendor_projects[0]
157172

vendor/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ endif ()
99
include(boost.cmake)
1010
include(googletest.cmake)
1111
include(jsoncpp.cmake)
12+
include(node-addon-api.cmake)
13+
include(node.cmake)
1214
include(simdjson.cmake)
1315

1416
# quick-lint-js finds bugs in JavaScript programs.

vendor/node-addon-api.cmake

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright (C) 2020 Matthew "strager" Glazar
2+
# See end of file for extended copyright information.
3+
4+
add_library(node-addon-api INTERFACE)
5+
target_compile_definitions(node-addon-api INTERFACE NAPI_DISABLE_CPP_EXCEPTIONS)
6+
target_include_directories(node-addon-api SYSTEM INTERFACE node-addon-api)
7+
target_link_libraries(node-addon-api INTERFACE node-napi)
8+
9+
# quick-lint-js finds bugs in JavaScript programs.
10+
# Copyright (C) 2020 Matthew "strager" Glazar
11+
#
12+
# This file is part of quick-lint-js.
13+
#
14+
# quick-lint-js is free software: you can redistribute it and/or modify
15+
# it under the terms of the GNU General Public License as published by
16+
# the Free Software Foundation, either version 3 of the License, or
17+
# (at your option) any later version.
18+
#
19+
# quick-lint-js is distributed in the hope that it will be useful,
20+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
# GNU General Public License for more details.
23+
#
24+
# You should have received a copy of the GNU General Public License
25+
# along with quick-lint-js. If not, see <https://www.gnu.org/licenses/>.

vendor/node.cmake

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright (C) 2020 Matthew "strager" Glazar
2+
# See end of file for extended copyright information.
3+
4+
add_library(node-napi INTERFACE)
5+
target_compile_definitions(node-napi INTERFACE BUILDING_NODE_EXTENSION)
6+
target_include_directories(node-napi SYSTEM INTERFACE node/src)
7+
# Users should also set the NAPI_VERSION compile definition.
8+
9+
if (APPLE)
10+
# Allow the linker to succeed by effectively ignoring undefined-symbol errors.
11+
target_link_libraries(node-napi INTERFACE "-undefined dynamic_lookup")
12+
endif ()
13+
if (WIN32)
14+
# Create a .lib file for linking based on the symbol list in node.def.
15+
if (CMAKE_SYSTEM_PROCESSOR STREQUAL AMD64)
16+
set(LIB_MACHINE /MACHINE:X64)
17+
else ()
18+
set(LIB_MACHINE)
19+
endif ()
20+
add_custom_command(
21+
OUTPUT node-napi.lib node-napi.exp
22+
COMMAND
23+
lib
24+
"/DEF:${CMAKE_CURRENT_SOURCE_DIR}/node.def"
25+
/OUT:node-napi.lib
26+
/WX
27+
${LIB_MACHINE}
28+
DEPENDS node.def
29+
COMMENT "Generating node-napi implib"
30+
)
31+
add_custom_target(
32+
node-napi-implib
33+
DEPENDS node-napi.lib
34+
SOURCES node.def
35+
)
36+
add_dependencies(node-napi node-napi-implib)
37+
target_link_libraries(
38+
node-napi
39+
INTERFACE
40+
"${CMAKE_CURRENT_BINARY_DIR}/node-napi.lib"
41+
)
42+
endif ()
43+
44+
# quick-lint-js finds bugs in JavaScript programs.
45+
# Copyright (C) 2020 Matthew "strager" Glazar
46+
#
47+
# This file is part of quick-lint-js.
48+
#
49+
# quick-lint-js is free software: you can redistribute it and/or modify
50+
# it under the terms of the GNU General Public License as published by
51+
# the Free Software Foundation, either version 3 of the License, or
52+
# (at your option) any later version.
53+
#
54+
# quick-lint-js is distributed in the hope that it will be useful,
55+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
56+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57+
# GNU General Public License for more details.
58+
#
59+
# You should have received a copy of the GNU General Public License
60+
# along with quick-lint-js. If not, see <https://www.gnu.org/licenses/>.

vendor/node.def

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; Copyright (C) 2020 Matthew "strager" Glazar
2+
; See end of file for extended copyright information.
3+
4+
; This file is used to create an implib (.imp) file for node.exe on Windows.
5+
;
6+
; This file contains a list of all N-API symbols exported by node.exe for use by
7+
; addons.
8+
9+
LIBRARY NODE.EXE
10+
EXPORTS
11+
napi_add_finalizer
12+
napi_close_handle_scope
13+
napi_create_error
14+
napi_create_function
15+
napi_create_reference
16+
napi_create_string_utf8
17+
napi_create_type_error
18+
napi_delete_reference
19+
napi_fatal_error
20+
napi_get_and_clear_last_exception
21+
napi_get_cb_info
22+
napi_get_last_error_info
23+
napi_get_reference_value
24+
napi_is_exception_pending
25+
napi_module_register
26+
napi_open_handle_scope
27+
napi_set_property
28+
napi_throw
29+
; TODO(strager): Complete this list. Many symbols are missing.
30+
31+
; quick-lint-js finds bugs in JavaScript programs.
32+
; Copyright (C) 2020 Matthew "strager" Glazar
33+
;
34+
; This file is part of quick-lint-js.
35+
;
36+
; quick-lint-js is free software: you can redistribute it and/or modify
37+
; it under the terms of the GNU General Public License as published by
38+
; the Free Software Foundation, either version 3 of the License, or
39+
; (at your option) any later version.
40+
;
41+
; quick-lint-js is distributed in the hope that it will be useful,
42+
; but WITHOUT ANY WARRANTY; without even the implied warranty of
43+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44+
; GNU General Public License for more details.
45+
;
46+
; You should have received a copy of the GNU General Public License
47+
; along with quick-lint-js. If not, see <https://www.gnu.org/licenses/>.

0 commit comments

Comments
 (0)