3 * Copyright (C) 2006-2010 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
20 * Jürg Billeter <j@bitron.ch>
25 class Vala
.VAPIGen
: Object
{
26 static string directory
;
28 static bool quiet_mode
;
29 [CCode (array_length
= false, array_null_terminated
= true)]
30 static string[] sources
;
31 [CCode (array_length
= false, array_null_terminated
= true)]
32 static string[] vapi_directories
;
33 static string library
;
34 [CCode (array_length
= false, array_null_terminated
= true)]
35 static string[] packages
;
36 static string metadata_filename
;
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..." },
52 if (context
.report
.get_errors () == 0) {
54 stdout
.printf ("Generation succeeded - %d warning(s)\n", context
.report
.get_warnings ());
59 stdout
.printf ("Generation failed: %d error(s), %d warning(s)\n", context
.report
.get_errors (), context
.report
.get_warnings ());
65 /* TODO: this is duplicated between here and the compiler. its should go somewhere on its own */
66 private bool add_package (string pkg
) {
67 if (context
.has_package (pkg
)) {
68 // ignore multiple occurences of the same package
72 var package_path
= context
.get_package_path (pkg
, vapi_directories
);
74 if (package_path
== null) {
78 context
.add_package (pkg
);
80 context
.add_source_file (new
SourceFile (context
, package_path
, true));
82 var deps_filename
= Path
.build_filename (Path
.get_dirname (package_path
), "%s.deps".printf (pkg
));
83 if (FileUtils
.test (deps_filename
, FileTest
.EXISTS
)) {
87 FileUtils
.get_contents (deps_filename
, out deps_content
, out deps_len
);
88 foreach (string dep
in deps_content
.split ("\n")) {
91 if (!add_package (dep
)) {
92 Report
.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep
, pkg
));
96 } catch (FileError e
) {
97 Report
.error (null, "Unable to read dependency file: %s".printf (e
.message
));
104 private static string[]?
get_packages_from_depsfile (string depsfile
) {
107 FileUtils
.get_contents (depsfile
, out contents
);
108 return contents
.strip ().split ("\n");
109 } catch (FileError e
) {
110 // deps files are optional
116 context
= new
CodeContext ();
117 context
.profile
= Profile
.GOBJECT
;
118 CodeContext
.push (context
);
120 /* default package */
121 if (!add_package ("glib-2.0")) {
122 Report
.error (null, "glib-2.0 not found in specified Vala API directories");
124 if (!add_package ("gobject-2.0")) {
125 Report
.error (null, "gobject-2.0 not found in specified Vala API directories");
128 /* load packages from .deps file */
129 foreach (string source
in sources
) {
130 if (!source
.has_suffix (".gi")) {
134 var depsfile
= source
.substring (0, source
.len () - "gi".len ()) + "deps";
136 if (!FileUtils
.test (depsfile
, FileTest
.EXISTS
)) continue;
138 string[] deps
= get_packages_from_depsfile (depsfile
);
140 foreach (string dep
in deps
) {
141 if (!add_package (dep
)) {
142 Report
.error (null, "%s not found in specified Vala API directories".printf (dep
));
147 // depsfile for gir case
148 if (library
!= null) {
149 var depsfile
= library
+ ".deps";
150 if (FileUtils
.test (depsfile
, FileTest
.EXISTS
)) {
152 string[] deps
= get_packages_from_depsfile (depsfile
);
154 foreach (string dep
in deps
) {
155 if (!add_package (dep
)) {
156 Report
.error (null, "%s not found in specified Vala API directories".printf (dep
));
161 Report
.error (null, "--library option must be specified");
164 if (packages
!= null) {
165 foreach (string package
in packages
) {
166 if (!add_package (package
)) {
167 Report
.error (null, "%s not found in specified Vala API directories".printf (package
));
173 if (context
.report
.get_errors () > 0) {
177 foreach (string source
in sources
) {
178 if (FileUtils
.test (source
, FileTest
.EXISTS
)) {
179 context
.add_source_file (new
SourceFile (context
, source
, true));
181 Report
.error (null, "%s not found".printf (source
));
186 if (context
.report
.get_errors () > 0) {
190 var parser
= new
Parser ();
191 parser
.parse (context
);
193 if (context
.report
.get_errors () > 0) {
197 var girparser
= new
GirParser ();
198 if (metadata_filename
!= null) {
199 girparser
.parse_metadata (metadata_filename
);
201 girparser
.parse (context
);
203 if (context
.report
.get_errors () > 0) {
207 var gidlparser
= new
GIdlParser ();
208 gidlparser
.parse (context
);
210 if (context
.report
.get_errors () > 0) {
214 var resolver
= new
SymbolResolver ();
215 resolver
.resolve (context
);
217 if (context
.report
.get_errors () > 0) {
221 var analyzer
= new
SemanticAnalyzer ();
222 analyzer
.analyze (context
);
224 if (context
.report
.get_errors () > 0) {
228 if (library
== null && girparser
.get_package_names () != null) {
229 var names
= girparser
.get_package_names ();
231 if (names
.length
!= 1) {
232 Report
.error (null, "multiple packages encountered and no library name given");
239 if (library
!= null) {
240 // interface writer ignores external packages
241 foreach (SourceFile file
in context
.get_source_files ()) {
242 if (!file
.filename
.has_suffix (".vapi")) {
243 file
.external_package
= false;
247 var interface_writer
= new
CodeWriter ();
248 interface_writer
.write_file (context
, "%s.vapi".printf (library
));
256 static int main (string[] args
) {
258 var opt_context
= new
OptionContext ("- Vala API Generator");
259 opt_context
.set_help_enabled (true);
260 opt_context
.add_main_entries (options
, null);
261 opt_context
.parse (ref args
);
262 } catch (OptionError e
) {
263 stdout
.printf ("%s\n", e
.message
);
264 stdout
.printf ("Run '%s --help' to see a full list of available command line options.\n", args
[0]);
269 stdout
.printf ("Vala API Generator %s\n", Config
.BUILD_VERSION
);
273 if (sources
== null) {
274 stderr
.printf ("No source file specified.\n");
278 var vapigen
= new
VAPIGen ();
279 return vapigen
.run ();