CMake 또는 ndk-build를 사용하지 않고 Android Gradle 플러그인(AGP) C/C++ 빌드와 Android 스튜디오를 완전히 통합하려면 Ninja 빌드 파일 형식으로 빌드 정보를 작성하는 셸 스크립트를 만들어서 맞춤 C/C++ 빌드 시스템을 생성하면 됩니다.
맞춤 C/C++ 빌드 시스템의 실험적 지원 기능이 Android 스튜디오 및 AGP에 추가되었습니다. 이 기능은 Android 스튜디오 Dolphin | 2021.3.1 Canary 4부터 사용할 수 있습니다.
개요
C/C++ 프로젝트(특히 여러 플랫폼을 타겟팅하는 프로젝트)의 일반적인 패턴은 일부 기본 표현에서 플랫폼별로 프로젝트를 생성하는 것입니다.
이러한 패턴의 대표적인 예는 CMake입니다. CMake는 CMakeLists.txt
파일에 저장된 단일 기본 표현으로 Android, iOS, 기타 플랫폼용 프로젝트를 생성할 수 있습니다.
CMake는 AGP에서 직접 지원됩니다. 다음과 같이 직접 지원되지 않는 다른 프로젝트 생성기를 사용할 수도 있습니다.
이러한 유형의 프로젝트 생성기는 Ninja를 C/C++ 빌드의 백엔드 표현으로 지원하거나 Ninja를 백엔드 표현으로 생성하도록 조정할 수 있습니다.
통합 C/C++ 프로젝트 시스템 생성기가 포함된 AGP 프로젝트를 올바르게 구성하면 사용자가 다음을 할 수 있게 됩니다.
명령줄 및 Android 스튜디오에서 빌드합니다.
Android 스튜디오에서 전체 언어 서비스 지원(예: 정의로 이동)을 사용하여 소스를 수정합니다.
Android 스튜디오 디버거를 사용하여 네이티브 및 혼합 프로세스를 디버그합니다.
맞춤 C/C++ 빌드 구성 스크립트를 사용하도록 빌드를 수정하는 방법
이 섹션에서는 AGP에서 맞춤 C/C++ 빌드 구성 스크립트를 사용하기 위한 단계를 안내합니다.
1단계: 구성 스크립트를 참조하도록 모듈 수준 build.gradle
파일 수정하기
AGP에서 Ninja 지원을 사용 설정하려면 모듈 수준 build.gradle
파일에서 experimentalProperties
를 구성합니다.
android {
defaultConfig {
externalNativeBuild {
experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
experimentalProperties["ninja.path"] = "source-file-list.txt"
experimentalProperties["ninja.configure"] = "configure-ninja"
experimentalProperties["ninja.arguments"] = [
"\${ndk.moduleMakeFile}",
"--variant=\${ndk.variantName}",
"--abi=Android-\${ndk.abi}",
"--configuration-dir=\${ndk.configurationDir}",
"--ndk-version=\${ndk.moduleNdkVersion}",
"--min-sdk-version=\${ndk.minSdkVersion}"
]
}
}
속성은 AGP에서 다음과 같이 해석됩니다.
ninja.abiFilters
는 빌드할 ABI 목록입니다. 유효한 값은x86
,x86-64
,armeabi-v7a
,arm64-v8a
입니다.ninja.path
는 C/C++ 프로젝트 파일의 경로입니다. 파일의 형식은 원하는 대로 지정할 수 있습니다. 이 파일을 변경하면 Android 스튜디오에서 Gradle 동기화 메시지가 트리거됩니다.ninja.configure
는 C/C++ 프로젝트를 구성해야 할 때 Gradle에서 실행할 스크립트 파일의 경로입니다. 프로젝트는 첫 번째 빌드(Android 스튜디오에서 Gradle 동기화 중)에서 구성되거나 구성 스크립트 입력 중 하나가 변경될 때 구성됩니다.ninja.arguments
는 ninja.configure로 정의된 스크립트에 전달되는 인수 목록입니다. 이 목록의 요소는 AGP의 현재 구성 컨텍스트에 따라 값이 달라지는 매크로 집합을 참조할 수 있습니다.${ndk.moduleMakeFile}
은ninja.configure
파일의 전체 경로입니다. 이 예에서는C:\path\to\configure-ninja.bat
입니다.${ndk.variantName}
은 빌드 중인 현재 AGP 변형의 이름입니다. 예를 들어 debug 또는 release입니다.${ndk.abi}
는 빌드 중인 현재 AGP ABI의 이름입니다. 예를 들어x86
또는arm64-v8a
입니다.
${ndk.buildRoot}
는 스크립트가 출력물을 기록하는 폴더 이름으로 AGP에서 생성합니다. 자세한 내용은 2단계: 구성 스크립트 만들기에서 설명합니다.${ndk.ndkVersion}
은 사용할 NDK 버전입니다. 일반적으로build.gradle
파일의 android.ndkVersion에 전달된 값이거나 기본값입니다(전달된 값이 없는 경우).${ndk.minPlatform}
은 AGP에서 요청하는 최소 타겟 Android 플랫폼입니다.
ninja.targets
는 빌드해야 하는 특정 Ninja 타겟의 목록입니다.
2단계: 구성 스크립트 만들기
Ninja로 빌드할 때 프로젝트의 모든 네이티브 출력을 컴파일하고 연결하는 build.ninja
파일을 생성하는 것이 구성 스크립트(이전 예에서 configure-ninja.bat
)의 최소한의 역할입니다. 일반적으로 .o
(객체), .a
(보관 파일), .so
(공유 객체) 파일이 여기에 해당됩니다.
구성 스크립트는 필요에 따라 두 개의 다른 위치에 build.ninja
파일을 쓸 수 있습니다.
AGP에서 위치를 선택해도 괜찮다면 구성 스크립트는
${ndk.buildRoot}
매크로에 설정된 위치에build.ninja
를 작성합니다.구성 스크립트에서
build.ninja
파일의 위치를 선택해야 하는 경우${ndk.buildRoot}
매크로에 설정된 위치에build.ninja.txt
라는 파일도 작성합니다. 이 파일에는 구성 스크립트가 작성한build.ninja
파일의 전체 경로가 포함됩니다.
build.ninja
파일의 구조
일반적으로 Android C/C++ 빌드를 정확하게 나타내는 구조는 대부분 작동합니다. AGP 및 Android 스튜디오에 필요한 핵심 요소는 다음과 같습니다.
C/C++ 소스 파일과 이를 컴파일하기 위해 Clang에 필요한 플래그 목록
출력 라이브러리 목록. 일반적으로
.so
(공유 객체) 파일이지만.a
(보관 파일) 또는 실행 파일(확장자 없음)일 수도 있습니다.
build.ninja
파일을 생성하는 방법의 예가 필요하면 build.ninja
생성기를 사용할 때 CMake의 출력을 확인하세요.
다음은 최소 build.ninja
템플릿의 예입니다.
rule COMPILE
command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
권장사항
다음은 요구사항(소스 파일 및 출력 라이브러리 목록) 외에 권장되는 몇 가지 사항입니다.
phony
규칙으로 이름이 지정된 출력 선언
가능하면 build.ninja
구조체에서 phony
규칙을 사용하여 사람이 읽을 수 있는 빌드 출력 이름을 제공하는 것이 좋습니다. 예를 들어 c:/path/to/lib.so
라는 출력이 있으면 다음과 같이 사람이 읽을 수 있는 이름을 지정할 수 있습니다.
build curl: phony /path/to/lib.so
이렇게 하면 build.gradle
파일에서 이 이름을 빌드 타겟으로 지정할 수 있습니다. 예:
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
'all' 타겟 지정
all
타겟을 지정하면 build.gradle
파일에 명시적으로 지정된 타겟이 없는 경우 이것이 AGP에서 빌드한 기본 라이브러리 집합이 됩니다.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so
대체 빌드 메서드 지정(선택사항)
더 고급 사용 사례는 Ninja 기반이 아닌 기존 빌드 시스템을 래핑하는 것입니다. 이 경우에도 Android 스튜디오에서 자동 완성 및 정의로 이동과 같은 적절한 언어 서비스 기능을 제공할 수 있도록 모든 소스와 플래그 및 출력 라이브러리를 표현해야 합니다. 그러나 AGP에서 실제 빌드 중에 기본 빌드 시스템으로 지연해야 하는 경우도 있습니다.
이 경우 Ninja 빌드 출력에 특정 확장자 .passthrough
를 사용하면 됩니다.
좀 더 구체적인 예로, MSBuild를 래핑한다고 가정해 보겠습니다. 구성 스크립트는 평상시와 같이 build.ninja
를 생성하지만, AGP에서 MSBuild를 호출하는 방법을 정의하는 패스 스루 타겟도 추가합니다.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
rule MBSUILD_CURL
command = /path/to/msbuild {flags to build curl with MSBuild}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL
의견 보내기
이 기능은 실험적 기능이므로 의견을 보내주시면 큰 도움이 됩니다. 다음 채널을 통해 의견을 보낼 수 있습니다.
일반적인 의견을 보내려면 이 버그에 댓글을 추가하세요.
버그를 신고하려면 Android 스튜디오를 열고 Help > Submit Feedback을 클릭합니다. 해당 버그를 찾을 수 있도록 '맞춤 C/C++ 빌드 시스템'을 언급해 주세요.
Android 스튜디오를 설치하지 않은 경우에는 이 템플릿을 사용하여 버그를 신고하세요.