# provides tools to write C .c and .h files
module c_tools
-import compiling_writer
+import template
# Accumulates all C code for a compilation unit
class CCompilationUnit
## header
# comments and native interface imports
- var header_c_base : Writer = new Writer
+ var header_c_base = new Template
# custom C header code or generated for other languages
- var header_custom : Writer = new Writer
+ var header_custom = new Template
# types of extern classes and friendly types
- var header_c_types : Writer = new Writer
+ var header_c_types = new Template
# implementation declaration for extern methods
- var header_decl : Writer = new Writer
+ var header_decl = new Template
## body
# comments, imports, etc
- var body_decl : Writer = new Writer
+ var body_decl = new Template
# custom code and generated for ffi
- var body_custom : Writer = new Writer
+ var body_custom = new Template
# implementation body of extern methods
- var body_impl : Writer = new Writer
+ var body_impl = new Template
# files to compile TODO check is appropriate
- #var files = new Array[String]
+ var files = new Array[String]
- fun add_local_function( efc : CFunction )
+ # Add a `static` `c_function` to be strictly local to this unit
+ fun add_local_function(c_function: CFunction)
do
- body_decl.add( "{efc.signature};\n" )
- body_impl.add( "\n" )
- body_impl.append( efc.to_writer )
+ body_decl.add "static {c_function.signature};\n"
+ body_impl.add "\n"
+ body_impl.add c_function.to_writer
end
- fun add_exported_function( efc : CFunction )
+ # Add a public `c_function` accessible from outside this compilation unit
+ fun add_exported_function(c_function: CFunction)
do
- header_decl.add( "{efc.signature};\n" )
- body_impl.add( "\n" )
- body_impl.append( efc.to_writer )
+ body_decl.add "{c_function.signature};\n"
+ body_impl.add "\n"
+ body_impl.add c_function.to_writer
end
- fun compile_header_core( stream : OStream )
+ # Write the core of the header to `stream`
+ fun compile_header_core(stream: Writer)
do
- header_c_base.write_to_stream( stream )
- header_custom.write_to_stream( stream )
- header_c_types.write_to_stream( stream )
- header_decl.write_to_stream( stream )
+ header_c_base.write_to stream
+ header_custom.write_to stream
+ header_c_types.write_to stream
+ header_decl.write_to stream
end
- fun compile_body_core( stream : OStream )
+ # Write the core of the body to `stream`
+ fun compile_body_core(stream: Writer)
do
- body_decl.write_to_stream( stream )
- body_custom.write_to_stream( stream )
- body_impl.write_to_stream( stream )
+ body_decl.write_to stream
+ body_custom.write_to stream
+ body_impl.write_to stream
end
end
class CFunction
var signature : String
- var decls : Writer = new Writer
- var exprs : Writer = new Writer
+ var decls = new Template
+ var exprs = new Template
- fun to_writer : Writer
+ fun to_writer: Template
do
- var w = new Writer
+ var w = new Template
- w.add( "{signature}\n\{\n" )
+ w.add(signature)
+ w.add("\n\{\n")
+ w.add(decls)
+ w.add("\n")
+ w.add(exprs)
+ w.add("\}\n")
- w.append( decls )
- w.add( "\n" )
- w.append( exprs )
+ return w
+ end
+end
- w.add( "\}\n" )
+# An extern file to compile
+class ExternFile
+ # The filename of the file
+ var filename: String
- return w
+ # The name of the target in the Makefile
+ # Usually the produced .o file
+ fun makefile_rule_name: String is abstract
+
+ # The content of the rule in the make
+ # Usually the one-line shell command after the tabulation
+ fun makefile_rule_content: String is abstract
+
+ fun compiles_to_o_file: Bool do return false
+
+ fun add_to_jar: Bool do return false
+
+ # Additional libraries needed for the compilation
+ # Will be used with pkg-config
+ var pkgconfigs = new Array[String]
+end
+
+# An extern C file to compile
+class ExternCFile
+ super ExternFile
+
+ # Custom options for the C compiler (CFLAGS)
+ var cflags: String
+
+ redef fun hash do return filename.hash
+ redef fun ==(o) do return o isa ExternCFile and filename == o.filename
+
+ redef fun makefile_rule_name do
+ var basename = filename.basename(".c")
+ var res = "{basename}.extern.o"
+ return res
end
+
+ redef fun makefile_rule_content do
+ var ff = filename.basename
+ var o = makefile_rule_name
+ var pkg = ""
+ if not pkgconfigs.is_empty then
+ pkg = "`pkg-config --cflags {pkgconfigs.join(" ")}`"
+ end
+ return "$(CC) $(CFLAGS) -Wall -Wno-unused-function {self.cflags} {pkg} -c -o {o} {ff}"
+ end
+
+ redef fun compiles_to_o_file do return true
end
+