From: Jean Privat Date: Fri, 16 Jan 2015 10:36:02 +0000 (+0700) Subject: Merge: Better Objective-C FFI and cleanup for OS X X-Git-Tag: v0.7.1~25 X-Git-Url: http://nitlanguage.org?hp=d0bc63d8b8f520bc43b850dd0978890bb5e96f0e Merge: Better Objective-C FFI and cleanup for OS X 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 Reviewed-by: Lucas Bajolet Reviewed-by: Jean Privat --- diff --git a/lib/cocoa/examples/cocoa_message_box.nit b/lib/cocoa/examples/cocoa_message_box.nit index 72e35d7..224c7ab 100644 --- a/lib/cocoa/examples/cocoa_message_box.nit +++ b/lib/cocoa/examples/cocoa_message_box.nit @@ -19,10 +19,6 @@ module cocoa_message_box import cocoa -in "ObjC" `{ - #import -`} - fun dialog in "ObjC" `{ NSAlert *alert = [[[NSAlert alloc] init] autorelease]; [alert setMessageText:@"Hello world!"]; diff --git a/lib/cocoa/examples/hello_cocoa.nit b/lib/cocoa/examples/hello_cocoa.nit index 3a2b168..960b001 100644 --- a/lib/cocoa/examples/hello_cocoa.nit +++ b/lib/cocoa/examples/hello_cocoa.nit @@ -19,10 +19,6 @@ module hello_cocoa import cocoa::foundation -in "ObjC" `{ - #import -`} - # Print `"Hello world!"` to the log fun hello_world in "ObjC" `{ @autoreleasepool { diff --git a/lib/glesv2/examples/opengles2_hello_triangle.nit b/lib/glesv2/examples/opengles2_hello_triangle.nit index cfab7ae..cbf851f 100644 --- a/lib/glesv2/examples/opengles2_hello_triangle.nit +++ b/lib/glesv2/examples/opengles2_hello_triangle.nit @@ -22,7 +22,7 @@ module opengles2_hello_triangle import glesv2 import egl -import mnit_linux # for sdl +import mnit_linux::sdl import x11 if "NIT_TESTING".environ == "true" then exit(0) diff --git a/src/compiler/compiler.nit b/src/compiler/compiler.nit index 902a656..ea60c0a 100644 --- a/src/compiler/compiler.nit +++ b/src/compiler/compiler.nit @@ -19,6 +19,6 @@ import separate_erasure_compiler import global_compiler import compiler_ffi -import android_platform -import pnacl_platform -import emscripten_platform +import platform::android +import platform::pnacl +import platform::emscripten diff --git a/src/ffi/header_dependency.nit b/src/ffi/header_dependency.nit index 10c1db3..84bbb29 100644 --- a/src/ffi/header_dependency.nit +++ b/src/ffi/header_dependency.nit @@ -33,36 +33,32 @@ redef class AModule 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 diff --git a/src/ffi/objc.nit b/src/ffi/objc.nit index 5c7eeeb..f031289 100644 --- a/src/ffi/objc.nit +++ b/src/ffi/objc.nit @@ -32,6 +32,27 @@ 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 @@ -47,6 +68,8 @@ class ObjCLanguage 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 @@ -77,6 +100,12 @@ class ObjCLanguage 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" @@ -211,6 +240,13 @@ end 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 diff --git a/src/compiler/android_platform.nit b/src/platform/android.nit similarity index 99% rename from src/compiler/android_platform.nit rename to src/platform/android.nit index b7069e3..6ba5502 100644 --- a/src/compiler/android_platform.nit +++ b/src/platform/android.nit @@ -15,10 +15,10 @@ # 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 diff --git a/src/compiler/android_annotations.nit b/src/platform/android_annotations.nit similarity index 100% rename from src/compiler/android_annotations.nit rename to src/platform/android_annotations.nit diff --git a/src/compiler/emscripten_platform.nit b/src/platform/emscripten.nit similarity index 97% rename from src/compiler/emscripten_platform.nit rename to src/platform/emscripten.nit index 6332098..dc2662f 100644 --- a/src/compiler/emscripten_platform.nit +++ b/src/platform/emscripten.nit @@ -15,10 +15,10 @@ # 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) diff --git a/src/platform.nit b/src/platform/platform.nit similarity index 100% rename from src/platform.nit rename to src/platform/platform.nit diff --git a/src/compiler/pnacl_platform.nit b/src/platform/pnacl.nit similarity index 99% rename from src/compiler/pnacl_platform.nit rename to src/platform/pnacl.nit index 3f96318..9fceaad 100644 --- a/src/compiler/pnacl_platform.nit +++ b/src/platform/pnacl.nit @@ -15,10 +15,10 @@ # 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) diff --git a/tests/sav/opengles2_hello_triangle.res b/tests/sav/opengles2_hello_triangle.res deleted file mode 100644 index c1dad34..0000000 --- a/tests/sav/opengles2_hello_triangle.res +++ /dev/null @@ -1,2 +0,0 @@ -../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.