Line data Source code
1 : /* valavapigen.vala
2 : *
3 : * Copyright (C) 2006-2010 Jürg Billeter
4 : *
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.
9 :
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.
14 :
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
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 : using GLib;
24 :
25 284 : class Vala.VAPIGen {
26 : static string directory;
27 : static bool version;
28 : static bool quiet_mode;
29 : static bool disable_warnings;
30 : [CCode (array_length = false, array_null_terminated = true)]
31 : static string[] sources;
32 : [CCode (array_length = false, array_null_terminated = true)]
33 : static string[] vapi_directories;
34 : [CCode (array_length = false, array_null_terminated = true)]
35 : static string[] gir_directories;
36 : [CCode (array_length = false, array_null_terminated = true)]
37 : static string[] metadata_directories;
38 : static string library;
39 : [CCode (array_length = false, array_null_terminated = true)]
40 : static string[] packages;
41 : static bool nostdpkg;
42 :
43 71 : CodeContext context;
44 :
45 : const OptionEntry[] options = {
46 : { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
47 : { "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for GIR bindings in DIRECTORY", "DIRECTORY..." },
48 : { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR .metadata files in DIRECTORY", "DIRECTORY..." },
49 : { "nostdpkg", 0, 0, OptionArg.NONE, ref nostdpkg, "Do not include standard packages", null },
50 : { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
51 : { "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
52 : { "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" },
53 : { "disable-warnings", 0, 0, OptionArg.NONE, ref disable_warnings, "Disable warnings", null },
54 : { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
55 : { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null },
56 : { OPTION_REMAINING, 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
57 : { null }
58 : };
59 :
60 71 : private int quit () {
61 71 : if (context.report.get_errors () == 0) {
62 71 : if (!quiet_mode) {
63 71 : print ("Generation succeeded - %d warning(s)\n", context.report.get_warnings ());
64 : }
65 71 : CodeContext.pop ();
66 71 : return 0;
67 : } else {
68 0 : if (!quiet_mode) {
69 0 : print ("Generation failed: %d error(s), %d warning(s)\n", context.report.get_errors (), context.report.get_warnings ());
70 : }
71 0 : CodeContext.pop ();
72 0 : return 1;
73 : }
74 : }
75 :
76 71 : private int run () {
77 71 : context = new CodeContext ();
78 142 : context.vapi_directories = vapi_directories;
79 96 : context.gir_directories = gir_directories;
80 72 : context.metadata_directories = metadata_directories;
81 71 : context.report.enable_warnings = !disable_warnings;
82 71 : context.report.set_verbose_errors (!quiet_mode);
83 71 : CodeContext.push (context);
84 71 : context.set_target_profile (Profile.GOBJECT, !nostdpkg);
85 :
86 71 : if (context.report.get_errors () > 0) {
87 0 : return quit ();
88 : }
89 :
90 : /* load packages from .deps file */
91 312 : foreach (string source in sources) {
92 85 : if (!source.has_suffix (".gi")) {
93 60 : continue;
94 : }
95 :
96 25 : var depsfile = source.substring (0, source.length - "gi".length) + "deps";
97 25 : context.add_packages_from_file (depsfile);
98 : }
99 :
100 71 : if (context.report.get_errors () > 0) {
101 0 : return quit ();
102 : }
103 :
104 : // depsfile for gir case
105 142 : if (library != null) {
106 71 : var depsfile = library + ".deps";
107 71 : context.add_packages_from_file (depsfile);
108 : } else {
109 0 : Report.error (null, "--library option must be specified");
110 : }
111 :
112 71 : if (context.report.get_errors () > 0) {
113 0 : return quit ();
114 : }
115 :
116 71 : if (packages != null) {
117 92 : foreach (string package in packages) {
118 46 : context.add_external_package (package);
119 : }
120 138 : packages = null;
121 : }
122 :
123 71 : if (context.report.get_errors () > 0) {
124 0 : return quit ();
125 : }
126 :
127 312 : foreach (string source in sources) {
128 170 : if (FileUtils.test (source, FileTest.EXISTS)) {
129 85 : var source_file = new SourceFile (context, SourceFileType.PACKAGE, source);
130 85 : source_file.from_commandline = true;
131 85 : context.add_source_file (source_file);
132 : } else {
133 0 : Report.error (null, "%s not found", source);
134 : }
135 : }
136 :
137 71 : if (context.report.get_errors () > 0) {
138 0 : return quit ();
139 : }
140 :
141 71 : var parser = new Parser ();
142 71 : parser.parse (context);
143 :
144 71 : if (context.report.get_errors () > 0) {
145 0 : return quit ();
146 : }
147 :
148 71 : var girparser = new GirParser ();
149 71 : girparser.parse (context);
150 :
151 71 : if (context.report.get_errors () > 0) {
152 0 : return quit ();
153 : }
154 :
155 71 : var gidlparser = new GIdlParser ();
156 71 : gidlparser.parse (context);
157 :
158 71 : if (context.report.get_errors () > 0) {
159 0 : return quit ();
160 : }
161 :
162 71 : context.check ();
163 :
164 71 : if (context.report.get_errors () > 0) {
165 0 : return quit ();
166 : }
167 :
168 : // candidates to match library against
169 71 : string[] package_names = {};
170 :
171 : // interface writer ignores external packages
172 858 : foreach (SourceFile file in context.get_source_files ()) {
173 577 : if (file.filename.has_suffix (".vapi")) {
174 367 : continue;
175 : }
176 769 : if (file.filename in sources) {
177 85 : file.file_type = SourceFileType.SOURCE;
178 131 : if (file.filename.has_suffix (".gir")) {
179 : // mark relative metadata as source
180 46 : string? metadata_filename = context.get_metadata_path (file.filename);
181 46 : if (metadata_filename != null) {
182 1 : unowned SourceFile? metadata_file = context.get_source_file (metadata_filename);
183 1 : if (metadata_file != null) {
184 1 : metadata_file.file_type = SourceFileType.SOURCE;
185 : }
186 : }
187 46 : if (file.from_commandline && file.package_name != null) {
188 0 : package_names += file.package_name;
189 : }
190 : }
191 : }
192 : }
193 :
194 71 : var library_name = Path.get_basename (library);
195 71 : if (package_names.length > 0 && !(library_name in package_names)) {
196 0 : Report.warning (null, "Given library name `%s' does not match pkg-config name `%s'", library_name, string.join ("', `", package_names));
197 : }
198 :
199 71 : var interface_writer = new CodeWriter (CodeWriterType.VAPIGEN);
200 71 : var vapi_filename = "%s.vapi".printf (library);
201 71 : if (directory != null) {
202 0 : vapi_filename = Path.build_path ("/", directory, vapi_filename);
203 : }
204 :
205 71 : interface_writer.write_file (context, vapi_filename);
206 :
207 71 : library = null;
208 :
209 142 : return quit ();
210 : }
211 :
212 71 : static int main (string[] args) {
213 71 : Intl.setlocale (LocaleCategory.ALL, "");
214 :
215 71 : if (Vala.get_build_version () != Vala.BUILD_VERSION) {
216 0 : printerr ("Integrity check failed (libvala %s doesn't match vapigen %s)\n", Vala.get_build_version (), Vala.BUILD_VERSION);
217 0 : return 1;
218 : }
219 :
220 71 : try {
221 71 : var opt_context = new OptionContext ("- Vala API Generator");
222 71 : opt_context.set_help_enabled (true);
223 71 : opt_context.add_main_entries (options, null);
224 71 : opt_context.parse (ref args);
225 : } catch (OptionError e) {
226 0 : print ("%s\n", e.message);
227 0 : print ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
228 0 : return 1;
229 : }
230 :
231 71 : if (version) {
232 0 : print ("Vala API Generator %s\n", Vala.BUILD_VERSION);
233 0 : return 0;
234 : }
235 :
236 71 : if (sources == null) {
237 0 : printerr ("No source file specified.\n");
238 0 : return 1;
239 : }
240 :
241 71 : var vapigen = new VAPIGen ();
242 71 : return vapigen.run ();
243 : }
244 : }
|