세분화된 헤더

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")