From 7f6e023b2a583ac77abbc4f3ecd0dc610c205fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= Date: Thu, 11 Jul 2024 20:52:41 -0600 Subject: [PATCH 1/6] vala: Create Vala template Initial work to port Vala to Meson --- src/langs/vala/meson.build | 2 + src/langs/vala/template/meson.build | 39 ++++++++++++++++++++ src/langs/vala/{ => template}/workbench.vala | 0 src/meson.build | 2 +- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/langs/vala/meson.build create mode 100644 src/langs/vala/template/meson.build rename src/langs/vala/{ => template}/workbench.vala (100%) diff --git a/src/langs/vala/meson.build b/src/langs/vala/meson.build new file mode 100644 index 000000000..52d566beb --- /dev/null +++ b/src/langs/vala/meson.build @@ -0,0 +1,2 @@ +install_data(['template/meson.build', 'template/workbench.vala'], + install_dir : join_paths(pkgdatadir, 'langs/vala/template')) \ No newline at end of file diff --git a/src/langs/vala/template/meson.build b/src/langs/vala/template/meson.build new file mode 100644 index 000000000..738d86a5b --- /dev/null +++ b/src/langs/vala/template/meson.build @@ -0,0 +1,39 @@ +project('demo', ['c', 'vala'], + version: '0.1', + meson_version: '>= 0.59.0', + default_options: [ 'warning_level=2', 'werror=false', ], +) + +i18n = import('i18n') +gnome = import('gnome') + +source_files = [ + 'main.vala', + 'workbench.vala' +] + +cc = meson.get_compiler('c') +m_dep = cc.find_library('m', required : false) + +add_project_arguments( + '-shared', + '-fpic', + language: 'c' +) + +dependencies = [ + m_dep, + dependency('libadwaita-1'), + dependency('shumate-1.0'), + dependency('libportal-gtk4'), + dependency('libsoup-3.0'), + dependency('webkitgtk-6.0'), + dependency('gstreamer-1.0'), + dependency('gtksourceview-5'), +] + +executable('demo', source_files, + objects: 'libworkbenchcode.so', + dependencies: dependencies, + install: true, +) \ No newline at end of file diff --git a/src/langs/vala/workbench.vala b/src/langs/vala/template/workbench.vala similarity index 100% rename from src/langs/vala/workbench.vala rename to src/langs/vala/template/workbench.vala diff --git a/src/meson.build b/src/meson.build index a07187bd5..9d8db22f9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -18,6 +18,7 @@ meson.add_install_script('../build-aux/library.js', pkgdatadir) subdir('langs/javascript') subdir('langs/rust/template') subdir('langs/typescript') +subdir('langs/vala') configure_file( input: 'bin.js', @@ -46,7 +47,6 @@ configure_file( install_dir: get_option('bindir') ) -install_data('langs/vala/workbench.vala', install_dir: pkgdatadir) install_data('langs/javascript/biome.json', install_dir: pkgdatadir) install_data('project-readme.md', install_dir: pkgdatadir) subdir('libworkbench') From 0672cbb055ab859c871dc671cadcfb996dd4095e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= Date: Thu, 11 Jul 2024 23:05:47 -0600 Subject: [PATCH 2/6] vala: Compile and run using Meson --- src/PanelCode.js | 5 +++ src/langs/vala/Compiler.js | 67 ++++++++++++----------------- src/langs/vala/template/meson.build | 4 +- src/langs/vala/vala.js | 23 +++++++++- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/PanelCode.js b/src/PanelCode.js index fb95b424a..0ea3f5eb4 100644 --- a/src/PanelCode.js +++ b/src/PanelCode.js @@ -5,6 +5,7 @@ import { makeDropdownFlat, settings as global_settings } from "./util.js"; import { setupRustProject } from "./langs/rust/rust.js"; import { setupTypeScriptProject } from "./langs/typescript/typescript.js"; import { setupJavascriptProject } from "./langs/javascript/javascript.js"; +import { setupValaProject } from "./langs/vala/vala.js"; export default function PanelCode({ builder, @@ -62,6 +63,10 @@ export default function PanelCode({ ); } + if (panel.language.toLowerCase() === "vala") { + setupValaProject(file).catch(console.error); + } + if (panel.language.toLowerCase() === "rust") { setupRustProject(file).catch(console.error); } diff --git a/src/langs/vala/Compiler.js b/src/langs/vala/Compiler.js index 6590493f8..7b4fbed7d 100644 --- a/src/langs/vala/Compiler.js +++ b/src/langs/vala/Compiler.js @@ -1,49 +1,44 @@ import Gio from "gi://Gio"; import dbus_previewer from "../../Previewer/DBusPreviewer.js"; -import { decode } from "../../util.js"; export default function ValaCompiler({ session }) { const { file } = session; - const module_file = file.get_child("libworkbenchcode.so"); - const file_vala = file.get_child("main.vala"); + const meson_builddir = "builddir"; + const module_file = file + .get_child(meson_builddir) + .get_child("libworkbenchcode.so"); async function compile() { - let args; + // TODO: Do not run setup if the build directory is already + // configured + const meson_launcher = new Gio.SubprocessLauncher(); + meson_launcher.set_cwd(file.get_path()); + const meson_setup = meson_launcher.spawnv([ + "meson", + "setup", + meson_builddir, + ]); - try { - const [contents] = await file_vala.load_contents_async(null); - const code = decode(contents); - args = getValaCompilerArguments(code); - } catch (error) { - console.debug(error); - return; + await meson_setup.wait_async(null); + const setup_result = meson_setup.get_successful(); + if (!setup_result) { + return false; } - const valac_launcher = new Gio.SubprocessLauncher(); - valac_launcher.set_cwd(file.get_path()); - const valac = valac_launcher.spawnv([ - "valac", - file_vala.get_path(), - "--hide-internal", - "-X", - "-shared", - "-X", - "-fpic", - "--library", - "workbench", - "-o", - module_file.get_path(), - "--vapi", - "/dev/null", - ...args, + const meson_compile = meson_launcher.spawnv([ + "meson", + "compile", + "-C", + meson_builddir, ]); - await valac.wait_async(null); + await meson_compile.wait_async(null); + const compile_result = meson_compile.get_successful(); - const result = valac.get_successful(); - valac_launcher.close(); - return result; + meson_launcher.close(); + + return compile_result; } async function run() { @@ -60,11 +55,3 @@ export default function ValaCompiler({ session }) { return { compile, run }; } - -// Takes a string starting with the line -// #!/usr/bin/env -S vala workbench.vala --pkg gtk4 --pkg libadwaita-1 -// and return ["--pkg", "gtk4", "--pkg", "libadwaita-1"] -// FIXME: consider using https://docs.gtk.org/glib/struct.OptionContext.html instead -function getValaCompilerArguments(text) { - return text.split("\n")[0]?.split("-S vala ")[1]?.split(" ") || []; -} diff --git a/src/langs/vala/template/meson.build b/src/langs/vala/template/meson.build index 738d86a5b..54e19be49 100644 --- a/src/langs/vala/template/meson.build +++ b/src/langs/vala/template/meson.build @@ -30,10 +30,10 @@ dependencies = [ dependency('webkitgtk-6.0'), dependency('gstreamer-1.0'), dependency('gtksourceview-5'), + dependency('json-glib-1.0'), ] -executable('demo', source_files, - objects: 'libworkbenchcode.so', +library('workbenchcode', source_files, dependencies: dependencies, install: true, ) \ No newline at end of file diff --git a/src/langs/vala/vala.js b/src/langs/vala/vala.js index 319a98dc7..eef189ab6 100644 --- a/src/langs/vala/vala.js +++ b/src/langs/vala/vala.js @@ -2,7 +2,7 @@ import Gio from "gi://Gio"; import { isValaAvailable } from "../../Extensions/Extensions.js"; import { createLSPClient } from "../../common.js"; -import { getLanguage } from "../../util.js"; +import { getLanguage, copy } from "../../util.js"; export function setup({ document }) { if (!isValaAvailable()) return; @@ -44,3 +44,24 @@ export function setup({ document }) { return lspc; } + +const vala_template_dir = Gio.File.new_for_path( + pkg.pkgdatadir, +).resolve_relative_path("langs/vala/template"); + +export async function setupValaProject(destination) { + return Promise.all([ + copy( + "meson.build", + vala_template_dir, + destination, + Gio.FileCopyFlags.OVERWRITE, + ), + copy( + "workbench.vala", + vala_template_dir, + destination, + Gio.FileCopyFlags.OVERWRITE, + ), + ]); +} From 7172d064b0286b887df246a733653e23f40cb8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= Date: Fri, 12 Jul 2024 10:04:54 -0600 Subject: [PATCH 3/6] vala: Setup Vala project before starting the language server Closes #913 --- src/langs/vala/vala.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/langs/vala/vala.js b/src/langs/vala/vala.js index eef189ab6..002d25885 100644 --- a/src/langs/vala/vala.js +++ b/src/langs/vala/vala.js @@ -9,15 +9,9 @@ export function setup({ document }) { const { file, buffer, code_view } = document; - const api_file = Gio.File.new_for_path(pkg.pkgdatadir).get_child( - "workbench.vala", - ); - api_file.copy( - file.get_parent().get_child("workbench.vala"), - Gio.FileCopyFlags.OVERWRITE, - null, - null, - ); + // VLS needs the project to be already setup once it starts, + // otherwise it won't pick it up later. + setupValaProject(file.get_parent()).catch(console.error); const lspc = createLSPClient({ lang: getLanguage("vala"), From 7826298795006d2b84b94e6a98eddb8a42362263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n=20M=2EE?= Date: Mon, 14 Oct 2024 10:05:36 -0600 Subject: [PATCH 4/6] util: Add createTmpDir function This function will allow to create temporary directory. This will allow, for instance, meson to create a builddir that will not be stored inside a session. --- src/util.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/util.js b/src/util.js index 958307cb2..86e3aff72 100644 --- a/src/util.js +++ b/src/util.js @@ -211,3 +211,25 @@ export async function copy(filename, source_dir, dest_dir, flags) { return dest_file; } + +const tmp_dirs = {}; + +export async function createTmpDir(filename) { + if (filename in tmp_dirs) { + return tmp_dirs[filename]; + } + + const tmp_dir = Gio.File.new_for_path( + GLib.build_filenamev([GLib.get_tmp_dir(), filename]), + ); + + try { + tmp_dir.make_directory(null); + tmp_dirs[filename] = tmp_dir; + } catch (err) { + console.error(err); + return null; + } + + return tmp_dir; +} From 4696398d5e0e4e8d6569cdb147236a6ef63e3ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n=20M=2EE?= Date: Mon, 14 Oct 2024 10:11:42 -0600 Subject: [PATCH 5/6] vala: Compile inside a temporary directory This allows to compile projects without granting access to the filesystem. Additionally, all sessions opened that compile Vala code will use the same build directory, allowing us to reuse the same meson configuration. --- src/langs/vala/Compiler.js | 39 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/langs/vala/Compiler.js b/src/langs/vala/Compiler.js index 7b4fbed7d..c951b6ab3 100644 --- a/src/langs/vala/Compiler.js +++ b/src/langs/vala/Compiler.js @@ -1,19 +1,41 @@ import Gio from "gi://Gio"; import dbus_previewer from "../../Previewer/DBusPreviewer.js"; +import { createTmpDir, copy } from "../../util.js"; +import { setupValaProject } from "./vala.js"; + +let ready_to_build = false; +const session_build_dir = await createTmpDir("vala"); export default function ValaCompiler({ session }) { const { file } = session; const meson_builddir = "builddir"; - const module_file = file + const module_file = session_build_dir .get_child(meson_builddir) .get_child("libworkbenchcode.so"); async function compile() { + if (!ready_to_build) { + try { + await setupValaProject(session_build_dir); + ready_to_build = true; + } catch (err) { + console.error(err); + return false; + } + } + + await copy( + "main.vala", + file, + session_build_dir, + Gio.FileCopyFlags.OVERWRITE | Gio.FileCopyFlags.ALL_METADATA, + ); + // TODO: Do not run setup if the build directory is already // configured const meson_launcher = new Gio.SubprocessLauncher(); - meson_launcher.set_cwd(file.get_path()); + meson_launcher.set_cwd(session_build_dir.get_path()); const meson_setup = meson_launcher.spawnv([ "meson", "setup", @@ -26,6 +48,19 @@ export default function ValaCompiler({ session }) { return false; } + const meson_clean = meson_launcher.spawnv([ + "meson", + "compile", + "--clean", + "-C", + meson_builddir, + ]); + + await meson_clean.wait_async(null); + if (!meson_clean.get_successful()) { + return false; + } + const meson_compile = meson_launcher.spawnv([ "meson", "compile", From fc77803aca9d379a8002a3eaed1e5fa9d71c20db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= Date: Sat, 13 Jul 2024 14:56:12 -0600 Subject: [PATCH 6/6] cli: Use Meson in Vala checks --- src/cli/main.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cli/main.js b/src/cli/main.js index 77ca0f791..1ea39519e 100644 --- a/src/cli/main.js +++ b/src/cli/main.js @@ -352,16 +352,30 @@ async function ci({ filenames }) { const languageId = "vala"; let version = 0; - const file_api = Gio.File.new_for_path(pkg.pkgdatadir).get_child( - "workbench.vala", - ); - file_api.copy( + const current_dir = Gio.File.new_for_path(GLib.get_current_dir()); + + const template_dir = GLib.getenv("FLATPAK_ID") + ? Gio.File.new_for_path( + `/app/share/${GLib.getenv("FLATPAK_ID")}/langs/vala/template`, + ) + : current_dir.resolve_relative_path("src/langs/vala/template"); + + const api_file = template_dir.get_child("workbench.vala"); + api_file.copy( demo_dir.get_child("workbench.vala"), Gio.FileCopyFlags.OVERWRITE, null, null, ); + const meson_file = template_dir.get_child("meson.build"); + meson_file.copy( + demo_dir.get_child("meson.build"), + Gio.FileCopyFlags.OVERWRITE, + null, + null, + ); + const [contents] = await file_vala.load_contents_async(null); const text = new TextDecoder().decode(contents);