update for 0.4.0 release
[vala-lang.git] / vapigen / valavapigen.vala
blobdded1d140e2369a44641957bf2066da42d85d178
1 /* valavapigen.vala
3 * Copyright (C) 2006-2008 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 class Vala.VAPIGen : Object {
26 static string directory;
27 static bool version;
28 static bool quiet_mode;
29 [NoArrayLength ()]
30 static string[] sources;
31 [NoArrayLength ()]
32 static string[] vapi_directories;
33 static string library;
34 [NoArrayLength ()]
35 static string[] packages;
36 static string metadata_filename;
37 CodeContext context;
39 const OptionEntry[] options = {
40 { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
41 { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
42 { "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
43 { "metadata", 0, 0, OptionArg.FILENAME, ref metadata_filename, "Metadata filename", "FILE" },
44 { "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" },
45 { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
46 { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null },
47 { "", 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
48 { null }
51 private int quit () {
52 if (Report.get_errors () == 0) {
53 if (!quiet_mode) {
54 stdout.printf ("Generation succeeded - %d warning(s)\n", Report.get_warnings ());
56 return 0;
57 } else {
58 if (!quiet_mode) {
59 stdout.printf ("Generation failed: %d error(s), %d warning(s)\n", Report.get_errors (), Report.get_warnings ());
61 return 1;
65 private bool add_package (string pkg) {
66 if (context.has_package (pkg)) {
67 // ignore multiple occurences of the same package
68 return true;
71 var package_path = context.get_package_path (pkg, vapi_directories);
73 if (package_path == null) {
74 return false;
77 context.add_package (pkg);
79 context.add_source_file (new SourceFile (context, package_path, true));
81 return true;
84 private static string[]? get_packages_from_depsfile (string depsfile) {
85 try {
86 string contents;
87 FileUtils.get_contents (depsfile, out contents);
88 return contents.strip ().split ("\n");
89 } catch (FileError e) {
90 // deps files are optional
91 return null;
95 private int run () {
96 context = new CodeContext ();
98 /* default package */
99 if (!add_package ("glib-2.0")) {
100 Report.error (null, "glib-2.0 not found in specified Vala API directories");
103 /* load packages from .deps file */
104 foreach (string source in sources) {
105 if (!source.has_suffix (".gi")) {
106 continue;
109 var depsfile = source.substring (0, source.len () - "gi".len ()) + "deps";
111 if (!FileUtils.test (depsfile, FileTest.EXISTS)) continue;
113 string[] deps = get_packages_from_depsfile (depsfile);
115 foreach (string dep in deps) {
116 if (!add_package (dep)) {
117 Report.error (null, "%s not found in specified Vala API directories".printf (dep));
122 if (packages != null) {
123 foreach (string package in packages) {
124 if (!add_package (package)) {
125 Report.error (null, "%s not found in specified Vala API directories".printf (package));
128 packages = null;
131 if (Report.get_errors () > 0) {
132 return quit ();
135 foreach (string source in sources) {
136 if (FileUtils.test (source, FileTest.EXISTS)) {
137 context.add_source_file (new SourceFile (context, source));
138 } else {
139 Report.error (null, "%s not found".printf (source));
142 sources = null;
144 if (Report.get_errors () > 0) {
145 return quit ();
148 var parser = new Parser ();
149 parser.parse (context);
151 if (Report.get_errors () > 0) {
152 return quit ();
155 var attributeprocessor = new AttributeProcessor ();
156 attributeprocessor.process (context);
158 if (Report.get_errors () > 0) {
159 return quit ();
162 var girparser = new GirParser ();
163 if (metadata_filename != null) {
164 girparser.parse_metadata (metadata_filename);
166 girparser.parse (context);
168 if (Report.get_errors () > 0) {
169 return quit ();
172 var gidlparser = new GIdlParser ();
173 gidlparser.parse (context);
175 if (Report.get_errors () > 0) {
176 return quit ();
179 var resolver = new SymbolResolver ();
180 resolver.resolve (context);
182 if (Report.get_errors () > 0) {
183 return quit ();
186 if (library != null) {
187 var interface_writer = new InterfaceWriter ();
188 interface_writer.write_file (context, "%s.vapi".printf (library));
190 library = null;
193 return quit ();
196 static int main (string[] args) {
197 try {
198 var opt_context = new OptionContext ("- Vala API Generator");
199 opt_context.set_help_enabled (true);
200 opt_context.add_main_entries (options, null);
201 opt_context.parse (ref args);
202 } catch (OptionError e) {
203 stdout.printf ("%s\n", e.message);
204 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
205 return 1;
208 if (version) {
209 stdout.printf ("Vala API Generator %s\n", Config.PACKAGE_VERSION);
210 return 0;
213 if (sources == null) {
214 stderr.printf ("No source file specified.\n");
215 return 1;
218 var vapigen = new VAPIGen ();
219 return vapigen.run ();