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) {
// Requiring the extended class
if (r.ext.cpp) {
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
......
......@@ -27,6 +27,7 @@ object Main {
var cppOutFolder: Option[File] = None
var cppNamespace: String = ""
var cppIncludePrefix: String = ""
var cppExtendedRecordIncludePrefix: String = ""
var cppFileIdentStyle: IdentConverter = IdentStyle.underLower
var cppOptionalTemplate: String = "std::optional"
var cppOptionalHeader: String = "<optional>"
......@@ -62,6 +63,7 @@ object Main {
var objcIdentStyle = IdentStyle.objcDefault
var objcTypePrefix: String = ""
var objcIncludePrefix: String = ""
var objcExtendedRecordIncludePrefix: String = ""
var objcppIncludePrefix: String = ""
var objcppIncludeCppPrefix: String = ""
var objcppIncludeObjcPrefixOptional: Option[String] = None
......@@ -161,6 +163,10 @@ object Main {
.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))
.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 = _)
.text("The namespace name to use for generated Objective-C++ classes.")
opt[String]("objc-base-lib-include-prefix").valueName("...").foreach(x => objcBaseLibIncludePrefix = x)
......@@ -273,6 +279,7 @@ object Main {
cppOutFolder,
cppHeaderOutFolder,
cppIncludePrefix,
cppExtendedRecordIncludePrefix,
cppNamespace,
cppIdentStyle,
cppFileIdentStyle,
......@@ -299,6 +306,7 @@ object Main {
objcppExt,
objcHeaderExt,
objcIncludePrefix,
objcExtendedRecordIncludePrefix,
objcppIncludePrefix,
objcppIncludeCppPrefix,
objcppIncludeObjcPrefix,
......
......@@ -178,7 +178,7 @@ class ObjcGenerator(spec: Spec) extends Generator(spec) {
val self = marshal.typename(objcName, r)
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) {
refs.header.add(s"@class $noBaseSelf;")
......
......@@ -66,8 +66,8 @@ class ObjcMarshal(spec: Spec) extends Marshal(spec) {
}
case DRecord =>
val r = d.body.asInstanceOf[Record]
val prefix = if (r.ext.objc) "../" else ""
List(ImportRef(q(spec.objcIncludePrefix + prefix + headerName(d.name))))
val prefix = if (r.ext.objc) spec.objcExtendedRecordIncludePrefix else spec.objcIncludePrefix
List(ImportRef(q(prefix + headerName(d.name))))
}
case e: MExtern => List(ImportRef(e.objc.header))
case p: MParam => List()
......
......@@ -302,8 +302,8 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
val noBaseSelf = objcMarshal.typename(ident, r) // Used for constant names
val cppSelf = cppMarshal.fqTypename(ident, r)
refs.privHeader.add("!#import " + q(spec.objcppIncludeObjcPrefix + (if(r.ext.objc) "../" else "") + headerName(ident)))
refs.privHeader.add("!#include " + q(spec.objcppIncludeCppPrefix + (if(r.ext.cpp) "../" else "") + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt))
refs.privHeader.add("!#import " + q((if(r.ext.objc) spec.objcExtendedRecordIncludePrefix else spec.objcppIncludeObjcPrefix) + headerName(ident)))
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("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(objcName)))
......
......@@ -38,6 +38,7 @@ package object generatorTools {
cppOutFolder: Option[File],
cppHeaderOutFolder: Option[File],
cppIncludePrefix: String,
cppExtendedRecordIncludePrefix: String,
cppNamespace: String,
cppIdentStyle: CppIdentStyle,
cppFileIdentStyle: IdentConverter,
......@@ -64,6 +65,7 @@ package object generatorTools {
objcppExt: String,
objcHeaderExt: String,
objcIncludePrefix: String,
objcExtendedRecordIncludePrefix: String,
objcppIncludePrefix: String,
objcppIncludeCppPrefix: String,
objcppIncludeObjcPrefix: String,
......
......@@ -12,3 +12,4 @@
@import "constants.djinni"
@import "multiple_inheritance.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
djinni/constants.djinni
djinni/multiple_inheritance.djinni
djinni/single_language_interfaces.djinni
djinni/extended_record.djinni
djinni/date.djinni
djinni/date.yaml
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
djinni-output-temp/cpp/date_record.hpp
djinni-output-temp/cpp/date_record.cpp
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/java_only_listener.hpp
djinni-output-temp/cpp/uses_single_language_listeners.hpp
......@@ -41,6 +42,7 @@ djinni-output-temp/java/TestDuration.java
djinni-output-temp/java/RecordWithDurationAndDerivings.java
djinni-output-temp/java/DateRecord.java
djinni-output-temp/java/MapDateRecord.java
djinni-output-temp/java/ExtendedRecord.java
djinni-output-temp/java/ObjcOnlyListener.java
djinni-output-temp/java/JavaOnlyListener.java
djinni-output-temp/java/UsesSingleLanguageListeners.java
......@@ -77,6 +79,8 @@ djinni-output-temp/jni/NativeDateRecord.hpp
djinni-output-temp/jni/NativeDateRecord.cpp
djinni-output-temp/jni/NativeMapDateRecord.hpp
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.cpp
djinni-output-temp/jni/NativeJavaOnlyListener.hpp
......@@ -139,6 +143,8 @@ djinni-output-temp/objc/DBDateRecord.h
djinni-output-temp/objc/DBDateRecord.mm
djinni-output-temp/objc/DBMapDateRecord.h
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/DBJavaOnlyListener.h
djinni-output-temp/objc/DBUsesSingleLanguageListeners.h
......@@ -189,6 +195,8 @@ djinni-output-temp/objc/DBDateRecord+Private.h
djinni-output-temp/objc/DBDateRecord+Private.mm
djinni-output-temp/objc/DBMapDateRecord+Private.h
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.mm
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
--ident-cpp-enum-type foo_bar \
--cpp-optional-template "std::experimental::optional" \
--cpp-optional-header "<experimental/optional>" \
--cpp-extended-record-include-prefix "../../handwritten-src/cpp/" \
\
--jni-out "$temp_out_relative/jni" \
--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