Skip to content

Instantly share code, notes, and snippets.

@darkoverlordofdata
Created May 13, 2017 22:20
Show Gist options
  • Save darkoverlordofdata/2dd3fe13ba077c6303bc73e07b8fdfbb to your computer and use it in GitHub Desktop.
Save darkoverlordofdata/2dd3fe13ba077c6303bc73e07b8fdfbb to your computer and use it in GitHub Desktop.
wrap valac for use from script (nodejs)
#!/usr/bin/env vala
/**
* ValaC2
*
* breaks valac into 2 steps with plugin pre/post processing
* this front end just collects all of the command line arguments and runs the coffeescript.
*
* command line flags are mangled to prevent the cli from expanding them.
*
*
* Adds 2 new optiona:
* --plugin=FILE
* plugin to call with the rest of the input params
* --builddir=DIRECTORY
* required location for out of tree build
* no in tree builds allowed
*
* use case: emscripten
*
* possibly over engineered, but it keeps the flags intact.
*
* using the command line interface described in valacompiler.vala
* @see https://github.com/GNOME/vala/blob/master/compiler/valacompiler.vala
*/
using GLib;
class Valac2 {
static string builddir;
static string builder;
static string basedir;
static string directory;
static bool version;
static bool api_version;
[CCode (array_length = false, array_null_terminated = true)]
static string[] sources;
[CCode (array_length = false, array_null_terminated = true)]
static string[] vapi_directories;
[CCode (array_length = false, array_null_terminated = true)]
static string[] gir_directories;
[CCode (array_length = false, array_null_terminated = true)]
static string[] metadata_directories;
static string vapi_filename;
static string library;
static string shared_library;
static string gir;
[CCode (array_length = false, array_null_terminated = true)]
static string[] packages;
[CCode (array_length = false, array_null_terminated = true)]
static string[] fast_vapis;
static string target_glib;
[CCode (array_length = false, array_null_terminated = true)]
static string[] gresources;
static bool ccode_only;
static string header_filename;
static bool use_header;
static string internal_header_filename;
static string internal_vapi_filename;
static string fast_vapi_filename;
static bool vapi_comments;
static string symbocmd_filename;
static string includedir;
static bool compile_only;
static string output;
static bool debug;
static bool thread;
static bool mem_profiler;
static bool disable_assert;
static bool enable_checking;
static bool deprecated;
static bool hide_internal;
static bool experimental;
static bool experimental_non_null;
static bool gobject_tracing;
static bool disable_since_check;
static bool disable_warnings;
static string cc_command;
[CCode (array_length = false, array_null_terminated = true)]
static string[] cc_options;
static string pkg_config_command;
static string dump_tree;
static bool save_temps;
[CCode (array_length = false, array_null_terminated = true)]
static string[] defines;
static bool quiet_mode;
static bool verbose_mode;
static string profile;
static bool nostdpkg;
static bool enable_version_header;
static bool disable_version_header;
static bool fatal_warnings;
static bool disable_colored_output;
static string dependencies;
static string entry_point;
static bool run_output;
const OptionEntry[] options = {
{ "plugin", 0, 0, OptionArg.FILENAME, ref builder, "Plugin build process", "FILE" },
{ "builddir", 0, 0, OptionArg.FILENAME, ref builddir, "Out of tree location for build", "DIRECTORY" },
{ "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
{ "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for .gir files in DIRECTORY", "DIRECTORY..." },
{ "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR .metadata files in DIRECTORY", "DIRECTORY..." },
{ "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
{ "vapi", 0, 0, OptionArg.FILENAME, ref vapi_filename, "Output VAPI file name", "FILE" },
{ "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
{ "shared-library", 0, 0, OptionArg.STRING, ref shared_library, "Shared library name used in generated gir", "NAME" },
{ "gir", 0, 0, OptionArg.STRING, ref gir, "GObject-Introspection repository file name", "NAME-VERSION.gir" },
{ "basedir", 'b', 0, OptionArg.FILENAME, ref basedir, "Base source directory", "DIRECTORY" },
{ "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Change output directory from current working directory", "DIRECTORY" },
{ "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
{ "api-version", 0, 0, OptionArg.NONE, ref api_version, "Display API version number", null },
{ "ccode", 'C', 0, OptionArg.NONE, ref ccode_only, "Output C code", null },
{ "header", 'H', 0, OptionArg.FILENAME, ref header_filename, "Output C header file", "FILE" },
{ "use-header", 0, 0, OptionArg.NONE, ref use_header, "Use C header file", null },
{ "includedir", 0, 0, OptionArg.FILENAME, ref includedir, "Directory used to include the C header file", "DIRECTORY" },
{ "internal-header", 'h', 0, OptionArg.FILENAME, ref internal_header_filename, "Output internal C header file", "FILE" },
{ "internal-vapi", 0, 0, OptionArg.FILENAME, ref internal_vapi_filename, "Output vapi with internal api", "FILE" },
{ "fast-vapi", 0, 0, OptionArg.STRING, ref fast_vapi_filename, "Output vapi without performing symbol resolution", null },
{ "use-fast-vapi", 0, 0, OptionArg.STRING_ARRAY, ref fast_vapis, "Use --fast-vapi output during this compile", null },
{ "vapi-comments", 0, 0, OptionArg.NONE, ref vapi_comments, "Include comments in generated vapi", null },
{ "deps", 0, 0, OptionArg.STRING, ref dependencies, "Write make-style dependency information to this file", null },
{ "symbols", 0, 0, OptionArg.FILENAME, ref symbocmd_filename, "Output symbols file", "FILE" },
{ "compile", 'c', 0, OptionArg.NONE, ref compile_only, "Compile but do not link", null },
{ "output", 'o', 0, OptionArg.FILENAME, ref output, "Place output in file FILE", "FILE" },
{ "debug", 'g', 0, OptionArg.NONE, ref debug, "Produce debug information", null },
{ "thread", 0, 0, OptionArg.NONE, ref thread, "Enable multithreading support (DEPRECATED AND IGNORED)", null },
{ "enable-mem-profiler", 0, 0, OptionArg.NONE, ref mem_profiler, "Enable GLib memory profiler", null },
{ "define", 'D', 0, OptionArg.STRING_ARRAY, ref defines, "Define SYMBOL", "SYMBOL..." },
{ "main", 0, 0, OptionArg.STRING, ref entry_point, "Use SYMBOL as entry point", "SYMBOL..." },
{ "nostdpkg", 0, 0, OptionArg.NONE, ref nostdpkg, "Do not include standard packages", null },
{ "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
{ "enable-checking", 0, 0, OptionArg.NONE, ref enable_checking, "Enable additional run-time checks", null },
{ "enable-deprecated", 0, 0, OptionArg.NONE, ref deprecated, "Enable deprecated features", null },
{ "hide-internal", 0, 0, OptionArg.NONE, ref hide_internal, "Hide symbols marked as internal", null },
{ "enable-experimental", 0, 0, OptionArg.NONE, ref experimental, "Enable experimental features", null },
{ "disable-warnings", 0, 0, OptionArg.NONE, ref disable_warnings, "Disable warnings", null },
{ "fatal-warnings", 0, 0, OptionArg.NONE, ref fatal_warnings, "Treat warnings as fatal", null },
{ "disable-since-check", 0, 0, OptionArg.NONE, ref disable_since_check, "Do not check whether used symbols exist in local packages", null },
{ "enable-experimental-non-null", 0, 0, OptionArg.NONE, ref experimental_non_null, "Enable experimental enhancements for non-null types", null },
{ "enable-gobject-tracing", 0, 0, OptionArg.NONE, ref gobject_tracing, "Enable GObject creation tracing", null },
{ "cc", 0, 0, OptionArg.STRING, ref cc_command, "Use COMMAND as C compiler command", "COMMAND" },
{ "Xcc", 'X', 0, OptionArg.STRING_ARRAY, ref cc_options, "Pass OPTION to the C compiler", "OPTION..." },
{ "pkg-config", 0, 0, OptionArg.STRING, ref pkg_config_command, "Use COMMAND as pkg-config command", "COMMAND" },
{ "dump-tree", 0, 0, OptionArg.FILENAME, ref dump_tree, "Write code tree to FILE", "FILE" },
{ "save-temps", 0, 0, OptionArg.NONE, ref save_temps, "Keep temporary files", null },
{ "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the default", "PROFILE" },
{ "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null },
{ "verbose", 'v', 0, OptionArg.NONE, ref verbose_mode, "Print additional messages to the console", null },
{ "no-color", 0, 0, OptionArg.NONE, ref disable_colored_output, "Disable colored output, alias for --color=never", null },
{ "target-glib", 0, 0, OptionArg.STRING, ref target_glib, "Target version of glib for code generation", "MAJOR.MINOR" },
{ "gresources", 0, 0, OptionArg.STRING_ARRAY, ref gresources, "XML of gresources", "FILE..." },
{ "enable-version-header", 0, 0, OptionArg.NONE, ref enable_version_header, "Write vala build version in generated files", null },
{ "disable-version-header", 0, 0, OptionArg.NONE, ref disable_version_header, "Do not write vala build version in generated files", null },
{ "", 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
{ null }
};
static int main (string[] args) {
try {
var opt_context = new OptionContext ("- ValaC2");
opt_context.set_help_enabled (true);
opt_context.add_main_entries (options, null);
opt_context.parse (ref args);
} catch (OptionError e) {
stdout.printf ("error: %s\n", e.message);
stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
return 0;
}
if (version) {
stdout.printf ("ValaC2 Beta 0.0.1\n");
return 0;
}
if (builddir == null) {
stderr.printf ("In tree build not allowed.\n");
return 1;
}
if (builder == null) {
stderr.printf ("Build plugin required.\n");
return 1;
}
if (sources == null && fast_vapis == null) {
stderr.printf ("No source file specified.\n");
return 1;
}
/** Ok, call the back end */
spawn(build());
return 0;
}
/** mangle the flags so they pass thru unchanged */
static string build() {
StringBuilder sb = new StringBuilder();
sb.append(builder);
sb.append(" ");
sb.append("~~builddir ");
sb.append(builddir);
sb.append(" ");
if (ccode_only) sb.append("~C ");
if (save_temps) sb.append("~~save~temps ");
if (quiet_mode) sb.append("~~quiet ");
if (verbose_mode) sb.append("~~verbose ");
if (vapi_comments) sb.append("~~vapi~comments ");
if (compile_only) sb.append("~~compile~only ");
if (api_version) sb.append("~~api-version ");
if (use_header) sb.append("~~use~header ");
if (debug) sb.append("~~debug ");
if (thread) sb.append("~~thread ");
if (mem_profiler) sb.append("~~enable~mem~profiler ");
if (disable_assert) sb.append("~~disable~assert ");
if (enable_checking) sb.append("~~enable~checking ");
if (deprecated) sb.append("~~enable-deprecated ");
if (hide_internal) sb.append("~~hide~internal ");
if (experimental) sb.append("~~enable~experimental ");
if (experimental_non_null) sb.append("~~enable-experimental-non-null ");
if (gobject_tracing) sb.append("~~enable~gobject~tracing ");
if (disable_since_check) sb.append("~~disable~since~check ");
if (disable_warnings) sb.append("~~disable~warnings ");
if (nostdpkg) sb.append("~~nostdpkg ");
if (enable_version_header) sb.append("~~enable~version~header ");
if (disable_version_header) sb.append("~~disable~version~header ");
if (fatal_warnings) sb.append("~~fatal~warnings ");
if (disable_colored_output) sb.append("~~no-color ");
if (basedir != null) {
sb.append("~~basedir ");
sb.append(basedir);
sb.append(" ");
}
if (directory != null) {
sb.append("~~directory ");
sb.append(directory);
sb.append(" ");
}
if (vapi_directories != null) {
foreach (var v in vapi_directories) {
sb.append("~~vapidir ");
sb.append(v);
sb.append(" ");
}
}
if (gir_directories != null) {
foreach (var g in gir_directories) {
sb.append("~~girdir ");
sb.append(g);
sb.append(" ");
}
}
if (metadata_directories != null) {
foreach (var m in metadata_directories) {
sb.append("~~metadatadir ");
sb.append(m);
sb.append(" ");
}
}
if (vapi_filename != null) {
sb.append("~~vapi ");
sb.append(vapi_filename);
sb.append(" ");
}
if (library != null) {
sb.append("~~library ");
sb.append(library);
sb.append(" ");
}
if (shared_library != null) {
sb.append("~~shared~library ");
sb.append(shared_library);
sb.append(" ");
}
if (gir != null) {
sb.append("~~gir ");
sb.append(gir);
sb.append(" ");
}
if (packages != null) {
foreach (var p in packages) {
sb.append("~~pkg ");
sb.append(p);
sb.append(" ");
}
}
if (fast_vapis != null) {
foreach (var f in fast_vapis) {
sb.append("~~fast~vapi ");
sb.append(f);
sb.append(" ");
}
}
if (target_glib != null) {
sb.append("~~target~glib ");
sb.append(target_glib);
sb.append(" ");
}
if (gresources != null) {
foreach (var g in gresources) {
sb.append("~~gresources ");
sb.append(g);
sb.append(" ");
}
}
if (header_filename != null) {
sb.append("~~header~filename ");
sb.append(header_filename);
sb.append(" ");
}
if (internal_header_filename != null) {
sb.append("~~internal~header ");
sb.append(internal_header_filename);
sb.append(" ");
}
if (internal_vapi_filename != null) {
sb.append("~~internal~vapi ");
sb.append(internal_vapi_filename);
sb.append(" ");
}
if (fast_vapi_filename != null) {
sb.append("~~fast~vapi ");
sb.append(fast_vapi_filename);
sb.append(" ");
}
if (symbocmd_filename != null) {
sb.append("~~symbols ");
sb.append(symbocmd_filename);
sb.append(" ");
}
if (includedir != null) {
sb.append("~~includedir ");
sb.append(includedir);
sb.append(" ");
}
if (output != null) {
sb.append("~~output ");
sb.append(output);
sb.append(" ");
}
if (cc_command != null) {
sb.append("~~cc ");
sb.append(cc_command);
sb.append(" ");
}
if (cc_options != null) {
foreach (var o in cc_options) {
sb.append("~~Xcc ");
while (o.index_of("-")>-1) o = o.replace("-", "~");
while (o.index_of(" ")>-1) o = o.replace(" ", "%20");
sb.append(o);
sb.append(" ");
}
}
if (pkg_config_command != null) {
sb.append("~~pkg-config ");
sb.append(pkg_config_command);
sb.append(" ");
}
if (dump_tree != null) {
sb.append("~~dump~tree ");
sb.append(dump_tree);
sb.append(" ");
}
if (defines != null) {
foreach (var d in defines) {
sb.append("~~define ");
sb.append(d);
sb.append(" ");
}
}
if (profile != null) {
sb.append("~~profile ");
sb.append(profile);
sb.append(" ");
}
foreach (var s in sources) {
sb.append(s);
sb.append(" ");
}
return sb.str;
}
static void spawn(string cmd) {
stdout.printf("%s\n", cmd);
try {
string[] spawn_args = cmd.split(" ");
string[] spawn_env = Environ.get();
string cmd_stdout;
string cmd_stderr;
int cmd_status;
Process.spawn_sync(null,
spawn_args,
spawn_env,
SpawnFlags.SEARCH_PATH,
null,
out cmd_stdout,
out cmd_stderr,
out cmd_status);
stdout.printf("stdout:\n");
stdout.puts(cmd_stdout);
stdout.printf("stderr:\n");
stdout.puts(cmd_stderr);
stdout.printf("status: %d\n", cmd_status);
} catch (SpawnError e) {
stdout.printf("Error: %s\n", e.message);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment