From cc182e748b16073e9c41443485e40c42907aadce Mon Sep 17 00:00:00 2001 From: magic-akari Date: Fri, 20 Sep 2024 04:18:22 +0800 Subject: [PATCH] fix: Build independent target for cli --- CMakeLists.txt | 42 ++++- package.json | 2 +- scripts/build.sh | 9 +- src/binding.cc | 4 +- src/clang-format-cli.js | 341 ---------------------------------------- 5 files changed, 44 insertions(+), 354 deletions(-) delete mode 100755 src/clang-format-cli.js diff --git a/CMakeLists.txt b/CMakeLists.txt index 76d9375..78057e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,14 @@ include(FetchContent) set(LLVM_ENABLE_PROJECTS clang CACHE STRING "") +set(LLVM_INCLUDE_UTILS OFF) +set(LLVM_INCLUDE_EXAMPLES OFF) +set(LLVM_INCLUDE_TESTS OFF) +set(LLVM_INCLUDE_BENCHMARKS OFF) + +set(NO_RTTI "-fno-rtti") +add_definitions(${NO_RTTI}) + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "MinSizeRel") endif() @@ -38,20 +46,22 @@ set(LLVM_LIBRARIES ) project(clang-format-wasm) -add_executable(clang-format-wasm src/lib.cc src/binding.cc) -target_include_directories(clang-format-wasm PRIVATE ${LLVM_INCLUDE_DIRS}) -target_compile_features(clang-format-wasm PRIVATE cxx_std_17) -target_compile_options(clang-format-wasm PRIVATE +add_custom_target(clang-format-wasm) +add_dependencies(clang-format-wasm clang-format-esm clang-format-cli) + +add_executable(clang-format-esm src/lib.cc src/binding.cc) +target_include_directories(clang-format-esm PRIVATE ${LLVM_INCLUDE_DIRS}) +target_compile_features(clang-format-esm PRIVATE cxx_std_17) +target_compile_options(clang-format-esm PRIVATE -Os -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 ) -target_link_libraries(clang-format-wasm PRIVATE +target_link_libraries(clang-format-esm PRIVATE ${LLVM_LIBRARIES} "-lembind" "-fno-rtti" - # "-flto" "-s MINIMAL_RUNTIME=1" "-s DYNAMIC_EXECUTION=0" "-s FILESYSTEM=0" @@ -61,3 +71,23 @@ target_link_libraries(clang-format-wasm PRIVATE "-s ALLOW_MEMORY_GROWTH=1" "-s MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION=1" ) + +add_executable(clang-format-cli + ${llvm_project_SOURCE_DIR}/clang/tools/clang-format/ClangFormat.cpp +) +target_include_directories(clang-format-cli PRIVATE ${LLVM_INCLUDE_DIRS}) +target_compile_features(clang-format-cli PRIVATE cxx_std_17) +target_compile_options(clang-format-cli PRIVATE + -Os + -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 +) + +target_link_libraries(clang-format-cli PRIVATE + ${LLVM_LIBRARIES} + "-fno-rtti" + "-lnodefs.js" + "-s DYNAMIC_EXECUTION=0" + "-s ENVIRONMENT=node" + "-s NODERAWFS=1" + "-s ALLOW_MEMORY_GROWTH=1" +) diff --git a/package.json b/package.json index 49b91d1..14b5e8d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "url": "git+https://github.com/wasm-fmt/clang-format.git" }, "bin": { - "clang-format": "./clang-format-cli.js", + "clang-format": "./clang-format-cli.cjs", "git-clang-format": "./git-clang-format", "clang-format-diff": "./clang-format-diff.py" }, diff --git a/scripts/build.sh b/scripts/build.sh index 8fb557a..706259a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -16,14 +16,17 @@ ninja clang-format-wasm cd $project_root if [[ ! -z "${WASM_OPT}" ]]; then - wasm-opt -Os build/clang-format-wasm.wasm -o build/clang-format-Os.wasm - wasm-opt -Oz build/clang-format-wasm.wasm -o build/clang-format-Oz.wasm + wasm-opt -Os build/clang-format-esm.wasm -o build/clang-format-Os.wasm + wasm-opt -Oz build/clang-format-esm.wasm -o build/clang-format-Oz.wasm fi SMALLEST_WASM=$(ls -Sr build/*.wasm | head -1) cp $SMALLEST_WASM pkg/clang-format.wasm -npm exec terser -- src/template.js build/clang-format-wasm.js --config-file .terser.json --output pkg/clang-format.js +npm exec terser -- src/template.js build/clang-format-esm.js --config-file .terser.json --output pkg/clang-format.js + +cp ./build/clang-format-cli.wasm ./pkg/ +cp ./build/clang-format-cli.js ./pkg/clang-format-cli.cjs cp ./src/clang-format.d.ts src/clang-format-*.js ./pkg/ cp ./package.json LICENSE README.md .npmignore ./pkg/ diff --git a/src/binding.cc b/src/binding.cc index 9c90be0..1b798d9 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -19,6 +19,4 @@ EMSCRIPTEN_BINDINGS(my_module) { function("dump_config", &dump_config); } -auto main(int argc, const char** argv) -> int { - return 0; -} +int main(void) {} diff --git a/src/clang-format-cli.js b/src/clang-format-cli.js deleted file mode 100755 index 29f93ec..0000000 --- a/src/clang-format-cli.js +++ /dev/null @@ -1,341 +0,0 @@ -#!/usr/bin/env node -import { existsSync, readFileSync } from "node:fs"; -import { readFile, writeFile } from "node:fs/promises"; -import path from "node:path"; -import { parseArgs } from "node:util"; -import init, { - dump_config, - format, - format_byte_range, - format_line_range, - set_fallback_style, - set_sort_includes, - version, -} from "./clang-format-node.js"; - -await init(); - -const help = `OVERVIEW: A tool to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code. - -If no arguments are specified, it formats the code from standard input -and writes the result to the standard output. -If s are given, it reformats the files. If -i is specified -together with s, the files are edited in-place. Otherwise, the -result is written to the standard output. - -USAGE: clang-format [options] [@] [ ...]`; - -const { values, positionals, tokens } = parseArgs({ - args: process.argv.slice(2), - allowPositionals: true, - tokens: true, - options: { - "assume-filename": { - type: "string", - }, - "dump-config": { - type: "boolean", - }, - "fallback-style": { - type: "string", - }, - files: { - type: "string", - }, - help: { - type: "boolean", - }, - inplace: { - short: "i", - type: "boolean", - }, - length: { - default: [], - multiple: true, - type: "string", - }, - lines: { - default: [], - multiple: true, - type: "string", - }, - offset: { - default: [], - multiple: true, - type: "string", - }, - "sort-includes": { - type: "boolean", - }, - style: { - type: "string", - }, - verbose: { - type: "boolean", - }, - version: { - type: "boolean", - }, - }, -}); - -for (const token of tokens) { - switch (token.name) { - case "help": { - console.log(help); - process.exit(0); - } - case "version": { - console.log(version()); - process.exit(0); - } - } -} - -let fileNames = positionals; -if (values.files) { - const external_file_of_files = await readFile(values.files, { - encoding: "utf-8", - }); - fileNames = fileNames.concat( - external_file_of_files.split("\n").filter(Boolean), - ); -} - -if (fileNames.length === 0 && !values["dump-config"]) { - fileNames = ["-"]; -} - -if (values["fallback-style"]) { - set_fallback_style(values["fallback-style"]); -} - -if (values["sort-includes"]) { - set_sort_includes(true); -} - -let style = values.style || "file"; - -if (style.startsWith("file:")) { - const file = values.style.slice(5); - style = await readFile(file, { encoding: "utf-8" }); -} - -function get_style(filename) { - if (style === "file") { - return load_style(filename); - } - - return style; -} - -const loaded_style = ["file"]; -const style_map = new Map(); - -function load_style(filename) { - if (filename === "-") { - filename = "."; - } - let parent_path = path.resolve(filename, ".."); - let config_path = path.join(parent_path, ".clang-format"); - - if (style_map.has(config_path)) { - const index = style_map.get(config_path); - return loaded_style[index]; - } - - const stack = [config_path]; - while (true) { - if (style_map.has(config_path)) { - const index = style_map.get(config_path); - stack.forEach((s) => { - style_map.set(s, index); - }); - return loaded_style[index]; - } - - stack.push(config_path); - if (existsSync(config_path)) { - const style = readFileSync(config_path, { encoding: "utf-8" }); - const index = loaded_style.push(style) - 1; - stack.forEach((s) => { - style_map.set(s, index); - }); - return style; - } - - let new_parent_path = path.resolve(parent_path, ".."); - if (new_parent_path === parent_path) { - stack.forEach((s) => { - style_map.set(s, 0); - }); - return loaded_style[0]; - } - parent_path = new_parent_path; - config_path = path.join(parent_path, ".clang-format"); - } -} - -if (values["dump-config"]) { - const style = values.style || "file"; - let code = ""; - if (fileNames[0]) { - code = await get_file_or_stdin(fileNames[0]); - } - - process.stdout.write( - dump_config({ - style, - filename: get_file_name(fileNames[0] || "-"), - code, - }), - ); - process.exit(0); -} - -if ( - fileNames.length !== 1 && - (!empty(values.offset) || !empty(values.length) || !empty(values.lines)) -) { - console.error( - "error: -offset, -length and -lines can only be used for single file", - ); - process.exit(1); -} - -if (!empty(values.lines) && (!empty(values.offset) || !empty(values.length))) { - console.error("error: cannot use -lines with -offset/-length"); - process.exit(1); -} - -if (!empty(values.lines)) { - const [file] = fileNames; - const content = await get_file_or_stdin(file); - - const range = []; - for (const line of values.lines) { - const [form_line_text, to_line_text] = line.split(":"); - const [from_line, to_line] = [ - Number.parseInt(form_line_text, 10), - Number.parseInt(to_line_text, 10), - ]; - if (!Number.isFinite(from_line) || !Number.isFinite(to_line)) { - console.error("error: invalid : pair"); - process.exit(1); - } - range.push([from_line, to_line]); - } - - const formatted = format_line_range( - content, - range, - get_file_name(file), - get_style(file), - ); - - if (values.inplace) { - if (content !== formatted) { - await writeFile(file, formatted, { encoding: "utf-8" }); - } - } else { - process.stdout.write(formatted); - } - process.exit(0); -} - -format_range: { - const range = []; - - fill_range: { - if (values.offset.length === 1 && values.length.length === 0) { - const offset = expect_number(values.offset[0], "offset"); - range.push([offset]); - break fill_range; - } - - if (values.offset.length !== values.length.length) { - console.error( - "error: number of -offset and -length arguments must match", - ); - process.exit(1); - } - - for (let i = 0; i < values.offset.length; ++i) { - const offset = expect_number(values.offset[i], "offset"); - const length = expect_number(values.length[i], "length"); - range.push([offset, length]); - } - - function expect_number(value, name) { - const num = Number.parseInt(value, 10); - if (!Number.isFinite(num)) { - console.error(`error: invalid ${name}`); - process.exit(1); - } - return num; - } - } - - if (empty(range)) { - break format_range; - } - - const [file] = fileNames; - const content = await get_file_or_stdin(file); - - const formatted = format_byte_range( - content, - range, - get_file_name(file), - get_style(file), - ); - - if (values.inplace) { - if (content !== formatted) { - await writeFile(file, formatted, { encoding: "utf-8" }); - } - } else { - process.stdout.write(formatted); - } - - process.exit(0); -} - -for (const [file_no, file] of fileNames.entries()) { - if (values.verbose) { - console.error( - `Formatting [${file_no + 1}/${fileNames.length}] ${file}`, - ); - } - const content = await get_file_or_stdin(file); - const formatted = format(content, get_file_name(file), get_style(file)); - if (values.inplace) { - if (content !== formatted) { - await writeFile(file, formatted, { encoding: "utf-8" }); - } - } else { - process.stdout.write(formatted); - } -} - -function empty(array) { - return array.length === 0; -} - -async function get_file_or_stdin(fileName) { - if (fileName === "-") { - if (values.inplace) { - console.error("error: cannot use -i when reading from stdin"); - process.exit(1); - } - return readFileSync(0, { encoding: "utf-8" }); - } - return await readFile(fileName, { encoding: "utf-8" }); -} - -function get_file_name(fileName) { - if (fileName === "-") { - return values.assume_filename || ""; - } - return fileName; -}