Release 0.41.92
[vala-gnome.git] / compiler / valacompiler.vala
blobb6a21e5378ca85bacab2d3365aa7bb3ffa799c00
1 /* valacompiler.vala
3 * Copyright (C) 2006-2012 Jürg Billeter
4 * Copyright (C) 1996-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
24 using GLib;
26 class Vala.Compiler {
27 private const string DEFAULT_COLORS = "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01";
29 static string basedir;
30 static string directory;
31 static bool version;
32 static bool api_version;
33 [CCode (array_length = false, array_null_terminated = true)]
34 static string[] sources;
35 [CCode (array_length = false, array_null_terminated = true)]
36 static string[] vapi_directories;
37 [CCode (array_length = false, array_null_terminated = true)]
38 static string[] gir_directories;
39 [CCode (array_length = false, array_null_terminated = true)]
40 static string[] metadata_directories;
41 static string vapi_filename;
42 static string library;
43 static string shared_library;
44 static string gir;
45 [CCode (array_length = false, array_null_terminated = true)]
46 static string[] packages;
47 [CCode (array_length = false, array_null_terminated = true)]
48 static string[] fast_vapis;
49 static string target_glib;
50 [CCode (array_length = false, array_null_terminated = true)]
51 static string[] gresources;
52 [CCode (array_length = false, array_null_terminated = true)]
53 static string[] gresources_directories;
55 static bool ccode_only;
56 static bool abi_stability;
57 static string header_filename;
58 static bool use_header;
59 static string internal_header_filename;
60 static string internal_vapi_filename;
61 static string fast_vapi_filename;
62 static bool vapi_comments;
63 static string symbols_filename;
64 static string includedir;
65 static bool compile_only;
66 static string output;
67 static bool debug;
68 static bool thread;
69 static bool mem_profiler;
70 static bool disable_assert;
71 static bool enable_checking;
72 static bool deprecated;
73 static bool hide_internal;
74 static bool experimental;
75 static bool experimental_non_null;
76 static bool gobject_tracing;
77 static bool disable_since_check;
78 static bool disable_warnings;
79 static string cc_command;
80 [CCode (array_length = false, array_null_terminated = true)]
81 static string[] cc_options;
82 static string pkg_config_command;
83 static string dump_tree;
84 static bool save_temps;
85 [CCode (array_length = false, array_null_terminated = true)]
86 static string[] defines;
87 static bool quiet_mode;
88 static bool verbose_mode;
89 static string profile;
90 static bool nostdpkg;
91 static bool enable_version_header;
92 static bool disable_version_header;
93 static bool fatal_warnings;
94 static bool disable_colored_output;
95 static Report.Colored colored_output = Report.Colored.AUTO;
96 static string dependencies;
98 static string entry_point;
100 static bool run_output;
101 static string run_args;
103 private CodeContext context;
105 const OptionEntry[] options = {
106 { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
107 { "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for .gir files in DIRECTORY", "DIRECTORY..." },
108 { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR .metadata files in DIRECTORY", "DIRECTORY..." },
109 { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
110 { "vapi", 0, 0, OptionArg.FILENAME, ref vapi_filename, "Output VAPI file name", "FILE" },
111 { "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
112 { "shared-library", 0, 0, OptionArg.STRING, ref shared_library, "Shared library name used in generated gir", "NAME" },
113 { "gir", 0, 0, OptionArg.STRING, ref gir, "GObject-Introspection repository file name", "NAME-VERSION.gir" },
114 { "basedir", 'b', 0, OptionArg.FILENAME, ref basedir, "Base source directory", "DIRECTORY" },
115 { "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Change output directory from current working directory", "DIRECTORY" },
116 { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
117 { "api-version", 0, 0, OptionArg.NONE, ref api_version, "Display API version number", null },
118 { "ccode", 'C', 0, OptionArg.NONE, ref ccode_only, "Output C code", null },
119 { "header", 'H', 0, OptionArg.FILENAME, ref header_filename, "Output C header file", "FILE" },
120 { "use-header", 0, 0, OptionArg.NONE, ref use_header, "Use C header file", null },
121 { "includedir", 0, 0, OptionArg.FILENAME, ref includedir, "Directory used to include the C header file", "DIRECTORY" },
122 { "internal-header", 'h', 0, OptionArg.FILENAME, ref internal_header_filename, "Output internal C header file", "FILE" },
123 { "internal-vapi", 0, 0, OptionArg.FILENAME, ref internal_vapi_filename, "Output vapi with internal api", "FILE" },
124 { "fast-vapi", 0, 0, OptionArg.STRING, ref fast_vapi_filename, "Output vapi without performing symbol resolution", null },
125 { "use-fast-vapi", 0, 0, OptionArg.STRING_ARRAY, ref fast_vapis, "Use --fast-vapi output during this compile", null },
126 { "vapi-comments", 0, 0, OptionArg.NONE, ref vapi_comments, "Include comments in generated vapi", null },
127 { "deps", 0, 0, OptionArg.STRING, ref dependencies, "Write make-style dependency information to this file", null },
128 { "symbols", 0, 0, OptionArg.FILENAME, ref symbols_filename, "Output symbols file", "FILE" },
129 { "compile", 'c', 0, OptionArg.NONE, ref compile_only, "Compile but do not link", null },
130 { "output", 'o', 0, OptionArg.FILENAME, ref output, "Place output in file FILE", "FILE" },
131 { "debug", 'g', 0, OptionArg.NONE, ref debug, "Produce debug information", null },
132 { "thread", 0, 0, OptionArg.NONE, ref thread, "Enable multithreading support (DEPRECATED AND IGNORED)", null },
133 { "enable-mem-profiler", 0, 0, OptionArg.NONE, ref mem_profiler, "Enable GLib memory profiler", null },
134 { "define", 'D', 0, OptionArg.STRING_ARRAY, ref defines, "Define SYMBOL", "SYMBOL..." },
135 { "main", 0, 0, OptionArg.STRING, ref entry_point, "Use SYMBOL as entry point", "SYMBOL..." },
136 { "nostdpkg", 0, 0, OptionArg.NONE, ref nostdpkg, "Do not include standard packages", null },
137 { "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
138 { "enable-checking", 0, 0, OptionArg.NONE, ref enable_checking, "Enable additional run-time checks", null },
139 { "enable-deprecated", 0, 0, OptionArg.NONE, ref deprecated, "Enable deprecated features", null },
140 { "hide-internal", 0, 0, OptionArg.NONE, ref hide_internal, "Hide symbols marked as internal", null },
141 { "enable-experimental", 0, 0, OptionArg.NONE, ref experimental, "Enable experimental features", null },
142 { "disable-warnings", 0, 0, OptionArg.NONE, ref disable_warnings, "Disable warnings", null },
143 { "fatal-warnings", 0, 0, OptionArg.NONE, ref fatal_warnings, "Treat warnings as fatal", null },
144 { "disable-since-check", 0, 0, OptionArg.NONE, ref disable_since_check, "Do not check whether used symbols exist in local packages", null },
145 { "enable-experimental-non-null", 0, 0, OptionArg.NONE, ref experimental_non_null, "Enable experimental enhancements for non-null types", null },
146 { "enable-gobject-tracing", 0, 0, OptionArg.NONE, ref gobject_tracing, "Enable GObject creation tracing", null },
147 { "cc", 0, 0, OptionArg.STRING, ref cc_command, "Use COMMAND as C compiler command", "COMMAND" },
148 { "Xcc", 'X', 0, OptionArg.STRING_ARRAY, ref cc_options, "Pass OPTION to the C compiler", "OPTION..." },
149 { "pkg-config", 0, 0, OptionArg.STRING, ref pkg_config_command, "Use COMMAND as pkg-config command", "COMMAND" },
150 { "dump-tree", 0, 0, OptionArg.FILENAME, ref dump_tree, "Write code tree to FILE", "FILE" },
151 { "save-temps", 0, 0, OptionArg.NONE, ref save_temps, "Keep temporary files", null },
152 { "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the default", "PROFILE" },
153 { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null },
154 { "verbose", 'v', 0, OptionArg.NONE, ref verbose_mode, "Print additional messages to the console", null },
155 { "no-color", 0, 0, OptionArg.NONE, ref disable_colored_output, "Disable colored output, alias for --color=never", null },
156 { "color", 0, OptionFlags.OPTIONAL_ARG, OptionArg.CALLBACK, (void*) option_parse_color, "Enable color output, options are 'always', 'never', or 'auto'", "WHEN" },
157 { "target-glib", 0, 0, OptionArg.STRING, ref target_glib, "Target version of glib for code generation", "MAJOR.MINOR" },
158 { "gresources", 0, 0, OptionArg.FILENAME_ARRAY, ref gresources, "XML of gresources", "FILE..." },
159 { "gresourcesdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gresources_directories, "Look for resources in DIRECTORY", "DIRECTORY..." },
160 { "enable-version-header", 0, 0, OptionArg.NONE, ref enable_version_header, "Write vala build version in generated files", null },
161 { "disable-version-header", 0, 0, OptionArg.NONE, ref disable_version_header, "Do not write vala build version in generated files", null },
162 { "run-args", 0, 0, OptionArg.STRING, ref run_args, "Arguments passed to directly compiled executeable", null },
163 { "abi-stability", 0, 0, OptionArg.NONE, ref abi_stability, "Enable support for ABI stability", null },
164 { OPTION_REMAINING, 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
165 { null }
168 static bool option_parse_color (string option_name, string? val, void* data) throws OptionError {
169 switch (val) {
170 case "auto": colored_output = Report.Colored.AUTO; break;
171 case "never": colored_output = Report.Colored.NEVER; break;
172 case null:
173 case "always": colored_output = Report.Colored.ALWAYS; break;
174 default: throw new OptionError.FAILED ("Invalid --color argument '%s'", val);
176 return true;
179 private int quit () {
180 if (context.report.get_errors () == 0 && context.report.get_warnings () == 0) {
181 return 0;
183 if (context.report.get_errors () == 0 && (!fatal_warnings || context.report.get_warnings () == 0)) {
184 if (!quiet_mode) {
185 stdout.printf ("Compilation succeeded - %d warning(s)\n", context.report.get_warnings ());
187 return 0;
188 } else {
189 if (!quiet_mode) {
190 stdout.printf ("Compilation failed: %d error(s), %d warning(s)\n", context.report.get_errors (), context.report.get_warnings ());
192 return 1;
196 private int run () {
197 context = new CodeContext ();
198 CodeContext.push (context);
200 if (disable_colored_output) {
201 colored_output = Report.Colored.NEVER;
204 if (colored_output != Report.Colored.NEVER) {
205 unowned string env_colors = Environment.get_variable ("VALA_COLORS");
206 if (env_colors != null) {
207 context.report.set_colors (env_colors, colored_output);
208 } else {
209 context.report.set_colors (DEFAULT_COLORS, colored_output);
214 // default to build executable
215 if (!ccode_only && !compile_only && output == null) {
216 // strip extension if there is one
217 // else we use the default output file of the C compiler
218 if (sources[0].last_index_of_char ('.') != -1) {
219 int dot = sources[0].last_index_of_char ('.');
220 output = Path.get_basename (sources[0].substring (0, dot));
224 context.assert = !disable_assert;
225 context.checking = enable_checking;
226 context.deprecated = deprecated;
227 context.since_check = !disable_since_check;
228 context.hide_internal = hide_internal;
229 context.experimental = experimental;
230 context.experimental_non_null = experimental_non_null;
231 context.gobject_tracing = gobject_tracing;
232 context.report.enable_warnings = !disable_warnings;
233 context.report.set_verbose_errors (!quiet_mode);
234 context.verbose_mode = verbose_mode;
235 context.version_header = !disable_version_header;
237 context.ccode_only = ccode_only;
238 if (ccode_only && cc_options != null) {
239 Report.warning (null, "-X has no effect when -C or --ccode is set");
241 context.abi_stability = abi_stability;
242 context.compile_only = compile_only;
243 context.header_filename = header_filename;
244 if (header_filename == null && use_header) {
245 Report.error (null, "--use-header may only be used in combination with --header");
247 context.use_header = use_header;
248 context.internal_header_filename = internal_header_filename;
249 context.symbols_filename = symbols_filename;
250 context.includedir = includedir;
251 context.output = output;
252 if (output != null && ccode_only) {
253 Report.warning (null, "--output and -o have no effect when -C or --ccode is set");
255 if (basedir == null) {
256 context.basedir = CodeContext.realpath (".");
257 } else {
258 context.basedir = CodeContext.realpath (basedir);
260 if (directory != null) {
261 context.directory = CodeContext.realpath (directory);
262 } else {
263 context.directory = context.basedir;
265 context.vapi_directories = vapi_directories;
266 context.vapi_comments = vapi_comments;
267 context.gir_directories = gir_directories;
268 context.metadata_directories = metadata_directories;
269 context.debug = debug;
270 context.mem_profiler = mem_profiler;
271 context.save_temps = save_temps;
272 if (ccode_only && save_temps) {
273 Report.warning (null, "--save-temps has no effect when -C or --ccode is set");
275 if (profile == "posix") {
276 context.profile = Profile.POSIX;
277 context.add_define ("POSIX");
278 } else if (profile == "gobject-2.0" || profile == "gobject" || profile == null) {
279 // default profile
280 context.profile = Profile.GOBJECT;
281 context.add_define ("GOBJECT");
282 } else {
283 Report.error (null, "Unknown profile %s".printf (profile));
285 nostdpkg |= fast_vapi_filename != null;
286 context.nostdpkg = nostdpkg;
288 context.entry_point_name = entry_point;
290 context.run_output = run_output;
292 if (pkg_config_command == null) {
293 pkg_config_command = Environment.get_variable ("PKG_CONFIG") ?? "pkg-config";
295 context.pkg_config_command = pkg_config_command;
297 if (defines != null) {
298 foreach (string define in defines) {
299 context.add_define (define);
303 for (int i = 2; i <= 42; i += 2) {
304 context.add_define ("VALA_0_%d".printf (i));
307 if (context.profile == Profile.POSIX) {
308 if (!nostdpkg) {
309 /* default package */
310 context.add_external_package ("posix");
312 } else if (context.profile == Profile.GOBJECT) {
313 int glib_major = 2;
314 int glib_minor = 40;
315 if (target_glib != null && target_glib.scanf ("%d.%d", out glib_major, out glib_minor) != 2) {
316 Report.error (null, "Invalid format for --target-glib");
319 context.target_glib_major = glib_major;
320 context.target_glib_minor = glib_minor;
321 if (context.target_glib_major != 2) {
322 Report.error (null, "This version of valac only supports GLib 2");
325 for (int i = 16; i <= glib_minor; i += 2) {
326 context.add_define ("GLIB_2_%d".printf (i));
329 if (!nostdpkg) {
330 /* default packages */
331 context.add_external_package ("glib-2.0");
332 context.add_external_package ("gobject-2.0");
336 if (packages != null) {
337 foreach (string package in packages) {
338 context.add_external_package (package);
340 packages = null;
343 if (fast_vapis != null) {
344 foreach (string vapi in fast_vapis) {
345 var rpath = CodeContext.realpath (vapi);
346 var source_file = new SourceFile (context, SourceFileType.FAST, rpath);
347 context.add_source_file (source_file);
349 context.use_fast_vapi = true;
352 context.gresources = gresources;
353 context.gresources_directories = gresources_directories;
355 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
356 return quit ();
359 if (context.profile == Profile.GOBJECT) {
360 context.codegen = new GDBusServerModule ();
361 } else {
362 context.codegen = new CCodeDelegateModule ();
365 bool has_c_files = false;
366 bool has_h_files = false;
368 foreach (string source in sources) {
369 if (context.add_source_filename (source, run_output, true)) {
370 if (source.has_suffix (".c")) {
371 has_c_files = true;
372 } else if (source.has_suffix (".h")) {
373 has_h_files = true;
377 sources = null;
378 if (ccode_only && (has_c_files || has_h_files)) {
379 Report.warning (null, "C header and source files are ignored when -C or --ccode is set");
382 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
383 return quit ();
386 var parser = new Parser ();
387 parser.parse (context);
389 var genie_parser = new Genie.Parser ();
390 genie_parser.parse (context);
392 var gir_parser = new GirParser ();
393 gir_parser.parse (context);
395 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
396 return quit ();
399 if (fast_vapi_filename != null) {
400 var interface_writer = new CodeWriter (CodeWriterType.FAST);
401 interface_writer.write_file (context, fast_vapi_filename);
402 return quit ();
405 context.check ();
407 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
408 return quit ();
411 if (!ccode_only && !compile_only && library == null) {
412 // building program, require entry point
413 if (!has_c_files && context.entry_point == null) {
414 Report.error (null, "program does not contain a static `main' method");
418 if (dump_tree != null) {
419 var code_writer = new CodeWriter (CodeWriterType.DUMP);
420 code_writer.write_file (context, dump_tree);
423 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
424 return quit ();
427 context.codegen.emit (context);
429 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
430 return quit ();
433 if (vapi_filename == null && library != null) {
434 // keep backward compatibility with --library option
435 vapi_filename = "%s.vapi".printf (library);
438 if (library != null) {
439 if (gir != null) {
440 if (context.profile == Profile.GOBJECT) {
441 string gir_base = Path.get_basename (gir);
442 long gir_len = gir_base.length;
443 int last_hyphen = gir_base.last_index_of_char ('-');
445 if (last_hyphen == -1 || !gir_base.has_suffix (".gir")) {
446 Report.error (null, "GIR file name `%s' is not well-formed, expected NAME-VERSION.gir".printf (gir));
447 } else {
448 string gir_namespace = gir_base.substring (0, last_hyphen);
449 string gir_version = gir_base.substring (last_hyphen + 1, gir_len - last_hyphen - 5);
450 gir_version.canon ("0123456789.", '?');
451 if (gir_namespace == "" || gir_version == "" || !gir_version[0].isdigit () || gir_version.contains ("?")) {
452 Report.error (null, "GIR file name `%s' is not well-formed, expected NAME-VERSION.gir".printf (gir));
453 } else {
454 var gir_writer = new GIRWriter ();
456 // put .gir file in current directory unless -d has been explicitly specified
457 string gir_directory = ".";
458 if (directory != null) {
459 gir_directory = context.directory;
462 gir_writer.write_file (context, gir_directory, gir, gir_namespace, gir_version, library, shared_library);
467 gir = null;
470 library = null;
471 } else {
472 if (gir != null) {
473 Report.warning (null, "--gir has no effect without --library");
474 gir = null;
478 // The GIRWriter places the gir_namespace and gir_version into the top namespace, so write the vapi after that stage
479 if (vapi_filename != null) {
480 var interface_writer = new CodeWriter ();
482 // put .vapi file in current directory unless -d has been explicitly specified
483 if (directory != null && !Path.is_absolute (vapi_filename)) {
484 vapi_filename = "%s%c%s".printf (context.directory, Path.DIR_SEPARATOR, vapi_filename);
487 interface_writer.write_file (context, vapi_filename);
490 if (internal_vapi_filename != null) {
491 if (internal_header_filename == null ||
492 header_filename == null) {
493 Report.error (null, "--internal-vapi may only be used in combination with --header and --internal-header");
494 return quit();
497 var interface_writer = new CodeWriter (CodeWriterType.INTERNAL);
499 if (context.includedir != null) {
500 var prefixed_header_filename = Path.build_path ("/", context.includedir, Path.get_basename (header_filename));
501 var prefixed_internal_header_filename = Path.build_path ("/", context.includedir, Path.get_basename (internal_header_filename));
502 interface_writer.set_cheader_override (prefixed_header_filename, prefixed_internal_header_filename);
503 } else {
504 interface_writer.set_cheader_override (header_filename, internal_header_filename);
507 string vapi_filename = internal_vapi_filename;
509 // put .vapi file in current directory unless -d has been explicitly specified
510 if (directory != null && !Path.is_absolute (vapi_filename)) {
511 vapi_filename = "%s%c%s".printf (context.directory, Path.DIR_SEPARATOR, vapi_filename);
514 interface_writer.write_file (context, vapi_filename);
516 internal_vapi_filename = null;
519 if (dependencies != null) {
520 context.write_dependencies (dependencies);
523 if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
524 return quit ();
527 if (!ccode_only) {
528 var ccompiler = new CCodeCompiler ();
529 if (cc_command == null && Environment.get_variable ("CC") != null) {
530 cc_command = Environment.get_variable ("CC");
532 if (cc_options == null) {
533 ccompiler.compile (context, cc_command, new string[] { });
534 } else {
535 ccompiler.compile (context, cc_command, cc_options);
539 return quit ();
542 static int run_source (string[] args) {
543 try {
544 var opt_context = new OptionContext ("- Vala Interpreter");
545 opt_context.set_help_enabled (true);
546 opt_context.add_main_entries (options, null);
547 opt_context.parse (ref args);
548 } catch (OptionError e) {
549 stdout.printf ("%s\n", e.message);
550 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
551 return 1;
554 if (version) {
555 stdout.printf ("Vala %s\n", Vala.BUILD_VERSION);
556 return 0;
557 } else if (api_version) {
558 stdout.printf ("%s\n", Vala.API_VERSION);
559 return 0;
562 if (sources == null) {
563 stderr.printf ("No source file specified.\n");
564 return 1;
567 output = "%s/%s.XXXXXX".printf (Environment.get_tmp_dir (), Path.get_basename (sources[0]));
568 int outputfd = FileUtils.mkstemp (output);
569 if (outputfd < 0) {
570 return 1;
573 ccode_only = false;
574 compile_only = false;
575 run_output = true;
576 disable_warnings = true;
577 quiet_mode = true;
578 library = null;
579 shared_library = null;
581 var compiler = new Compiler ();
582 int ret = compiler.run ();
583 if (ret != 0) {
584 return ret;
587 FileUtils.close (outputfd);
588 if (FileUtils.chmod (output, 0700) != 0) {
589 FileUtils.unlink (output);
590 return 1;
593 string[] target_args = { output };
594 if (run_args != null) {
595 string[] target_run_args = run_args.split (" ");
596 foreach (string arg in target_run_args) {
597 target_args += arg;
601 try {
602 Pid pid;
603 var loop = new MainLoop ();
604 int child_status = 0;
606 Process.spawn_async (null, target_args, null, SpawnFlags.CHILD_INHERITS_STDIN | SpawnFlags.DO_NOT_REAP_CHILD, null, out pid);
608 FileUtils.unlink (output);
609 ChildWatch.add (pid, (pid, status) => {
610 child_status = (status & 0xff00) >> 8;
611 loop.quit ();
614 loop.run ();
616 return child_status;
617 } catch (SpawnError e) {
618 stdout.printf ("%s\n", e.message);
619 return 1;
623 static int main (string[] args) {
624 // initialize locale
625 Intl.setlocale (LocaleCategory.ALL, "");
627 if (Path.get_basename (args[0]) == "vala" || Path.get_basename (args[0]) == "vala" + Config.PACKAGE_SUFFIX) {
628 return run_source (args);
631 try {
632 var opt_context = new OptionContext ("- Vala Compiler");
633 opt_context.set_help_enabled (true);
634 opt_context.add_main_entries (options, null);
635 opt_context.parse (ref args);
636 } catch (OptionError e) {
637 stdout.printf ("%s\n", e.message);
638 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
639 return 1;
642 if (version) {
643 stdout.printf ("Vala %s\n", Vala.BUILD_VERSION);
644 return 0;
645 } else if (api_version) {
646 stdout.printf ("%s\n", Vala.API_VERSION);
647 return 0;
650 if (sources == null && fast_vapis == null) {
651 stderr.printf ("No source file specified.\n");
652 return 1;
655 var compiler = new Compiler ();
656 return compiler.run ();