Commit 06cdb828 authored by Guy Nicholas's avatar Guy Nicholas

*** POTENTIAL BREAKING CHANGE ***

When extending a record using the +c or +o option the resultant Objective C code includes/imports the subclass assuming it is one level above the generated source. i.e.
#include "../myExtendedRecord.h"
To make the code positioning more flexible a pair of options were added to allow the developer to indicate the path prefix:
cpp-extended-record-include-prefix
objc-extended-record-include-prefix

To use these options you would write something like this:
djinni/src/run \
--cpp-extended-record-include-prefix "path_to_my_src/"

doing this will result in an include of the form:
#include "path_to_my_src/myExtendedRecord.h"

The breaking change part of this is that the default is now no path, so if you are now not compiling, you probably just need to add the following to your djinni run command
--cpp-extended-record-include-prefix "../"
parent f2e35572
...@@ -147,7 +147,7 @@ class CppGenerator(spec: Spec) extends Generator(spec) { ...@@ -147,7 +147,7 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
// Requiring the extended class // Requiring the extended class
if (r.ext.cpp) { if (r.ext.cpp) {
refs.hpp.add(s"struct $self; // Requiring extended class") refs.hpp.add(s"struct $self; // Requiring extended class")
refs.cpp.add("#include "+q("../" + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt)) refs.cpp.add("#include "+q(spec.cppExtendedRecordIncludePrefix + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt))
} }
// C++ Header // C++ Header
......
...@@ -27,6 +27,7 @@ object Main { ...@@ -27,6 +27,7 @@ object Main {
var cppOutFolder: Option[File] = None var cppOutFolder: Option[File] = None
var cppNamespace: String = "" var cppNamespace: String = ""
var cppIncludePrefix: String = "" var cppIncludePrefix: String = ""
var cppExtendedRecordIncludePrefix: String = ""
var cppFileIdentStyle: IdentConverter = IdentStyle.underLower var cppFileIdentStyle: IdentConverter = IdentStyle.underLower
var cppOptionalTemplate: String = "std::optional" var cppOptionalTemplate: String = "std::optional"
var cppOptionalHeader: String = "<optional>" var cppOptionalHeader: String = "<optional>"
...@@ -62,6 +63,7 @@ object Main { ...@@ -62,6 +63,7 @@ object Main {
var objcIdentStyle = IdentStyle.objcDefault var objcIdentStyle = IdentStyle.objcDefault
var objcTypePrefix: String = "" var objcTypePrefix: String = ""
var objcIncludePrefix: String = "" var objcIncludePrefix: String = ""
var objcExtendedRecordIncludePrefix: String = ""
var objcppIncludePrefix: String = "" var objcppIncludePrefix: String = ""
var objcppIncludeCppPrefix: String = "" var objcppIncludeCppPrefix: String = ""
var objcppIncludeObjcPrefixOptional: Option[String] = None var objcppIncludeObjcPrefixOptional: Option[String] = None
...@@ -74,7 +76,7 @@ object Main { ...@@ -74,7 +76,7 @@ object Main {
var yamlOutFolder: Option[File] = None var yamlOutFolder: Option[File] = None
var yamlOutFile: Option[String] = None var yamlOutFile: Option[String] = None
var yamlPrefix: String = "" var yamlPrefix: String = ""
val argParser = new scopt.OptionParser[Unit]("djinni") { val argParser = new scopt.OptionParser[Unit]("djinni") {
def identStyle(optionName: String, update: IdentConverter => Unit) = { def identStyle(optionName: String, update: IdentConverter => Unit) = {
...@@ -161,6 +163,10 @@ object Main { ...@@ -161,6 +163,10 @@ object Main {
.text("The prefix for #include of the main C++ header files from Objective-C++ files.") .text("The prefix for #include of the main C++ header files from Objective-C++ files.")
opt[String]("objcpp-include-objc-prefix").valueName("<prefix>").foreach(x => objcppIncludeObjcPrefixOptional = Some(x)) opt[String]("objcpp-include-objc-prefix").valueName("<prefix>").foreach(x => objcppIncludeObjcPrefixOptional = Some(x))
.text("The prefix for #import of the Objective-C header files from Objective-C++ files (default: the same as --objcpp-include-prefix)") .text("The prefix for #import of the Objective-C header files from Objective-C++ files (default: the same as --objcpp-include-prefix)")
opt[String]("cpp-extended-record-include-prefix").valueName("<prefix>").foreach(cppExtendedRecordIncludePrefix = _)
.text("The prefix for #include of the extended record header files from C++ files.")
opt[String]("objc-extended-record-include-prefix").valueName("<prefix>").foreach(objcExtendedRecordIncludePrefix = _)
.text("The prefix for #import of the extended record header files from Objective-C++ files.")
opt[String]("objcpp-namespace").valueName("<prefix>").foreach(objcppNamespace = _) opt[String]("objcpp-namespace").valueName("<prefix>").foreach(objcppNamespace = _)
.text("The namespace name to use for generated Objective-C++ classes.") .text("The namespace name to use for generated Objective-C++ classes.")
opt[String]("objc-base-lib-include-prefix").valueName("...").foreach(x => objcBaseLibIncludePrefix = x) opt[String]("objc-base-lib-include-prefix").valueName("...").foreach(x => objcBaseLibIncludePrefix = x)
...@@ -273,6 +279,7 @@ object Main { ...@@ -273,6 +279,7 @@ object Main {
cppOutFolder, cppOutFolder,
cppHeaderOutFolder, cppHeaderOutFolder,
cppIncludePrefix, cppIncludePrefix,
cppExtendedRecordIncludePrefix,
cppNamespace, cppNamespace,
cppIdentStyle, cppIdentStyle,
cppFileIdentStyle, cppFileIdentStyle,
...@@ -299,6 +306,7 @@ object Main { ...@@ -299,6 +306,7 @@ object Main {
objcppExt, objcppExt,
objcHeaderExt, objcHeaderExt,
objcIncludePrefix, objcIncludePrefix,
objcExtendedRecordIncludePrefix,
objcppIncludePrefix, objcppIncludePrefix,
objcppIncludeCppPrefix, objcppIncludeCppPrefix,
objcppIncludeObjcPrefix, objcppIncludeObjcPrefix,
......
...@@ -178,7 +178,7 @@ class ObjcGenerator(spec: Spec) extends Generator(spec) { ...@@ -178,7 +178,7 @@ class ObjcGenerator(spec: Spec) extends Generator(spec) {
val self = marshal.typename(objcName, r) val self = marshal.typename(objcName, r)
refs.header.add("#import <Foundation/Foundation.h>") refs.header.add("#import <Foundation/Foundation.h>")
refs.body.add("!#import " + q(spec.objcIncludePrefix + (if (r.ext.objc) "../" else "") + marshal.headerName(ident))) refs.body.add("!#import " + q((if (r.ext.objc) spec.objcExtendedRecordIncludePrefix else spec.objcIncludePrefix) + marshal.headerName(ident)))
if (r.ext.objc) { if (r.ext.objc) {
refs.header.add(s"@class $noBaseSelf;") refs.header.add(s"@class $noBaseSelf;")
......
...@@ -66,8 +66,8 @@ class ObjcMarshal(spec: Spec) extends Marshal(spec) { ...@@ -66,8 +66,8 @@ class ObjcMarshal(spec: Spec) extends Marshal(spec) {
} }
case DRecord => case DRecord =>
val r = d.body.asInstanceOf[Record] val r = d.body.asInstanceOf[Record]
val prefix = if (r.ext.objc) "../" else "" val prefix = if (r.ext.objc) spec.objcExtendedRecordIncludePrefix else spec.objcIncludePrefix
List(ImportRef(q(spec.objcIncludePrefix + prefix + headerName(d.name)))) List(ImportRef(q(prefix + headerName(d.name))))
} }
case e: MExtern => List(ImportRef(e.objc.header)) case e: MExtern => List(ImportRef(e.objc.header))
case p: MParam => List() case p: MParam => List()
......
...@@ -302,8 +302,8 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -302,8 +302,8 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
val noBaseSelf = objcMarshal.typename(ident, r) // Used for constant names val noBaseSelf = objcMarshal.typename(ident, r) // Used for constant names
val cppSelf = cppMarshal.fqTypename(ident, r) val cppSelf = cppMarshal.fqTypename(ident, r)
refs.privHeader.add("!#import " + q(spec.objcppIncludeObjcPrefix + (if(r.ext.objc) "../" else "") + headerName(ident))) refs.privHeader.add("!#import " + q((if(r.ext.objc) spec.objcExtendedRecordIncludePrefix else spec.objcppIncludeObjcPrefix) + headerName(ident)))
refs.privHeader.add("!#include " + q(spec.objcppIncludeCppPrefix + (if(r.ext.cpp) "../" else "") + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt)) refs.privHeader.add("!#include " + q((if(r.ext.cpp) spec.cppExtendedRecordIncludePrefix else spec.objcppIncludeCppPrefix) + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt))
refs.body.add("#include <cassert>") refs.body.add("#include <cassert>")
refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(objcName))) refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(objcName)))
......
...@@ -38,6 +38,7 @@ package object generatorTools { ...@@ -38,6 +38,7 @@ package object generatorTools {
cppOutFolder: Option[File], cppOutFolder: Option[File],
cppHeaderOutFolder: Option[File], cppHeaderOutFolder: Option[File],
cppIncludePrefix: String, cppIncludePrefix: String,
cppExtendedRecordIncludePrefix: String,
cppNamespace: String, cppNamespace: String,
cppIdentStyle: CppIdentStyle, cppIdentStyle: CppIdentStyle,
cppFileIdentStyle: IdentConverter, cppFileIdentStyle: IdentConverter,
...@@ -64,6 +65,7 @@ package object generatorTools { ...@@ -64,6 +65,7 @@ package object generatorTools {
objcppExt: String, objcppExt: String,
objcHeaderExt: String, objcHeaderExt: String,
objcIncludePrefix: String, objcIncludePrefix: String,
objcExtendedRecordIncludePrefix: String,
objcppIncludePrefix: String, objcppIncludePrefix: String,
objcppIncludeCppPrefix: String, objcppIncludeCppPrefix: String,
objcppIncludeObjcPrefix: String, objcppIncludeObjcPrefix: String,
......
...@@ -12,3 +12,4 @@ ...@@ -12,3 +12,4 @@
@import "constants.djinni" @import "constants.djinni"
@import "multiple_inheritance.djinni" @import "multiple_inheritance.djinni"
@import "single_language_interfaces.djinni" @import "single_language_interfaces.djinni"
@import "extended_record.djinni"
# Extended record
extended_record = record +c {
foo: bool;
}
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#pragma once
#include <utility>
struct ExtendedRecord; // Requiring extended class
namespace testsuite {
/** Extended record */
struct ExtendedRecordBase {
bool foo;
ExtendedRecordBase(bool foo_)
: foo(std::move(foo_))
{}
virtual ~ExtendedRecordBase() = default;
protected:
ExtendedRecordBase(const ExtendedRecordBase&) = default;
ExtendedRecordBase(ExtendedRecordBase&&) = default;
ExtendedRecordBase& operator=(const ExtendedRecordBase&) = default;
ExtendedRecordBase& operator=(ExtendedRecordBase&&) = default;
};
} // namespace testsuite
...@@ -14,6 +14,7 @@ djinni/primtypes.djinni ...@@ -14,6 +14,7 @@ djinni/primtypes.djinni
djinni/constants.djinni djinni/constants.djinni
djinni/multiple_inheritance.djinni djinni/multiple_inheritance.djinni
djinni/single_language_interfaces.djinni djinni/single_language_interfaces.djinni
djinni/extended_record.djinni
djinni/date.djinni djinni/date.djinni
djinni/date.yaml djinni/date.yaml
djinni/duration.djinni djinni/duration.djinni
......
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
package com.dropbox.djinni.test;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/** Extended record */
public final class ExtendedRecord {
/*package*/ final boolean mFoo;
public ExtendedRecord(
boolean foo) {
this.mFoo = foo;
}
public boolean getFoo() {
return mFoo;
}
@Override
public String toString() {
return "ExtendedRecord{" +
"mFoo=" + mFoo +
"}";
}
}
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#include "NativeExtendedRecord.hpp" // my header
#include "Marshal.hpp"
namespace djinni_generated {
NativeExtendedRecord::NativeExtendedRecord() = default;
NativeExtendedRecord::~NativeExtendedRecord() = default;
auto NativeExtendedRecord::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
const auto& data = ::djinni::JniClass<NativeExtendedRecord>::get();
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
::djinni::get(::djinni::Bool::fromCpp(jniEnv, c.foo)))};
::djinni::jniExceptionCheck(jniEnv);
return r;
}
auto NativeExtendedRecord::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
::djinni::JniLocalScope jscope(jniEnv, 2);
assert(j != nullptr);
const auto& data = ::djinni::JniClass<NativeExtendedRecord>::get();
return {::djinni::Bool::toCpp(jniEnv, jniEnv->GetBooleanField(j, data.field_mFoo))};
}
} // namespace djinni_generated
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#pragma once
#include "djinni_support.hpp"
#include "extended_record.hpp"
namespace djinni_generated {
class NativeExtendedRecord final {
public:
using CppType = ::testsuite::ExtendedRecord;
using JniType = jobject;
using Boxed = NativeExtendedRecord;
~NativeExtendedRecord();
static CppType toCpp(JNIEnv* jniEnv, JniType j);
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
private:
NativeExtendedRecord();
friend ::djinni::JniClass<NativeExtendedRecord>;
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("com/dropbox/djinni/test/ExtendedRecord") };
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Z)V") };
const jfieldID field_mFoo { ::djinni::jniGetFieldID(clazz.get(), "mFoo", "Z") };
};
} // namespace djinni_generated
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#import "DBExtendedRecord.h"
#include "../../handwritten-src/cpp/extended_record.hpp"
static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");
@class DBExtendedRecord;
namespace djinni_generated {
struct ExtendedRecord
{
using CppType = ::testsuite::ExtendedRecord;
using ObjcType = DBExtendedRecord*;
using Boxed = ExtendedRecord;
static CppType toCpp(ObjcType objc);
static ObjcType fromCpp(const CppType& cpp);
};
} // namespace djinni_generated
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#import "DBExtendedRecord+Private.h"
#import "DJIMarshal+Private.h"
#include <cassert>
namespace djinni_generated {
auto ExtendedRecord::toCpp(ObjcType obj) -> CppType
{
assert(obj);
return {::djinni::Bool::toCpp(obj.foo)};
}
auto ExtendedRecord::fromCpp(const CppType& cpp) -> ObjcType
{
return [[DBExtendedRecord alloc] initWithFoo:(::djinni::Bool::fromCpp(cpp.foo))];
}
} // namespace djinni_generated
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#import <Foundation/Foundation.h>
/** Extended record */
@interface DBExtendedRecord : NSObject
- (nonnull instancetype)initWithFoo:(BOOL)foo;
+ (nonnull instancetype)extendedRecordWithFoo:(BOOL)foo;
@property (nonatomic, readonly) BOOL foo;
@end
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from extended_record.djinni
#import "DBExtendedRecord.h"
@implementation DBExtendedRecord
- (nonnull instancetype)initWithFoo:(BOOL)foo
{
if (self = [super init]) {
_foo = foo;
}
return self;
}
+ (nonnull instancetype)extendedRecordWithFoo:(BOOL)foo
{
return [[self alloc] initWithFoo:foo];
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@ %p foo:%@>", self.class, self, @(self.foo)];
}
@end
...@@ -4,6 +4,7 @@ djinni-output-temp/cpp/record_with_duration_and_derivings.cpp ...@@ -4,6 +4,7 @@ djinni-output-temp/cpp/record_with_duration_and_derivings.cpp
djinni-output-temp/cpp/date_record.hpp djinni-output-temp/cpp/date_record.hpp
djinni-output-temp/cpp/date_record.cpp djinni-output-temp/cpp/date_record.cpp
djinni-output-temp/cpp/map_date_record.hpp djinni-output-temp/cpp/map_date_record.hpp
djinni-output-temp/cpp/extended_record_base.hpp
djinni-output-temp/cpp/objc_only_listener.hpp djinni-output-temp/cpp/objc_only_listener.hpp
djinni-output-temp/cpp/java_only_listener.hpp djinni-output-temp/cpp/java_only_listener.hpp
djinni-output-temp/cpp/uses_single_language_listeners.hpp djinni-output-temp/cpp/uses_single_language_listeners.hpp
...@@ -41,6 +42,7 @@ djinni-output-temp/java/TestDuration.java ...@@ -41,6 +42,7 @@ djinni-output-temp/java/TestDuration.java
djinni-output-temp/java/RecordWithDurationAndDerivings.java djinni-output-temp/java/RecordWithDurationAndDerivings.java
djinni-output-temp/java/DateRecord.java djinni-output-temp/java/DateRecord.java
djinni-output-temp/java/MapDateRecord.java djinni-output-temp/java/MapDateRecord.java
djinni-output-temp/java/ExtendedRecord.java
djinni-output-temp/java/ObjcOnlyListener.java djinni-output-temp/java/ObjcOnlyListener.java
djinni-output-temp/java/JavaOnlyListener.java djinni-output-temp/java/JavaOnlyListener.java
djinni-output-temp/java/UsesSingleLanguageListeners.java djinni-output-temp/java/UsesSingleLanguageListeners.java
...@@ -77,6 +79,8 @@ djinni-output-temp/jni/NativeDateRecord.hpp ...@@ -77,6 +79,8 @@ djinni-output-temp/jni/NativeDateRecord.hpp
djinni-output-temp/jni/NativeDateRecord.cpp djinni-output-temp/jni/NativeDateRecord.cpp
djinni-output-temp/jni/NativeMapDateRecord.hpp djinni-output-temp/jni/NativeMapDateRecord.hpp
djinni-output-temp/jni/NativeMapDateRecord.cpp djinni-output-temp/jni/NativeMapDateRecord.cpp
djinni-output-temp/jni/NativeExtendedRecord.hpp
djinni-output-temp/jni/NativeExtendedRecord.cpp
djinni-output-temp/jni/NativeObjcOnlyListener.hpp djinni-output-temp/jni/NativeObjcOnlyListener.hpp
djinni-output-temp/jni/NativeObjcOnlyListener.cpp djinni-output-temp/jni/NativeObjcOnlyListener.cpp
djinni-output-temp/jni/NativeJavaOnlyListener.hpp djinni-output-temp/jni/NativeJavaOnlyListener.hpp
...@@ -139,6 +143,8 @@ djinni-output-temp/objc/DBDateRecord.h ...@@ -139,6 +143,8 @@ djinni-output-temp/objc/DBDateRecord.h
djinni-output-temp/objc/DBDateRecord.mm djinni-output-temp/objc/DBDateRecord.mm
djinni-output-temp/objc/DBMapDateRecord.h djinni-output-temp/objc/DBMapDateRecord.h
djinni-output-temp/objc/DBMapDateRecord.mm djinni-output-temp/objc/DBMapDateRecord.mm
djinni-output-temp/objc/DBExtendedRecord.h
djinni-output-temp/objc/DBExtendedRecord.mm
djinni-output-temp/objc/DBObjcOnlyListener.h djinni-output-temp/objc/DBObjcOnlyListener.h
djinni-output-temp/objc/DBJavaOnlyListener.h djinni-output-temp/objc/DBJavaOnlyListener.h
djinni-output-temp/objc/DBUsesSingleLanguageListeners.h djinni-output-temp/objc/DBUsesSingleLanguageListeners.h
...@@ -189,6 +195,8 @@ djinni-output-temp/objc/DBDateRecord+Private.h ...@@ -189,6 +195,8 @@ djinni-output-temp/objc/DBDateRecord+Private.h
djinni-output-temp/objc/DBDateRecord+Private.mm djinni-output-temp/objc/DBDateRecord+Private.mm
djinni-output-temp/objc/DBMapDateRecord+Private.h djinni-output-temp/objc/DBMapDateRecord+Private.h
djinni-output-temp/objc/DBMapDateRecord+Private.mm djinni-output-temp/objc/DBMapDateRecord+Private.mm
djinni-output-temp/objc/DBExtendedRecord+Private.h
djinni-output-temp/objc/DBExtendedRecord+Private.mm
djinni-output-temp/objc/DBObjcOnlyListener+Private.h djinni-output-temp/objc/DBObjcOnlyListener+Private.h
djinni-output-temp/objc/DBObjcOnlyListener+Private.mm djinni-output-temp/objc/DBObjcOnlyListener+Private.mm
djinni-output-temp/objc/DBJavaOnlyListener+Private.h djinni-output-temp/objc/DBJavaOnlyListener+Private.h
......
#pragma once
#include "extended_record_base.hpp"
namespace testsuite {
struct ExtendedRecord : public ExtendedRecordBase
{
using ExtendedRecordBase::ExtendedRecordBase;
};
}
\ No newline at end of file
...@@ -71,6 +71,7 @@ fi ...@@ -71,6 +71,7 @@ fi
--ident-cpp-enum-type foo_bar \ --ident-cpp-enum-type foo_bar \
--cpp-optional-template "std::experimental::optional" \ --cpp-optional-template "std::experimental::optional" \
--cpp-optional-header "<experimental/optional>" \ --cpp-optional-header "<experimental/optional>" \
--cpp-extended-record-include-prefix "../../handwritten-src/cpp/" \
\ \
--jni-out "$temp_out_relative/jni" \ --jni-out "$temp_out_relative/jni" \
--ident-jni-class NativeFooBar \ --ident-jni-class NativeFooBar \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment