일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 안드로이드
- Java
- 프로그래머스
- 코틀린
- Django REST
- RxAndroid
- flutter firestore
- C/C++
- livedata
- Python
- 안드로이드 구글맵
- Django REST framework
- kodility
- C
- Kotlin
- FLUTTER
- C++
- 알고리즘
- UWP
- Android
- dart
- Rxjava2
- RxJava
- Android P
- mfc
- Flutter TextField
- Django REST Android
- NDK
- android push
- android architecture component
- Today
- Total
개발하는 두더지
Android NDK 32bit 64bit abi 와 2GB 이상 파일 지원 본문
NDK의 경우 LP64 를 사용해서 타입의 크기가 아래와 같다
32bit 64bit (LP64 vs LLP64)
Target API Set Higher Than Device API
The target API level in the NDK has a very different meaning than targetSdkVersion
does in Java. The NDK target API level is your app's minimum supported API level. In ndk-build, this is your APP_PLATFORM
setting.
Android에서의 TargetSdkVersion과 NDK에서의 TargetSdkVersion은 의미하는게 서로 다르다.
NDK에서는 최소 API 지원 레벨을 의미한다.
Since references to functions are (typically) resolved when a library is loaded rather than when they are first called, you cannot reference APIs that are not always present and guard their use with API level checks. If they are referred to at all, they must be present.
Problem: Your target API level is higher than the API supported by your device.
Solution: Set your target API level (APP_PLATFORM
) to the minimum version of Android your app supports.
Build System | Setting |
---|---|
ndk-build | APP_PLATFORM |
CMake | ANDROID_PLATFORM |
Standalone Toolchain | --api |
Gradle | TODO: No idea |
자바는 long type이 signed 8byte라 범위가 -9223372036854775808 ~ 9223372036854775807이다.
2GB 이상 파일을 지원한다. 하지만 NDK r14 이전에는 2GB이상 파일을 지원하지 않았다.
파일을 생성하고 데이터를 쓰고 핸들을 닫는 함수들은 사용가능하지만,
fseek, ftell 과 같이 파일 포인터를 이동하고, 파일의 크기를 구해오는 함수는 사용할 수 없다.
이유는 c의 long type을 반환하는 함수들인데 long은 32bit 아키텍처에서 4byte 크기이기 때문에
즉, signed int와 크기가 똑같다.
Linux에서는 2GB 이상 지원하기 위해 컴파일 옵션에 아래 옵션을 주거나 #define FILE_OFFSET_BITS 64 를 정의하여 2GB 파일을 지원할 수 있다.
LOCAL_CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
물론 NDK에서도 지원 가능해졌다. 정확히 몇 버전부터 몇 버전까지 위 옵션을 주는 것이 가능한지는 모르겠지만
포스팅 기준 r17 버전에서는 이미 Unifited Header라고 통합헤더가 나왔다.
통합 헤더가 나온 이유는 버전 별 헤더의 불 일치로 인한 불편함으로 완성되었다고 한다.
어쨌든, Unified Header가 있는 환경에서
#define FILE_OFFSET_BITS 64 을 적용하면 컴파일 에러가 발생한다.
친절하게도 문서에서 아래의 옵션이 정의되어있으면 다 삭제하라고 가이드를 한다.
#if _FILE_OFFSET_BITS == 64
#error "oops, file _FILE_OFFSET_BITS == 64"
#elif defined(__USE_FILE_OFFSET64)
#error "oops, __USE_FILE_OFFSET64 is defined"
#endif
어찌됐건, 32bit, 64bit cpu 아키텍쳐 환경에서 2GB 파일을 지원하려면 off64_t 를 이용해야 될 것 같다.
/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
/* See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64) || defined(__LP64__)
typedef int64_t off_t;
typedef off_t loff_t;
typedef loff_t off64_t;
보기엔 off_t 와 off64_t가 typedef로 이름만 재정의 한 것인데 size를 찍어보면 32bit 환경에서 4byte, 8byte로 크기가 다르다.
또한 fseeko 는 off_t 타입을 반환 fseek64는 off64_t 를 반환한다. ftello는 off_t 반환하고 ftello64는 off64_t를 반환한다.
문제는 32bit에서 ftello64를 사용하려면 minSdkVersion을 24로 지정해야 된다. 마시멜로우도 아니고 누가부터..
off_t가 4byte가 아닌 8byte가 된다면 낮은 API 레벨로도 사용이 가능한데 아직까지는 어떻게 옵션을 주는지 모르겠다.
직접 정의하는건 컴파일 오류, 컴파일 옵션에 Flag값 설정하는건 옵션 무시를 당한다..
_FILE_OFFSET_BITS=64
Don't set _FILE_OFFSET_BITS=64
if you want to keep the
behavior present in old NDKs.
Historically, setting _FILE_OFFSET_BITS=64
in the NDK did nothing.
This feature was not present in the deprecated headers at all. With unified
headers, the NDK now has up to date headers with support for this feature.
_FILE_OFFSET_BITS=64
is a macro you can define in your application
to get support for a 64-bit off_t
in 32-bit code. This works by
both making off_t
64-bit (by default it is 32-bit in 32-bit code)
and by implicitly replacing calls to APIs like lseek
with calls to
lseek64
.
Support for _FILE_OFFSET_BITS=64
was not added to Android in a
single release. One API, lseek64
, has always been in bionic. Most
APIs were added in Lollipop, and a few more were not added until later releases.
If you're targeting a release that does not support the 64-bit
off_t
variant of a function you are using and have set
_FILE_OFFSET_BITS=64
, the function will not be available. This is
in contrast to the behavior for r15 and r15b (but matches r15c) where the
functions were wrongly exposed with a 32-bit off_t
that would be
silently truncated.
Note that the 64-bit off_t
APIs are still available without
_FILE_OFFSET_BITS=64
under different names. For example, instead of
lseek
, call lseek64
. Instead of off_t
,
use off64_t
.
Finally, since this feature is new to the NDK with unified headers, if you just
want to return to the pre-unified headers behavior, all you need to do is stop
setting _FILE_OFFSET_BITS=64
.
출처
Using _FILE_OFFSET_BITS=64 with early api level
'Java,Android' 카테고리의 다른 글
리틀엔디안(Little Endian)과 빅 엔디안(Big Endian) (0) | 2018.08.23 |
---|---|
Android Cannot fit requested classes in a single dex file. 해결 방법 - 190124 업데이트 (3) | 2018.08.19 |
Android Architecture Components ViewModel이란? (1) | 2018.08.12 |
Android NDK 빌드툴인 NDK-Build 와 CMake 정리 (1) | 2018.08.02 |
kotlin + firebase 를 이용한 Push Notification 구현(3) (1) | 2018.07.19 |