J2ObjC에서 생성된 헤더 파일은 세그먼트로 나뉘며 한 번에 하나의 세그먼트로 포함될 수 있습니다. 번역된 Java 유형마다 세그먼트가 하나씩 생성되므로 각 내부 클래스에는 자체 세그먼트가 있습니다. 전처리기 매크로는 헤더를 포함할 때 특정 세그먼트를 읽도록 컴파일러에 알리는 데 사용됩니다.세그먼트화된 헤더는 아래에 자세히 설명된 J2ObjC 생성 헤더의 포함 주기 문제를 해결합니다.
알아 두어야 할 사항
#import
대신#include
를 사용하여 J2ObjC에서 생성된 헤더를 포함합니다.- 분할된 헤더와 함께
#import
를 사용하면 컴파일러가 헤더를 이미 확인한 경우 헤더 읽기를 건너뛰게 되므로 문제가 됩니다. 하지만 헤더가 세분화되어 있으므로 처음에 컴파일러에서 완전히 파싱하지 않았을 수도 있습니다.
- 분할된 헤더와 함께
- 분할된 헤더는
--no-segmented-headers
플래그를 사용하여 사용 중지할 수 있습니다.
전단 포함
J2ObjC 생성 헤더 파일은 include 및 전달 선언을 사용하여 필요한 유형 정보를 확인해야 합니다. 전방 선언은 가능한 한 많이 사용되지만 컴파일러에 전체 유형 선언이 필요하기 때문에 유형을 확장하거나 구현하려면 include가 필요합니다.
J2ObjC에서 생성된 헤더 파일에서 포함 주기를 생성할 수 있습니다. 이러한 주기를 위해서는 파일 B의 클래스를 확장하는 파일 A의 클래스와 파일 A의 클래스를 확장하는 파일 B의 클래스가 필요합니다. 드물게 발생하는 시나리오는 아니지만, Guava의 코드베이스 및 다른 곳에서도 발생합니다.
.java 파일에서 발생하는 각 Java 유형에 대해 별도의 헤더 파일을 내보내면 이 문제를 자연스럽게 해결할 수 있습니다. 그러나 J2ObjC는 빌드 도구로 사용되도록 설계되었으며, 양호한 빌드 시스템은 각 입력의 예측 가능한 출력에 의존합니다. 즉, 각 .java 파일이 정확히 하나의 .h와 하나의 .m 파일을 생성해야 합니다.
예
Foo.java:
class Foo extends Bar {}
Bar.java:
class Bar {
static class Baz extends Foo {}
}
Foo.h (분류되지 않음):
#ifndef _Foo_H_
#define _Foo_H_
#include "Bar.h"
#include "J2ObjC_header.h"
@interface Foo : Bar
- (instancetype)init;
@end
#endif // _Foo_H_
Bar.h (세분화되지 않음):
#ifndef _Bar_H_
#define _Bar_H_
#include "Foo.h"
#include "J2ObjC_header.h"
@interface Bar : NSObject
- (instancetype)init;
@end
@interface Bar_Baz : Foo
- (instancetype)init;
@end
#endif // _Bar_H_
Foo.h에는 Bar.h가, Bar.h에는 Foo.h가 포함되어 있습니다. 따라서 이러한 헤더는 컴파일에 실패합니다.
../dist/j2objcc -c Foo.m
In file included from Foo.m:6: In file included from ./Bar.h:9: ./Foo.h:12:18: error: cannot find interface declaration for 'Bar', superclass of 'Foo' @interface Foo : Bar ~~~~~~~~~~~~~~ ^
다음은 오류 없이 컴파일되는 Foo.h 및 Bar.h의 분할 버전입니다.
Foo.h (분류됨):
#include "J2ObjC_header.h"
#pragma push_macro("Foo_INCLUDE_ALL")
#if Foo_RESTRICT
#define Foo_INCLUDE_ALL 0
#else
#define Foo_INCLUDE_ALL 1
#endif
#undef Foo_RESTRICT
#if !defined (_Foo_) && (Foo_INCLUDE_ALL || Foo_INCLUDE)
#define _Foo_
#define Bar_RESTRICT 1
#define Bar_INCLUDE 1
#include "Bar.h"
@interface Foo : Bar
- (instancetype)init;
@end
#endif
#pragma pop_macro("Foo_INCLUDE_ALL")
Bar.h (분류됨):
#include "J2ObjC_header.h"
#pragma push_macro("Bar_INCLUDE_ALL")
#if Bar_RESTRICT
#define Bar_INCLUDE_ALL 0
#else
#define Bar_INCLUDE_ALL 1
#endif
#undef Bar_RESTRICT
#if !defined (_Bar_) && (Bar_INCLUDE_ALL || Bar_INCLUDE)
#define _Bar_
@interface Bar : NSObject
- (instancetype)init;
@end
#endif
#if !defined (_Bar_Baz_) && (Bar_INCLUDE_ALL || Bar_Baz_INCLUDE)
#define _Bar_Baz_
#define Foo_RESTRICT 1
#define Foo_INCLUDE 1
#include "Foo.h"
@interface Bar_Baz : Foo
- (instancetype)init;
@end
#endif
#pragma pop_macro("Bar_INCLUDE_ALL")