This PR opens the way for the iOS platform support.
Two commits may look very similar: "ObjC FFI: import public Objective-C headers for imported modules" and "nitc: fix duplication on imports of public foreign code". They both manage importing headers from other modules so public extern classes may work across module, but one is for Objective-C and the other for C. This service will have to be implemented for other languages too (mostly C++), I'll be looking for a higher level service at that time.
Pull-Request: #1105
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>
import cocoa
-in "ObjC" `{
- #import <Cocoa/Cocoa.h>
-`}
-
fun dialog in "ObjC" `{
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Hello world!"];
import cocoa::foundation
-in "ObjC" `{
- #import <Foundation/Foundation.h>
-`}
-
# Print `"Hello world!"` to the log
fun hello_world in "ObjC" `{
@autoreleasepool {
import glesv2
import egl
-import mnit_linux # for sdl
+import mnit_linux::sdl
import x11
if "NIT_TESTING".environ == "true" then exit(0)
import global_compiler
import compiler_ffi
-import android_platform
-import pnacl_platform
-import emscripten_platform
+import platform::android
+import platform::pnacl
+import platform::emscripten
end
redef class MModule
- private var header_dependencies_cache: nullable Array[MModule] = null
- fun header_dependencies: Array[MModule]
- do
- var cache = header_dependencies_cache
- assert cache != null
- return cache
- end
+ # Modules with public foreign code blocks (C header)
+ var header_dependencies: nullable HashSet[MModule] = null
private fun compute_header_dependencies(v: HeaderDependancyPhase)
do
- if header_dependencies_cache != null then return
+ if header_dependencies != null then return
- var header_dependencies = new Array[MModule]
+ var header_dependencies = new HashSet[MModule]
# gather from importation
for m in in_importation.direct_greaters do
- m.compute_header_dependencies(v)
+ m.compute_header_dependencies v
- # does the super module has inherited dependancies?
+ # does the super module has inherited dependencies?
var hd = m.header_dependencies
+ assert hd != null
if not hd.is_empty then
- header_dependencies.add_all(hd)
+ header_dependencies.add_all hd
end
- # does the super module itself has extern dependancies?
+ # does the super module itself has extern dependencies?
var amodule = v.toolcontext.modelbuilder.mmodule2node(m)
if amodule != null and amodule.has_public_c_header then header_dependencies.add(m)
end
- header_dependencies_cache = header_dependencies
+ self.header_dependencies = header_dependencies
end
end
redef class MModule
private var objc_file: nullable ObjCCompilationUnit = null
+
+ private var has_public_objc_header = false
+
+ # Imported modules with public Objective-C code blocks
+ var objc_imported_headers: HashSet[MModule] is lazy do
+ var dep = new HashSet[MModule]
+
+ # gather from importation
+ for m in in_importation.direct_greaters do
+ # does the super module has inherited dependencies?
+ var import_dep = m.objc_imported_headers
+ if not import_dep.is_empty then
+ dep.add_all import_dep
+ end
+
+ # does the super module itself has a public header?
+ if m.has_public_objc_header then dep.add(m)
+ end
+
+ return dep
+ end
end
# The Objective-C langugage visitor
if block.is_objc_header then
mmodule.objc_file.header_custom.add block.location.as_line_pragma
mmodule.objc_file.header_custom.add block.code
+
+ mmodule.has_public_objc_header = true
else if block.is_objc_body then
mmodule.objc_file.body_custom.add block.location.as_line_pragma
mmodule.objc_file.body_custom.add block.code
var objc_file = mmodule.objc_file
assert objc_file != null
+ # Import public Objective-C header of imported modules
+ var dep = mmodule.objc_imported_headers
+ for mod in dep do
+ objc_file.header_custom.add "#include \"{mod.c_name}._ffi_m.h\"\n"
+ end
+
# write .m and _m.h file
mmodule.objc_file.header_c_types.add """
#include "{{{mmodule.c_name}}}._ffi.h"
private class FromObjCCallContext
super ObjCCallContext
+ redef fun cast_to(mtype, name)
+ do
+ if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then
+ return "(__bridge void*)({name})"
+ else return name
+ end
+
redef fun cast_from(mtype, name)
do
if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then
# limitations under the License.
# Compile program for the Android platform
-module android_platform
+module android
import platform
-import abstract_compiler
+import compiler::abstract_compiler
import ffi
intrude import ffi::extra_java_files
import android_annotations
# limitations under the License.
# Compile to JavaScript using the Emscripten SDK
-module emscripten_platform
+module emscripten
import platform
-import abstract_compiler
+import compiler::abstract_compiler
redef class ToolContext
redef fun platform_from_name(name)
# limitations under the License.
# Compile program for the PNaCl platform
-module pnacl_platform
+module pnacl
import platform
-import abstract_compiler
+import compiler::abstract_compiler
redef class ToolContext
redef fun platform_from_name(name)
+++ /dev/null
-../lib/mnit_linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined.
-../lib/mnit_linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.