Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vala: Port Vala to Meson #969

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/PanelCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
22 changes: 18 additions & 4 deletions src/cli/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Comment on lines +355 to +364
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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(
const template_dir = Gio.File.new_for_path(pkg.pkgdatadir).get_child("langs/vala/template");
template_dir.get_child("workbench.vala").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);

Expand Down
102 changes: 62 additions & 40 deletions src/langs/vala/Compiler.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,79 @@
import Gio from "gi://Gio";
import dbus_previewer from "../../Previewer/DBusPreviewer.js";
import { decode } from "../../util.js";
import { createTmpDir, copy } from "../../util.js";
import { setupValaProject } from "./vala.js";

let ready_to_build = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about why this is needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this to know if the Vala builddir was already setup (as it needs a meson file and the workbench API). This could be done checking if a build file (like workbench.vala) exists, but I went for this instead as it is one less I/O operation.

const session_build_dir = await createTmpDir("vala");

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 = session_build_dir
.get_child(meson_builddir)
.get_child("libworkbenchcode.so");

async function compile() {
let args;
if (!ready_to_build) {
try {
await setupValaProject(session_build_dir);
ready_to_build = true;
} catch (err) {
console.error(err);
return false;
}
}

try {
const [contents] = await file_vala.load_contents_async(null);
const code = decode(contents);
args = getValaCompilerArguments(code);
} catch (error) {
console.debug(error);
return;
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(session_build_dir.get_path());
const meson_setup = meson_launcher.spawnv([
"meson",
"setup",
meson_builddir,
]);

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_clean = meson_launcher.spawnv([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why cleaning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When replacing the file in the build dir, meson will not detect any changes on the file, thus not compiling anything and just running the project right away. This is a problem when a user has two open projects and working on them simultaneously, so I went for cleaning the build files and recompiling. I thought this approach was OK since we don't really compile much.

"meson",
"compile",
"--clean",
"-C",
meson_builddir,
]);

await valac.wait_async(null);
await meson_clean.wait_async(null);
if (!meson_clean.get_successful()) {
return false;
}

const meson_compile = meson_launcher.spawnv([
"meson",
"compile",
"-C",
meson_builddir,
]);

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() {
Expand All @@ -60,11 +90,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(" ") || [];
}
Comment on lines -63 to -70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

2 changes: 2 additions & 0 deletions src/langs/vala/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
install_data(['template/meson.build', 'template/workbench.vala'],
install_dir : join_paths(pkgdatadir, 'langs/vala/template'))
39 changes: 39 additions & 0 deletions src/langs/vala/template/meson.build
Original file line number Diff line number Diff line change
@@ -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'),
dependency('json-glib-1.0'),
Comment on lines +26 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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'),
dependency('json-glib-1.0'),
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'),
dependency('json-glib-1.0'),
dependency('libspelling-1'),

]

library('workbenchcode', source_files,
dependencies: dependencies,
install: true,
)
35 changes: 25 additions & 10 deletions src/langs/vala/vala.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@ 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;

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);
Comment on lines +12 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to move the meson and workbench.vala files under a subdir? to avoid cluttering the project

and we might need meson.build for other purposes too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I think this is possible. Would that subdir still be inside the project folder? Or do you mean saving just the main.vala in the project directory and get rid of all of the build stuff? I'm guessing this last option is also possible.


const lspc = createLSPClient({
lang: getLanguage("vala"),
Expand All @@ -44,3 +38,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,
),
]);
}
2 changes: 1 addition & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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')
Expand Down
22 changes: 22 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll check them out!

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;
}
Loading