using GLib; namespace Spry.Cli { /** * Maintains a `compile_commands.json` in the application root for the * Vala language server: meson emits the database as a build artifact in * `builddir/`, and it is copied out to the root whenever a build * happens (the initial build on `spry new`, and every `spry dev` * build/rebuild). The copied file is generated state — gitignored and * excluded from packaging. */ public class CompileCommands : Object { /** * Runs the initial meson setup + build of a freshly scaffolded * application (so the compile database exists) and copies the * database to the project root. Failures are reported but do not * fail scaffolding itself. */ public static void build_initial(string app_dir, string? libdir) { var launcher = new SubprocessLauncher(SubprocessFlags.NONE); Tools.apply_env(launcher, libdir); stdout.printf("[spry] Running initial build (for compile_commands.json)…\n"); if (!run_step(launcher, app_dir, { "meson", "setup", ".", "builddir" }) || !run_step(launcher, app_dir, { "ninja", "-C", "builddir" })) { return; } copy_from_builddir(app_dir); } private static bool run_step(SubprocessLauncher launcher, string app_dir, string[] argv) { try { var previous = Environment.get_current_dir(); Environment.set_current_dir(app_dir); var process = launcher.spawnv(argv); Environment.set_current_dir(previous); if (!process.wait_check()) { stderr.printf("[spry] Initial build failed — compile_commands.json not generated\n"); return false; } } catch (Error e) { stderr.printf("[spry] Initial build could not run: %s\n", e.message); return false; } return true; } /** * Copies `builddir/compile_commands.json` to the project root when * it exists; a no-op otherwise (e.g. the build failed or produced * none). */ public static void copy_from_builddir(string app_dir) { try { var source = File.new_for_path(Path.build_filename(app_dir, "builddir", "compile_commands.json")); if (!source.query_exists()) { return; } var destination = File.new_for_path(Path.build_filename(app_dir, "compile_commands.json")); if (!destination.query_exists() || source.query_info("time::modified", FileQueryInfoFlags.NONE).get_modification_date_time() .difference(destination.query_info("time::modified", FileQueryInfoFlags.NONE).get_modification_date_time()) > 0) { source.copy(destination, FileCopyFlags.OVERWRITE); stdout.printf("[spry] compile_commands.json copied to the project root\n"); } } catch (Error e) { } } } }