+2007-06-15 Jürg Billeter <j@bitron.ch>
+
+ * vala/valacodecontext.vala, gobject/valaccodecompiler.vala,
+ compiler/valacompiler.vala: enhance commandline interface, add support
+ for invoking c compiler
+ * gobject/Makefile.am: update
+ * vapi/glib-2.0.vala: add shell-related utilities
+
2007-06-05 Jürg Billeter <j@bitron.ch>
* gobject/valacodegeneratorassignment.vala: correct invocation of setter
/* valacompiler.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
static string[] packages;
static bool disable_memory_management;
+ static bool ccode_only;
+ static bool compile_only;
+ static string output;
+ static bool debug;
+ static int optlevel;
+ static bool disable_assert;
+ static bool enable_checking;
+
private CodeContext context;
- private List<string> added_packages;
const OptionEntry[] options = {
{ "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, out vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
{ "directory", 'd', 0, OptionArg.FILENAME, out directory, "Output directory", "DIRECTORY" },
{ "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
{ "disable-memory-management", 0, 0, OptionArg.NONE, ref disable_memory_management, "Disable memory management", null },
+ { "ccode", 'C', 0, OptionArg.NONE, ref ccode_only, "Output C code", null },
+ { "compile", 'c', 0, OptionArg.NONE, ref compile_only, "Compile but do not link", null },
+ { "output", 'o', 0, OptionArg.FILENAME, out output, "Place output in file FILE", "FILE" },
+ { "debug", 'g', 0, OptionArg.NONE, ref debug, "Produce debug information", null },
+ { "optimize", 'O', 0, OptionArg.INT, ref optlevel, "Optimization level", "OPTLEVEL" },
+ { "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
+ { "enable-checking", 0, 0, OptionArg.NONE, ref enable_checking, "Enable run-time checks", null },
{ "", 0, 0, OptionArg.FILENAME_ARRAY, out sources, null, "FILE..." },
{ null }
};
return null;
}
- private bool add_package (string! pkg) {
- if (added_packages.find_custom (pkg, strcmp) != null) {
+ private bool add_package (CodeContext! context, string! pkg) {
+ if (context.has_package (pkg)) {
// ignore multiple occurences of the same package
return true;
}
return false;
}
- added_packages.append (pkg);
+ context.add_package (pkg);
context.add_source_file (new SourceFile (context, package_path, true));
File.get_contents (deps_filename, out deps_content, null, null);
foreach (string dep in deps_content.split ("\n")) {
if (dep != "") {
- if (!add_package (dep)) {
+ if (!add_package (context, dep)) {
Report.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep, pkg));
}
}
private int run () {
context = new CodeContext ();
-
+
+ /* support old command line interface */
+ if (!ccode_only && !compile_only && output == null) {
+ ccode_only = true;
+ }
+
context.library = library;
-
+ context.memory_management = !disable_memory_management;
+ context.assert = !disable_assert;
+ context.checking = enable_checking;
+
+ context.ccode_only = ccode_only;
+ context.compile_only = compile_only;
+ context.output = output;
+ context.debug = debug;
+ context.optlevel = optlevel;
+
/* default package */
- if (!add_package ("glib-2.0")) {
+ if (!add_package (context, "glib-2.0")) {
Report.error (null, "glib-2.0 not found in specified Vala API directories");
}
if (packages != null) {
foreach (string package in packages) {
- if (!add_package (package)) {
+ if (!add_package (context, package)) {
Report.error (null, "%s not found in specified Vala API directories".printf (package));
}
}
library = null;
}
-
+
+ if (!ccode_only) {
+ var ccompiler = new CCodeCompiler ();
+ ccompiler.compile (context);
+ }
+
return quit ();
}
libvala_la_SOURCES = \
gobject.vala.stamp \
+ valaccodecompiler.c \
+ valaccodecompiler.h \
+ valaccodecompiler.vala \
valaclassregisterfunction.c \
valaclassregisterfunction.h \
valaclassregisterfunction.vala \
gobjectincludedir = $(includedir)/vala-1.0/gobject
gobjectinclude_HEADERS = \
+ valaccodecompiler.h \
valaclassregisterfunction.h \
valacodegenerator.h \
valacodegeneratorassignment.h \
--- /dev/null
+/* valaccodecompiler.vala
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Interface to the C compiler.
+ */
+public class Vala.CCodeCompiler {
+ public CCodeCompiler () {
+ }
+
+ /**
+ * Compile generated C code to object code and optionally link object
+ * files.
+ *
+ * @param context a code context
+ */
+ public void compile (CodeContext! context) {
+ string pc = "pkg-config --cflags";
+ if (!context.compile_only) {
+ pc += " --libs";
+ }
+ foreach (string pkg in context.get_packages ()) {
+ pc += " " + pkg;
+ }
+ string pkgflags;
+ int exit_status;
+ Error err = null;
+ if (!Process.spawn_command_line_sync (pc, out pkgflags, null, ref exit_status, out err)) {
+ Report.error (null, err.message);
+ return;
+ } else if (exit_status != 0) {
+ Report.error (null, "pkg-config exited with status %d".printf (exit_status));
+ return;
+ }
+
+ // TODO compile the C code files in parallel
+
+ string cmdline = "cc";
+ if (context.debug) {
+ cmdline += " -g";
+ }
+ cmdline += " -O%d".printf (context.optlevel);
+ if (context.compile_only) {
+ cmdline += " -c";
+ } else if (context.output != null) {
+ cmdline += " -o " + Shell.quote (context.output);
+ }
+ cmdline += " " + pkgflags;
+
+ /* we're only interested in non-pkg source files */
+ var source_files = context.get_source_files ();
+ foreach (SourceFile file in source_files) {
+ if (!file.pkg) {
+ cmdline += " " + Shell.quote (file.get_csource_filename ());
+ }
+ }
+
+ bool success = Process.spawn_command_line_sync (cmdline, null, null, ref exit_status, out err);
+
+ /* remove generated C source and header files */
+ foreach (SourceFile file in source_files) {
+ if (!file.pkg) {
+ File.unlink (file.get_csource_filename ());
+ File.unlink (file.get_cheader_filename ());
+ }
+ }
+
+ if (!success) {
+ Report.error (null, err.message);
+ } else if (exit_status != 0) {
+ Report.error (null, "cc exited with status %d".printf (exit_status));
+ }
+ }
+}
*/
public string library { get; set; }
+ /**
+ * Enable automatic memory management.
+ */
+ public bool memory_management { get; set; }
+
+ /**
+ * Enable run-time checks for programming errors.
+ */
+ public bool assert { get; set; }
+
+ /**
+ * Enable additional run-time checks.
+ */
+ public bool checking { get; set; }
+
+ /**
+ * Output C code, don't compile to object code.
+ */
+ public bool ccode_only { get; set; }
+
+ /**
+ * Compile but do not link.
+ */
+ public bool compile_only { get; set; }
+
+ /**
+ * Output filename.
+ */
+ public string output { get; set; }
+
+ /**
+ * Produce debug information.
+ */
+ public bool debug { get; set; }
+
+ /**
+ * Optimization level.
+ */
+ public int optlevel { get; set; }
+
/**
* Specifies the optional module initialization method.
*/
private Symbol! root = new Symbol ();
List<SourceFileCycle> cycles;
-
+
+ private List<string> packages;
+
/**
* Returns the root symbol of the code tree.
*
public void add_source_file (SourceFile! file) {
source_files.append (file);
}
-
+
+ /**
+ * Returns a copy of the list of used packages.
+ *
+ * @return list of used packages
+ */
+ public List<weak string> get_packages () {
+ return packages.copy ();
+ }
+
+ /**
+ * Returns whether the specified package is being used.
+ *
+ * @param pkg a package name
+ * @return true if the specified package is being used
+ */
+ public bool has_package (string! pkg) {
+ return packages.find_custom (pkg, strcmp) != null;
+ }
+
+ /**
+ * Adds the specified package to the list of used packages.
+ *
+ * @param pkg a package name
+ */
+ public void add_package (string! pkg) {
+ packages.append (pkg);
+ }
+
/**
* Visits the complete code tree file by file.
*
[CCode (cname = "stderr", cheader_filename = "stdio.h")]
public static File stderr;
+ /* Shell-related Utilities */
+
+ public struct Shell {
+ public static bool parse_argv (string! command_line, ref int argcp, out string[] argvp, out Error error);
+ public static string! quote (string! unquoted_string);
+ public static string! unquote (string! quoted_string, out Error error);
+ }
+
/* Commandline option parser */
[ReferenceType (free_function = "g_option_context_free")]